Switch to buffer

Oleh Krehel edited this page Apr 11, 2015 · 3 revisions
(defun my/name-of-buffers (n)
  "Return the names of the first N buffers from `buffer-list'."
  (let ((bns
         (delq nil
               (mapcar
                (lambda (b)
                  (unless (string-match "^ " (setq b (buffer-name b)))
                    b))
                (buffer-list)))))
    (subseq bns 1 (min (1+ n) (length bns)))))

;; Given ("a", "b", "c"), return "1. a, 2. b, 3. c".
(defun my/number-names (list)
  "Enumerate and concatenate LIST."
  (let ((i 0))
    (mapconcat
     (lambda (x)
       (format "%d. %s" (cl-incf i) x))
     list
     ", ")))

(defvar my/last-buffers nil)

(defun my/switch-to-buffer (arg)
  (interactive "p")
  (switch-to-buffer
   (nth (1- arg) my/last-buffers)))

(defun my/switch-to-buffer-other-window (arg)
  (interactive "p")
  (switch-to-buffer-other-window
   (nth (1- arg) my/last-buffers)))

(global-set-key
 "\C-o"
 (defhydra my/switch-to-buffer (:exit t
                                :body-pre (setq my/last-buffers
                                                (my/name-of-buffers 4)))
   "
_o_ther buffers: %s(my/number-names my/last-buffers)

"
   ("o" my/switch-to-buffer "this window")
   ("O" my/switch-to-buffer-other-window "other window")
   ("<escape>" nil)))

Pressing C-o activates the hydra with names of the first 4 most recently visited "other" buffers listed:

  • A single o switches to the first buffer in that list, same as what M-:(switch-to-buffer (other-buffer)) would do. In other words, you can quickly switch between two buffers back and forth with C-o o.

  • Prefixed with a numeric prefix, say, 2 o, selects the 2nd buffer from the list, 3 o selects the 3rd, ... Negative prefixes and the numeric prefix 1 are same as no prefix - all select the first buffer.

  • O does the same as o except that the buffer is switched in the "other window" - i.e. by switch-to-buffer-other-window.

In practice, this hydra usually can have more heads to call, for example, ido-find-file, ido-switch-buffer, etc.

If you don't need to visit buffers in the "other window", a variant of this hydra can be:

(global-set-key
 "\C-o"
 (defhydra my/switch-to-buffer (:exit t
                                :body-pre (setq my/last-buffers
                                                (my/name-of-buffers 4)))
   "
other buffers: %s(my/number-names my/last-buffers)

"
   ("o" (my/switch-to-buffer 1))
   ("1" (my/switch-to-buffer 1))
   ("2" (my/switch-to-buffer 2))
   ("3" (my/switch-to-buffer 3))
   ("4" (my/switch-to-buffer 4))
   ("<escape>" nil)))

Then C-o 1 selects the 1st buffer, C-o 2 selects the 2nd, and so on, and still retain the quick C-o o.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.