in Helm I ignore some buffers from showing when using C-x b
, I'm looking for a way to make the commands previous-buffer
and next-buffer
behave the same ignoring some buffers.
Here are two ways:
If you take a look at the definition of function
switch-to-next-buffer
(in librarywindow.el
) you will see that it filters the buffers by the predicate (if any) that is the value of frame parameterbuffer-predicate
. That function is used bynext-buffer
.You can set that frame parameter to a predicate that filters the way you want.
You can simply advise function
switch-to-next-buffer
to filter the way you want. You will essentially replace its definition by almost the same definition, but filter additionally the way you want.
Similarly for switch-to-previous-buffer
.
(defcustom my-skippable-buffers '("*Messages*" "*scratch*" "*Help*")
"Buffer names ignored by `my-next-buffer' and `my-previous-buffer'."
:type '(repeat string))
(defun my-change-buffer (change-buffer)
"Call CHANGE-BUFFER until current buffer is not in `my-skippable-buffers'."
(let ((initial (current-buffer)))
(funcall change-buffer)
(let ((first-change (current-buffer)))
(catch 'loop
(while (member (buffer-name) my-skippable-buffers)
(funcall change-buffer)
(when (eq (current-buffer) first-change)
(switch-to-buffer initial)
(throw 'loop t)))))))
(defun my-next-buffer ()
"Variant of `next-buffer' that skips `my-skippable-buffers'."
(interactive)
(my-change-buffer 'next-buffer))
(defun my-previous-buffer ()
"Variant of `previous-buffer' that skips `my-skippable-buffers'."
(interactive)
(my-change-buffer 'previous-buffer))
(global-set-key [remap next-buffer] 'my-next-buffer)
(global-set-key [remap previous-buffer] 'my-previous-buffer)
Or if you wanted to ignore buffer names matching a pattern, you could use this variant.
(defcustom my-skippable-buffer-regexp
(rx bos (or "*Messages*" "*scratch*" "*Help*") eos)
"Matching buffer names are ignored by `my-next-buffer'
and `my-previous-buffer'."
:type 'regexp)
(defun my-change-buffer (change-buffer)
"Call CHANGE-BUFFER until `my-skippable-buffer-regexp' doesn't match."
(let ((initial (current-buffer)))
(funcall change-buffer)
(let ((first-change (current-buffer)))
(catch 'loop
(while (string-match-p my-skippable-buffer-regexp (buffer-name))
(funcall change-buffer)
(when (eq (current-buffer) first-change)
(switch-to-buffer initial)
(throw 'loop t)))))))
(defun my-next-buffer ()
"Variant of `next-buffer' that skips `my-skippable-buffer-regexp'."
(interactive)
(my-change-buffer 'next-buffer))
(defun my-previous-buffer ()
"Variant of `previous-buffer' that skips `my-skippable-buffer-regexp'."
(interactive)
(my-change-buffer 'previous-buffer))
(global-set-key [remap next-buffer] 'my-next-buffer)
(global-set-key [remap previous-buffer] 'my-previous-buffer)
For the example from the comments, to tell this latter version to also skip all buffer names beginning with helm
, we could use:
(setq my-skippable-buffer-regexp
(rx bos (or (or "*Messages*" "*scratch*" "*Help*")
(seq "helm" (zero-or-more anything)))
eos))
-
-
-
-
With the current updated code it works without a problem. If I add new patterns would I just add
(seq "patter" (zero-or-more anything)
line? – alper Aug 10 '20 at 1:19 -
1You can do, but I would suggest using
(seq (or "helm" "foo" "bar") (zero-or-more anything))
to match a variety of prefixes. – phils Aug 10 '20 at 1:43