diff options
| author | Colin Walters | 2002-04-23 20:34:58 +0000 |
|---|---|---|
| committer | Colin Walters | 2002-04-23 20:34:58 +0000 |
| commit | 68608d9c9fd22c29aa52ba67aabbfff8fbf5e73d (patch) | |
| tree | fad3e1f837947ea823f65f1515a9ffa70585a8b9 /lisp | |
| parent | 973c3c870b901ba27b3c6dce9397b742184cbb7a (diff) | |
| download | emacs-68608d9c9fd22c29aa52ba67aabbfff8fbf5e73d.tar.gz emacs-68608d9c9fd22c29aa52ba67aabbfff8fbf5e73d.zip | |
(toplevel): Require `cl' while compiling.
(occur-buffer, occur-nlines): Delete.
(occur-revert-properties): Rename to `occur-revert-properties'.
(occur-mode): Handle it. Set up font lock.
(occur-revert-function): Simply apply `occur-1'.
(occur-mode-find-occurence, occur-mode-mouse-goto)
(occur-mode-goto-occurrence-other-window)
(occur-mode-display-occurrence): Handle buffer property.
(list-matching-lines-face): Use defcustom.
(list-matching-lines-buffer-name-face): New variable.
(occur-accumulate-lines): Renamed from `ibuffer-accumulate-lines',
in ibuffer.el.
(occur-read-primary-args): Move out of `occur'.
(occur): Delete. Now simply call `occur-1'.
(multi-occur, multi-occur-by-filename-regexp): New functions.
(occur-1): New function.
(occur-engine): Renamed from `ibuffer-occur-engine' to replace the
previous implementation of `occur'; taken from ibuf-ext.el.
(occur-fontify-on-property): New function.
(occur-fontify-region-function, occur-unfontify-region-function):
New functions.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/replace.el | 551 |
1 files changed, 291 insertions, 260 deletions
diff --git a/lisp/replace.el b/lisp/replace.el index 0e5f05aea7f..ad197fff56f 100644 --- a/lisp/replace.el +++ b/lisp/replace.el | |||
| @@ -27,6 +27,9 @@ | |||
| 27 | 27 | ||
| 28 | ;;; Code: | 28 | ;;; Code: |
| 29 | 29 | ||
| 30 | (eval-when-compile | ||
| 31 | (require 'cl)) | ||
| 32 | |||
| 30 | (defcustom case-replace t | 33 | (defcustom case-replace t |
| 31 | "*Non-nil means `query-replace' should preserve case in replacements." | 34 | "*Non-nil means `query-replace' should preserve case in replacements." |
| 32 | :type 'boolean | 35 | :type 'boolean |
| @@ -446,19 +449,9 @@ end of the buffer." | |||
| 446 | map) | 449 | map) |
| 447 | "Keymap for `occur-mode'.") | 450 | "Keymap for `occur-mode'.") |
| 448 | 451 | ||
| 449 | 452 | (defvar occur-revert-properties nil) | |
| 450 | (defvar occur-buffer nil | ||
| 451 | "Name of buffer for last occur.") | ||
| 452 | |||
| 453 | |||
| 454 | (defvar occur-nlines nil | ||
| 455 | "Number of lines of context to show around matching line.") | ||
| 456 | |||
| 457 | (defvar occur-command-arguments nil | ||
| 458 | "Arguments that were given to `occur' when it made this buffer.") | ||
| 459 | 453 | ||
| 460 | (put 'occur-mode 'mode-class 'special) | 454 | (put 'occur-mode 'mode-class 'special) |
| 461 | |||
| 462 | (defun occur-mode () | 455 | (defun occur-mode () |
| 463 | "Major mode for output from \\[occur]. | 456 | "Major mode for output from \\[occur]. |
| 464 | \\<occur-mode-map>Move point to one of the items in this buffer, then use | 457 | \\<occur-mode-map>Move point to one of the items in this buffer, then use |
| @@ -471,70 +464,68 @@ Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. | |||
| 471 | (setq major-mode 'occur-mode) | 464 | (setq major-mode 'occur-mode) |
| 472 | (setq mode-name "Occur") | 465 | (setq mode-name "Occur") |
| 473 | (make-local-variable 'revert-buffer-function) | 466 | (make-local-variable 'revert-buffer-function) |
| 467 | (set (make-local-variable 'font-lock-defaults) | ||
| 468 | '(nil t nil nil nil | ||
| 469 | (font-lock-fontify-region-function . occur-fontify-region-function) | ||
| 470 | (font-lock-unfontify-region-function . occur-unfontify-region-function))) | ||
| 474 | (setq revert-buffer-function 'occur-revert-function) | 471 | (setq revert-buffer-function 'occur-revert-function) |
| 475 | (set (make-local-variable 'revert-buffer-function) 'occur-revert-function) | 472 | (set (make-local-variable 'revert-buffer-function) 'occur-revert-function) |
| 476 | (make-local-variable 'occur-buffer) | 473 | (make-local-variable 'occur-revert-properties) |
| 477 | (make-local-variable 'occur-nlines) | ||
| 478 | (make-local-variable 'occur-command-arguments) | ||
| 479 | (run-hooks 'occur-mode-hook)) | 474 | (run-hooks 'occur-mode-hook)) |
| 480 | 475 | ||
| 481 | (defun occur-revert-function (ignore1 ignore2) | 476 | (defun occur-revert-function (ignore1 ignore2) |
| 482 | "Handle `revert-buffer' for *Occur* buffers." | 477 | "Handle `revert-buffer' for *Occur* buffers." |
| 483 | (let ((args occur-command-arguments )) | 478 | (apply 'occur-1 occur-revert-properties)) |
| 484 | (save-excursion | ||
| 485 | (set-buffer occur-buffer) | ||
| 486 | (apply 'occur args)))) | ||
| 487 | 479 | ||
| 488 | (defun occur-mode-mouse-goto (event) | 480 | (defun occur-mode-mouse-goto (event) |
| 489 | "In Occur mode, go to the occurrence whose line you click on." | 481 | "In Occur mode, go to the occurrence whose line you click on." |
| 490 | (interactive "e") | 482 | (interactive "e") |
| 491 | (let (buffer pos) | 483 | (let ((buffer nil) |
| 484 | (pos nil)) | ||
| 492 | (save-excursion | 485 | (save-excursion |
| 493 | (set-buffer (window-buffer (posn-window (event-end event)))) | 486 | (set-buffer (window-buffer (posn-window (event-end event)))) |
| 494 | (save-excursion | 487 | (save-excursion |
| 495 | (goto-char (posn-point (event-end event))) | 488 | (goto-char (posn-point (event-end event))) |
| 496 | (setq pos (occur-mode-find-occurrence)) | 489 | (let ((props (occur-mode-find-occurrence))) |
| 497 | (setq buffer occur-buffer))) | 490 | (setq buffer (car props)) |
| 491 | (setq pos (cdr props))))) | ||
| 498 | (pop-to-buffer buffer) | 492 | (pop-to-buffer buffer) |
| 499 | (goto-char (marker-position pos)))) | 493 | (goto-char (marker-position pos)))) |
| 500 | 494 | ||
| 501 | (defun occur-mode-find-occurrence () | 495 | (defun occur-mode-find-occurrence () |
| 502 | (if (or (null occur-buffer) | 496 | (let ((props (get-text-property (point) 'occur-target))) |
| 503 | (null (buffer-name occur-buffer))) | 497 | (unless props |
| 504 | (progn | 498 | (error "No occurrence on this line")) |
| 505 | (setq occur-buffer nil) | 499 | (unless (buffer-live-p (car props)) |
| 506 | (error "Buffer in which occurrences were found is deleted"))) | 500 | (error "Buffer in which occurrence was found is deleted")) |
| 507 | (let ((pos (get-text-property (point) 'occur))) | 501 | props)) |
| 508 | (if (null pos) | ||
| 509 | (error "No occurrence on this line") | ||
| 510 | pos))) | ||
| 511 | 502 | ||
| 512 | (defun occur-mode-goto-occurrence () | 503 | (defun occur-mode-goto-occurrence () |
| 513 | "Go to the occurrence the current line describes." | 504 | "Go to the occurrence the current line describes." |
| 514 | (interactive) | 505 | (interactive) |
| 515 | (let ((pos (occur-mode-find-occurrence))) | 506 | (let ((target (occur-mode-find-occurrence))) |
| 516 | (pop-to-buffer occur-buffer) | 507 | (pop-to-buffer (car target)) |
| 517 | (goto-char (marker-position pos)))) | 508 | (goto-char (marker-position (cdr target))))) |
| 518 | 509 | ||
| 519 | (defun occur-mode-goto-occurrence-other-window () | 510 | (defun occur-mode-goto-occurrence-other-window () |
| 520 | "Go to the occurrence the current line describes, in another window." | 511 | "Go to the occurrence the current line describes, in another window." |
| 521 | (interactive) | 512 | (interactive) |
| 522 | (let ((pos (occur-mode-find-occurrence))) | 513 | (let ((target (occur-mode-find-occurrence))) |
| 523 | (switch-to-buffer-other-window occur-buffer) | 514 | (switch-to-buffer-other-window (car target)) |
| 524 | (goto-char (marker-position pos)))) | 515 | (goto-char (marker-position (cdr target))))) |
| 525 | 516 | ||
| 526 | (defun occur-mode-display-occurrence () | 517 | (defun occur-mode-display-occurrence () |
| 527 | "Display in another window the occurrence the current line describes." | 518 | "Display in another window the occurrence the current line describes." |
| 528 | (interactive) | 519 | (interactive) |
| 529 | (let ((pos (occur-mode-find-occurrence)) | 520 | (let ((target (occur-mode-find-occurrence)) |
| 530 | same-window-buffer-names | 521 | same-window-buffer-names |
| 531 | same-window-regexps | 522 | same-window-regexps |
| 532 | window) | 523 | window) |
| 533 | (setq window (display-buffer occur-buffer)) | 524 | (setq window (display-buffer (car target))) |
| 534 | ;; This is the way to set point in the proper window. | 525 | ;; This is the way to set point in the proper window. |
| 535 | (save-selected-window | 526 | (save-selected-window |
| 536 | (select-window window) | 527 | (select-window window) |
| 537 | (goto-char (marker-position pos))))) | 528 | (goto-char (marker-position (cdr target)))))) |
| 538 | 529 | ||
| 539 | (defun occur-next (&optional n) | 530 | (defun occur-next (&optional n) |
| 540 | "Move to the Nth (default 1) next match in the *Occur* buffer." | 531 | "Move to the Nth (default 1) next match in the *Occur* buffer." |
| @@ -550,8 +541,6 @@ Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. | |||
| 550 | (error "No more matches")) | 541 | (error "No more matches")) |
| 551 | (setq n (1- n))))) | 542 | (setq n (1- n))))) |
| 552 | 543 | ||
| 553 | |||
| 554 | |||
| 555 | (defun occur-prev (&optional n) | 544 | (defun occur-prev (&optional n) |
| 556 | "Move to the Nth (default 1) previous match in the *Occur* buffer." | 545 | "Move to the Nth (default 1) previous match in the *Occur* buffer." |
| 557 | (interactive "p") | 546 | (interactive "p") |
| @@ -578,9 +567,53 @@ A positive number means to include that many lines both before and after." | |||
| 578 | 567 | ||
| 579 | (defalias 'list-matching-lines 'occur) | 568 | (defalias 'list-matching-lines 'occur) |
| 580 | 569 | ||
| 581 | (defvar list-matching-lines-face 'bold | 570 | (defcustom list-matching-lines-face 'bold |
| 582 | "*Face used by \\[list-matching-lines] to show the text that matches. | 571 | "*Face used by \\[list-matching-lines] to show the text that matches. |
| 583 | If the value is nil, don't highlight the matching portions specially.") | 572 | If the value is nil, don't highlight the matching portions specially." |
| 573 | :type 'face | ||
| 574 | :group 'matching) | ||
| 575 | |||
| 576 | (defcustom list-matching-lines-buffer-name-face 'underline | ||
| 577 | "*Face used by \\[list-matching-lines] to show the names of buffers. | ||
| 578 | If the value is nil, don't highlight the buffer names specially." | ||
| 579 | :type 'face | ||
| 580 | :group 'matching) | ||
| 581 | |||
| 582 | (defun occur-accumulate-lines (count) | ||
| 583 | (save-excursion | ||
| 584 | (let ((forwardp (> count 0)) | ||
| 585 | (result nil)) | ||
| 586 | (while (not (or (zerop count) | ||
| 587 | (if forwardp | ||
| 588 | (eobp) | ||
| 589 | (bobp)))) | ||
| 590 | (if forwardp | ||
| 591 | (decf count) | ||
| 592 | (incf count)) | ||
| 593 | (push | ||
| 594 | (buffer-substring | ||
| 595 | (line-beginning-position) | ||
| 596 | (line-end-position)) | ||
| 597 | result) | ||
| 598 | (forward-line (if forwardp 1 -1))) | ||
| 599 | (nreverse result)))) | ||
| 600 | |||
| 601 | (defun occur-read-primary-args () | ||
| 602 | (list (let* ((default (car regexp-history)) | ||
| 603 | (input | ||
| 604 | (read-from-minibuffer | ||
| 605 | (if default | ||
| 606 | (format "List lines matching regexp (default `%s'): " | ||
| 607 | default) | ||
| 608 | "List lines matching regexp: ") | ||
| 609 | nil | ||
| 610 | nil | ||
| 611 | nil | ||
| 612 | 'regexp-history))) | ||
| 613 | (if (equal input "") | ||
| 614 | default | ||
| 615 | input)) | ||
| 616 | current-prefix-arg)) | ||
| 584 | 617 | ||
| 585 | (defun occur (regexp &optional nlines) | 618 | (defun occur (regexp &optional nlines) |
| 586 | "Show all lines in the current buffer containing a match for REGEXP. | 619 | "Show all lines in the current buffer containing a match for REGEXP. |
| @@ -598,226 +631,224 @@ It serves as a menu to find any of the occurrences in this buffer. | |||
| 598 | 631 | ||
| 599 | If REGEXP contains upper case characters (excluding those preceded by `\\'), | 632 | If REGEXP contains upper case characters (excluding those preceded by `\\'), |
| 600 | the matching is case-sensitive." | 633 | the matching is case-sensitive." |
| 634 | (interactive (occur-read-primary-args)) | ||
| 635 | (occur-1 regexp nlines (list (current-buffer)))) | ||
| 636 | |||
| 637 | (defun multi-occur (bufs regexp &optional nlines) | ||
| 638 | "Show all lines in buffers BUFS containing a match for REGEXP. | ||
| 639 | This function acts on multiple buffers; otherwise, it is exactly like | ||
| 640 | `occur'." | ||
| 601 | (interactive | 641 | (interactive |
| 602 | (list (let* ((default (car regexp-history)) | 642 | (cons |
| 603 | (input | 643 | (let ((bufs (list (read-buffer "First buffer to search: " |
| 604 | (read-from-minibuffer | 644 | (current-buffer) t))) |
| 605 | (if default | 645 | (buf nil)) |
| 606 | (format "List lines matching regexp (default `%s'): " | 646 | (while (not (string-equal |
| 607 | default) | 647 | (setq buf (read-buffer "Next buffer to search (RET to end): " |
| 608 | "List lines matching regexp: ") | 648 | nil t)) |
| 609 | nil nil nil 'regexp-history default t))) | 649 | "")) |
| 610 | (and (equal input "") default | 650 | (push buf bufs)) |
| 611 | (setq input default)) | 651 | (nreverse (mapcar #'get-buffer bufs))) |
| 612 | input) | 652 | (occur-read-primary-args))) |
| 613 | current-prefix-arg)) | 653 | (occur-1 regexp nlines bufs)) |
| 614 | (let* ((nlines (if nlines | 654 | |
| 615 | (prefix-numeric-value nlines) | 655 | (defun multi-occur-by-filename-regexp (bufregexp regexp &optional nlines) |
| 616 | list-matching-lines-default-context-lines)) | 656 | "Show all lines in buffers containing REGEXP, named by BUFREGEXP. |
| 617 | (current-tab-width tab-width) | 657 | See also `multi-occur'." |
| 618 | (inhibit-read-only t) | 658 | (interactive |
| 619 | ;; Minimum width of line number plus trailing colon. | 659 | (cons |
| 620 | (min-line-number-width 6) | 660 | (let* ((default (car regexp-history)) |
| 621 | ;; Width of line number prefix without the colon. Choose a | 661 | (input |
| 622 | ;; width that's a multiple of `tab-width' in the original | 662 | (read-from-minibuffer |
| 623 | ;; buffer so that lines in *Occur* appear right. | 663 | "List lines in buffers whose filename matches regexp: " |
| 624 | (line-number-width (1- (* (/ (- (+ min-line-number-width | 664 | nil |
| 625 | tab-width) | 665 | nil |
| 626 | 1) | 666 | nil |
| 627 | tab-width) | 667 | 'regexp-history))) |
| 628 | tab-width))) | 668 | (if (equal input "") |
| 629 | ;; Format string for line numbers. | 669 | default |
| 630 | (line-number-format (format "%%%dd" line-number-width)) | 670 | input)) |
| 631 | (empty (make-string line-number-width ?\ )) | 671 | (occur-read-primary-args))) |
| 632 | (first t) | 672 | (when bufregexp |
| 633 | ;;flag to prevent printing separator for first match | 673 | (occur-1 regexp nlines |
| 634 | (occur-num-matches 0) | 674 | (delq nil |
| 635 | (buffer (current-buffer)) | 675 | (mapcar (lambda (buf) |
| 636 | (dir default-directory) | 676 | (when (and (buffer-file-name buf) |
| 637 | (linenum 1) | 677 | (string-match bufregexp |
| 638 | (prevpos | 678 | (buffer-file-name buf))) |
| 639 | ;;position of most recent match | 679 | buf)) |
| 640 | (point-min)) | 680 | (buffer-list)))))) |
| 641 | (case-fold-search (and case-fold-search | 681 | |
| 642 | (isearch-no-upper-case-p regexp t))) | 682 | (defun occur-1 (regexp nlines bufs) |
| 643 | (final-context-start | 683 | (let ((occur-buf (get-buffer-create "*Occur*"))) |
| 644 | ;; Marker to the start of context immediately following | 684 | (with-current-buffer occur-buf |
| 645 | ;; the matched text in *Occur*. | 685 | (setq buffer-read-only nil) |
| 646 | (make-marker))) | 686 | (occur-mode) |
| 647 | ;;; (save-excursion | 687 | (erase-buffer) |
| 648 | ;;; (beginning-of-line) | 688 | (let ((count (occur-engine |
| 649 | ;;; (setq linenum (1+ (count-lines (point-min) (point)))) | 689 | regexp bufs occur-buf |
| 650 | ;;; (setq prevpos (point))) | 690 | (or nlines list-matching-lines-default-context-lines) |
| 651 | (save-excursion | 691 | (and case-fold-search |
| 692 | (isearch-no-upper-case-p regexp t)) | ||
| 693 | nil nil nil nil))) | ||
| 694 | (message "Searched %d buffers; %s matches for `%s'" (length bufs) | ||
| 695 | (if (zerop count) | ||
| 696 | "no" | ||
| 697 | (format "%d" count)) | ||
| 698 | regexp) | ||
| 699 | (if (> count 0) | ||
| 700 | (display-buffer occur-buf) | ||
| 701 | (kill-buffer occur-buf))) | ||
| 652 | (goto-char (point-min)) | 702 | (goto-char (point-min)) |
| 653 | ;; Check first whether there are any matches at all. | 703 | (setq occur-revert-properties (list regexp nlines bufs) |
| 654 | (if (not (re-search-forward regexp nil t)) | 704 | buffer-read-only t)))) |
| 655 | (message "No matches for `%s'" regexp) | 705 | |
| 656 | ;; Back up, so the search loop below will find the first match. | 706 | ;; Most of these are macros becuase if we used `flet', it wouldn't |
| 657 | (goto-char (match-beginning 0)) | 707 | ;; create a closure, so things would blow up at run time. Ugh. :( |
| 658 | (with-output-to-temp-buffer "*Occur*" | 708 | (macrolet ((insert-get-point (obj) |
| 659 | (save-excursion | 709 | `(progn |
| 660 | (set-buffer standard-output) | 710 | (insert ,obj) |
| 661 | (setq default-directory dir) | 711 | (point))) |
| 662 | ;; We will insert the number of lines, and "lines", later. | 712 | (add-prefix (lines) |
| 663 | (insert " matching ") | 713 | `(mapcar |
| 664 | (let ((print-escape-newlines t)) | 714 | #'(lambda (line) |
| 665 | (prin1 regexp)) | 715 | (concat " :" line "\n")) |
| 666 | (insert " in buffer " (buffer-name buffer) ?. ?\n) | 716 | ,lines))) |
| 667 | (occur-mode) | 717 | (defun occur-engine (regexp buffers out-buf nlines case-fold-search |
| 668 | (setq occur-buffer buffer) | 718 | title-face prefix-face match-face keep-props) |
| 669 | (setq occur-nlines nlines) | 719 | (with-current-buffer out-buf |
| 670 | (setq occur-command-arguments | 720 | (setq buffer-read-only nil) |
| 671 | (list regexp nlines))) | 721 | (let ((globalcount 0)) |
| 672 | (if (eq buffer standard-output) | 722 | ;; Map over all the buffers |
| 673 | (goto-char (point-max))) | 723 | (dolist (buf buffers) |
| 674 | (save-excursion | 724 | (when (buffer-live-p buf) |
| 675 | ;; Find next match, but give up if prev match was at end of buffer. | 725 | (let ((c 0) ;; count of matched lines |
| 676 | (while (and (not (eobp)) | 726 | (l 1) ;; line count |
| 677 | (re-search-forward regexp nil t)) | 727 | (matchbeg 0) |
| 678 | (goto-char (match-beginning 0)) | 728 | (matchend 0) |
| 679 | (beginning-of-line) | 729 | (origpt nil) |
| 680 | (save-match-data | 730 | (begpt nil) |
| 681 | (setq linenum (+ linenum (count-lines prevpos (point))))) | 731 | (endpt nil) |
| 682 | (setq prevpos (point)) | 732 | (marker nil) |
| 683 | (goto-char (match-end 0)) | 733 | (curstring "") |
| 684 | (let* (;;start point of text in source buffer to be put | 734 | (headerpt (with-current-buffer out-buf (point)))) |
| 685 | ;;into *Occur* | 735 | (save-excursion |
| 686 | (start (save-excursion | 736 | (set-buffer buf) |
| 687 | (goto-char (match-beginning 0)) | ||
| 688 | (forward-line (if (< nlines 0) | ||
| 689 | nlines | ||
| 690 | (- nlines))) | ||
| 691 | (point))) | ||
| 692 | ;; end point of text in source buffer to be put | ||
| 693 | ;; into *Occur* | ||
| 694 | (end (save-excursion | ||
| 695 | (goto-char (match-end 0)) | ||
| 696 | (if (> nlines 0) | ||
| 697 | (forward-line (1+ nlines)) | ||
| 698 | (forward-line 1)) | ||
| 699 | (point))) | ||
| 700 | ;; Amount of context before matching text | ||
| 701 | (match-beg (- (match-beginning 0) start)) | ||
| 702 | ;; Length of matching text | ||
| 703 | (match-len (- (match-end 0) (match-beginning 0))) | ||
| 704 | (tag (format line-number-format linenum)) | ||
| 705 | tem | ||
| 706 | insertion-start | ||
| 707 | ;; Number of lines of context to show for current match. | ||
| 708 | occur-marker | ||
| 709 | ;; Marker pointing to end of match in source buffer. | ||
| 710 | (text-beg | ||
| 711 | ;; Marker pointing to start of text for one | ||
| 712 | ;; match in *Occur*. | ||
| 713 | (make-marker)) | ||
| 714 | (text-end | ||
| 715 | ;; Marker pointing to end of text for one match | ||
| 716 | ;; in *Occur*. | ||
| 717 | (make-marker))) | ||
| 718 | (save-excursion | 737 | (save-excursion |
| 719 | (setq occur-marker (make-marker)) | 738 | (goto-char (point-min)) ;; begin searching in the buffer |
| 720 | (set-marker occur-marker (point)) | 739 | (while (not (eobp)) |
| 721 | (set-buffer standard-output) | 740 | (setq origpt (point)) |
| 722 | (setq occur-num-matches (1+ occur-num-matches)) | 741 | (when (setq endpt (re-search-forward regexp nil t)) |
| 723 | (or first (zerop nlines) | 742 | (incf c) ;; increment match count |
| 724 | (insert "--------\n")) | 743 | (incf globalcount) |
| 725 | (setq first nil) | 744 | (setq matchbeg (match-beginning 0) |
| 726 | (save-excursion | 745 | matchend (match-end 0)) |
| 727 | (set-buffer "*Occur*") | 746 | (setq begpt (save-excursion |
| 728 | (setq tab-width current-tab-width)) | 747 | (goto-char matchbeg) |
| 729 | 748 | (line-beginning-position))) | |
| 730 | ;; Insert matching text including context lines from | 749 | (incf l (1- (count-lines origpt endpt))) |
| 731 | ;; source buffer into *Occur* | 750 | (setq marker (make-marker)) |
| 732 | (set-marker text-beg (point)) | 751 | (set-marker marker matchbeg) |
| 733 | (setq insertion-start (point)) | 752 | (setq curstring (buffer-substring begpt |
| 734 | (insert-buffer-substring buffer start end) | 753 | (line-end-position))) |
| 735 | (or (and (/= (+ start match-beg) end) | 754 | ;; Depropertize the string, and maybe |
| 736 | (with-current-buffer buffer | 755 | ;; highlight the matches |
| 737 | (eq (char-before end) ?\n))) | 756 | (let ((len (length curstring)) |
| 738 | (insert "\n")) | 757 | (start 0)) |
| 739 | (set-marker final-context-start | 758 | (unless keep-props |
| 740 | (+ (- (point) (- end (match-end 0))) | 759 | (set-text-properties 0 len nil curstring)) |
| 741 | (if (save-excursion | 760 | (while (and (< start len) |
| 742 | (set-buffer buffer) | 761 | (string-match regexp curstring start)) |
| 743 | (save-excursion | 762 | (add-text-properties (match-beginning 0) |
| 744 | (goto-char (match-end 0)) | 763 | (match-end 0) |
| 745 | (end-of-line) | 764 | (append |
| 746 | (bolp))) | 765 | '(occur-match t) |
| 747 | 1 0))) | 766 | (when match-face |
| 748 | (set-marker text-end (point)) | 767 | `(face ,match-face))) |
| 749 | 768 | curstring) | |
| 750 | ;; Highlight text that was matched. | 769 | (setq start (match-end 0)))) |
| 751 | (if list-matching-lines-face | 770 | ;; Generate the string to insert for this match |
| 752 | (put-text-property | 771 | (let* ((out-line |
| 753 | (+ (marker-position text-beg) match-beg) | 772 | (concat |
| 754 | (+ (marker-position text-beg) match-beg match-len) | 773 | (apply #'propertize (format "%-6d:" l) |
| 755 | 'face list-matching-lines-face)) | 774 | (append |
| 756 | 775 | (when prefix-face | |
| 757 | ;; `occur-point' property is used by occur-next and | 776 | `(face prefix-face)) |
| 758 | ;; occur-prev to move between matching lines. | 777 | '(occur-prefix t))) |
| 759 | (put-text-property | 778 | curstring |
| 760 | (+ (marker-position text-beg) match-beg match-len) | 779 | "\n")) |
| 761 | (+ (marker-position text-beg) match-beg match-len 1) | 780 | (data |
| 762 | 'occur-point t) | 781 | (if (= nlines 1) |
| 763 | 782 | ;; The simple display style | |
| 764 | ;; Now go back to the start of the matching text | 783 | out-line |
| 765 | ;; adding the space and colon to the start of each line. | 784 | ;; The complex multi-line display |
| 766 | (goto-char insertion-start) | 785 | ;; style. Generate a list of lines, |
| 767 | ;; Insert space and colon for lines of context before match. | 786 | ;; concatenate them all together. |
| 768 | (setq tem (if (< linenum nlines) | 787 | (apply #'concat |
| 769 | (- nlines linenum) | 788 | (nconc |
| 770 | nlines)) | 789 | (add-prefix (nreverse (cdr (occur-accumulate-lines (- nlines))))) |
| 771 | (while (> tem 0) | 790 | (list out-line) |
| 772 | (insert empty ?:) | 791 | (add-prefix (cdr (occur-accumulate-lines nlines)))))))) |
| 773 | (forward-line 1) | 792 | ;; Actually insert the match display data |
| 774 | (setq tem (1- tem))) | 793 | (with-current-buffer out-buf |
| 775 | 794 | (let ((beg (point)) | |
| 776 | ;; Insert line number and colon for the lines of | 795 | (end (insert-get-point data))) |
| 777 | ;; matching text. | 796 | (unless (= nlines 1) |
| 778 | (let ((this-linenum linenum)) | 797 | (insert-get-point "-------\n")) |
| 779 | (while (< (point) final-context-start) | 798 | (add-text-properties |
| 780 | (if (null tag) | 799 | beg (1- end) |
| 781 | (setq tag (format line-number-format this-linenum))) | 800 | `(occur-target ,(cons buf marker) |
| 782 | (insert tag ?:) | 801 | mouse-face highlight help-echo |
| 783 | (forward-line 1) | 802 | "mouse-2: go to this occurrence"))))) |
| 784 | (setq tag nil) | 803 | (goto-char endpt)) |
| 785 | (setq this-linenum (1+ this-linenum))) | 804 | (incf l) |
| 786 | (while (and (not (eobp)) (<= (point) final-context-start)) | 805 | ;; On to the next match... |
| 787 | (insert empty ?:) | 806 | (forward-line 1)))) |
| 788 | (forward-line 1) | 807 | (when (not (zerop c)) ;; is the count zero? |
| 789 | (setq this-linenum (1+ this-linenum)))) | 808 | (with-current-buffer out-buf |
| 790 | 809 | (goto-char headerpt) | |
| 791 | ;; Insert space and colon for lines of context after match. | 810 | (let ((beg (point)) |
| 792 | (while (and (< (point) (point-max)) (< tem nlines)) | 811 | (end (insert-get-point |
| 793 | (insert empty ?:) | 812 | (format "%d lines matching \"%s\" in buffer: %s\n" |
| 794 | (forward-line 1) | 813 | c regexp (buffer-name buf))))) |
| 795 | (setq tem (1+ tem))) | 814 | (add-text-properties beg end |
| 796 | 815 | (append | |
| 797 | ;; Add text properties. The `occur' prop is used to | 816 | (when title-face |
| 798 | ;; store the marker of the matching text in the | 817 | `(face ,title-face)) |
| 799 | ;; source buffer. | 818 | `(occur-title ,buf)))) |
| 800 | (add-text-properties | 819 | (goto-char (point-max))))))) |
| 801 | (marker-position text-beg) (- (marker-position text-end) 1) | 820 | ;; Return the number of matches |
| 802 | '(mouse-face highlight | 821 | globalcount)))) |
| 803 | help-echo "mouse-2: go to this occurrence")) | 822 | |
| 804 | (put-text-property (marker-position text-beg) | 823 | (defun occur-fontify-on-property (prop face beg end) |
| 805 | (marker-position text-end) | 824 | (let ((prop-beg (or (and (get-text-property (point) prop) (point)) |
| 806 | 'occur occur-marker) | 825 | (next-single-property-change (point) prop nil end)))) |
| 807 | (goto-char (point-max))) | 826 | (when (and prop-beg (not (= prop-beg end))) |
| 808 | (forward-line 1))) | 827 | (let ((prop-end (next-single-property-change beg prop nil end))) |
| 809 | (set-buffer standard-output) | 828 | (when (and prop-end (not (= prop-end end))) |
| 810 | ;; Go back to top of *Occur* and finish off by printing the | 829 | (put-text-property prop-beg prop-end 'face face) |
| 811 | ;; number of matching lines. | 830 | prop-end))))) |
| 812 | (goto-char (point-min)) | 831 | |
| 813 | (let ((message-string | 832 | (defun occur-fontify-region-function (beg end &optional verbose) |
| 814 | (if (= occur-num-matches 1) | 833 | (when verbose (message "Fontifying...")) |
| 815 | "1 line" | 834 | (let ((inhibit-read-only t)) |
| 816 | (format "%d lines" occur-num-matches)))) | 835 | (save-excursion |
| 817 | (insert message-string) | 836 | (dolist (e `((occur-title . ,list-matching-lines-buffer-name-face) |
| 818 | (if (interactive-p) | 837 | (occur-match . ,list-matching-lines-face))) |
| 819 | (message "%s matched" message-string))) | 838 | ; (occur-prefix . ,list-matching-lines-prefix-face))) |
| 820 | (setq buffer-read-only t))))))) | 839 | (goto-char beg) |
| 840 | (let ((change-end nil)) | ||
| 841 | (while (setq change-end (occur-fontify-on-property (car e) | ||
| 842 | (cdr e) | ||
| 843 | (point) | ||
| 844 | end)) | ||
| 845 | (goto-char change-end)))))) | ||
| 846 | (when verbose (message "Fontifying...done"))) | ||
| 847 | |||
| 848 | (defun occur-unfontify-region-function (beg end) | ||
| 849 | (let ((inhibit-read-only t)) | ||
| 850 | (remove-text-properties beg end '(face nil)))) | ||
| 851 | |||
| 821 | 852 | ||
| 822 | ;; It would be nice to use \\[...], but there is no reasonable way | 853 | ;; It would be nice to use \\[...], but there is no reasonable way |
| 823 | ;; to make that display both SPC and Y. | 854 | ;; to make that display both SPC and Y. |