* [patch] Run occur command restricted to a region @ 2016-12-29 6:36 Tino Calancha 2016-12-29 16:10 ` Eli Zaretskii 2016-12-29 23:31 ` [patch] Run occur command restricted to a region Juri Linkov 0 siblings, 2 replies; 39+ messages in thread From: Tino Calancha @ 2016-12-29 6:36 UTC (permalink / raw) To: Emacs developers; +Cc: tino.calancha Hi, is it worth to have versions of `occur' restricting the search to lines before (after) the current line? Maybe there is already a way to do that, and i just ignore it. I usually just i copy the region into a temporary buffer; then i run `occur' there. I just wrote a patch to show my point; it adds the following commands: 1) occur-backward: for lines before the current one. 2) occur-forward: for lines after the current one. 3) occur-in-region: for lines within the active region. Not sure if we want to bind them to keys. Tentatively, i have assigned `M-s b' and `M-s f' for 1) and 2) in the `search-map'. That means, these bindings are not available in all modes; OTOH command `occur' is in the `global-map', so it's always available. Any comment about this proposal? Thanks, Tino ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From 61097b346737aa1960da568c54fc2b9211e5fe5c Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Thu, 29 Dec 2016 15:02:47 +0900 Subject: [PATCH] New commands: occur-forward, occur-backward, occur-in-region * lisp/replace.el (occur-matches-threshold): New variable. (occur-in-region, occur-forward, occur-backward): New commands. * lisp/bindings.el (search-map): Bind occur-backward to 'M-s b' and occur-forward to 'M-s f'. --- lisp/bindings.el | 2 ++ lisp/replace.el | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/lisp/bindings.el b/lisp/bindings.el index c13f4b156a..4b1c88a3c5 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -928,6 +928,8 @@ search-map (define-key esc-map "s" search-map) (define-key search-map "o" 'occur) +(define-key search-map "b" 'occur-backward) +(define-key search-map "f" 'occur-forward) (define-key search-map "\M-w" 'eww-search-words) (define-key search-map "hr" 'highlight-regexp) (define-key search-map "hp" 'highlight-phrase) diff --git a/lisp/replace.el b/lisp/replace.el index a172174633..09e0bf1e1f 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1322,11 +1322,12 @@ occur-excluded-properties :group 'matching :version "22.1") -(defun occur-read-primary-args () - (let* ((perform-collect (consp current-prefix-arg)) +(defun occur-read-primary-args (&optional where) + (let* ((str (if where (concat " " where) "")) + (perform-collect (consp current-prefix-arg)) (regexp (read-regexp (if perform-collect - "Collect strings matching regexp" - "List lines matching regexp") + (concat "Collect strings matching regexp" str) + (concat "List lines matching regexp" str)) 'regexp-history-last))) (list regexp (if perform-collect @@ -1389,6 +1390,42 @@ occur (interactive (occur-read-primary-args)) (occur-1 regexp nlines (list (current-buffer)))) +(defun occur-backward (regexp &optional nlines) + "Show all lines before current line containing a match for REGEXP. +Each line is displayed with NLINES lines before and after, or -NLINES +before if NLINES is negative. +As `occur' but restricted to lines before the current one." + (interactive (occur-read-primary-args "backward")) + (narrow-to-region (point-min) (point)) + (occur regexp nlines) + (widen)) + +(defun occur-forward (regexp &optional nlines) + "Show all lines after current line containing a match for REGEXP. +Each line is displayed with NLINES lines before and after, or -NLINES +before if NLINES is negative. +As `occur' but restricted to lines after the current one." + (interactive (occur-read-primary-args "forward")) + (let ((occur-matches-threshold + (line-number-at-pos (point)))) + (narrow-to-region (point) (point-max)) + (occur regexp nlines)) + (widen)) + +(defun occur-in-region (regexp &optional nlines) + "Show all lines in the active region containing a match for REGEXP. +Each line is displayed with NLINES lines before and after, or -NLINES +before if NLINES is negative. +As `occur' but restricted to lines within the active region." + (interactive (occur-read-primary-args "in region")) + (unless (use-region-p) + (error "Region not active")) + (let ((occur-matches-threshold + (line-number-at-pos (region-beginning)))) + (narrow-to-region (region-beginning) (region-end)) + (occur regexp nlines)) + (widen)) + (defvar ido-ignore-item-temp-list) (defun multi-occur (bufs regexp &optional nlines) @@ -1539,6 +1576,9 @@ occur-1 (set-buffer-modified-p nil) (run-hooks 'occur-hook))))))) +;; Let binded in `occur-forward' and `occur-in-region'. +(defvar occur-matches-threshold nil) + (defun occur-engine (regexp buffers out-buf nlines case-fold title-face prefix-face match-face keep-props) (with-current-buffer out-buf @@ -1551,7 +1591,8 @@ occur-engine (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur-matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.5) of 2016-12-28 Repository revision: 112460da705c2a6716d7b6bc72501de0a3757259 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-29 6:36 [patch] Run occur command restricted to a region Tino Calancha @ 2016-12-29 16:10 ` Eli Zaretskii 2016-12-29 16:54 ` Tino Calancha 2017-01-03 17:37 ` Region argument (was: [patch] Run occur command restricted to a region) Stefan Monnier 2016-12-29 23:31 ` [patch] Run occur command restricted to a region Juri Linkov 1 sibling, 2 replies; 39+ messages in thread From: Eli Zaretskii @ 2016-12-29 16:10 UTC (permalink / raw) To: Tino Calancha; +Cc: emacs-devel > From: Tino Calancha <tino.calancha@gmail.com> > Date: Thu, 29 Dec 2016 15:36:56 +0900 > Cc: tino.calancha@gmail.com > > Any comment about this proposal? I have one comment: > +(defun occur-in-region (regexp &optional nlines) > + "Show all lines in the active region containing a match for REGEXP. > +Each line is displayed with NLINES lines before and after, or -NLINES > +before if NLINES is negative. > +As `occur' but restricted to lines within the active region." > + (interactive (occur-read-primary-args "in region")) > + (unless (use-region-p) > + (error "Region not active")) I think our convention for functions that act on the region is to accept BEG and END arguments, so that the function could be called from Lisp. The 'interactive' form/spec should then provide these arguments for the interactive use. Also, this will need a NEWS entry, and possibly also an addition to the user manual. Thanks. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-29 16:10 ` Eli Zaretskii @ 2016-12-29 16:54 ` Tino Calancha 2016-12-29 18:16 ` Drew Adams 2017-01-03 17:37 ` Region argument (was: [patch] Run occur command restricted to a region) Stefan Monnier 1 sibling, 1 reply; 39+ messages in thread From: Tino Calancha @ 2016-12-29 16:54 UTC (permalink / raw) To: Eli Zaretskii; +Cc: tino.calancha, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> +(defun occur-in-region (regexp &optional nlines) >> + "Show all lines in the active region containing a match for REGEXP. >> +Each line is displayed with NLINES lines before and after, or -NLINES >> +before if NLINES is negative. >> +As `occur' but restricted to lines within the active region." >> + (interactive (occur-read-primary-args "in region")) >> + (unless (use-region-p) >> + (error "Region not active")) > > I think our convention for functions that act on the region is to > accept BEG and END arguments, so that the function could be called > from Lisp. The 'interactive' form/spec should then provide these > arguments for the interactive use. Right! Thank you. > Also, this will need a NEWS entry, and possibly also an addition to > the user manual. Sure, i have added a NEWS entry for the commands. I don't see a clear place in the manual where to mention about these commands: it seems `occur' is just defined in the intro as an example on how to make keybindings. Here is the updated patch: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From fbee1d786c35b6148112f32717d30e17836fd4ae Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Fri, 30 Dec 2016 01:42:00 +0900 Subject: [PATCH] New commands: occur-forward, occur-backward, occur-in-region * lisp/replace.el (occur-matches-threshold): New variable. (occur-in-region, occur-forward, occur-backward): New commands. * lisp/bindings.el (search-map): Bind occur-backward to 'M-s b' and occur-forward to 'M-s f'. ; etc/DEBUG: Add entry for the new commands. --- etc/NEWS | 5 +++++ lisp/bindings.el | 2 ++ lisp/replace.el | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index e2ada7c1be..9cfd5ed340 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -294,6 +294,11 @@ substituted by a home directory by writing it as "/foo:/:/~/file". \f * Editing Changes in Emacs 26.1 +--- +** New commands 'occur-in-region', 'occur-forward' and 'occur-backward' +run 'occur' restricted to a region of the current buffer; 'occur-backward' +bound to 'M-s b' and 'occur-forward' bound to 'M-s f'. + +++ ** New bindings for 'query-replace-map'. 'undo', undo the last replacement; bound to 'u'. diff --git a/lisp/bindings.el b/lisp/bindings.el index c13f4b156a..4b1c88a3c5 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -928,6 +928,8 @@ search-map (define-key esc-map "s" search-map) (define-key search-map "o" 'occur) +(define-key search-map "b" 'occur-backward) +(define-key search-map "f" 'occur-forward) (define-key search-map "\M-w" 'eww-search-words) (define-key search-map "hr" 'highlight-regexp) (define-key search-map "hp" 'highlight-phrase) diff --git a/lisp/replace.el b/lisp/replace.el index a172174633..95af63b108 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1092,6 +1092,9 @@ occur-mode (set (make-local-variable 'revert-buffer-function) 'occur-revert-function) (setq next-error-function 'occur-next-error)) +;; Let binded in `occur-forward' and `occur-in-region'. +(defvar occur-matches-threshold nil) + \f ;;; Occur Edit mode @@ -1322,11 +1325,12 @@ occur-excluded-properties :group 'matching :version "22.1") -(defun occur-read-primary-args () - (let* ((perform-collect (consp current-prefix-arg)) +(defun occur-read-primary-args (&optional where) + (let* ((str (if where (concat " " where) "")) + (perform-collect (consp current-prefix-arg)) (regexp (read-regexp (if perform-collect - "Collect strings matching regexp" - "List lines matching regexp") + (concat "Collect strings matching regexp" str) + (concat "List lines matching regexp" str)) 'regexp-history-last))) (list regexp (if perform-collect @@ -1389,6 +1393,45 @@ occur (interactive (occur-read-primary-args)) (occur-1 regexp nlines (list (current-buffer)))) +(defun occur-backward (regexp &optional nlines) + "Show all lines before current line containing a match for REGEXP. +Each line is displayed with NLINES lines before and after, or -NLINES +before if NLINES is negative. +As `occur' but restricted to lines before the current one." + (interactive (occur-read-primary-args "backward")) + (narrow-to-region (point-min) (point)) + (occur regexp nlines) + (widen)) + +(defun occur-forward (regexp &optional nlines) + "Show all lines after current line containing a match for REGEXP. +Each line is displayed with NLINES lines before and after, or -NLINES +before if NLINES is negative. +As `occur' but restricted to lines after the current one." + (interactive (occur-read-primary-args "forward")) + (let ((occur-matches-threshold + (line-number-at-pos (point)))) + (narrow-to-region (point) (point-max)) + (occur regexp nlines)) + (widen)) + +(defun occur-in-region (regexp beg end &optional nlines) + "Show all lines in the active region containing a match for REGEXP. +BEG and END define the region. +Each line is displayed with NLINES lines before and after, or -NLINES +before if NLINES is negative. +As `occur' but restricted to lines within the active region." + (interactive + (if (null (use-region-p)) + (error "Region not active") + (let ((args (occur-read-primary-args "in region"))) + (list (car args) (region-beginning) (region-end) (cadr args))))) + (let ((occur-matches-threshold + (line-number-at-pos beg))) + (narrow-to-region beg end) + (occur regexp nlines)) + (widen)) + (defvar ido-ignore-item-temp-list) (defun multi-occur (bufs regexp &optional nlines) @@ -1551,7 +1594,8 @@ occur-engine (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur-matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.5) of 2016-12-30 Repository revision: 11b81a54d538e8deca3cd64521cf85409efb617b ^ permalink raw reply related [flat|nested] 39+ messages in thread
* RE: [patch] Run occur command restricted to a region 2016-12-29 16:54 ` Tino Calancha @ 2016-12-29 18:16 ` Drew Adams 2016-12-29 18:50 ` Kaushal Modi 2016-12-30 2:57 ` Tino Calancha 0 siblings, 2 replies; 39+ messages in thread From: Drew Adams @ 2016-12-29 18:16 UTC (permalink / raw) To: Tino Calancha, Eli Zaretskii; +Cc: emacs-devel > (define-key search-map "o" 'occur) > +(define-key search-map "b" 'occur-backward) > +(define-key search-map "f" 'occur-forward) FWIW, I don't think those keys (`M-s b' and `M-s f') should be bound to those commands. If we want to bind the new commands during Isearch then I suggest that the occur commands be grouped on prefix key `M-s o': M-s oo occur M-s ob occur-backward M-s of occur-backward `M-s' is a _general_ search prefix key. There is nothing particularly mnemonic about `b' or `f' being `occur-backward' or `occur-forward'. And we should not sacrifice 3 `M-s' keys to these commands. I, and perhaps other users, and perhaps in the future vanilla Emacs, have other bindings on `M-s'. And `M-s' bindings can be anything at all related to the encompassing context of searching. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-29 18:16 ` Drew Adams @ 2016-12-29 18:50 ` Kaushal Modi 2016-12-29 20:52 ` Drew Adams 2016-12-30 2:57 ` Tino Calancha 1 sibling, 1 reply; 39+ messages in thread From: Kaushal Modi @ 2016-12-29 18:50 UTC (permalink / raw) To: Drew Adams, Tino Calancha, Eli Zaretskii; +Cc: emacs-devel [-- Attachment #1: Type: text/plain, Size: 1438 bytes --] I agree with Drew's reasoning behind not using up the M-s b/f bindings for occur-backward/forward. But I don't like the idea of having M-s o as a submap binding. M-s o is super useful as it is now. Here's a suggestion for bindings that might work out. I am not at a computer, so cannot verify if M-s M-o is already taken,.. but if not then how about M-s M-o f for occur-forward, and M-s M-o b for occur-backward ?? The above bindings are easy to press and also easy to remember. On Thu, Dec 29, 2016, 11:47 PM Drew Adams <drew.adams@oracle.com> wrote: > > (define-key search-map "o" 'occur) > > +(define-key search-map "b" 'occur-backward) > > +(define-key search-map "f" 'occur-forward) > > FWIW, I don't think those keys (`M-s b' and `M-s f') should be > bound to those commands. If we want to bind the new commands > during Isearch then I suggest that the occur commands be grouped > on prefix key `M-s o': > > M-s oo occur > M-s ob occur-backward > M-s of occur-backward > > `M-s' is a _general_ search prefix key. There is nothing > particularly mnemonic about `b' or `f' being `occur-backward' > or `occur-forward'. And we should not sacrifice 3 `M-s' keys > to these commands. > > I, and perhaps other users, and perhaps in the future vanilla > Emacs, have other bindings on `M-s'. And `M-s' bindings can > be anything at all related to the encompassing context of > searching. > > -- Kaushal Modi [-- Attachment #2: Type: text/html, Size: 2459 bytes --] ^ permalink raw reply [flat|nested] 39+ messages in thread
* RE: [patch] Run occur command restricted to a region 2016-12-29 18:50 ` Kaushal Modi @ 2016-12-29 20:52 ` Drew Adams 0 siblings, 0 replies; 39+ messages in thread From: Drew Adams @ 2016-12-29 20:52 UTC (permalink / raw) To: Kaushal Modi, Tino Calancha, Eli Zaretskii; +Cc: emacs-devel > I agree with Drew's reasoning behind not using up the M-s b/f > bindings for occur-backward/forward. But I don't like the idea > of having M-s o as a submap binding. M-s o is super useful as > it is now. It is simple to hit `o o' instead of `o'. And it has the advantage of reminding you of the fact that there are also `o f' and `o b'. `M-s o o' is no less "super useful" than `M-s o'. > Here's a suggestion for bindings that might work out. > I am not at a computer, so cannot verify if M-s M-o is > already taken,.. but if not then how about M-s M-o f > for occur-forward, and M-s M-o b for occur-backward?? > > The above bindings are easy to press and also easy to remember. Those are horrible, IMO. Instead of sacrificing `M-s b' and `M-s f' you are sacrificing `M-s M-o'. So you've saved only one key. And at the cost of introducing more complexity. And inconsistency, unless you also move `occur' to `M-s M-o o'. If you do that, then I'm in favor. The point is to group all of the occur commands wrt keys: have them use the same prefix. Prefix `M-s M-o' is at least as easy to use as prefix `M-s o'. ^ permalink raw reply [flat|nested] 39+ messages in thread
* RE: [patch] Run occur command restricted to a region 2016-12-29 18:16 ` Drew Adams 2016-12-29 18:50 ` Kaushal Modi @ 2016-12-30 2:57 ` Tino Calancha 1 sibling, 0 replies; 39+ messages in thread From: Tino Calancha @ 2016-12-30 2:57 UTC (permalink / raw) To: Drew Adams Cc: kaushal.modi, juri, Eli Zaretskii, Emacs developers, Tino Calancha On Thu, 29 Dec 2016, Drew Adams wrote: >> (define-key search-map "o" 'occur) >> +(define-key search-map "b" 'occur-backward) >> +(define-key search-map "f" 'occur-forward) > > FWIW, I don't think those keys (`M-s b' and `M-s f') should be > bound to those commands. If we want to bind the new commands > during Isearch then I suggest that the occur commands be grouped > on prefix key `M-s o': > > M-s oo occur > M-s ob occur-backward > M-s of occur-backward > > `M-s' is a _general_ search prefix key. There is nothing > particularly mnemonic about `b' or `f' being `occur-backward' > or `occur-forward'. And we should not sacrifice 3 `M-s' keys > to these commands. > > I, and perhaps other users, and perhaps in the future vanilla > Emacs, have other bindings on `M-s'. And `M-s' bindings can > be anything at all related to the encompassing context of > searching. I agree with you that my suggested keybindings are not a good choice. To me, grouping related commands under a common prefix sounds like a good idea. I am also OK with not providing keybindings to these new commands at all. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Region argument (was: [patch] Run occur command restricted to a region) 2016-12-29 16:10 ` Eli Zaretskii 2016-12-29 16:54 ` Tino Calancha @ 2017-01-03 17:37 ` Stefan Monnier 2017-01-03 18:34 ` Eli Zaretskii 1 sibling, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2017-01-03 17:37 UTC (permalink / raw) To: emacs-devel > I think our convention for functions that act on the region is to > accept BEG and END arguments, so that the function could be called > from Lisp. Indeed. Note also that in order to support rectangular regions (which are currently poorly supported, but which we'd like to see supported more generally), we should change/tweak this convention. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Region argument (was: [patch] Run occur command restricted to a region) 2017-01-03 17:37 ` Region argument (was: [patch] Run occur command restricted to a region) Stefan Monnier @ 2017-01-03 18:34 ` Eli Zaretskii 2017-01-03 18:59 ` Region argument Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2017-01-03 18:34 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Date: Tue, 03 Jan 2017 12:37:20 -0500 > > Note also that in order to support rectangular regions (which are > currently poorly supported, but which we'd like to see supported more > generally), we should change/tweak this convention. We could start by having Someone™ "in the know" (hint, hint) describe the new conventions in the ELisp manual. Right now, there's nothing there about rectangular regions. Nothing at all. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Region argument 2017-01-03 18:34 ` Eli Zaretskii @ 2017-01-03 18:59 ` Stefan Monnier 2017-01-03 19:19 ` Eli Zaretskii 2017-01-04 0:57 ` Juri Linkov 0 siblings, 2 replies; 39+ messages in thread From: Stefan Monnier @ 2017-01-03 18:59 UTC (permalink / raw) To: emacs-devel > We could start by having Someone™ "in the know" (hint, hint) describe > the new conventions in the ELisp manual. I remember we discussed a new convention, but I'm not sure if we did end up implementing one. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Region argument 2017-01-03 18:59 ` Region argument Stefan Monnier @ 2017-01-03 19:19 ` Eli Zaretskii 2017-01-04 0:57 ` Juri Linkov 1 sibling, 0 replies; 39+ messages in thread From: Eli Zaretskii @ 2017-01-03 19:19 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Date: Tue, 03 Jan 2017 13:59:46 -0500 > > > We could start by having Someone™ "in the know" (hint, hint) describe > > the new conventions in the ELisp manual. > > I remember we discussed a new convention, but I'm not sure if we did end > up implementing one. Then what exactly are we talking about here? If a new convention doesn't exist, we obviously cannot change the existing convention to a new one, can we? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Region argument 2017-01-03 18:59 ` Region argument Stefan Monnier 2017-01-03 19:19 ` Eli Zaretskii @ 2017-01-04 0:57 ` Juri Linkov 1 sibling, 0 replies; 39+ messages in thread From: Juri Linkov @ 2017-01-04 0:57 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel >> We could start by having Someone™ "in the know" (hint, hint) describe >> the new conventions in the ELisp manual. > > I remember we discussed a new convention, but I'm not sure if we did end > up implementing one. IIRC, the missing piece is just a small function: (defun region () (funcall region-extract-function 'bounds)) to provide all info including former region-beginning and region-end for ordinary regions as well as a list of boundaries in case of rectangular regions. Then it could be used in the interactive spec: (defun occur (regexp &optional nlines region) (interactive (nconc (occur-read-primary-args) (list (and (use-region-p) (region))))) (occur-1 regexp nlines (list (current-buffer)))) Here nconc for occur-read-primary-args complicates the issue a little, but in the general case what is needed is only (interactive (list (and (use-region-p) (region)))) ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-29 6:36 [patch] Run occur command restricted to a region Tino Calancha 2016-12-29 16:10 ` Eli Zaretskii @ 2016-12-29 23:31 ` Juri Linkov 2016-12-30 2:47 ` Tino Calancha 2016-12-30 7:53 ` Eli Zaretskii 1 sibling, 2 replies; 39+ messages in thread From: Juri Linkov @ 2016-12-29 23:31 UTC (permalink / raw) To: Tino Calancha; +Cc: Emacs developers > is it worth to have versions of `occur' restricting the > search to lines before (after) the current line? > > Maybe there is already a way to do that, and i just ignore it. > I usually just i copy the region into a temporary buffer; then > i run `occur' there. (info "(emacs) Other Repeating Search") says what is the recommended way to do this is: `M-x occur' Prompt for a regexp, and display a list showing each line in the buffer that contains a match for it. The text that matched is highlighted using the `match' face. To limit the search to part of the buffer, narrow to that part (*note Narrowing::). > I just wrote a patch to show my point; it adds the following commands: > 1) occur-backward: for lines before the current one. The name occur-backward falsely implies it uses re-search-backward, and I'm unsure if we need it as a counter part of isearch-backward. > 2) occur-forward: for lines after the current one. > 3) occur-in-region: for lines within the active region. Maybe we should use the same logic of other related commands in replace.el how-many, keep-lines, flush-lines that limit the affected lines to the active region, or when the region is not active, take only lines after the current line. Then we don't need separate commands, and no keys for them. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-29 23:31 ` [patch] Run occur command restricted to a region Juri Linkov @ 2016-12-30 2:47 ` Tino Calancha 2016-12-30 23:20 ` Juri Linkov 2016-12-30 7:53 ` Eli Zaretskii 1 sibling, 1 reply; 39+ messages in thread From: Tino Calancha @ 2016-12-30 2:47 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha On Fri, 30 Dec 2016, Juri Linkov wrote: > Maybe we should use the same logic of other related commands in replace.el > how-many, keep-lines, flush-lines that limit the affected lines to the > active region, or when the region is not active, take only lines after > the current line. Then we don't need separate commands, and no keys for them. Yeah, that is a source of confusion when using those tools: 1) Commands like `how-many' or `flush-lines' by default apply to the lines after point; they accept optional arguments to cover a region as well. 2) OTOH `occur' by default uses the entire buffer; it doesn't accept arguments to select a region. It's a nice thing if all related tools follow similar defaults. Command `occur' is also used in `multi-occur', to search in multiple buffers: in that case you must search in the entire buffers. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-30 2:47 ` Tino Calancha @ 2016-12-30 23:20 ` Juri Linkov 0 siblings, 0 replies; 39+ messages in thread From: Juri Linkov @ 2016-12-30 23:20 UTC (permalink / raw) To: Tino Calancha; +Cc: Emacs developers >> Maybe we should use the same logic of other related commands in replace.el >> how-many, keep-lines, flush-lines that limit the affected lines to the >> active region, or when the region is not active, take only lines after >> the current line. Then we don't need separate commands, and no keys for them. > Yeah, that is a source of confusion when using those tools: > 1) Commands like `how-many' or `flush-lines' by default apply to the lines > after point; they accept optional arguments to cover a region as well. > 2) OTOH `occur' by default uses the entire buffer; it doesn't accept > arguments to select a region. > > It's a nice thing if all related tools follow similar defaults. Command > `occur' is also used in `multi-occur', to search in multiple buffers: in > that case you must search in the entire buffers. Like other commands, ‘occur’ could handle the active region, but please show this fact in the header of the output *Occur* buffer, so the users will immediately notice the scope of the output. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-29 23:31 ` [patch] Run occur command restricted to a region Juri Linkov 2016-12-30 2:47 ` Tino Calancha @ 2016-12-30 7:53 ` Eli Zaretskii 2016-12-30 23:16 ` Juri Linkov 1 sibling, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2016-12-30 7:53 UTC (permalink / raw) To: Juri Linkov; +Cc: emacs-devel, tino.calancha > From: Juri Linkov <juri@linkov.net> > Date: Fri, 30 Dec 2016 01:31:04 +0200 > Cc: Emacs developers <emacs-devel@gnu.org> > > > 1) occur-backward: for lines before the current one. > > The name occur-backward falsely implies it uses re-search-backward, > and I'm unsure if we need it as a counter part of isearch-backward. I can suggest occur-before and occur-after instead. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-30 7:53 ` Eli Zaretskii @ 2016-12-30 23:16 ` Juri Linkov 2016-12-31 8:37 ` Eli Zaretskii [not found] ` <87r34ozq20.fsf@gmail.com> 0 siblings, 2 replies; 39+ messages in thread From: Juri Linkov @ 2016-12-30 23:16 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel, tino.calancha >> > 1) occur-backward: for lines before the current one. >> >> The name occur-backward falsely implies it uses re-search-backward, >> and I'm unsure if we need it as a counter part of isearch-backward. > > I can suggest occur-before and occur-after instead. Or occur-above and occur-below. What causes the doubt is that there are no other commands like that. No ‘count-words-before’, no ‘count-words-above’, just ‘count-words-region’ no ‘comment-before’, no ‘comment-above’, just ‘comment-region’, no ‘delete-before’, no ‘delete-above’, just ‘delete-region’, and tens of other similar commands. This means that it's simple enough to select the region (e.g. ‘M-<’ to the beginning of the buffer) and use ‘*-region’ commands to operate on the active region. So it should be enough to handle the active region in ‘occur’ without creating new commands. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2016-12-30 23:16 ` Juri Linkov @ 2016-12-31 8:37 ` Eli Zaretskii [not found] ` <87r34ozq20.fsf@gmail.com> 1 sibling, 0 replies; 39+ messages in thread From: Eli Zaretskii @ 2016-12-31 8:37 UTC (permalink / raw) To: Juri Linkov; +Cc: emacs-devel, tino.calancha > From: Juri Linkov <juri@linkov.net> > Cc: tino.calancha@gmail.com, emacs-devel@gnu.org > Date: Sat, 31 Dec 2016 01:16:34 +0200 > > >> > 1) occur-backward: for lines before the current one. > >> > >> The name occur-backward falsely implies it uses re-search-backward, > >> and I'm unsure if we need it as a counter part of isearch-backward. > > > > I can suggest occur-before and occur-after instead. > > Or occur-above and occur-below. > > What causes the doubt is that there are no other commands like that. > No ‘count-words-before’, no ‘count-words-above’, just ‘count-words-region’ > no ‘comment-before’, no ‘comment-above’, just ‘comment-region’, > no ‘delete-before’, no ‘delete-above’, just ‘delete-region’, > and tens of other similar commands. This command emulates Grep, with its -A and -B options. That's why I suggested "after" and "before". No other command need to show context, so it's quite understandable why this one is unique in that sense. > This means that it's simple enough to select the region (e.g. ‘M-<’ > to the beginning of the buffer) and use ‘*-region’ commands to > operate on the active region. So it should be enough to handle the > active region in ‘occur’ without creating new commands. The problem is that the meaning of the region here says nothing about the context lines the user wants displayed in the Occur buffer. I agree that an active region should mean "find matches in that region", but we still need a way for the user to specify non-default number of context lines to show with the matches, I think. ^ permalink raw reply [flat|nested] 39+ messages in thread
[parent not found: <87r34ozq20.fsf@gmail.com>]
[parent not found: <87inq0xhiw.fsf@mail.linkov.net>]
[parent not found: <alpine.DEB.2.20.1701011834290.1852@calancha-pc>]
[parent not found: <87d1g55h8d.fsf@mail.linkov.net>]
* Re: [patch] Run occur command restricted to a region [not found] ` <87d1g55h8d.fsf@mail.linkov.net> @ 2017-01-03 10:19 ` Tino Calancha 2017-01-18 11:04 ` Tino Calancha 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-01-03 10:19 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha (Re-send with emacs-devel@gnu.org as CC) On Mon, 2 Jan 2017, Juri Linkov wrote: >>> If you need to see whether matching lines are before or after >>> the current line, then what do you think about showing and highlighting >>> the current line in the output *Occur* buffer? >> Inserting the current line, which might not match the regexp, in *Occur*; >> i am not sure about it. >> Please, try the second part of the patch, and let me know if looks >> useful for you. > > I tried it, and I'm not sure - the problem is that it's not obvious > that the highlighted line is the current line. Maybe better to put the cursor > in *Occur* on the first matching line after the current line? But I doubt whether > users will like this change in cursor positioning. See the updated patch. Play with it and let me know how you see it. In my case, just the first part of the patch, i.e., to run `occur' restricted to the region is all that i need. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From d2334a303db81f69b09dfe09d3332905dab6be68 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Tue, 3 Jan 2017 19:00:08 +0900 Subject: [PATCH 1/3] Allow occur command to operate on the region See discussion in: https://lists.gnu.org/archive/html/emacs-devel/2016-12/msg01084.html * lisp/replace.el (occur--region-start, occur--region-end) (occur--matches-threshold): New variables. (occur-engine): Use them. (occur): Idem. Add optional args START, END; if non-nil occur applies in that region. * doc/lispintro/emacs-lisp-intro.texi (Keybindings): Update manual * doc/emacs/search.texi (Other Repeating Search: Idem. ; etc/NEWS: Add entry to announce the change. --- doc/emacs/search.texi | 3 +++ doc/lispintro/emacs-lisp-intro.texi | 8 ++++--- etc/NEWS | 2 ++ lisp/replace.el | 48 +++++++++++++++++++++++++++++++------ 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index b728258973..28e25bec43 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1672,6 +1672,9 @@ Other Repeating Search no upper-case letters and @code{case-fold-search} is non-@code{nil}. Aside from @code{occur} and its variants, all operate on the text from point to the end of the buffer, or on the region if it is active. +The command @code{occur} will operate on the region if +it is active as well; when the region is not active, @code{occur} +operates in the whole buffer. @findex list-matching-lines @findex occur diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 830c072cf5..36d767737d 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -17151,9 +17151,11 @@ Keybindings @findex occur The @code{occur} command shows all the lines in the current buffer -that contain a match for a regular expression. Matching lines are -shown in a buffer called @file{*Occur*}. That buffer serves as a menu -to jump to occurrences. +that contain a match for a regular expression. When the region is +active, @code{occur} restricts matches to such region. Otherwise it +uses the entire buffer. +Matching lines are shown in a buffer called @file{*Occur*}. +That buffer serves as a menu to jump to occurrences. @findex global-unset-key @cindex Unbinding key diff --git a/etc/NEWS b/etc/NEWS index d91204b21b..cb01e03971 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -301,6 +301,8 @@ substituted by a home directory by writing it as "/foo:/:/~/file". * Editing Changes in Emacs 26.1 + +** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. 'undo', undo the last replacement; bound to 'u'. diff --git a/lisp/replace.el b/lisp/replace.el index ff91734445..cedf8e0c67 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1360,7 +1360,12 @@ occur-rename-buffer "*") (or unique-p (not interactive-p))))) -(defun occur (regexp &optional nlines) +;; Region limits when `occur' applies on a region. +(defvar occur--region-start nil) +(defvar occur--region-end nil) +(defvar occur--matches-threshold nil) + +(defun occur (regexp &optional nlines start end) "Show all lines in the current buffer containing a match for REGEXP. If a match spreads across multiple lines, all those lines are shown. @@ -1369,6 +1374,13 @@ occur NLINES defaults to `list-matching-lines-default-context-lines'. Interactively it is the prefix arg. +Optional args START and END, if non-nil, mean restrict search to the +specified region. + When START is non-nil and END is nil, END defaults to the last + accessible position in the current buffer. + When END is non-nil and START is nil, START defaults to the first + accessible position in the current buffer. + The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. @@ -1386,8 +1398,23 @@ occur program. When there is no parenthesized subexpressions in REGEXP the entire match is collected. In any case the searched buffer is not modified." - (interactive (occur-read-primary-args)) - (occur-1 regexp nlines (list (current-buffer)))) + (interactive + (nconc (occur-read-primary-args) + (list (and (use-region-p) (region-beginning)) + (and (use-region-p) (region-end))))) + (let ((in-region-p (or start end))) + (when in-region-p + (or start (setq start (point-min))) + (or end (setq end (point-max)))) + (let ((occur--region-start start) + (occur--region-end end) + (occur--matches-threshold + (and in-region-p + (line-number-at-pos (min start end))))) + (save-excursion ; If no matches `occur-1' doesn't restore the point. + (and in-region-p (narrow-to-region start end)) + (occur-1 regexp nlines (list (current-buffer))) + (and in-region-p (widen)))))) (defvar ido-ignore-item-temp-list) @@ -1545,13 +1572,15 @@ occur-engine (let ((global-lines 0) ;; total count of matching lines (global-matches 0) ;; total count of matches (coding nil) - (case-fold-search case-fold)) + (case-fold-search case-fold) + (in-region-p (and occur--region-start occur--region-end))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur--matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) @@ -1684,7 +1713,7 @@ occur-engine (let ((beg (point)) end) (insert (propertize - (format "%d match%s%s%s in buffer: %s\n" + (format "%d match%s%s%s in buffer: %s%s\n" matches (if (= matches 1) "" "es") ;; Don't display the same number of lines ;; and matches in case of 1 match per line. @@ -1694,7 +1723,12 @@ occur-engine ;; Don't display regexp for multi-buffer. (if (> (length buffers) 1) "" (occur-regexp-descr regexp)) - (buffer-name buf)) + (buffer-name buf) + (if in-region-p + (format " within region: %d-%d" + occur--region-start + occur--region-end) + "")) 'read-only t)) (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) -- 2.11.0 From 5a27c052cc1469c72a57d624010a2a8d0c0543b9 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Tue, 3 Jan 2017 19:00:29 +0900 Subject: [PATCH 2/3] Show current line highlighted in *Occur* buffer * lisp/replace.el (occur--orig-line, occur--orig-line-str): New variables. (occur, occur-engine): Use them. --- lisp/replace.el | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lisp/replace.el b/lisp/replace.el index cedf8e0c67..448ac2cf3c 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1364,6 +1364,8 @@ occur-rename-buffer (defvar occur--region-start nil) (defvar occur--region-end nil) (defvar occur--matches-threshold nil) +(defvar occur--orig-line nil) +(defvar occur--orig-line-str nil) (defun occur (regexp &optional nlines start end) "Show all lines in the current buffer containing a match for REGEXP. @@ -1410,7 +1412,13 @@ occur (occur--region-end end) (occur--matches-threshold (and in-region-p - (line-number-at-pos (min start end))))) + (line-number-at-pos (min start end)))) + (occur--orig-line + (line-number-at-pos (point))) + (occur--orig-line-str + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) (save-excursion ; If no matches `occur-1' doesn't restore the point. (and in-region-p (narrow-to-region start end)) (occur-1 regexp nlines (list (current-buffer))) @@ -1581,6 +1589,9 @@ occur-engine (matches 0) ;; count of matches (curr-line ;; line count (or occur--matches-threshold 1)) + (orig-line occur--orig-line) + (orig-line-str occur--orig-line-str) + (orig-line-shown-p) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) @@ -1687,6 +1698,12 @@ occur-engine (nth 0 ret)))) ;; Actually insert the match display data (with-current-buffer out-buf + (when (and (not orig-line-shown-p) + (>= curr-line orig-line)) + (insert + (concat + (propertize orig-line-str 'face 'query-replace) "\n")) + (setq orig-line-shown-p t)) (insert data))) (goto-char endpt)) (if endpt @@ -1700,6 +1717,12 @@ occur-engine (forward-line 1)) (goto-char (point-max))) (setq prev-line (1- curr-line))) + ;; Insert original line if haven't done yet. + (unless orig-line-shown-p + (with-current-buffer out-buf + (insert + (concat + (propertize orig-line-str 'face 'query-replace) "\n")))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf -- 2.11.0 From 366d7e5118d1411b7b43925c3a95bcb50a04db90 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Tue, 3 Jan 2017 19:00:47 +0900 Subject: [PATCH 3/3] occur: Set point on the first matching line after the current one * lisp/replace.el (occur-current-line-face): New face. (occur--final-pos): New variable. (occur-1): Use it. (occur-engine): Idem. Show the current line with 'occur-current-line-face'. --- lisp/replace.el | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/lisp/replace.el b/lisp/replace.el index 448ac2cf3c..0c67fe3640 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1081,6 +1081,12 @@ occur-mode-find-occurrence-hook :type 'hook :group 'matching) +(defface occur-current-line-face + '((t (:inherit lazy-highlight))) + "Face for highlighting the current line in *Occur* buffer." + :group 'matching + :version "26.1") + (put 'occur-mode 'mode-class 'special) (define-derived-mode occur-mode special-mode "Occur" "Major mode for output from \\[occur]. @@ -1366,6 +1372,7 @@ occur--region-end (defvar occur--matches-threshold nil) (defvar occur--orig-line nil) (defvar occur--orig-line-str nil) +(defvar occur--final-pos nil) (defun occur (regexp &optional nlines start end) "Show all lines in the current buffer containing a match for REGEXP. @@ -1517,7 +1524,8 @@ occur-1 (occur-mode)) (let ((inhibit-read-only t) ;; Don't generate undo entries for creation of the initial contents. - (buffer-undo-list t)) + (buffer-undo-list t) + (occur--final-pos nil)) (erase-buffer) (let ((count (if (stringp nlines) @@ -1569,6 +1577,10 @@ occur-1 (if (= count 0) (kill-buffer occur-buf) (display-buffer occur-buf) + (when occur--final-pos + (set-window-point + (get-buffer-window occur-buf 'all-frames) + occur--final-pos)) (setq next-error-last-buffer occur-buf) (setq buffer-read-only t) (set-buffer-modified-p nil) @@ -1581,7 +1593,8 @@ occur-engine (global-matches 0) ;; total count of matches (coding nil) (case-fold-search case-fold) - (in-region-p (and occur--region-start occur--region-end))) + (in-region-p (and occur--region-start occur--region-end)) + (multi-occur-p (cdr buffers))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) @@ -1598,6 +1611,7 @@ occur-engine (origpt nil) (begpt nil) (endpt nil) + (finalpt nil) (marker nil) (curstring "") (ret nil) @@ -1698,12 +1712,17 @@ occur-engine (nth 0 ret)))) ;; Actually insert the match display data (with-current-buffer out-buf - (when (and (not orig-line-shown-p) + (when (and (not multi-occur-p) + (not orig-line-shown-p) (>= curr-line orig-line)) (insert (concat - (propertize orig-line-str 'face 'query-replace) "\n")) - (setq orig-line-shown-p t)) + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face 'occur-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")) + (setq orig-line-shown-p t finalpt (point))) (insert data))) (goto-char endpt)) (if endpt @@ -1718,11 +1737,16 @@ occur-engine (goto-char (point-max))) (setq prev-line (1- curr-line))) ;; Insert original line if haven't done yet. - (unless orig-line-shown-p + (when (and (not multi-occur-p) + (not orig-line-shown-p)) (with-current-buffer out-buf (insert (concat - (propertize orig-line-str 'face 'query-replace) "\n")))) + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face 'occur-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf @@ -1756,8 +1780,11 @@ occur-engine (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) (when title-face - (add-face-text-property beg end title-face))) - (goto-char (point-min))))))) + (add-face-text-property beg end title-face)) + (goto-char (if finalpt + (setq occur--final-pos + (cl-incf finalpt (- end beg))) + (point-min))))))))) ;; Display total match count and regexp for multi-buffer. (when (and (not (zerop global-lines)) (> (length buffers) 1)) (goto-char (point-min)) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.5) of 2017-01-03 Repository revision: 975b2acfe6a4e246631c372063d7bdef0f832d3d ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-03 10:19 ` Tino Calancha @ 2017-01-18 11:04 ` Tino Calancha 2017-01-19 23:51 ` Juri Linkov 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-01-18 11:04 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha On Tue, 3 Jan 2017, Tino Calancha wrote: >> users will like this change in cursor positioning. > See the updated patch. Play with it and let me know how you see it. > In my case, just the first part of the patch, i.e., to run `occur' restricted > to the region is all that i need. Hi Juri, do you have any preference on the proposed patches? Regards, Tino ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-18 11:04 ` Tino Calancha @ 2017-01-19 23:51 ` Juri Linkov 2017-01-20 13:48 ` Tino Calancha 0 siblings, 1 reply; 39+ messages in thread From: Juri Linkov @ 2017-01-19 23:51 UTC (permalink / raw) To: Tino Calancha; +Cc: Emacs developers >> See the updated patch. Play with it and let me know how you see it. >> In my case, just the first part of the patch, i.e., to run `occur' >> restricted to the region is all that i need. > > do you have any preference on the proposed patches? Please see the thread regarding the region argument: http://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00044.html i.e. a new convention is to add a single arg ‘region’ instead of the ‘start’/‘end’ pair. Could you try to update your patch accordingly? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-19 23:51 ` Juri Linkov @ 2017-01-20 13:48 ` Tino Calancha 2017-01-20 16:46 ` Davis Herring 2017-01-20 23:17 ` Juri Linkov 0 siblings, 2 replies; 39+ messages in thread From: Tino Calancha @ 2017-01-20 13:48 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha Juri Linkov <juri@linkov.net> writes: >>> See the updated patch. Play with it and let me know how you see it. >>> In my case, just the first part of the patch, i.e., to run `occur' >>> restricted to the region is all that i need. >> >> do you have any preference on the proposed patches? > > Please see the thread regarding the region argument: > http://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00044.html > i.e. a new convention is to add a single arg ‘region’ > instead of the ‘start’/‘end’ pair. > > Could you try to update your patch accordingly? OK. Updated the patch. *) First patch allow `occur' handle the region with the new convention, i.e., region argument instead of BEG, END. **) The second patch add your suggestion on showing highlighted the current line. When there are matches after the current line, the point in *Occur* is set right after such line. I am fine with just adding *). In case we also want **), an option to enable/disable that behaviour might be desirable. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From 5d69affd729ceed80de9f1ede37a5c7a541b23d4 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Fri, 20 Jan 2017 22:11:11 +0900 Subject: [PATCH 1/2] Allow occur command to operate on the region See discussion in: https://lists.gnu.org/archive/html/emacs-devel/2016-12/msg01084.html * lisp/simple.el (region): New defun. * lisp/replace.el (occur--region-start, occur--region-end) (occur--matches-threshold): New variables. (occur-engine): Use them. (occur): Idem. Add optional arg REGION; if non-nil occur applies in that region. * doc/lispintro/emacs-lisp-intro.texi (Keybindings): Update manual * doc/emacs/search.texi (Other Repeating Search: Idem. ; etc/NEWS: Add entry to announce the change. --- doc/emacs/search.texi | 3 +++ doc/lispintro/emacs-lisp-intro.texi | 8 ++++--- etc/NEWS | 2 ++ lisp/replace.el | 46 +++++++++++++++++++++++++++++++------ lisp/simple.el | 3 +++ 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index b728258973..28e25bec43 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1672,6 +1672,9 @@ Other Repeating Search no upper-case letters and @code{case-fold-search} is non-@code{nil}. Aside from @code{occur} and its variants, all operate on the text from point to the end of the buffer, or on the region if it is active. +The command @code{occur} will operate on the region if +it is active as well; when the region is not active, @code{occur} +operates in the whole buffer. @findex list-matching-lines @findex occur diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 830c072cf5..36d767737d 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -17151,9 +17151,11 @@ Keybindings @findex occur The @code{occur} command shows all the lines in the current buffer -that contain a match for a regular expression. Matching lines are -shown in a buffer called @file{*Occur*}. That buffer serves as a menu -to jump to occurrences. +that contain a match for a regular expression. When the region is +active, @code{occur} restricts matches to such region. Otherwise it +uses the entire buffer. +Matching lines are shown in a buffer called @file{*Occur*}. +That buffer serves as a menu to jump to occurrences. @findex global-unset-key @cindex Unbinding key diff --git a/etc/NEWS b/etc/NEWS index 051b97e146..d4917f402f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -301,6 +301,8 @@ substituted by a home directory by writing it as "/foo:/:/~/file". \f * Editing Changes in Emacs 26.1 + +** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. 'undo', undo the last replacement; bound to 'u'. diff --git a/lisp/replace.el b/lisp/replace.el index ff91734445..d9c3a4ff3e 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1360,7 +1360,12 @@ occur-rename-buffer "*") (or unique-p (not interactive-p))))) -(defun occur (regexp &optional nlines) +;; Region limits when `occur' applies on a region. +(defvar occur--region-start nil) +(defvar occur--region-end nil) +(defvar occur--matches-threshold nil) + +(defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. If a match spreads across multiple lines, all those lines are shown. @@ -1369,6 +1374,10 @@ occur NLINES defaults to `list-matching-lines-default-context-lines'. Interactively it is the prefix arg. +Optional arg REGION, if non-nil, mean restrict search to the +specified region. Otherwise search the entire buffer. +When REGION is non-nil, it must be a cons (START . END). + The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. @@ -1386,8 +1395,24 @@ occur program. When there is no parenthesized subexpressions in REGEXP the entire match is collected. In any case the searched buffer is not modified." - (interactive (occur-read-primary-args)) - (occur-1 regexp nlines (list (current-buffer)))) + (interactive + (nconc (occur-read-primary-args) + (and (use-region-p) (region)))) + (let* ((start (car region)) + (end (cdr region)) + (in-region-p (or start end))) + (when in-region-p + (or start (setq start (point-min))) + (or end (setq end (point-max)))) + (let ((occur--region-start start) + (occur--region-end end) + (occur--matches-threshold + (and in-region-p + (line-number-at-pos (min start end))))) + (save-excursion ; If no matches `occur-1' doesn't restore the point. + (and in-region-p (narrow-to-region start end)) + (occur-1 regexp nlines (list (current-buffer))) + (and in-region-p (widen)))))) (defvar ido-ignore-item-temp-list) @@ -1545,13 +1570,15 @@ occur-engine (let ((global-lines 0) ;; total count of matching lines (global-matches 0) ;; total count of matches (coding nil) - (case-fold-search case-fold)) + (case-fold-search case-fold) + (in-region-p (and occur--region-start occur--region-end))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur--matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) @@ -1684,7 +1711,7 @@ occur-engine (let ((beg (point)) end) (insert (propertize - (format "%d match%s%s%s in buffer: %s\n" + (format "%d match%s%s%s in buffer: %s%s\n" matches (if (= matches 1) "" "es") ;; Don't display the same number of lines ;; and matches in case of 1 match per line. @@ -1694,7 +1721,12 @@ occur-engine ;; Don't display regexp for multi-buffer. (if (> (length buffers) 1) "" (occur-regexp-descr regexp)) - (buffer-name buf)) + (buffer-name buf) + (if in-region-p + (format " within region: %d-%d" + occur--region-start + occur--region-end) + "")) 'read-only t)) (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) diff --git a/lisp/simple.el b/lisp/simple.el index f798cd4384..56c4551490 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1015,6 +1015,9 @@ region-extract-function If anything else, delete the region and return its content as a string, after filtering it with `filter-buffer-substring'.") +(defun region () + (funcall region-extract-function 'bounds)) + (defvar region-insert-function (lambda (lines) (let ((first t)) -- 2.11.0 From 763ca506fed54afacc30ca1904f0727bf0bf2dbf Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Fri, 20 Jan 2017 22:14:39 +0900 Subject: [PATCH 2/2] Show current line highlighted in *Occur* buffer * lisp/replace.el (occur--orig-line, occur--orig-line-str): New variables. (occur, occur-engine): Use them. (occur--final-pos): New variable. (occur-1): Use it. (occur-engine): Idem. Show the current line with 'occur-current-line-face'. Set point on the first matching line after the current one. --- lisp/replace.el | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/lisp/replace.el b/lisp/replace.el index d9c3a4ff3e..ed5cdb718b 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1081,6 +1081,12 @@ occur-mode-find-occurrence-hook :type 'hook :group 'matching) +(defface occur-current-line-face + '((t (:inherit lazy-highlight))) + "Face for highlighting the current line in *Occur* buffer." + :group 'matching + :version "26.1") + (put 'occur-mode 'mode-class 'special) (define-derived-mode occur-mode special-mode "Occur" "Major mode for output from \\[occur]. @@ -1364,6 +1370,9 @@ occur-rename-buffer (defvar occur--region-start nil) (defvar occur--region-end nil) (defvar occur--matches-threshold nil) +(defvar occur--orig-line nil) +(defvar occur--orig-line-str nil) +(defvar occur--final-pos nil) (defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. @@ -1408,7 +1417,13 @@ occur (occur--region-end end) (occur--matches-threshold (and in-region-p - (line-number-at-pos (min start end))))) + (line-number-at-pos (min start end)))) + (occur--orig-line + (line-number-at-pos (point))) + (occur--orig-line-str + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) (save-excursion ; If no matches `occur-1' doesn't restore the point. (and in-region-p (narrow-to-region start end)) (occur-1 regexp nlines (list (current-buffer))) @@ -1507,7 +1522,8 @@ occur-1 (occur-mode)) (let ((inhibit-read-only t) ;; Don't generate undo entries for creation of the initial contents. - (buffer-undo-list t)) + (buffer-undo-list t) + (occur--final-pos nil)) (erase-buffer) (let ((count (if (stringp nlines) @@ -1559,6 +1575,10 @@ occur-1 (if (= count 0) (kill-buffer occur-buf) (display-buffer occur-buf) + (when occur--final-pos + (set-window-point + (get-buffer-window occur-buf 'all-frames) + occur--final-pos)) (setq next-error-last-buffer occur-buf) (setq buffer-read-only t) (set-buffer-modified-p nil) @@ -1571,7 +1591,8 @@ occur-engine (global-matches 0) ;; total count of matches (coding nil) (case-fold-search case-fold) - (in-region-p (and occur--region-start occur--region-end))) + (in-region-p (and occur--region-start occur--region-end)) + (multi-occur-p (cdr buffers))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) @@ -1579,12 +1600,16 @@ occur-engine (matches 0) ;; count of matches (curr-line ;; line count (or occur--matches-threshold 1)) + (orig-line occur--orig-line) + (orig-line-str occur--orig-line-str) + (orig-line-shown-p) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) (origpt nil) (begpt nil) (endpt nil) + (finalpt nil) (marker nil) (curstring "") (ret nil) @@ -1685,6 +1710,17 @@ occur-engine (nth 0 ret)))) ;; Actually insert the match display data (with-current-buffer out-buf + (when (and (not multi-occur-p) + (not orig-line-shown-p) + (>= curr-line orig-line)) + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face 'occur-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")) + (setq orig-line-shown-p t finalpt (point))) (insert data))) (goto-char endpt)) (if endpt @@ -1698,6 +1734,17 @@ occur-engine (forward-line 1)) (goto-char (point-max))) (setq prev-line (1- curr-line))) + ;; Insert original line if haven't done yet. + (when (and (not multi-occur-p) + (not orig-line-shown-p)) + (with-current-buffer out-buf + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face 'occur-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf @@ -1731,8 +1778,11 @@ occur-engine (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) (when title-face - (add-face-text-property beg end title-face))) - (goto-char (point-min))))))) + (add-face-text-property beg end title-face)) + (goto-char (if finalpt + (setq occur--final-pos + (cl-incf finalpt (- end beg))) + (point-min))))))))) ;; Display total match count and regexp for multi-buffer. (when (and (not (zerop global-lines)) (> (length buffers) 1)) (goto-char (point-min)) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.6) of 2017-01-20 Repository revision: 82a5e4dc889ecbfa35374616fe9c5edfa23f4504 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-20 13:48 ` Tino Calancha @ 2017-01-20 16:46 ` Davis Herring 2017-01-20 23:17 ` Juri Linkov 1 sibling, 0 replies; 39+ messages in thread From: Davis Herring @ 2017-01-20 16:46 UTC (permalink / raw) To: Tino Calancha; +Cc: Emacs developers, Juri Linkov > **) The second patch add your suggestion on showing highlighted the > current line. When there are matches after the current line, the > point in *Occur* is set right after such line. I don't care about the highlighting, but I like very much the idea of locating point in *Occur* at the place that corresponds to point in the source buffer. It provides for free most of the benefit of `occur-above' and `occur-below' (by whatever names) by partitioning the results in an intuitive fashion. (It's also the same idea as in my vc-diff patch (which I still need to finish): to show a map of interesting things in the buffer centered on point.) Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-20 13:48 ` Tino Calancha 2017-01-20 16:46 ` Davis Herring @ 2017-01-20 23:17 ` Juri Linkov 2017-01-22 10:32 ` Tino Calancha 1 sibling, 1 reply; 39+ messages in thread From: Juri Linkov @ 2017-01-20 23:17 UTC (permalink / raw) To: Tino Calancha; +Cc: Emacs developers > OK. Updated the patch. > *) First patch allow `occur' handle the region with the new convention, > i.e., region argument instead of BEG, END. Thanks. As a prerequisite I'm going to install this patch: diff --git a/lisp/simple.el b/lisp/simple.el index 3d25ec1..610846b 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1015,6 +1015,9 @@ (defvar region-extract-function If anything else, delete the region and return its content as a string, after filtering it with `filter-buffer-substring'.") +(defun region-bounds () + "Return the boundaries of the region as a list of (START . END) positions." + (funcall region-extract-function 'bounds)) + (defvar region-insert-function (lambda (lines) (let ((first t)) > **) The second patch add your suggestion on showing highlighted the > current line. When there are matches after the current line, the > point in *Occur* is set right after such line. > > I am fine with just adding *). In case we also want **), > an option to enable/disable that behaviour might be desirable. Keeping traditional behaviour means not jumping to the middle of the *Occur* output by default. Then maybe we could use the same option to highlight the current line and to jump to it? Like the existing ‘list-matching-lines-buffer-name-face’, adding a nil/face choice for ‘list-matching-lines-current-line-face’, so when it's nil then don't highlight/jump? ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-20 23:17 ` Juri Linkov @ 2017-01-22 10:32 ` Tino Calancha 2017-01-22 23:50 ` Juri Linkov 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-01-22 10:32 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha Juri Linkov <juri@linkov.net> writes: >> OK. Updated the patch. >> *) First patch allow `occur' handle the region with the new convention, >> i.e., region argument instead of BEG, END. > > Thanks. As a prerequisite I'm going to install this patch: > +(defun region-bounds () > + "Return the boundaries of the region as a list of (START . END) positions." > + (funcall region-extract-function 'bounds)) > + > (defvar region-insert-function > (lambda (lines) > (let ((first t)) Thank you. >> **) The second patch add your suggestion on showing highlighted the >> current line. When there are matches after the current line, the >> point in *Occur* is set right after such line. >> >> I am fine with just adding *). In case we also want **), >> an option to enable/disable that behaviour might be desirable. > > Keeping traditional behaviour means not jumping to the middle of the > *Occur* output by default. Then maybe we could use the same option > to highlight the current line and to jump to it? Like the existing > ‘list-matching-lines-buffer-name-face’, adding a nil/face choice for > ‘list-matching-lines-current-line-face’, so when it's nil then don't > highlight/jump? OK, why not? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From c9a6891187de8c4df6294777ea745810d405b07a Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Sun, 22 Jan 2017 19:12:35 +0900 Subject: [PATCH 1/2] Allow occur command to operate on the region See discussion in: https://lists.gnu.org/archive/html/emacs-devel/2016-12/msg01084.html * lisp/replace.el (occur--region-start, occur--region-end) (occur--matches-threshold): New variables. (occur-engine): Use them. (occur): Idem. Add optional arg REGION; if non-nil occur applies in that region. * doc/lispintro/emacs-lisp-intro.texi (Keybindings): Update manual * doc/emacs/search.texi (Other Repeating Search: Idem. ; etc/NEWS: Add entry to announce the change. --- doc/emacs/search.texi | 3 +++ doc/lispintro/emacs-lisp-intro.texi | 8 ++++--- etc/NEWS | 2 ++ lisp/replace.el | 46 +++++++++++++++++++++++++++++++------ 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index b728258973..28e25bec43 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1672,6 +1672,9 @@ Other Repeating Search no upper-case letters and @code{case-fold-search} is non-@code{nil}. Aside from @code{occur} and its variants, all operate on the text from point to the end of the buffer, or on the region if it is active. +The command @code{occur} will operate on the region if +it is active as well; when the region is not active, @code{occur} +operates in the whole buffer. @findex list-matching-lines @findex occur diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 830c072cf5..36d767737d 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -17151,9 +17151,11 @@ Keybindings @findex occur The @code{occur} command shows all the lines in the current buffer -that contain a match for a regular expression. Matching lines are -shown in a buffer called @file{*Occur*}. That buffer serves as a menu -to jump to occurrences. +that contain a match for a regular expression. When the region is +active, @code{occur} restricts matches to such region. Otherwise it +uses the entire buffer. +Matching lines are shown in a buffer called @file{*Occur*}. +That buffer serves as a menu to jump to occurrences. @findex global-unset-key @cindex Unbinding key diff --git a/etc/NEWS b/etc/NEWS index ca66df6261..9eb5d82099 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -310,6 +310,8 @@ substituted by a home directory by writing it as "/foo:/:/~/file". \f * Editing Changes in Emacs 26.1 + +** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. 'undo', undo the last replacement; bound to 'u'. diff --git a/lisp/replace.el b/lisp/replace.el index ff91734445..00e73157ff 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1360,7 +1360,12 @@ occur-rename-buffer "*") (or unique-p (not interactive-p))))) -(defun occur (regexp &optional nlines) +;; Region limits when `occur' applies on a region. +(defvar occur--region-start nil) +(defvar occur--region-end nil) +(defvar occur--matches-threshold nil) + +(defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. If a match spreads across multiple lines, all those lines are shown. @@ -1369,6 +1374,10 @@ occur NLINES defaults to `list-matching-lines-default-context-lines'. Interactively it is the prefix arg. +Optional arg REGION, if non-nil, mean restrict search to the +specified region. Otherwise search the entire buffer. +When REGION is non-nil, it must be a cons (START . END). + The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. @@ -1386,8 +1395,24 @@ occur program. When there is no parenthesized subexpressions in REGEXP the entire match is collected. In any case the searched buffer is not modified." - (interactive (occur-read-primary-args)) - (occur-1 regexp nlines (list (current-buffer)))) + (interactive + (nconc (occur-read-primary-args) + (and (use-region-p) (region-bounds)))) + (let* ((start (car region)) + (end (cdr region)) + (in-region-p (or start end))) + (when in-region-p + (or start (setq start (point-min))) + (or end (setq end (point-max)))) + (let ((occur--region-start start) + (occur--region-end end) + (occur--matches-threshold + (and in-region-p + (line-number-at-pos (min start end))))) + (save-excursion ; If no matches `occur-1' doesn't restore the point. + (and in-region-p (narrow-to-region start end)) + (occur-1 regexp nlines (list (current-buffer))) + (and in-region-p (widen)))))) (defvar ido-ignore-item-temp-list) @@ -1545,13 +1570,15 @@ occur-engine (let ((global-lines 0) ;; total count of matching lines (global-matches 0) ;; total count of matches (coding nil) - (case-fold-search case-fold)) + (case-fold-search case-fold) + (in-region-p (and occur--region-start occur--region-end))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur--matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) @@ -1684,7 +1711,7 @@ occur-engine (let ((beg (point)) end) (insert (propertize - (format "%d match%s%s%s in buffer: %s\n" + (format "%d match%s%s%s in buffer: %s%s\n" matches (if (= matches 1) "" "es") ;; Don't display the same number of lines ;; and matches in case of 1 match per line. @@ -1694,7 +1721,12 @@ occur-engine ;; Don't display regexp for multi-buffer. (if (> (length buffers) 1) "" (occur-regexp-descr regexp)) - (buffer-name buf)) + (buffer-name buf) + (if in-region-p + (format " within region: %d-%d" + occur--region-start + occur--region-end) + "")) 'read-only t)) (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) -- 2.11.0 From 31b578636731c0a67dc64aad8d880d82d7c8804d Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Sun, 22 Jan 2017 19:25:34 +0900 Subject: [PATCH 2/2] Show current line highlighted in *Occur* buffer * lisp/replace.el (occur-current-line-face): New face. (list-matching-lines-current-line-face): New user option. (occur--orig-line, occur--orig-line-str): New variables. (occur, occur-engine): Use them. (occur--final-pos): New variable. (occur-1): Use it. (occur-engine): Idem. Show the current line with 'occur-current-line-face'. Set point on the first matching line after the current one. * etc/NEWS: Add entry for the new option. --- etc/NEWS | 3 +++ lisp/replace.el | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 9eb5d82099..ff8246506d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -311,6 +311,9 @@ substituted by a home directory by writing it as "/foo:/:/~/file". * Editing Changes in Emacs 26.1 +** A new user option 'list-matching-lines-current-line-face' +to show highlighted the current line in the *Occur* buffer. + ** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. diff --git a/lisp/replace.el b/lisp/replace.el index 00e73157ff..3de09b48cc 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1081,6 +1081,12 @@ occur-mode-find-occurrence-hook :type 'hook :group 'matching) +(defface occur-current-line-face + '((t (:inherit lazy-highlight))) + "Face for highlighting the current line in *Occur* buffer." + :group 'matching + :version "26.1") + (put 'occur-mode 'mode-class 'special) (define-derived-mode occur-mode special-mode "Occur" "Major mode for output from \\[occur]. @@ -1304,6 +1310,13 @@ list-matching-lines-buffer-name-face :type 'face :group 'matching) +(defcustom list-matching-lines-current-line-face nil + "If non-nil, \\[list-matching-lines] shows the current line highlighted. +Set the point right after such line when there are matches after it." + :type '(choice (const :tag "Unset" nil) + (const :tag "highlight current line" occur-current-line-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, @@ -1364,6 +1377,9 @@ occur-rename-buffer (defvar occur--region-start nil) (defvar occur--region-end nil) (defvar occur--matches-threshold nil) +(defvar occur--orig-line nil) +(defvar occur--orig-line-str nil) +(defvar occur--final-pos nil) (defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. @@ -1381,6 +1397,9 @@ occur The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. +If `list-matching-lines-current-line-face' is non-nil, then show highlighted +the current line; if there are matches after it, then set the +point right after such line. If REGEXP contains upper case characters (excluding those preceded by `\\') and `search-upper-case' is non-nil, the matching is case-sensitive. @@ -1408,7 +1427,13 @@ occur (occur--region-end end) (occur--matches-threshold (and in-region-p - (line-number-at-pos (min start end))))) + (line-number-at-pos (min start end)))) + (occur--orig-line + (line-number-at-pos (point))) + (occur--orig-line-str + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) (save-excursion ; If no matches `occur-1' doesn't restore the point. (and in-region-p (narrow-to-region start end)) (occur-1 regexp nlines (list (current-buffer))) @@ -1507,7 +1532,8 @@ occur-1 (occur-mode)) (let ((inhibit-read-only t) ;; Don't generate undo entries for creation of the initial contents. - (buffer-undo-list t)) + (buffer-undo-list t) + (occur--final-pos nil)) (erase-buffer) (let ((count (if (stringp nlines) @@ -1559,6 +1585,10 @@ occur-1 (if (= count 0) (kill-buffer occur-buf) (display-buffer occur-buf) + (when occur--final-pos + (set-window-point + (get-buffer-window occur-buf 'all-frames) + occur--final-pos)) (setq next-error-last-buffer occur-buf) (setq buffer-read-only t) (set-buffer-modified-p nil) @@ -1571,7 +1601,8 @@ occur-engine (global-matches 0) ;; total count of matches (coding nil) (case-fold-search case-fold) - (in-region-p (and occur--region-start occur--region-end))) + (in-region-p (and occur--region-start occur--region-end)) + (multi-occur-p (cdr buffers))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) @@ -1579,12 +1610,16 @@ occur-engine (matches 0) ;; count of matches (curr-line ;; line count (or occur--matches-threshold 1)) + (orig-line occur--orig-line) + (orig-line-str occur--orig-line-str) + (orig-line-shown-p) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) (origpt nil) (begpt nil) (endpt nil) + (finalpt nil) (marker nil) (curstring "") (ret nil) @@ -1685,6 +1720,18 @@ occur-engine (nth 0 ret)))) ;; Actually insert the match display data (with-current-buffer out-buf + (when (and list-matching-lines-current-line-face + (not multi-occur-p) + (not orig-line-shown-p) + (>= curr-line orig-line)) + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face 'occur-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")) + (setq orig-line-shown-p t finalpt (point))) (insert data))) (goto-char endpt)) (if endpt @@ -1698,6 +1745,18 @@ occur-engine (forward-line 1)) (goto-char (point-max))) (setq prev-line (1- curr-line))) + ;; Insert original line if haven't done yet. + (when (and list-matching-lines-current-line-face + (not multi-occur-p) + (not orig-line-shown-p)) + (with-current-buffer out-buf + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face 'occur-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf @@ -1731,8 +1790,11 @@ occur-engine (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) (when title-face - (add-face-text-property beg end title-face))) - (goto-char (point-min))))))) + (add-face-text-property beg end title-face)) + (goto-char (if finalpt + (setq occur--final-pos + (cl-incf finalpt (- end beg))) + (point-min))))))))) ;; Display total match count and regexp for multi-buffer. (when (and (not (zerop global-lines)) (> (length buffers) 1)) (goto-char (point-min)) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.6) of 2017-01-22 Repository revision: 0a49f158f1598fb92989f3cbdc238a7e5f1bd8a3 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-22 10:32 ` Tino Calancha @ 2017-01-22 23:50 ` Juri Linkov 2017-01-23 7:32 ` Tino Calancha 0 siblings, 1 reply; 39+ messages in thread From: Juri Linkov @ 2017-01-22 23:50 UTC (permalink / raw) To: Tino Calancha; +Cc: Emacs developers >>> **) The second patch add your suggestion on showing highlighted the >>> current line. When there are matches after the current line, the >>> point in *Occur* is set right after such line. >>> >>> I am fine with just adding *). In case we also want **), >>> an option to enable/disable that behaviour might be desirable. >> >> Keeping traditional behaviour means not jumping to the middle of the >> *Occur* output by default. Then maybe we could use the same option >> to highlight the current line and to jump to it? Like the existing >> ‘list-matching-lines-buffer-name-face’, adding a nil/face choice for >> ‘list-matching-lines-current-line-face’, so when it's nil then don't >> highlight/jump? > OK, why not? Thanks. > +(defface occur-current-line-face > + '((t (:inherit lazy-highlight))) > + "Face for highlighting the current line in *Occur* buffer." I'm not sure about the new face ‘occur-current-line-face’. Looking at the list of faces from ‘M-x list-faces-display’, there are no other occur faces. It would be confusing for the users to see a single occur-related face in this list, whereas all other occur-related faces are customized by ‘list-matching-lines-*’ variables only. For consistency with other occur faces, maybe better to have a variable (defcustom list-matching-lines-current-line-face 'lazy-highlight and another boolean customizable variable list-matching-lines-jump-to-current-line to enable locating the current line. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-22 23:50 ` Juri Linkov @ 2017-01-23 7:32 ` Tino Calancha [not found] ` <87lgtu4w5c.fsf@mail.linkov.net> 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-01-23 7:32 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha Juri Linkov <juri@linkov.net> writes: >> +(defface occur-current-line-face >> + '((t (:inherit lazy-highlight))) >> + "Face for highlighting the current line in *Occur* buffer." > > I'm not sure about the new face ‘occur-current-line-face’. > Looking at the list of faces from ‘M-x list-faces-display’, there are > no other occur faces. It would be confusing for the users to see > a single occur-related face in this list, whereas all other occur-related > faces are customized by ‘list-matching-lines-*’ variables only. > > For consistency with other occur faces, maybe better to have a variable > > (defcustom list-matching-lines-current-line-face 'lazy-highlight > > and another boolean customizable variable list-matching-lines-jump-to-current-line > to enable locating the current line. Thank you. Implemented in the new patch below: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From 56d13fa11b01260d9088d820a5cf6cd04d042848 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Mon, 23 Jan 2017 16:26:22 +0900 Subject: [PATCH 1/2] Allow occur command to operate on the region See discussion in: https://lists.gnu.org/archive/html/emacs-devel/2016-12/msg01084.html * lisp/replace.el (occur--region-start, occur--region-end) (occur--matches-threshold): New variables. (occur-engine): Use them. (occur): Idem. Add optional arg REGION; if non-nil occur applies in that region. * doc/lispintro/emacs-lisp-intro.texi (Keybindings): Update manual * doc/emacs/search.texi (Other Repeating Search: Idem. ; etc/NEWS: Add entry to announce the change. --- doc/emacs/search.texi | 3 +++ doc/lispintro/emacs-lisp-intro.texi | 8 ++++--- etc/NEWS | 2 ++ lisp/replace.el | 46 +++++++++++++++++++++++++++++++------ 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index b728258973..28e25bec43 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1672,6 +1672,9 @@ Other Repeating Search no upper-case letters and @code{case-fold-search} is non-@code{nil}. Aside from @code{occur} and its variants, all operate on the text from point to the end of the buffer, or on the region if it is active. +The command @code{occur} will operate on the region if +it is active as well; when the region is not active, @code{occur} +operates in the whole buffer. @findex list-matching-lines @findex occur diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 830c072cf5..36d767737d 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -17151,9 +17151,11 @@ Keybindings @findex occur The @code{occur} command shows all the lines in the current buffer -that contain a match for a regular expression. Matching lines are -shown in a buffer called @file{*Occur*}. That buffer serves as a menu -to jump to occurrences. +that contain a match for a regular expression. When the region is +active, @code{occur} restricts matches to such region. Otherwise it +uses the entire buffer. +Matching lines are shown in a buffer called @file{*Occur*}. +That buffer serves as a menu to jump to occurrences. @findex global-unset-key @cindex Unbinding key diff --git a/etc/NEWS b/etc/NEWS index ca66df6261..9eb5d82099 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -310,6 +310,8 @@ substituted by a home directory by writing it as "/foo:/:/~/file". \f * Editing Changes in Emacs 26.1 + +** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. 'undo', undo the last replacement; bound to 'u'. diff --git a/lisp/replace.el b/lisp/replace.el index ff91734445..00e73157ff 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1360,7 +1360,12 @@ occur-rename-buffer "*") (or unique-p (not interactive-p))))) -(defun occur (regexp &optional nlines) +;; Region limits when `occur' applies on a region. +(defvar occur--region-start nil) +(defvar occur--region-end nil) +(defvar occur--matches-threshold nil) + +(defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. If a match spreads across multiple lines, all those lines are shown. @@ -1369,6 +1374,10 @@ occur NLINES defaults to `list-matching-lines-default-context-lines'. Interactively it is the prefix arg. +Optional arg REGION, if non-nil, mean restrict search to the +specified region. Otherwise search the entire buffer. +When REGION is non-nil, it must be a cons (START . END). + The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. @@ -1386,8 +1395,24 @@ occur program. When there is no parenthesized subexpressions in REGEXP the entire match is collected. In any case the searched buffer is not modified." - (interactive (occur-read-primary-args)) - (occur-1 regexp nlines (list (current-buffer)))) + (interactive + (nconc (occur-read-primary-args) + (and (use-region-p) (region-bounds)))) + (let* ((start (car region)) + (end (cdr region)) + (in-region-p (or start end))) + (when in-region-p + (or start (setq start (point-min))) + (or end (setq end (point-max)))) + (let ((occur--region-start start) + (occur--region-end end) + (occur--matches-threshold + (and in-region-p + (line-number-at-pos (min start end))))) + (save-excursion ; If no matches `occur-1' doesn't restore the point. + (and in-region-p (narrow-to-region start end)) + (occur-1 regexp nlines (list (current-buffer))) + (and in-region-p (widen)))))) (defvar ido-ignore-item-temp-list) @@ -1545,13 +1570,15 @@ occur-engine (let ((global-lines 0) ;; total count of matching lines (global-matches 0) ;; total count of matches (coding nil) - (case-fold-search case-fold)) + (case-fold-search case-fold) + (in-region-p (and occur--region-start occur--region-end))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur--matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) @@ -1684,7 +1711,7 @@ occur-engine (let ((beg (point)) end) (insert (propertize - (format "%d match%s%s%s in buffer: %s\n" + (format "%d match%s%s%s in buffer: %s%s\n" matches (if (= matches 1) "" "es") ;; Don't display the same number of lines ;; and matches in case of 1 match per line. @@ -1694,7 +1721,12 @@ occur-engine ;; Don't display regexp for multi-buffer. (if (> (length buffers) 1) "" (occur-regexp-descr regexp)) - (buffer-name buf)) + (buffer-name buf) + (if in-region-p + (format " within region: %d-%d" + occur--region-start + occur--region-end) + "")) 'read-only t)) (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) -- 2.11.0 From 417ad35f210d74231a3529fcc44cb8f77127fb86 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Mon, 23 Jan 2017 16:26:35 +0900 Subject: [PATCH 2/2] Show current line highlighted in *Occur* buffer * lisp/replace.el (list-matching-lines-current-line-face) (list-matching-lines-jump-to-current-line): New user options. (occur--orig-line, occur--orig-line-str): New variables. (occur, occur-engine): Use them. (occur--final-pos): New variable. (occur-1): Use it. (occur-engine): Idem. Show the current line with 'list-matching-lines-current-line-face'. Set point on the first matching line after the current one. * etc/NEWS: Add entry for the new option. --- etc/NEWS | 4 ++++ lisp/replace.el | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 9eb5d82099..9b74ce16ed 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -311,6 +311,10 @@ substituted by a home directory by writing it as "/foo:/:/~/file". * Editing Changes in Emacs 26.1 +** Two new user options 'list-matching-lines-jump-to-current-line' and +'list-matching-lines-current-line-face' to show highlighted the current line +in the *Occur* buffer. + ** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. diff --git a/lisp/replace.el b/lisp/replace.el index 00e73157ff..1a80dc16c6 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1304,6 +1304,19 @@ list-matching-lines-buffer-name-face :type 'face :group 'matching) +(defcustom list-matching-lines-current-line-face 'lazy-highlight + "Face used by \\[list-matching-lines] to highlight the current line." + :type 'face + :group 'matching + :version "26.1") + +(defcustom list-matching-lines-jump-to-current-line nil + "If non-nil, \\[list-matching-lines] shows the current line highlighted. +Set the point right after such line when there are matches after it." +:type 'boolean +:group 'matching +:version "26.1") + (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, @@ -1364,6 +1377,9 @@ occur-rename-buffer (defvar occur--region-start nil) (defvar occur--region-end nil) (defvar occur--matches-threshold nil) +(defvar occur--orig-line nil) +(defvar occur--orig-line-str nil) +(defvar occur--final-pos nil) (defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. @@ -1381,6 +1397,9 @@ occur The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. +If `list-matching-lines-jump-to-current-line' is non-nil, then show +highlighted the current line and, if there are matches after it, then +set point in the first of those matches. If REGEXP contains upper case characters (excluding those preceded by `\\') and `search-upper-case' is non-nil, the matching is case-sensitive. @@ -1408,7 +1427,13 @@ occur (occur--region-end end) (occur--matches-threshold (and in-region-p - (line-number-at-pos (min start end))))) + (line-number-at-pos (min start end)))) + (occur--orig-line + (line-number-at-pos (point))) + (occur--orig-line-str + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) (save-excursion ; If no matches `occur-1' doesn't restore the point. (and in-region-p (narrow-to-region start end)) (occur-1 regexp nlines (list (current-buffer))) @@ -1507,7 +1532,8 @@ occur-1 (occur-mode)) (let ((inhibit-read-only t) ;; Don't generate undo entries for creation of the initial contents. - (buffer-undo-list t)) + (buffer-undo-list t) + (occur--final-pos nil)) (erase-buffer) (let ((count (if (stringp nlines) @@ -1559,6 +1585,10 @@ occur-1 (if (= count 0) (kill-buffer occur-buf) (display-buffer occur-buf) + (when occur--final-pos + (set-window-point + (get-buffer-window occur-buf 'all-frames) + occur--final-pos)) (setq next-error-last-buffer occur-buf) (setq buffer-read-only t) (set-buffer-modified-p nil) @@ -1571,7 +1601,8 @@ occur-engine (global-matches 0) ;; total count of matches (coding nil) (case-fold-search case-fold) - (in-region-p (and occur--region-start occur--region-end))) + (in-region-p (and occur--region-start occur--region-end)) + (multi-occur-p (cdr buffers))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) @@ -1579,12 +1610,16 @@ occur-engine (matches 0) ;; count of matches (curr-line ;; line count (or occur--matches-threshold 1)) + (orig-line occur--orig-line) + (orig-line-str occur--orig-line-str) + (orig-line-shown-p) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) (origpt nil) (begpt nil) (endpt nil) + (finalpt nil) (marker nil) (curstring "") (ret nil) @@ -1685,6 +1720,18 @@ occur-engine (nth 0 ret)))) ;; Actually insert the match display data (with-current-buffer out-buf + (when (and list-matching-lines-jump-to-current-line + (not multi-occur-p) + (not orig-line-shown-p) + (>= curr-line orig-line)) + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face list-matching-lines-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")) + (setq orig-line-shown-p t finalpt (point))) (insert data))) (goto-char endpt)) (if endpt @@ -1698,6 +1745,18 @@ occur-engine (forward-line 1)) (goto-char (point-max))) (setq prev-line (1- curr-line))) + ;; Insert original line if haven't done yet. + (when (and list-matching-lines-jump-to-current-line + (not multi-occur-p) + (not orig-line-shown-p)) + (with-current-buffer out-buf + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face list-matching-lines-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf @@ -1731,8 +1790,11 @@ occur-engine (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) (when title-face - (add-face-text-property beg end title-face))) - (goto-char (point-min))))))) + (add-face-text-property beg end title-face)) + (goto-char (if finalpt + (setq occur--final-pos + (cl-incf finalpt (- end beg))) + (point-min))))))))) ;; Display total match count and regexp for multi-buffer. (when (and (not (zerop global-lines)) (> (length buffers) 1)) (goto-char (point-min)) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.6) of 2017-01-22 Repository revision: 03de82fe7ca09ab40fbcae394d4fcdfe3374496e ^ permalink raw reply related [flat|nested] 39+ messages in thread
[parent not found: <87lgtu4w5c.fsf@mail.linkov.net>]
* Re: [patch] Run occur command restricted to a region [not found] ` <87lgtu4w5c.fsf@mail.linkov.net> @ 2017-01-29 6:00 ` Tino Calancha 2017-01-30 0:09 ` Juri Linkov 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-01-29 6:00 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha [-- Attachment #1: Type: text/plain, Size: 16084 bytes --] On Sun, 29 Jan 2017, Juri Linkov wrote: > I think this is a useful addition, thanks. One note below. > >> +Optional arg REGION, if non-nil, mean restrict search to the >> +specified region. Otherwise search the entire buffer. >> +When REGION is non-nil, it must be a cons (START . END). > > When someone decides to add support for rectangular regions in occur later, > your current implementation will make this problematic since it changes > the format ((START . END)) to (START . END), that makes difficult to support > ((START1 . END1) (START2 . END2) ...) later. > > Let's stick to the same format in all uses of the new ‘REGION’ arg, and > currently in occur support only the degenerate case of ((START . END)) > for non-rectangular regions. Thanks. I was also a bit worry with that detail. OK, i keep the general format ((START . END)). Let me know if the following patch is OK to be pushed: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From 40ac0b30445f9581a5b4d6988d31089468a6a969 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Sun, 29 Jan 2017 14:46:10 +0900 Subject: [PATCH 1/2] Allow occur command to operate on the region See discussion in: https://lists.gnu.org/archive/html/emacs-devel/2016-12/msg01084.html * lisp/replace.el (occur--region-start, occur--region-end) (occur--matches-threshold): New variables. (occur-engine): Use them. (occur): Idem. Add optional arg REGION; if non-nil occur applies in that region. * doc/lispintro/emacs-lisp-intro.texi (Keybindings): Update manual * doc/emacs/search.texi (Other Repeating Search: Idem. ; etc/NEWS: Add entry to announce the change. --- doc/emacs/search.texi | 3 +++ doc/lispintro/emacs-lisp-intro.texi | 8 ++++--- etc/NEWS | 2 ++ lisp/replace.el | 47 +++++++++++++++++++++++++++++++------ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index b728258973..28e25bec43 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1672,6 +1672,9 @@ Other Repeating Search no upper-case letters and @code{case-fold-search} is non-@code{nil}. Aside from @code{occur} and its variants, all operate on the text from point to the end of the buffer, or on the region if it is active. +The command @code{occur} will operate on the region if +it is active as well; when the region is not active, @code{occur} +operates in the whole buffer. @findex list-matching-lines @findex occur diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 830c072cf5..36d767737d 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -17151,9 +17151,11 @@ Keybindings @findex occur The @code{occur} command shows all the lines in the current buffer -that contain a match for a regular expression. Matching lines are -shown in a buffer called @file{*Occur*}. That buffer serves as a menu -to jump to occurrences. +that contain a match for a regular expression. When the region is +active, @code{occur} restricts matches to such region. Otherwise it +uses the entire buffer. +Matching lines are shown in a buffer called @file{*Occur*}. +That buffer serves as a menu to jump to occurrences. @findex global-unset-key @cindex Unbinding key diff --git a/etc/NEWS b/etc/NEWS index 12ff21f39a..a74cdb71df 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -310,6 +310,8 @@ substituted by a home directory by writing it as "/foo:/:/~/file". * Editing Changes in Emacs 26.1 + +** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. 'undo', undo the last replacement; bound to 'u'. diff --git a/lisp/replace.el b/lisp/replace.el index ff91734445..0a8e480485 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1360,7 +1360,12 @@ occur-rename-buffer "*") (or unique-p (not interactive-p))))) -(defun occur (regexp &optional nlines) +;; Region limits when `occur' applies on a region. +(defvar occur--region-start nil) +(defvar occur--region-end nil) +(defvar occur--matches-threshold nil) + +(defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. If a match spreads across multiple lines, all those lines are shown. @@ -1369,6 +1374,11 @@ occur NLINES defaults to `list-matching-lines-default-context-lines'. Interactively it is the prefix arg. +Optional arg REGION, if non-nil, mean restrict search to the +specified region. Otherwise search the entire buffer. +REGION must be a list of (START . END) positions as returned by +`region-bounds'. + The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. @@ -1386,8 +1396,24 @@ occur program. When there is no parenthesized subexpressions in REGEXP the entire match is collected. In any case the searched buffer is not modified." - (interactive (occur-read-primary-args)) - (occur-1 regexp nlines (list (current-buffer)))) + (interactive + (nconc (occur-read-primary-args) + (and (use-region-p) (list (region-bounds))))) + (let* ((start (and (caar region) (max (caar region) (point-min)))) + (end (and (cdar region) (min (cdar region) (point-max)))) + (in-region-p (or start end))) + (when in-region-p + (or start (setq start (point-min))) + (or end (setq end (point-max)))) + (let ((occur--region-start start) + (occur--region-end end) + (occur--matches-threshold + (and in-region-p + (line-number-at-pos (min start end))))) + (save-excursion ; If no matches `occur-1' doesn't restore the point. + (and in-region-p (narrow-to-region start end)) + (occur-1 regexp nlines (list (current-buffer))) + (and in-region-p (widen)))))) (defvar ido-ignore-item-temp-list) @@ -1545,13 +1571,15 @@ occur-engine (let ((global-lines 0) ;; total count of matching lines (global-matches 0) ;; total count of matches (coding nil) - (case-fold-search case-fold)) + (case-fold-search case-fold) + (in-region-p (and occur--region-start occur--region-end))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur--matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) @@ -1684,7 +1712,7 @@ occur-engine (let ((beg (point)) end) (insert (propertize - (format "%d match%s%s%s in buffer: %s\n" + (format "%d match%s%s%s in buffer: %s%s\n" matches (if (= matches 1) "" "es") ;; Don't display the same number of lines ;; and matches in case of 1 match per line. @@ -1694,7 +1722,12 @@ occur-engine ;; Don't display regexp for multi-buffer. (if (> (length buffers) 1) "" (occur-regexp-descr regexp)) - (buffer-name buf)) + (buffer-name buf) + (if in-region-p + (format " within region: %d-%d" + occur--region-start + occur--region-end) + "")) 'read-only t)) (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) -- 2.11.0 From a1ac23d9b5384524591fa9f6586a2665175caf6f Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Sun, 29 Jan 2017 14:46:27 +0900 Subject: [PATCH 2/2] Show current line highlighted in *Occur* buffer * lisp/replace.el (list-matching-lines-current-line-face) (list-matching-lines-jump-to-current-line): New user options. (occur--orig-line, occur--orig-line-str): New variables. (occur, occur-engine): Use them. (occur--final-pos): New variable. (occur-1): Use it. (occur-engine): Idem. Show the current line with 'list-matching-lines-current-line-face'. Set point on the first matching line after the current one. * etc/NEWS: Add entry for the new option. --- etc/NEWS | 4 ++++ lisp/replace.el | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index a74cdb71df..90b53aca16 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -311,6 +311,10 @@ substituted by a home directory by writing it as "/foo:/:/~/file". * Editing Changes in Emacs 26.1 +** Two new user options 'list-matching-lines-jump-to-current-line' and +'list-matching-lines-current-line-face' to show highlighted the current line +in the *Occur* buffer. + ** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. diff --git a/lisp/replace.el b/lisp/replace.el index 0a8e480485..8e51792f5e 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1304,6 +1304,19 @@ list-matching-lines-buffer-name-face :type 'face :group 'matching) +(defcustom list-matching-lines-current-line-face 'lazy-highlight + "Face used by \\[list-matching-lines] to highlight the current line." + :type 'face + :group 'matching + :version "26.1") + +(defcustom list-matching-lines-jump-to-current-line nil + "If non-nil, \\[list-matching-lines] shows the current line highlighted. +Set the point right after such line when there are matches after it." +:type 'boolean +:group 'matching +:version "26.1") + (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, @@ -1364,6 +1377,9 @@ occur-rename-buffer (defvar occur--region-start nil) (defvar occur--region-end nil) (defvar occur--matches-threshold nil) +(defvar occur--orig-line nil) +(defvar occur--orig-line-str nil) +(defvar occur--final-pos nil) (defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. @@ -1382,6 +1398,9 @@ occur The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. +If `list-matching-lines-jump-to-current-line' is non-nil, then show +highlighted the current line and, if there are matches after it, then +set point in the first of those matches. If REGEXP contains upper case characters (excluding those preceded by `\\') and `search-upper-case' is non-nil, the matching is case-sensitive. @@ -1409,7 +1428,13 @@ occur (occur--region-end end) (occur--matches-threshold (and in-region-p - (line-number-at-pos (min start end))))) + (line-number-at-pos (min start end)))) + (occur--orig-line + (line-number-at-pos (point))) + (occur--orig-line-str + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) (save-excursion ; If no matches `occur-1' doesn't restore the point. (and in-region-p (narrow-to-region start end)) (occur-1 regexp nlines (list (current-buffer))) @@ -1508,7 +1533,8 @@ occur-1 (occur-mode)) (let ((inhibit-read-only t) ;; Don't generate undo entries for creation of the initial contents. - (buffer-undo-list t)) + (buffer-undo-list t) + (occur--final-pos nil)) (erase-buffer) (let ((count (if (stringp nlines) @@ -1560,6 +1586,10 @@ occur-1 (if (= count 0) (kill-buffer occur-buf) (display-buffer occur-buf) + (when occur--final-pos + (set-window-point + (get-buffer-window occur-buf 'all-frames) + occur--final-pos)) (setq next-error-last-buffer occur-buf) (setq buffer-read-only t) (set-buffer-modified-p nil) @@ -1572,7 +1602,8 @@ occur-engine (global-matches 0) ;; total count of matches (coding nil) (case-fold-search case-fold) - (in-region-p (and occur--region-start occur--region-end))) + (in-region-p (and occur--region-start occur--region-end)) + (multi-occur-p (cdr buffers))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) @@ -1580,12 +1611,16 @@ occur-engine (matches 0) ;; count of matches (curr-line ;; line count (or occur--matches-threshold 1)) + (orig-line occur--orig-line) + (orig-line-str occur--orig-line-str) + (orig-line-shown-p) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) (origpt nil) (begpt nil) (endpt nil) + (finalpt nil) (marker nil) (curstring "") (ret nil) @@ -1686,6 +1721,18 @@ occur-engine (nth 0 ret)))) ;; Actually insert the match display data (with-current-buffer out-buf + (when (and list-matching-lines-jump-to-current-line + (not multi-occur-p) + (not orig-line-shown-p) + (>= curr-line orig-line)) + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face list-matching-lines-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")) + (setq orig-line-shown-p t finalpt (point))) (insert data))) (goto-char endpt)) (if endpt @@ -1699,6 +1746,18 @@ occur-engine (forward-line 1)) (goto-char (point-max))) (setq prev-line (1- curr-line))) + ;; Insert original line if haven't done yet. + (when (and list-matching-lines-jump-to-current-line + (not multi-occur-p) + (not orig-line-shown-p)) + (with-current-buffer out-buf + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face list-matching-lines-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf @@ -1732,8 +1791,11 @@ occur-engine (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) (when title-face - (add-face-text-property beg end title-face))) - (goto-char (point-min))))))) + (add-face-text-property beg end title-face)) + (goto-char (if finalpt + (setq occur--final-pos + (cl-incf finalpt (- end beg))) + (point-min))))))))) ;; Display total match count and regexp for multi-buffer. (when (and (not (zerop global-lines)) (> (length buffers) 1)) (goto-char (point-min)) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.6) of 2017-01-29 Repository revision: d12e1ddf42cddcac56f98c5b3a65f5219d2d5968 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-29 6:00 ` Tino Calancha @ 2017-01-30 0:09 ` Juri Linkov 2017-01-30 4:27 ` Tino Calancha 2017-01-30 4:48 ` Tino Calancha 0 siblings, 2 replies; 39+ messages in thread From: Juri Linkov @ 2017-01-30 0:09 UTC (permalink / raw) To: Tino Calancha; +Cc: Emacs developers >>> +Optional arg REGION, if non-nil, mean restrict search to the >>> +specified region. Otherwise search the entire buffer. >>> +When REGION is non-nil, it must be a cons (START . END). >> >> When someone decides to add support for rectangular regions in occur later, >> your current implementation will make this problematic since it changes >> the format ((START . END)) to (START . END), that makes difficult to support >> ((START1 . END1) (START2 . END2) ...) later. >> >> Let's stick to the same format in all uses of the new ‘REGION’ arg, and >> currently in occur support only the degenerate case of ((START . END)) >> for non-rectangular regions. > > Thanks. I was also a bit worry with that detail. > OK, i keep the general format ((START . END)). > Let me know if the following patch is OK to be pushed: Looks good to me, but you have to ask Eli for the permission to push. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-30 0:09 ` Juri Linkov @ 2017-01-30 4:27 ` Tino Calancha 2017-01-30 4:48 ` Tino Calancha 1 sibling, 0 replies; 39+ messages in thread From: Tino Calancha @ 2017-01-30 4:27 UTC (permalink / raw) To: Juri Linkov; +Cc: Emacs developers, Tino Calancha [-- Attachment #1: Type: text/plain, Size: 1022 bytes --] On Mon, 30 Jan 2017, Juri Linkov wrote: >>>> +Optional arg REGION, if non-nil, mean restrict search to the >>>> +specified region. Otherwise search the entire buffer. >>>> +When REGION is non-nil, it must be a cons (START . END). >>> >>> When someone decides to add support for rectangular regions in occur later, >>> your current implementation will make this problematic since it changes >>> the format ((START . END)) to (START . END), that makes difficult to support >>> ((START1 . END1) (START2 . END2) ...) later. >>> >>> Let's stick to the same format in all uses of the new ‘REGION’ arg, and >>> currently in occur support only the degenerate case of ((START . END)) >>> for non-rectangular regions. >> >> Thanks. I was also a bit worry with that detail. >> OK, i keep the general format ((START . END)). >> Let me know if the following patch is OK to be pushed: > > Looks good to me, but you have to ask Eli for the permission to push. OK, I will ask. Thank you very much for your help implementing this. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-30 0:09 ` Juri Linkov 2017-01-30 4:27 ` Tino Calancha @ 2017-01-30 4:48 ` Tino Calancha 2017-01-30 15:35 ` Eli Zaretskii 1 sibling, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-01-30 4:48 UTC (permalink / raw) To: John Wiegley, Eli Zaretskii; +Cc: tino.calancha, Emacs developers, Juri Linkov Hi, Juri and me have being working on extend `occur' so that it can run restricted to the region. We propose the patch below. Please let us know if it's OK for you to push this patch into the master branch. Best regards, Tino Juri Linkov <juri@linkov.net> writes: >>> Let's stick to the same format in all uses of the new ‘REGION’ arg, and >>> currently in occur support only the degenerate case of ((START . END)) >>> for non-rectangular regions. >> >> OK, i keep the general format ((START . END)). >> Let me know if the following patch is OK to be pushed: > > Looks good to me, but you have to ask Eli for the permission to push. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From 40ac0b30445f9581a5b4d6988d31089468a6a969 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Sun, 29 Jan 2017 14:46:10 +0900 Subject: [PATCH 1/2] Allow occur command to operate on the region See discussion in: https://lists.gnu.org/archive/html/emacs-devel/2016-12/msg01084.html * lisp/replace.el (occur--region-start, occur--region-end) (occur--matches-threshold): New variables. (occur-engine): Use them. (occur): Idem. Add optional arg REGION; if non-nil occur applies in that region. * doc/lispintro/emacs-lisp-intro.texi (Keybindings): Update manual * doc/emacs/search.texi (Other Repeating Search: Idem. ; etc/NEWS: Add entry to announce the change. --- doc/emacs/search.texi | 3 +++ doc/lispintro/emacs-lisp-intro.texi | 8 ++++--- etc/NEWS | 2 ++ lisp/replace.el | 47 +++++++++++++++++++++++++++++++------ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index b728258973..28e25bec43 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1672,6 +1672,9 @@ Other Repeating Search no upper-case letters and @code{case-fold-search} is non-@code{nil}. Aside from @code{occur} and its variants, all operate on the text from point to the end of the buffer, or on the region if it is active. +The command @code{occur} will operate on the region if +it is active as well; when the region is not active, @code{occur} +operates in the whole buffer. @findex list-matching-lines @findex occur diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 830c072cf5..36d767737d 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -17151,9 +17151,11 @@ Keybindings @findex occur The @code{occur} command shows all the lines in the current buffer -that contain a match for a regular expression. Matching lines are -shown in a buffer called @file{*Occur*}. That buffer serves as a menu -to jump to occurrences. +that contain a match for a regular expression. When the region is +active, @code{occur} restricts matches to such region. Otherwise it +uses the entire buffer. +Matching lines are shown in a buffer called @file{*Occur*}. +That buffer serves as a menu to jump to occurrences. @findex global-unset-key @cindex Unbinding key diff --git a/etc/NEWS b/etc/NEWS index 12ff21f39a..a74cdb71df 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -310,6 +310,8 @@ substituted by a home directory by writing it as "/foo:/:/~/file". * Editing Changes in Emacs 26.1 + +** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. 'undo', undo the last replacement; bound to 'u'. diff --git a/lisp/replace.el b/lisp/replace.el index ff91734445..0a8e480485 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1360,7 +1360,12 @@ occur-rename-buffer "*") (or unique-p (not interactive-p))))) -(defun occur (regexp &optional nlines) +;; Region limits when `occur' applies on a region. +(defvar occur--region-start nil) +(defvar occur--region-end nil) +(defvar occur--matches-threshold nil) + +(defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. If a match spreads across multiple lines, all those lines are shown. @@ -1369,6 +1374,11 @@ occur NLINES defaults to `list-matching-lines-default-context-lines'. Interactively it is the prefix arg. +Optional arg REGION, if non-nil, mean restrict search to the +specified region. Otherwise search the entire buffer. +REGION must be a list of (START . END) positions as returned by +`region-bounds'. + The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. @@ -1386,8 +1396,24 @@ occur program. When there is no parenthesized subexpressions in REGEXP the entire match is collected. In any case the searched buffer is not modified." - (interactive (occur-read-primary-args)) - (occur-1 regexp nlines (list (current-buffer)))) + (interactive + (nconc (occur-read-primary-args) + (and (use-region-p) (list (region-bounds))))) + (let* ((start (and (caar region) (max (caar region) (point-min)))) + (end (and (cdar region) (min (cdar region) (point-max)))) + (in-region-p (or start end))) + (when in-region-p + (or start (setq start (point-min))) + (or end (setq end (point-max)))) + (let ((occur--region-start start) + (occur--region-end end) + (occur--matches-threshold + (and in-region-p + (line-number-at-pos (min start end))))) + (save-excursion ; If no matches `occur-1' doesn't restore the point. + (and in-region-p (narrow-to-region start end)) + (occur-1 regexp nlines (list (current-buffer))) + (and in-region-p (widen)))))) (defvar ido-ignore-item-temp-list) @@ -1545,13 +1571,15 @@ occur-engine (let ((global-lines 0) ;; total count of matching lines (global-matches 0) ;; total count of matches (coding nil) - (case-fold-search case-fold)) + (case-fold-search case-fold) + (in-region-p (and occur--region-start occur--region-end))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) (let ((lines 0) ;; count of matching lines (matches 0) ;; count of matches - (curr-line 1) ;; line count + (curr-line ;; line count + (or occur--matches-threshold 1)) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) @@ -1684,7 +1712,7 @@ occur-engine (let ((beg (point)) end) (insert (propertize - (format "%d match%s%s%s in buffer: %s\n" + (format "%d match%s%s%s in buffer: %s%s\n" matches (if (= matches 1) "" "es") ;; Don't display the same number of lines ;; and matches in case of 1 match per line. @@ -1694,7 +1722,12 @@ occur-engine ;; Don't display regexp for multi-buffer. (if (> (length buffers) 1) "" (occur-regexp-descr regexp)) - (buffer-name buf)) + (buffer-name buf) + (if in-region-p + (format " within region: %d-%d" + occur--region-start + occur--region-end) + "")) 'read-only t)) (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) -- 2.11.0 From a1ac23d9b5384524591fa9f6586a2665175caf6f Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Sun, 29 Jan 2017 14:46:27 +0900 Subject: [PATCH 2/2] Show current line highlighted in *Occur* buffer * lisp/replace.el (list-matching-lines-current-line-face) (list-matching-lines-jump-to-current-line): New user options. (occur--orig-line, occur--orig-line-str): New variables. (occur, occur-engine): Use them. (occur--final-pos): New variable. (occur-1): Use it. (occur-engine): Idem. Show the current line with 'list-matching-lines-current-line-face'. Set point on the first matching line after the current one. * etc/NEWS: Add entry for the new option. --- etc/NEWS | 4 ++++ lisp/replace.el | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index a74cdb71df..90b53aca16 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -311,6 +311,10 @@ substituted by a home directory by writing it as "/foo:/:/~/file". * Editing Changes in Emacs 26.1 +** Two new user options 'list-matching-lines-jump-to-current-line' and +'list-matching-lines-current-line-face' to show highlighted the current line +in the *Occur* buffer. + ** The 'occur' command can now operate on the region. +++ ** New bindings for 'query-replace-map'. diff --git a/lisp/replace.el b/lisp/replace.el index 0a8e480485..8e51792f5e 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1304,6 +1304,19 @@ list-matching-lines-buffer-name-face :type 'face :group 'matching) +(defcustom list-matching-lines-current-line-face 'lazy-highlight + "Face used by \\[list-matching-lines] to highlight the current line." + :type 'face + :group 'matching + :version "26.1") + +(defcustom list-matching-lines-jump-to-current-line nil + "If non-nil, \\[list-matching-lines] shows the current line highlighted. +Set the point right after such line when there are matches after it." +:type 'boolean +:group 'matching +:version "26.1") + (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, @@ -1364,6 +1377,9 @@ occur-rename-buffer (defvar occur--region-start nil) (defvar occur--region-end nil) (defvar occur--matches-threshold nil) +(defvar occur--orig-line nil) +(defvar occur--orig-line-str nil) +(defvar occur--final-pos nil) (defun occur (regexp &optional nlines region) "Show all lines in the current buffer containing a match for REGEXP. @@ -1382,6 +1398,9 @@ occur The lines are shown in a buffer named `*Occur*'. It serves as a menu to find any of the occurrences in this buffer. \\<occur-mode-map>\\[describe-mode] in that buffer will explain how. +If `list-matching-lines-jump-to-current-line' is non-nil, then show +highlighted the current line and, if there are matches after it, then +set point in the first of those matches. If REGEXP contains upper case characters (excluding those preceded by `\\') and `search-upper-case' is non-nil, the matching is case-sensitive. @@ -1409,7 +1428,13 @@ occur (occur--region-end end) (occur--matches-threshold (and in-region-p - (line-number-at-pos (min start end))))) + (line-number-at-pos (min start end)))) + (occur--orig-line + (line-number-at-pos (point))) + (occur--orig-line-str + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) (save-excursion ; If no matches `occur-1' doesn't restore the point. (and in-region-p (narrow-to-region start end)) (occur-1 regexp nlines (list (current-buffer))) @@ -1508,7 +1533,8 @@ occur-1 (occur-mode)) (let ((inhibit-read-only t) ;; Don't generate undo entries for creation of the initial contents. - (buffer-undo-list t)) + (buffer-undo-list t) + (occur--final-pos nil)) (erase-buffer) (let ((count (if (stringp nlines) @@ -1560,6 +1586,10 @@ occur-1 (if (= count 0) (kill-buffer occur-buf) (display-buffer occur-buf) + (when occur--final-pos + (set-window-point + (get-buffer-window occur-buf 'all-frames) + occur--final-pos)) (setq next-error-last-buffer occur-buf) (setq buffer-read-only t) (set-buffer-modified-p nil) @@ -1572,7 +1602,8 @@ occur-engine (global-matches 0) ;; total count of matches (coding nil) (case-fold-search case-fold) - (in-region-p (and occur--region-start occur--region-end))) + (in-region-p (and occur--region-start occur--region-end)) + (multi-occur-p (cdr buffers))) ;; Map over all the buffers (dolist (buf buffers) (when (buffer-live-p buf) @@ -1580,12 +1611,16 @@ occur-engine (matches 0) ;; count of matches (curr-line ;; line count (or occur--matches-threshold 1)) + (orig-line occur--orig-line) + (orig-line-str occur--orig-line-str) + (orig-line-shown-p) (prev-line nil) ;; line number of prev match endpt (prev-after-lines nil) ;; context lines of prev match (matchbeg 0) (origpt nil) (begpt nil) (endpt nil) + (finalpt nil) (marker nil) (curstring "") (ret nil) @@ -1686,6 +1721,18 @@ occur-engine (nth 0 ret)))) ;; Actually insert the match display data (with-current-buffer out-buf + (when (and list-matching-lines-jump-to-current-line + (not multi-occur-p) + (not orig-line-shown-p) + (>= curr-line orig-line)) + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face list-matching-lines-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")) + (setq orig-line-shown-p t finalpt (point))) (insert data))) (goto-char endpt)) (if endpt @@ -1699,6 +1746,18 @@ occur-engine (forward-line 1)) (goto-char (point-max))) (setq prev-line (1- curr-line))) + ;; Insert original line if haven't done yet. + (when (and list-matching-lines-jump-to-current-line + (not multi-occur-p) + (not orig-line-shown-p)) + (with-current-buffer out-buf + (insert + (concat + (propertize + (format "%7d:%s" orig-line orig-line-str) + 'face list-matching-lines-current-line-face + 'mouse-face 'mode-line-highlight + 'help-echo "Current line") "\n")))) ;; Flush remaining context after-lines. (when prev-after-lines (with-current-buffer out-buf @@ -1732,8 +1791,11 @@ occur-engine (setq end (point)) (add-text-properties beg end `(occur-title ,buf)) (when title-face - (add-face-text-property beg end title-face))) - (goto-char (point-min))))))) + (add-face-text-property beg end title-face)) + (goto-char (if finalpt + (setq occur--final-pos + (cl-incf finalpt (- end beg))) + (point-min))))))))) ;; Display total match count and regexp for multi-buffer. (when (and (not (zerop global-lines)) (> (length buffers) 1)) (goto-char (point-min)) -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 26.0.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.6) of 2017-01-29 Repository revision: d12e1ddf42cddcac56f98c5b3a65f5219d2d5968 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-30 4:48 ` Tino Calancha @ 2017-01-30 15:35 ` Eli Zaretskii 2017-02-02 10:22 ` Tino Calancha 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2017-01-30 15:35 UTC (permalink / raw) To: Tino Calancha; +Cc: jwiegley, emacs-devel, juri > From: Tino Calancha <tino.calancha@gmail.com> > Cc: Juri Linkov <juri@linkov.net>, tino.calancha@gmail.com, Emacs developers <emacs-devel@gnu.org> > Date: Mon, 30 Jan 2017 13:48:02 +0900 > > Juri and me have being working on extend `occur' so that it > can run restricted to the region. > We propose the patch below. > Please let us know if it's OK for you to push this patch into > the master branch. If everyone is happy with this, I don't see any reasons not to push. One comment: the NEWS entry that describes features already documented in the corresponding manual should be marked with "+++", see the explanation at the head of NEWS. Thanks. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-01-30 15:35 ` Eli Zaretskii @ 2017-02-02 10:22 ` Tino Calancha 2017-02-02 21:08 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-02-02 10:22 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Emacs developers, Tino Calancha On Mon, 30 Jan 2017, Eli Zaretskii wrote: >> Please let us know if it's OK for you to push this patch into >> the master branch. > > If everyone is happy with this, I don't see any reasons not to push. > > One comment: the NEWS entry that describes features already documented > in the corresponding manual should be marked with "+++", see the > explanation at the head of NEWS. Pushed as commits: 8e871aef10455eefc34790a9ec011c6fec5e93fe e280b94dcd6ed42439718ddf9dd704169f6bb536 Thank you. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-02-02 10:22 ` Tino Calancha @ 2017-02-02 21:08 ` Eli Zaretskii 2017-02-03 3:11 ` Tino Calancha 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2017-02-02 21:08 UTC (permalink / raw) To: Tino Calancha; +Cc: emacs-devel > From: Tino Calancha <tino.calancha@gmail.com> > Date: Thu, 2 Feb 2017 19:22:24 +0900 (JST) > cc: Tino Calancha <tino.calancha@gmail.com>, > Emacs developers <emacs-devel@gnu.org> > > Pushed as commits: > 8e871aef10455eefc34790a9ec011c6fec5e93fe > e280b94dcd6ed42439718ddf9dd704169f6bb536 Thanks. In the future, when you introduce new variables/faces/functions/commands, please make sure to index them, unless they are defined with the likes of @defopt and @defun, which do that for you automatically. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-02-02 21:08 ` Eli Zaretskii @ 2017-02-03 3:11 ` Tino Calancha 2017-02-03 8:02 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-02-03 3:11 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel, Tino Calancha On Thu, 2 Feb 2017, Eli Zaretskii wrote: >> From: Tino Calancha <tino.calancha@gmail.com> >> Date: Thu, 2 Feb 2017 19:22:24 +0900 (JST) >> cc: Tino Calancha <tino.calancha@gmail.com>, >> Emacs developers <emacs-devel@gnu.org> >> >> Pushed as commits: >> 8e871aef10455eefc34790a9ec011c6fec5e93fe >> e280b94dcd6ed42439718ddf9dd704169f6bb536 > > Thanks. > > In the future, when you introduce new > variables/faces/functions/commands, please make sure to index them, > unless they are defined with the likes of @defopt and @defun, which do > that for you automatically. I just noticed your commit df915775bc4ead095aa37d2b098de748e1821027 Now i understand that you mean the concept index. Sure i will do this from now on. Thanks. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [patch] Run occur command restricted to a region 2017-02-03 3:11 ` Tino Calancha @ 2017-02-03 8:02 ` Eli Zaretskii 2017-02-03 10:04 ` CONTRIBUTE: Mention indexing new vars/commands in manual [was: Run occur command restricted to a region] Tino Calancha 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2017-02-03 8:02 UTC (permalink / raw) To: Tino Calancha; +Cc: emacs-devel > From: Tino Calancha <tino.calancha@gmail.com> > Date: Fri, 3 Feb 2017 12:11:11 +0900 (JST) > cc: Tino Calancha <tino.calancha@gmail.com>, emacs-devel@gnu.org > > I just noticed your commit df915775bc4ead095aa37d2b098de748e1821027 > Now i understand that you mean the concept index. Not just the concept index: the variables should go into the variable indec and functions/commands into their index. There are separate @cindex, @vindex, and @findex commands in Texinfo. > Sure i will do this from now on. Thanks in advance. ^ permalink raw reply [flat|nested] 39+ messages in thread
* CONTRIBUTE: Mention indexing new vars/commands in manual [was: Run occur command restricted to a region] 2017-02-03 8:02 ` Eli Zaretskii @ 2017-02-03 10:04 ` Tino Calancha 2017-02-03 10:37 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Tino Calancha @ 2017-02-03 10:04 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel, tino.calancha Eli Zaretskii <eliz@gnu.org> writes: >> From: Tino Calancha <tino.calancha@gmail.com> >> Date: Fri, 3 Feb 2017 12:11:11 +0900 (JST) >> cc: Tino Calancha <tino.calancha@gmail.com>, emacs-devel@gnu.org >> >> I just noticed your commit df915775bc4ead095aa37d2b098de748e1821027 >> Now i understand that you mean the concept index. > > Not just the concept index: the variables should go into the variable > indec and functions/commands into their index. There are separate > @cindex, @vindex, and @findex commands in Texinfo. Do you think would be worth to mention briefly about this in CONTRIBUTE? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From caa8e6955e65f3bb45e816dcfc3dc66cdd0fde28 Mon Sep 17 00:00:00 2001 From: Tino Calancha <tino.calancha@gmail.com> Date: Fri, 3 Feb 2017 18:55:00 +0900 Subject: [PATCH] * CONTRIBUTE (Documenting your changes): Index new vars/commands in manual. --- CONTRIBUTE | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CONTRIBUTE b/CONTRIBUTE index c12f0cc08d..49b8919f17 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -250,6 +250,12 @@ know it does not, mark the NEWS entry with "---". If you know that *all* the necessary documentation updates have been made, mark the entry with "+++". Otherwise do not mark it. +If your change requires updating the manuals to document new +functions/commands/variables/faces, then use the proper Texinfo +command to index them; for instance, use @vindex for variables and +@findex for functions/commands. For the full list of predefine indices, see +http://www.gnu.org/software/texinfo/manual/texinfo/html_node/Predefined-Indices.html + For more specific tips on Emacs's doc style, see http://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html Use 'checkdoc' to check for documentation errors before submitting a patch. -- 2.11.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; In GNU Emacs 25.1.91.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.6) of 2017-02-03 Repository revision: 7e02a477bbcabb4e65aeecade79b67357c0b9dae ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: CONTRIBUTE: Mention indexing new vars/commands in manual [was: Run occur command restricted to a region] 2017-02-03 10:04 ` CONTRIBUTE: Mention indexing new vars/commands in manual [was: Run occur command restricted to a region] Tino Calancha @ 2017-02-03 10:37 ` Eli Zaretskii 2017-02-03 11:02 ` Tino Calancha 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2017-02-03 10:37 UTC (permalink / raw) To: Tino Calancha; +Cc: emacs-devel > From: Tino Calancha <tino.calancha@gmail.com> > Cc: tino.calancha@gmail.com, emacs-devel@gnu.org > Date: Fri, 03 Feb 2017 19:04:27 +0900 > > > Not just the concept index: the variables should go into the variable > > indec and functions/commands into their index. There are separate > > @cindex, @vindex, and @findex commands in Texinfo. > Do you think would be worth to mention briefly about this in CONTRIBUTE? > ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; > >From caa8e6955e65f3bb45e816dcfc3dc66cdd0fde28 Mon Sep 17 00:00:00 2001 > From: Tino Calancha <tino.calancha@gmail.com> > Date: Fri, 3 Feb 2017 18:55:00 +0900 > Subject: [PATCH] * CONTRIBUTE (Documenting your changes): Index new > vars/commands in manual. Fine with me, but please also point to the node in Info notation, since the reader might have the Texinfo manual installed. This should go to the emacs-25 branch. Thanks. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: CONTRIBUTE: Mention indexing new vars/commands in manual [was: Run occur command restricted to a region] 2017-02-03 10:37 ` Eli Zaretskii @ 2017-02-03 11:02 ` Tino Calancha 0 siblings, 0 replies; 39+ messages in thread From: Tino Calancha @ 2017-02-03 11:02 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Emacs developers, Tino Calancha On Fri, 3 Feb 2017, Eli Zaretskii wrote: >> From: Tino Calancha <tino.calancha@gmail.com> >> Cc: tino.calancha@gmail.com, emacs-devel@gnu.org >> Date: Fri, 03 Feb 2017 19:04:27 +0900 >> >>> Not just the concept index: the variables should go into the variable >>> indec and functions/commands into their index. There are separate >>> @cindex, @vindex, and @findex commands in Texinfo. >> Do you think would be worth to mention briefly about this in CONTRIBUTE? >> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; >>> From caa8e6955e65f3bb45e816dcfc3dc66cdd0fde28 Mon Sep 17 00:00:00 2001 >> From: Tino Calancha <tino.calancha@gmail.com> >> Date: Fri, 3 Feb 2017 18:55:00 +0900 >> Subject: [PATCH] * CONTRIBUTE (Documenting your changes): Index new >> vars/commands in manual. > > Fine with me, but please also point to the node in Info notation, > since the reader might have the Texinfo manual installed. > > This should go to the emacs-25 branch. Pushed to emacs-25 branch as commit e1171de6d1922af4bb8e9b4eae2becf1b7b597d4 ^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2017-02-03 11:02 UTC | newest] Thread overview: 39+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-12-29 6:36 [patch] Run occur command restricted to a region Tino Calancha 2016-12-29 16:10 ` Eli Zaretskii 2016-12-29 16:54 ` Tino Calancha 2016-12-29 18:16 ` Drew Adams 2016-12-29 18:50 ` Kaushal Modi 2016-12-29 20:52 ` Drew Adams 2016-12-30 2:57 ` Tino Calancha 2017-01-03 17:37 ` Region argument (was: [patch] Run occur command restricted to a region) Stefan Monnier 2017-01-03 18:34 ` Eli Zaretskii 2017-01-03 18:59 ` Region argument Stefan Monnier 2017-01-03 19:19 ` Eli Zaretskii 2017-01-04 0:57 ` Juri Linkov 2016-12-29 23:31 ` [patch] Run occur command restricted to a region Juri Linkov 2016-12-30 2:47 ` Tino Calancha 2016-12-30 23:20 ` Juri Linkov 2016-12-30 7:53 ` Eli Zaretskii 2016-12-30 23:16 ` Juri Linkov 2016-12-31 8:37 ` Eli Zaretskii [not found] ` <87r34ozq20.fsf@gmail.com> [not found] ` <87inq0xhiw.fsf@mail.linkov.net> [not found] ` <alpine.DEB.2.20.1701011834290.1852@calancha-pc> [not found] ` <87d1g55h8d.fsf@mail.linkov.net> 2017-01-03 10:19 ` Tino Calancha 2017-01-18 11:04 ` Tino Calancha 2017-01-19 23:51 ` Juri Linkov 2017-01-20 13:48 ` Tino Calancha 2017-01-20 16:46 ` Davis Herring 2017-01-20 23:17 ` Juri Linkov 2017-01-22 10:32 ` Tino Calancha 2017-01-22 23:50 ` Juri Linkov 2017-01-23 7:32 ` Tino Calancha [not found] ` <87lgtu4w5c.fsf@mail.linkov.net> 2017-01-29 6:00 ` Tino Calancha 2017-01-30 0:09 ` Juri Linkov 2017-01-30 4:27 ` Tino Calancha 2017-01-30 4:48 ` Tino Calancha 2017-01-30 15:35 ` Eli Zaretskii 2017-02-02 10:22 ` Tino Calancha 2017-02-02 21:08 ` Eli Zaretskii 2017-02-03 3:11 ` Tino Calancha 2017-02-03 8:02 ` Eli Zaretskii 2017-02-03 10:04 ` CONTRIBUTE: Mention indexing new vars/commands in manual [was: Run occur command restricted to a region] Tino Calancha 2017-02-03 10:37 ` Eli Zaretskii 2017-02-03 11:02 ` Tino Calancha
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.