Package: emacs;
Reported by: Juri Linkov <juri <at> jurta.org>
Date: Thu, 21 Mar 2013 22:42:01 UTC
Severity: normal
Tags: fixed
Fixed in version 26.1
Done: Juri Linkov <juri <at> linkov.net>
Bug is archived. No further changes may be made.
Message #8 received at 14017 <at> debbugs.gnu.org (full text, mbox):
From: Juri Linkov <juri <at> jurta.org> To: 14017 <at> debbugs.gnu.org Subject: Re: bug#14017: Highlight prefix line numbers in occur Date: Sun, 24 Mar 2013 23:54:01 +0200
> Currently the `prefix-face' arg of `occur-engine' is unused. > Its caller `occur-1' just sends nil to `occur-engine'. > This is the reason why a bug in its usage in `occur-engine' > remained undiscovered for a long time. > > To take it into use I propose to add a new face option > `list-matching-lines-prefix-face' to accompany the existing > `list-matching-lines-buffer-name-face' and `list-matching-lines-face'. This is installed now. Another problem I found with the line numbers in `occur' is that the number of matches it reports in the header line is wrong. If there are more than one match on a line, the total number of matches is more than the total number of matching lines currently displayed in the header line. So I propose to change the format of the occur header line from: 2 matches for "is" in buffer: *scratch* to: 4 matches in 2 lines for "is" in buffer: *scratch* I found that the exact number of matches (as opposed to the number of matching lines) often is necessary to know beforehand how many times it requires to type C-s to visit all matches or how many times to type y/n to replace all matches in the buffer. === modified file 'lisp/replace.el' --- lisp/replace.el 2013-02-25 20:57:44 +0000 +++ lisp/replace.el 2013-03-24 21:48:28 +0000 @@ -1347,16 +1347,18 @@ (defun occur-1 (regexp nlines bufs &opti (defun occur-engine (regexp buffers out-buf nlines case-fold title-face prefix-face match-face keep-props) (with-current-buffer out-buf - (let ((globalcount 0) + (let ((global-lines 0) ;; total count of matching lines + (global-matches 0) ;; total count of matches (coding nil) (case-fold-search case-fold)) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) - (let ((matches 0) ;; count of matched lines - (lines 1) ;; line count - (prev-after-lines nil) ;; context lines of prev match - (prev-lines nil) ;; line number of prev match endpt + (let ((lines 0) ;; count of matching lines + (matches 0) ;; count of matches + (curr-line 1) ;; line count + (prev-line nil) ;; line number of prev match endpt + (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) (origpt nil) (begpt nil) @@ -1376,8 +1378,9 @@ (defun occur-engine (regexp buffers out- (while (not (eobp)) (setq origpt (point)) (when (setq endpt (re-search-forward regexp nil t)) - (setq matches (1+ matches)) ;; increment match count + (setq lines (1+ lines)) ;; increment matching lines count (setq matchbeg (match-beginning 0)) ;; Get beginning of first match line and end of the last. (save-excursion @@ -1386,7 +1389,7 @@ (defun occur-engine (regexp buffers out- (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 curr-line (+ curr-line (count-lines origpt begpt))) (setq marker (make-marker)) (set-marker marker matchbeg) (setq curstring (occur-engine-line begpt endpt keep-props)) @@ -1395,6 +1398,7 @@ (defun occur-engine (regexp buffers out- (start 0)) (while (and (< start len) (string-match regexp curstring start)) + (setq matches (1+ matches)) (add-text-properties (match-beginning 0) (match-end 0) (append @@ -1408,7 +1412,7 @@ (defun occur-engine (regexp buffers out- ;; Generate the string to insert for this match (let* ((match-prefix ;; Using 7 digits aligns tabs properly. - (apply #'propertize (format "%7d:" lines) + (apply #'propertize (format "%7d:" curr-line) (append (when prefix-face `(font-lock-face prefix-face)) @@ -1446,7 +1450,7 @@ (defun occur-engine (regexp buffers out- ;; The complex multi-line display style. (setq ret (occur-context-lines out-line nlines keep-props begpt endpt - lines prev-lines prev-after-lines)) + curr-line prev-line prev-after-lines)) ;; Set first elem of the returned list to `data', ;; and the second elem to `prev-after-lines'. (setq prev-after-lines (nth 1 ret)) @@ -1458,28 +1462,30 @@ (defun occur-engine (regexp buffers out- (if endpt (progn ;; 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))) + (setq curr-line (+ curr-line (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))) - (setq prev-lines (1- lines))) + (setq prev-line (1- curr-line))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf (insert (apply #'concat (occur-engine-add-prefix prev-after-lines))))))) - (when (not (zerop matches)) ;; is the count zero? - (setq globalcount (+ globalcount matches)) + (when (not (zerop lines)) ;; is the count zero? + (setq global-lines (+ global-lines lines) + global-matches (+ global-matches matches)) (with-current-buffer out-buf (goto-char headerpt) (let ((beg (point)) end) (insert (propertize - (format "%d match%s%s in buffer: %s\n" + (format "%d match%s in %d line%s%s in buffer: %s\n" matches (if (= matches 1) "" "es") + lines (if (= lines 1) "" "s") ;; Don't display regexp for multi-buffer. (if (> (length buffers) 1) "" (format " for \"%s\"" @@ -1494,12 +1500,13 @@ (defun occur-engine (regexp buffers out- `(occur-title ,buf)))) (goto-char (point-min))))))) ;; Display total match count and regexp for multi-buffer. - (when (and (not (zerop globalcount)) (> (length buffers) 1)) + (when (and (not (zerop global-lines)) (> (length buffers) 1)) (goto-char (point-min)) (let ((beg (point)) end) - (insert (format "%d match%s total for \"%s\":\n" - globalcount (if (= globalcount 1) "" "es") + (insert (format "%d match%s in %d line%s total for \"%s\":\n" + global-matches (if (= global-matches 1) "" "es") + global-lines (if (= global-lines 1) "" "s") (query-replace-descr regexp))) (setq end (point)) (add-text-properties beg end (when title-face @@ -1510,8 +1517,8 @@ (defun occur-engine (regexp buffers out- ;; that locally binds it. Let's use it also for the output ;; buffer. (set-buffer-file-coding-system coding)) - ;; Return the number of matches - globalcount))) + ;; Return the number of matching lines + global-lines))) (defun occur-engine-line (beg end &optional keep-props) (if (and keep-props (if (boundp 'jit-lock-mode) jit-lock-mode) @@ -1551,13 +1558,13 @@ (defun occur-accumulate-lines (count &op ;; Generate context display for occur. ;; OUT-LINE is the line where the match is. ;; NLINES and KEEP-PROPS are args to occur-engine. -;; LINES is line count of the current match, -;; PREV-LINES is line count of the previous match, +;; CURR-LINE is line count of the current match, +;; PREV-LINE is line count of the previous match, ;; PREV-AFTER-LINES is a list of after-context lines of the previous match. ;; Generate a list of lines, add prefixes to all but OUT-LINE, ;; then concatenate them all together. (defun occur-context-lines (out-line nlines keep-props begpt endpt - lines prev-lines prev-after-lines) + curr-line prev-line prev-after-lines) ;; Find after- and before-context lines of the current match. (let ((before-lines (nreverse (cdr (occur-accumulate-lines @@ -1572,22 +1579,22 @@ (defun occur-context-lines (out-line nli (when prev-after-lines ;; Don't overlap prev after-lines with current before-lines. - (if (>= (+ prev-lines (length prev-after-lines)) - (- lines (length before-lines))) + (if (>= (+ prev-line (length prev-after-lines)) + (- curr-line (length before-lines))) (setq prev-after-lines (butlast prev-after-lines (- (length prev-after-lines) - (- lines prev-lines (length before-lines) 1)))) + (- curr-line prev-line (length before-lines) 1)))) ;; Separate non-overlapping context lines with a dashed line. (setq separator "-------\n"))) - (when prev-lines + (when prev-line ;; Don't overlap current before-lines with previous match line. - (if (<= (- lines (length before-lines)) - prev-lines) + (if (<= (- curr-line (length before-lines)) + prev-line) (setq before-lines (nthcdr (- (length before-lines) - (- lines prev-lines 1)) + (- curr-line prev-line 1)) before-lines)) ;; Separate non-overlapping before-context lines. (unless (> nlines 0)
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.