unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#14017: Highlight prefix line numbers in occur
@ 2013-03-21 22:38 Juri Linkov
  2013-03-24 21:54 ` Juri Linkov
  0 siblings, 1 reply; 3+ messages in thread
From: Juri Linkov @ 2013-03-21 22:38 UTC (permalink / raw)
  To: 14017

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))))






^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#14017: Highlight prefix line numbers in occur
  2013-03-21 22:38 bug#14017: Highlight prefix line numbers in occur Juri Linkov
@ 2013-03-24 21:54 ` Juri Linkov
  2013-05-29 23:47   ` Juri Linkov
  0 siblings, 1 reply; 3+ messages in thread
From: Juri Linkov @ 2013-03-24 21:54 UTC (permalink / raw)
  To: 14017

> 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)





^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#14017: Highlight prefix line numbers in occur
  2013-03-24 21:54 ` Juri Linkov
@ 2013-05-29 23:47   ` Juri Linkov
  0 siblings, 0 replies; 3+ messages in thread
From: Juri Linkov @ 2013-05-29 23:47 UTC (permalink / raw)
  To: 14017

> 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





^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-05-29 23:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-21 22:38 bug#14017: Highlight prefix line numbers in occur Juri Linkov
2013-03-24 21:54 ` Juri Linkov
2013-05-29 23:47   ` Juri Linkov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).