0

I am looking for a way to count regexp matches across all buffers.

count-matches can count in current buffer. How to count across all buffers?

  • Some users have hundreds of buffers open at any given time. Some users only restart Emacs every few months and they might not even cleanup unused buffers. And, many buffers are hidden/uninteresting buffers that begin with a space in the buffer-name -- you probably do not care about those .... Would you like to limit your search to only some of the open buffers? A common method to loop through buffers would be to use something like dolist, where the list is obtained by calling (buffer-list). – lawlist Aug 6 '19 at 6:35
  • M-x multi-occur-in-matching-buffers or swiped-all – InHarmsWay May 3 at 6:34
1

One possible implementation that allows:

  • specifying the buffer list defaulting to the list of all buffers
  • specifying a filter predicate defaulting to file buffers only
(require 'cl-macs)
(cl-defun count-matches-in-buffers (regexp &key (buffers (buffer-list)) (predicate #'buffer-file-name))
  "Count all matches of REGEXP in BUFFERS filtered by PREDICATE.
BUFFERS defaults to `(buffer-list)`.
PREDICATE defaults to buffers that are associated with files.
Use your own buffer list (buf1 buf2 buf3 ...) by using

(count-matches-in-buffers REGEXP :buffers '(buf1 buf2 buf3 ...))

Apply your own predicate function bound to symbol MY-PREDICATE by calling

(count-matches-in-buffers REGEXP :predicate #'MY-PREDICATE)

Combinations are also possible:

(count-matches-in-buffers REGEXP :buffers '(buf1 buf2 buf3 ...) :predicate #'MY-PREDICATE)

Prompt user for the REGEXP the buffer list BUFFERS and the PREDICATE when called interactively.
The defaults for BUFFERS and PREDICATE are preset.
So the user only needs to press <RETURN> for these two arguments.
"
  (interactive (list (read-regexp "Regexp: ")
             :buffers
             (eval (read-from-minibuffer
                "Buffers (elisp expression): "
                "(buffer-list)"
                nil t
                nil
                "(buffer-list)"))
             :predicate
             (eval (read-from-minibuffer
                "Filter:"
                "#'buffer-file-name"
                nil t
                nil
                "#'identity"))))
  (let
      ((ret
    (cl-loop for buf
         in (cl-remove-if-not predicate buffers)
         sum (with-current-buffer buf
               (save-excursion
             (goto-char (point-min))
             (count-matches regexp))))))
    (when (called-interactively-p 'any)
      (message "Number of matches: %d" ret))
    ret))

Tested with GNU Emacs 26.2 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30) of 2019-04-12.

You can paste this stuff into your init file.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.