diff options
| author | Richard M. Stallman | 1997-07-23 02:52:57 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-07-23 02:52:57 +0000 |
| commit | 8d15583ff560b23e7482e588351300d9fdcc5720 (patch) | |
| tree | 780518bc4321579218530808dc99b4c86bbce917 | |
| parent | c8225cbef31d718d9a65b420faaf0bc387573acb (diff) | |
| download | emacs-8d15583ff560b23e7482e588351300d9fdcc5720.tar.gz emacs-8d15583ff560b23e7482e588351300d9fdcc5720.zip | |
(occur): Use text property `occur' to store the
marker for the occurrence in the source buffer. This replaces the
list `occur-pos-list', and fixes the bug for multi-line matches.
Set up `occur-point' text property for occur-next and occur-prev.
(occur): occur-num-matches stores the number of matches found.
(occur-mode-find-occurrence): Use `occur' text property to find
marker for locus of the occurrence.
(occur-next, occur-prev): New commands.
(occur): Fixed bug preventing line number being displayed if line
number is less than the number of lines of context.
| -rw-r--r-- | lisp/replace.el | 132 |
1 files changed, 81 insertions, 51 deletions
diff --git a/lisp/replace.el b/lisp/replace.el index f0dc0fc1cea..a13916bf280 100644 --- a/lisp/replace.el +++ b/lisp/replace.el | |||
| @@ -246,11 +246,12 @@ Applies to lines after point." | |||
| 246 | (define-key occur-mode-map [mouse-2] 'occur-mode-mouse-goto) | 246 | (define-key occur-mode-map [mouse-2] 'occur-mode-mouse-goto) |
| 247 | (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence) | 247 | (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence) |
| 248 | (define-key occur-mode-map "\C-m" 'occur-mode-goto-occurrence) | 248 | (define-key occur-mode-map "\C-m" 'occur-mode-goto-occurrence) |
| 249 | (define-key occur-mode-map "\M-n" 'occur-next) | ||
| 250 | (define-key occur-mode-map "\M-p" 'occur-prev) | ||
| 249 | (define-key occur-mode-map "g" 'revert-buffer)) | 251 | (define-key occur-mode-map "g" 'revert-buffer)) |
| 250 | 252 | ||
| 251 | (defvar occur-buffer nil) | 253 | (defvar occur-buffer nil) |
| 252 | (defvar occur-nlines nil) | 254 | (defvar occur-nlines nil) |
| 253 | (defvar occur-pos-list nil) | ||
| 254 | (defvar occur-command-arguments nil | 255 | (defvar occur-command-arguments nil |
| 255 | "Arguments that were given to `occur' when it made this buffer.") | 256 | "Arguments that were given to `occur' when it made this buffer.") |
| 256 | 257 | ||
| @@ -271,7 +272,6 @@ Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. | |||
| 271 | (setq revert-buffer-function 'occur-revert-function) | 272 | (setq revert-buffer-function 'occur-revert-function) |
| 272 | (make-local-variable 'occur-buffer) | 273 | (make-local-variable 'occur-buffer) |
| 273 | (make-local-variable 'occur-nlines) | 274 | (make-local-variable 'occur-nlines) |
| 274 | (make-local-variable 'occur-pos-list) | ||
| 275 | (make-local-variable 'occur-command-arguments) | 275 | (make-local-variable 'occur-command-arguments) |
| 276 | (run-hooks 'occur-mode-hook)) | 276 | (run-hooks 'occur-mode-hook)) |
| 277 | 277 | ||
| @@ -299,28 +299,12 @@ Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. | |||
| 299 | (if (or (null occur-buffer) | 299 | (if (or (null occur-buffer) |
| 300 | (null (buffer-name occur-buffer))) | 300 | (null (buffer-name occur-buffer))) |
| 301 | (progn | 301 | (progn |
| 302 | (setq occur-buffer nil | 302 | (setq occur-buffer nil) |
| 303 | occur-pos-list nil) | ||
| 304 | (error "Buffer in which occurrences were found is deleted"))) | 303 | (error "Buffer in which occurrences were found is deleted"))) |
| 305 | (let* ((line-count | 304 | (let ((pos (get-text-property (point) 'occur))) |
| 306 | (count-lines (point-min) | 305 | (if (null pos) |
| 307 | (save-excursion | 306 | (error "No occurrence on this line") |
| 308 | (beginning-of-line) | 307 | pos))) |
| 309 | (point)))) | ||
| 310 | (occur-number (save-excursion | ||
| 311 | (beginning-of-line) | ||
| 312 | (/ (1- line-count) | ||
| 313 | (cond ((< occur-nlines 0) | ||
| 314 | (- 2 occur-nlines)) | ||
| 315 | ((> occur-nlines 0) | ||
| 316 | (+ 2 (* 2 occur-nlines))) | ||
| 317 | (t 1))))) | ||
| 318 | (pos (nth occur-number occur-pos-list))) | ||
| 319 | (if (< line-count 1) | ||
| 320 | (error "No occurrence on this line")) | ||
| 321 | (or pos | ||
| 322 | (error "No occurrence on this line")) | ||
| 323 | pos)) | ||
| 324 | 308 | ||
| 325 | (defun occur-mode-goto-occurrence () | 309 | (defun occur-mode-goto-occurrence () |
| 326 | "Go to the occurrence the current line describes." | 310 | "Go to the occurrence the current line describes." |
| @@ -328,6 +312,39 @@ Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. | |||
| 328 | (let ((pos (occur-mode-find-occurrence))) | 312 | (let ((pos (occur-mode-find-occurrence))) |
| 329 | (pop-to-buffer occur-buffer) | 313 | (pop-to-buffer occur-buffer) |
| 330 | (goto-char (marker-position pos)))) | 314 | (goto-char (marker-position pos)))) |
| 315 | |||
| 316 | (defun occur-next (&optional n) | ||
| 317 | "Move to the Nth (default 1) next match in the *Occur* buffer." | ||
| 318 | (interactive "p") | ||
| 319 | (if (not n) (setq n 1)) | ||
| 320 | (let ((r)) | ||
| 321 | (while (> n 0) | ||
| 322 | (if (get-text-property (point) 'occur-point) | ||
| 323 | (forward-char 1)) | ||
| 324 | (setq r (next-single-property-change (point) 'occur-point)) | ||
| 325 | (if r | ||
| 326 | (goto-char r) | ||
| 327 | (error "no more matches")) | ||
| 328 | (setq n (1- n))))) | ||
| 329 | |||
| 330 | |||
| 331 | |||
| 332 | (defun occur-prev (&optional n) | ||
| 333 | "Move to the Nth (default 1) previous match in the *Occur* buffer." | ||
| 334 | (interactive "p") | ||
| 335 | (if (not n) (setq n 1)) | ||
| 336 | (let ((r)) | ||
| 337 | (while (> n 0) | ||
| 338 | |||
| 339 | (setq r (get-text-property (point) 'occur-point)) | ||
| 340 | (if r (forward-char -1)) | ||
| 341 | |||
| 342 | (setq r (previous-single-property-change (point) 'occur-point)) | ||
| 343 | (if r | ||
| 344 | (goto-char (- r 1)) | ||
| 345 | (error "no earlier matches")) | ||
| 346 | |||
| 347 | (setq n (1- n))))) | ||
| 331 | 348 | ||
| 332 | (defcustom list-matching-lines-default-context-lines 0 | 349 | (defcustom list-matching-lines-default-context-lines 0 |
| 333 | "*Default number of context lines to include around a `list-matching-lines' | 350 | "*Default number of context lines to include around a `list-matching-lines' |
| @@ -376,6 +393,7 @@ the matching is case-sensitive." | |||
| 376 | (prefix-numeric-value nlines) | 393 | (prefix-numeric-value nlines) |
| 377 | list-matching-lines-default-context-lines)) | 394 | list-matching-lines-default-context-lines)) |
| 378 | (first t) | 395 | (first t) |
| 396 | (occur-num-matches 0) | ||
| 379 | (buffer (current-buffer)) | 397 | (buffer (current-buffer)) |
| 380 | (dir default-directory) | 398 | (dir default-directory) |
| 381 | (linenum 1) | 399 | (linenum 1) |
| @@ -406,7 +424,6 @@ the matching is case-sensitive." | |||
| 406 | (occur-mode) | 424 | (occur-mode) |
| 407 | (setq occur-buffer buffer) | 425 | (setq occur-buffer buffer) |
| 408 | (setq occur-nlines nlines) | 426 | (setq occur-nlines nlines) |
| 409 | (setq occur-pos-list ()) | ||
| 410 | (setq occur-command-arguments | 427 | (setq occur-command-arguments |
| 411 | (list regexp nlines))) | 428 | (list regexp nlines))) |
| 412 | (if (eq buffer standard-output) | 429 | (if (eq buffer standard-output) |
| @@ -431,30 +448,45 @@ the matching is case-sensitive." | |||
| 431 | (forward-line (1+ nlines)) | 448 | (forward-line (1+ nlines)) |
| 432 | (forward-line 1)) | 449 | (forward-line 1)) |
| 433 | (point))) | 450 | (point))) |
| 434 | ;; Record where the actual match | 451 | (match-beg (- (match-beginning 0) start)) |
| 435 | (match-offset | ||
| 436 | (save-excursion | ||
| 437 | (goto-char (match-beginning 0)) | ||
| 438 | (beginning-of-line) | ||
| 439 | ;; +6 to skip over line number | ||
| 440 | (+ 6 (- (match-beginning 0) (point))))) | ||
| 441 | (match-len (- (match-end 0) (match-beginning 0))) | 452 | (match-len (- (match-end 0) (match-beginning 0))) |
| 442 | (tag (format "%5d" linenum)) | 453 | (tag (format "%5d" linenum)) |
| 443 | (empty (make-string (length tag) ?\ )) | 454 | (empty (make-string (length tag) ?\ )) |
| 444 | tem) | 455 | tem |
| 456 | occur-marker | ||
| 457 | (text-beg (make-marker)) | ||
| 458 | (text-end (make-marker)) | ||
| 459 | ) | ||
| 445 | (save-excursion | 460 | (save-excursion |
| 446 | (setq tem (make-marker)) | 461 | (setq occur-marker (make-marker)) |
| 447 | (set-marker tem (point)) | 462 | (set-marker occur-marker (point)) |
| 448 | (set-buffer standard-output) | 463 | (set-buffer standard-output) |
| 449 | (setq occur-pos-list (cons tem occur-pos-list)) | 464 | (setq occur-num-matches (1+ occur-num-matches)) |
| 450 | (or first (zerop nlines) | 465 | (or first (zerop nlines) |
| 451 | (insert "--------\n")) | 466 | (insert "--------\n")) |
| 452 | (setq first nil) | 467 | (setq first nil) |
| 468 | (set-marker text-beg (point)) | ||
| 453 | (insert-buffer-substring buffer start end) | 469 | (insert-buffer-substring buffer start end) |
| 470 | (set-marker text-end (point)) | ||
| 471 | (if list-matching-lines-face | ||
| 472 | (put-text-property | ||
| 473 | (+ (marker-position text-beg) match-beg) | ||
| 474 | (+ (marker-position text-beg) match-beg match-len) | ||
| 475 | 'face list-matching-lines-face)) | ||
| 476 | |||
| 477 | ;; Identify a place for occur-next and occur-prev | ||
| 478 | ;; to move to. | ||
| 479 | (put-text-property | ||
| 480 | (+ (marker-position text-beg) match-beg match-len) | ||
| 481 | (+ (marker-position text-beg) match-beg match-len 1) | ||
| 482 | 'occur-point t) | ||
| 454 | (set-marker final-context-start | 483 | (set-marker final-context-start |
| 455 | (- (point) (- end (match-end 0)))) | 484 | (- (point) (- end (match-end 0)))) |
| 456 | (goto-char (- (point) (- end start))) | 485 | (goto-char (- (point) (- end start))) |
| 457 | (setq tem nlines) | 486 | ;;(setq tem nlines) |
| 487 | (setq tem (if (< linenum nlines) | ||
| 488 | (- nlines linenum) | ||
| 489 | nlines)) | ||
| 458 | (while (> tem 0) | 490 | (while (> tem 0) |
| 459 | (insert empty ?:) | 491 | (insert empty ?:) |
| 460 | (forward-line 1) | 492 | (forward-line 1) |
| @@ -469,16 +501,6 @@ the matching is case-sensitive." | |||
| 469 | (save-excursion | 501 | (save-excursion |
| 470 | (beginning-of-line) | 502 | (beginning-of-line) |
| 471 | (point))) | 503 | (point))) |
| 472 | (put-text-property line-start | ||
| 473 | (save-excursion | ||
| 474 | (end-of-line) | ||
| 475 | (point)) | ||
| 476 | 'mouse-face 'highlight) | ||
| 477 | (if list-matching-lines-face | ||
| 478 | (put-text-property | ||
| 479 | (+ line-start match-offset) | ||
| 480 | (+ line-start match-offset match-len) | ||
| 481 | 'face list-matching-lines-face)) | ||
| 482 | (forward-line 1) | 504 | (forward-line 1) |
| 483 | (setq tag nil) | 505 | (setq tag nil) |
| 484 | (setq this-linenum (1+ this-linenum))) | 506 | (setq this-linenum (1+ this-linenum))) |
| @@ -486,20 +508,28 @@ the matching is case-sensitive." | |||
| 486 | (insert empty ?:) | 508 | (insert empty ?:) |
| 487 | (forward-line 1) | 509 | (forward-line 1) |
| 488 | (setq this-linenum (1+ this-linenum)))) | 510 | (setq this-linenum (1+ this-linenum)))) |
| 489 | (while (< tem nlines) | 511 | (while (and (< (point) (point-max)) (< tem nlines)) |
| 490 | (insert empty ?:) | 512 | (insert empty ?:) |
| 491 | (forward-line 1) | 513 | (forward-line 1) |
| 492 | (setq tem (1+ tem))) | 514 | (setq tem (1+ tem))) |
| 515 | |||
| 516 | ;; Add text properties. The `occur' prop is used to | ||
| 517 | ;; store the marker of the matching text in the | ||
| 518 | ;; source buffer. | ||
| 519 | (put-text-property (marker-position text-beg) | ||
| 520 | (- (marker-position text-end) 1) | ||
| 521 | 'mouse-face 'highlight) | ||
| 522 | (put-text-property (marker-position text-beg) | ||
| 523 | (- (marker-position text-end) 1) | ||
| 524 | 'occur occur-marker) | ||
| 493 | (goto-char (point-max))) | 525 | (goto-char (point-max))) |
| 494 | (forward-line 1))) | 526 | (forward-line 1))) |
| 495 | (set-buffer standard-output) | 527 | (set-buffer standard-output) |
| 496 | ;; Put positions in increasing order to go with buffer. | ||
| 497 | (setq occur-pos-list (nreverse occur-pos-list)) | ||
| 498 | (goto-char (point-min)) | 528 | (goto-char (point-min)) |
| 499 | (let ((message-string | 529 | (let ((message-string |
| 500 | (if (= (length occur-pos-list) 1) | 530 | (if (= occur-num-matches 1) |
| 501 | "1 line" | 531 | "1 line" |
| 502 | (format "%d lines" (length occur-pos-list))))) | 532 | (format "%d lines" occur-num-matches)))) |
| 503 | (insert message-string) | 533 | (insert message-string) |
| 504 | (if (interactive-p) | 534 | (if (interactive-p) |
| 505 | (message "%s matched" message-string))))))))) | 535 | (message "%s matched" message-string))))))))) |