unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Juri Linkov <juri@linkov.net>
To: Gabriele Nicolardi <gabriele@medialab.sissa.it>
Cc: 69542@debbugs.gnu.org
Subject: bug#69542: Feature request: making occur obey isearch-filter-predicate
Date: Tue, 05 Mar 2024 18:30:20 +0200	[thread overview]
Message-ID: <86msrdnjdn.fsf@mail.linkov.net> (raw)
In-Reply-To: <6071eb9a-fa15-45fb-9917-7a35c7556680@medialab.sissa.it> (Gabriele Nicolardi's message of "Mon, 4 Mar 2024 12:44:48 +0100")

> I’d like occur to obey to isearch-filter-predicate like query-replace* and
> isearch* commands.
>
> This is an example of what I do:
>
> (defmacro with-ifp-predicates (PREDICATES &rest body)
>    "Allows assigning a list of predicates to the
>  variable `isearch-filter-predicate'.
>
> Below is an example of usage:
>
> (with-ifp-predicates '(skip-maths skip-comments)
>   (query-replace \"foo\" \"bar\" nil (point-min) (point-max)))"
>   (declare (indent 1))
>   `(let ((isearch-filter-predicate isearch-filter-predicate))
>      (mapc (lambda (predicate)
>                (add-function :before-while isearch-filter-predicate predicate))
>              ,PREDICATES)
>      ,@body))
>
> (I always use let-binding for operations that involve
> isearch-filter-predicate.)
>
> In some cases, I would like to have something like this:
>
> (with-ifp-predicates '(predicate1 predicate2)
>    (save-window-excursion
>      (occur "foo")
>      (query-replace \"foo\" \"bar\" nil (point-min) (point-max)))) 
>
> with occur showing me only the strings that match the active predicates.
>
> I wrote a mail to emacs-devel@gnu.org and I have verified that others also
> believe that this solution would be helpful and consistent with the
> functioning of some other functions defined in replace.el.
>
> I’d also like to add this feature to the how-many function.
>
> I already wrote this modified version (Emacs 29.2):
>
> (defun re-search-forward-ifp (REGEXP &optional BOUND NOERROR COUNT)
>   "Modified version of `search-forward-regexp' that
>     filters (skips) matches according to `isearch-filter-predicate'."
>
>   (let ((POINT (point)))
>     (catch 'filtered
>       (while (search-forward-regexp REGEXP BOUND NOERROR COUNT)
>         (let ((B (match-beginning 0))
>               (E (match-end 0)))
>           (when (funcall isearch-filter-predicate B E)
>             (throw 'filtered (point)))))
>       (goto-char POINT)
>       nil)))
> (defalias 'search-forward-regexp-ifp 're-search-forward-ifp)

So you rewrote the loop from isearch-search:

	(while retry
	  (setq isearch-success
		(isearch-search-string isearch-string nil t))
	  (if (or (not isearch-success)
		  (funcall isearch-filter-predicate
			   (match-beginning 0) (match-end 0)))
	      (setq retry nil)

But this doesn't answer the question whether and how this could affect
re-search-forward in a non-hackish way.  Adding an option?  Not sure.

> (defun how-many-ifp (regexp &optional rstart rend interactive)
>   "Modified version of `how-many' that filters (skips) matches
>     according to `isearch-filter-predicate'."
>
>   (interactive
>    (keep-lines-read-args "How many matches for regexp"))
>   (save-excursion
>     (if rstart
>         (if rend
>             (progn
>               (goto-char (min rstart rend))
>               (setq rend (max rstart rend)))
>           (goto-char rstart)
>           (setq rend (point-max)))
>       (if (and interactive (use-region-p))
>           (setq rstart (region-beginning)
>                 rend (region-end))
>         (setq rstart (point)
>               rend (point-max)))
>       (goto-char rstart))
>     (let ((count 0)
>           (case-fold-search
>            (if (and case-fold-search search-upper-case)
>                (isearch-no-upper-case-p regexp t)
>              case-fold-search)))
>       (while (and (< (point) rend)
>                   (re-search-forward-ifp regexp rend t))
>         ;; Ensure forward progress on zero-length matches like "^$".
>         (when (and (= (match-beginning 0) (match-end 0))
>                    (not (eobp)))
>           (forward-char 1))
>         (setq count (1+ count)))
>       (when interactive (message (ngettext "%d occurrence"
>                                            "%d occurrences"
>                                            count)
>                                  count))
>       count)))
> (defalias 'count-matches-ifp 'how-many-ifp)

I think duplicating the whole body of functions is not better
than using advice.  An alternative would be to add a new variable
're-search-forward-function' and then to use it like
'(funcall re-search-forward-function)'.





  reply	other threads:[~2024-03-05 16:30 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-04 11:44 bug#69542: Feature request: making occur obey isearch-filter-predicate Gabriele Nicolardi
2024-03-05 16:30 ` Juri Linkov [this message]
2024-03-05 17:11   ` Gabriele Nicolardi
2024-03-06 17:47     ` Juri Linkov
2024-03-08 23:09     ` Gabriele Nicolardi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86msrdnjdn.fsf@mail.linkov.net \
    --to=juri@linkov.net \
    --cc=69542@debbugs.gnu.org \
    --cc=gabriele@medialab.sissa.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

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

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