Hi,
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)
(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)
Best regards,
Gabriele Nicolardi