bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#69542: Feature request: making occur obey isearch-filter-predicate


From: Gabriele Nicolardi
Subject: bug#69542: Feature request: making occur obey isearch-filter-predicate
Date: Mon, 4 Mar 2024 12:44:48 +0100
User-agent: Mozilla Thunderbird

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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]