# HG changeset patch # User Juri Linkov # Date 1269360585 -7200 # Node ID dc9e20df2b901ff53a8b110036cc758c829b8ddc # Parent 7913a8c227bd3daa543ac13e3fba39feac45505d Implement Occur multi-line matches. http://lists.gnu.org/archive/html/emacs-devel/2010-03/msg01044.html * replace.el (occur): Doc fix. (occur-engine): Set `begpt' to the beginning of the first line. Set `endpt' to the end of the last match line. At first, count line numbers between `origpt' and `begpt'. Split out code from `out-line' variable to new let-bindings `match-prefix' and `match-str'. In `out-line' add non-numeric prefix to all non-first lines of multi-line matches. Finally, count lines between `begpt' and `endpt' and add to `lines'. diff -r 7913a8c227bd -r dc9e20df2b90 etc/TODO --- a/etc/TODO Tue Mar 23 17:48:09 2010 +0200 +++ b/etc/TODO Tue Mar 23 18:09:45 2010 +0200 @@ -105,9 +105,6 @@ ** erase-buffer should perhaps disregard read-only properties of text. -** Make occur correctly handle matches that span more than one line, - as well as overlapping matches. - ** Fix the kill/yank treatment of invisible text. At the moment, invisible text is placed in the kill-ring, so that the contents of the ring may not correspond to the text as displayed to the user. diff -r 7913a8c227bd -r dc9e20df2b90 lisp/ChangeLog --- a/lisp/ChangeLog Tue Mar 23 17:48:09 2010 +0200 +++ b/lisp/ChangeLog Tue Mar 23 18:09:45 2010 +0200 @@ -1,3 +1,17 @@ +2010-03-23 Juri Linkov + + Implement Occur multi-line matches. + http://lists.gnu.org/archive/html/emacs-devel/2010-03/msg01044.html + + * replace.el (occur): Doc fix. + (occur-engine): Set `begpt' to the beginning of the first line. + Set `endpt' to the end of the last match line. At first, count + line numbers between `origpt' and `begpt'. Split out code from + `out-line' variable to new let-bindings `match-prefix' and + `match-str'. In `out-line' add non-numeric prefix to all + non-first lines of multi-line matches. Finally, count lines + between `begpt' and `endpt' and add to `lines'. + 2010-03-23 Juri Linkov * replace.el (occur-accumulate-lines, occur-engine): diff -r 7913a8c227bd -r dc9e20df2b90 lisp/replace.el --- a/lisp/replace.el Tue Mar 23 17:48:09 2010 +0200 +++ b/lisp/replace.el Tue Mar 23 18:09:45 2010 +0200 @@ -1045,7 +1045,7 @@ (defun occur (regexp &optional nlines) "Show all lines in the current buffer containing a match for REGEXP. -This function can not handle matches that span more than one line. +If a match spreads across multiple lines, all those lines are shown. Each line is displayed with NLINES lines before and after, or -NLINES before if NLINES is negative. @@ -1210,11 +1210,14 @@ (when (setq endpt (re-search-forward regexp nil t)) (setq matches (1+ matches)) ;; increment match count (setq matchbeg (match-beginning 0)) - (setq lines (+ lines (1- (count-lines origpt endpt)))) + ;; Get beginning of first match line and end of the last. (save-excursion (goto-char matchbeg) - (setq begpt (line-beginning-position) - endpt (line-end-position))) + (setq begpt (line-beginning-position)) + (goto-char endpt) + (setq endpt (line-end-position))) + ;; Sum line numbers up to the first match line. + (setq lines (+ lines (count-lines origpt begpt))) (setq marker (make-marker)) (set-marker marker matchbeg) (setq curstring (occur-engine-line begpt endpt keep-props)) @@ -1234,24 +1237,33 @@ curstring) (setq start (match-end 0)))) ;; Generate the string to insert for this match - (let* ((out-line + (let* ((match-prefix + ;; Using 7 digits aligns tabs properly. + (apply #'propertize (format "%7d:" lines) + (append + (when prefix-face + `(font-lock-face prefix-face)) + `(occur-prefix t mouse-face (highlight) + occur-target ,marker follow-link t + help-echo "mouse-2: go to this occurrence")))) + (match-str + ;; We don't put `mouse-face' on the newline, + ;; because that loses. And don't put it + ;; on context lines to reduce flicker. + (propertize curstring 'mouse-face (list 'highlight) + 'occur-target marker + 'follow-link t + 'help-echo + "mouse-2: go to this occurrence")) + (out-line (concat - ;; Using 7 digits aligns tabs properly. - (apply #'propertize (format "%7d:" lines) - (append - (when prefix-face - `(font-lock-face prefix-face)) - `(occur-prefix t mouse-face (highlight) - occur-target ,marker follow-link t - help-echo "mouse-2: go to this occurrence"))) - ;; We don't put `mouse-face' on the newline, - ;; because that loses. And don't put it - ;; on context lines to reduce flicker. - (propertize curstring 'mouse-face (list 'highlight) - 'occur-target marker - 'follow-link t - 'help-echo - "mouse-2: go to this occurrence") + match-prefix + ;; Add non-numeric prefix to all non-first lines + ;; of multi-line matches. + (replace-regexp-in-string + "\n" + "\n :" + match-str) ;; Add marker at eol, but no mouse props. (propertize "\n" 'occur-target marker))) (data @@ -1270,7 +1282,11 @@ (goto-char endpt)) (if endpt (progn - (setq lines (1+ lines)) + ;; Sum line numbers between first and last match lines. + (setq lines (+ lines (count-lines begpt endpt) + ;; Add 1 for empty last match line since + ;; count-lines returns 1 line less. + (if (and (bolp) (eolp)) 1 0))) ;; On to the next match... (forward-line 1)) (goto-char (point-max))))))