GNU bug report logs - #14017
Highlight prefix line numbers in occur

Previous Next

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.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 14017 in the body.
You can then email your comments to 14017 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#14017; Package emacs. (Thu, 21 Mar 2013 22:42:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Juri Linkov <juri <at> jurta.org>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Thu, 21 Mar 2013 22:42:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> jurta.org>
To: bug-gnu-emacs <at> gnu.org
Subject: Highlight prefix line numbers in occur
Date: Fri, 22 Mar 2013 00:38:17 +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.  The bug is that this code:

                            (when prefix-face
                              `(font-lock-face prefix-face))

should be fixed to:

                            (when prefix-face
                              `(font-lock-face ,prefix-face))

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'.

Its default value could be `shadow' - the same face as is used to
highlight line numbers in `linum-mode' (their output will look similar).

=== modified file 'lisp/replace.el'
--- lisp/replace.el	2013-03-10 08:44:07 +0000
+++ lisp/replace.el	2013-03-21 22:36:56 +0000
@@ -1125,6 +1125,14 @@ (defcustom list-matching-lines-buffer-name-face
   :type 'face
   :group 'matching)
 
+(defcustom list-matching-lines-prefix-face 'shadow
+  "Face used by \\[list-matching-lines] to show the prefix column.
+If the face doesn't differ from the default face,
+don't highlight the prefix with line numbers specially."
+  :type 'face
+  :group 'matching
+  :version "24.4")
+
 (defcustom occur-excluded-properties
   '(read-only invisible intangible field mouse-face help-echo local-map keymap
     yank-handler follow-link)
@@ -1334,7 +1342,9 @@ (defun occur-1 (regexp nlines bufs &opti
 		      (isearch-no-upper-case-p regexp t)
 		    case-fold-search)
 		  list-matching-lines-buffer-name-face
-		  nil list-matching-lines-face
+		  (if (face-differs-from-default-p list-matching-lines-prefix-face)
+		      list-matching-lines-prefix-face)
+		  list-matching-lines-face
 		  (not (eq occur-excluded-properties t))))))
 	  (let* ((bufcount (length active-bufs))
 		 (diff (- (length bufs) bufcount)))
@@ -1423,7 +1433,7 @@ (defun occur-engine (regexp buffers out-
 			    (apply #'propertize (format "%7d:" lines)
 				   (append
 				    (when prefix-face
-				      `(font-lock-face prefix-face))
+				      `(font-lock-face ,prefix-face))
 				    `(occur-prefix t mouse-face (highlight)
 				      ;; Allow insertion of text at
 				      ;; the end of the prefix (for
@@ -1447,7 +1457,9 @@ (defun occur-engine (regexp buffers out-
 			     ;; of multi-line matches.
 			     (replace-regexp-in-string
 			      "\n"
-			      "\n       :"
+			      (if prefix-face
+				  (propertize "\n       :" 'font-lock-face prefix-face)
+				"\n       :")
 			      match-str)
 			     ;; Add marker at eol, but no mouse props.
 			     (propertize "\n" 'occur-target marker)))
@@ -1458,7 +1470,8 @@ (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))
+					 lines prev-lines prev-after-lines
+					 prefix-face))
 			      ;; Set first elem of the returned list to `data',
 			      ;; and the second elem to `prev-after-lines'.
 			      (setq prev-after-lines (nth 1 ret))
@@ -1482,7 +1495,7 @@ (defun occur-engine (regexp buffers out-
 		(when prev-after-lines
 		  (with-current-buffer out-buf
 		    (insert (apply #'concat (occur-engine-add-prefix
-					     prev-after-lines)))))))
+					     prev-after-lines prefix-face)))))))
 	    (when (not (zerop matches)) ;; is the count zero?
 	      (setq globalcount (+ globalcount matches))
 	      (with-current-buffer out-buf
@@ -1537,10 +1550,13 @@ (defun occur-engine-line (beg end &optio
 	str)
     (buffer-substring-no-properties beg end)))
 
-(defun occur-engine-add-prefix (lines)
+(defun occur-engine-add-prefix (lines &optional prefix-face)
   (mapcar
    #'(lambda (line)
-       (concat "       :" line "\n"))
+       (concat (if prefix-face
+		   (propertize "       :" 'font-lock-face prefix-face)
+		 "       :")
+	       line "\n"))
    lines))
 
 (defun occur-accumulate-lines (count &optional keep-props pt)
@@ -1569,7 +1585,8 @@ (defun occur-accumulate-lines (count &op
 ;; 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)
+				     lines prev-lines prev-after-lines
+				     &optional prefix-face)
   ;; Find after- and before-context lines of the current match.
   (let ((before-lines
 	 (nreverse (cdr (occur-accumulate-lines
@@ -1609,10 +1626,13 @@ (defun occur-context-lines (out-line nli
      ;; Return a list where the first element is the output line.
      (apply #'concat
 	    (append
-	     (and prev-after-lines
-		  (occur-engine-add-prefix prev-after-lines))
-	     (and separator (list separator))
-	     (occur-engine-add-prefix before-lines)
+	     (if prev-after-lines
+		 (occur-engine-add-prefix prev-after-lines prefix-face))
+	     (if separator
+		 (list (if prefix-face
+			   (propertize separator 'font-lock-face prefix-face)
+			 separator)))
+	     (occur-engine-add-prefix before-lines prefix-face)
 	     (list out-line)))
      ;; And the second element is the list of context after-lines.
      (if (> nlines 0) after-lines))))





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14017; Package emacs. (Sun, 24 Mar 2013 22:01:02 GMT) Full text and rfc822 format available.

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)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14017; Package emacs. (Wed, 29 May 2013 23:53:02 GMT) Full text and rfc822 format available.

Message #11 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: Thu, 30 May 2013 02:47:51 +0300
> 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.

This is installed now.

I propose to use a similar message for grep output as well,
i.e. to change the current format:

  Grep finished with no matches found at Tue Jul 19 15:43:12
  Grep finished (matches found) at Thu Jul 21 15:02:15

to:

  Grep finished with no matches found at Tue Jul 19 15:43:12
  Grep finished with 42 matches found at Thu Jul 21 15:02:15

or if grep can count only matching lines then:

  Grep finished with 42 matching lines at Thu Jul 21 15:02:15

otherwise:

  Grep finished with 42 matches in 5 lines at Thu Jul 21 15:02:15




Added tag(s) fixed. Request was from Juri Linkov <juri <at> linkov.net> to control <at> debbugs.gnu.org. (Mon, 12 Feb 2018 21:41:02 GMT) Full text and rfc822 format available.

bug marked as fixed in version 26.1, send any further explanations to 14017 <at> debbugs.gnu.org and Juri Linkov <juri <at> jurta.org> Request was from Juri Linkov <juri <at> linkov.net> to control <at> debbugs.gnu.org. (Mon, 12 Feb 2018 21:41:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 13 Mar 2018 11:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 6 years and 53 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.