ControlTABbufferCycling

Last edit

Added:

> [new]
> @DrewAdams - In MS Windows, Alt-TAB cycles between apps' open windows, while Ctrl-TAB does the same **within** compliant apps that are capable of opening multiple "windows" (frames). Not sure of the cycle-order, not that relevant since it just whizzes through them all, user just stops when he gets to the one he wants.
> --HansBKK


This page is about buffer-cycling methods that are akin to the ‘Alt-Tab’ cycling of MS Windows.

Perhaps someone could explain just what that means? Does it mean simply showing the next buffer each time some key is pressed? Does it mean also that the “next” buffer is the next most recently used one?

Assuming it means these things, I’ve added Icicles to the list. If that’s not what’s meant, feel free to remove it from the list. In either case, it would be good to get a sentence or two explaining what is meant (that is, what “this page is about”). – DrewAdams

@DrewAdams: C-tab cycling means cycling back and forth your buffer list with Tab and Shift-Tab while keeping Control down. As soon as you release Control, the currently selected buffer becomes your current one, whilst your previous one becomes your most recently used one. As long as you keep Control down, you are in a sort of “cycling mode”. I don’t think such behavior can be achieved in Emacs which sees only isolated C-tab and C-S-tab events, unless some external application tells it when Control has been been released. That’s the reason every package in this page fails to achieve such behavior in a consistent manner. I’m writing such external application, Python-based, Linux-only at the moment, since I lack a MS Windows box. If you wish to help, let me know. – RaffaeleRicciardi

I looks like we’ve got information duplication: see SwitchingBuffers Shouldn’t these pages be merged? CategoryBufferSwitching describes SwitchingBuffers as a discussion/comparison of the various packages.StefanKamphausen

Please merge them and give the code fragments pages on their own. – LennartBorgman

Please do not just merge them. Restructure them if you like, and add cross references and remove redundancy as needed, but each is already plenty long.

But before doing anything, perhaps my question above needs to be answered: just what was this page for? The page title suggests something to do with Control and ALT, but most of the content here is not about that. – DrewAdams

@DrewAdams - In MS Windows, Alt-TAB cycles between apps’ open windows, while Ctrl-TAB does the same within compliant apps that are capable of opening multiple “windows” (frames). Not sure of the cycle-order, not that relevant since it just whizzes through them all, user just stops when he gets to the one he wants. --HansBKK?


Buffer Stack

This is mainly supported on XEmacs, but works in GnuEmacs too.

If you have used “Alt-Tab” in Windows, you know the basic principle behind this buffer model. Your buffers are in a stack, with the most recent on top. When you want a new buffer, you scan through them until you find the one you want, and then it goes on top of the stack.

Features:

LeWang

;;;;;;;;;;;;;;;;;
; buffer-stack ;;
;;;;;;;;;;;;;;;;;

(setq buffer-stack-show-position 'buffer-stack-show-position-buffers)

(autoload 'buffer-stack-down "buffer-stack"  nil t)
(autoload 'buffer-stack-up "buffer-stack"  nil t)
(autoload 'buffer-stack-bury-and-kill "buffer-stack"  nil t)
(autoload 'buffer-stack-bury "buffer-stack"  nil t)
(eval-after-load "buffer-stack" '(require 'buffer-stack-suppl))

(global-set-key [(f10)] 'buffer-stack-bury)
(global-set-key [(control f10)] 'buffer-stack-bury-and-kill)
(global-set-key [(f9)] 'buffer-stack-down)
(global-set-key [(f11)] 'buffer-stack-up)
(global-set-key [(shift f10)] 'buffer-stack-bury-thru-all)
(global-set-key [(shift f9)] 'buffer-stack-down-thru-all)
(global-set-key [(shift f11)] 'buffer-stack-up-thru-all)

PC-BufSw

A fast way to switch buffers working like Ctrl-Tab in Windows applications.

CRS

In windowed environments these days (and even simulated ones like session management on VT terminals, or screen switching in GNU screen), we have become used to the idea that we can have multiple things taking place at once, but usually only one of them commands our attention.

In Emacs, we usually see people with one window in a frame, and to switch to another buffer, we usually use something like C-x b and then type in the buffer we want. People who want to be more efficient about this use things like IswitchBuffers, InteractivelyDoThings, or Icicles to streamline the process and move to the buffer they want quickly.

I doubt, unfortunately, that most people use one window per frame. If you do use one window per frame (as I do), then I think you’re wasting your time if you use ‘bury-buffer’. I haven’t (intentionally) used it for twenty years. If you use one window per frame, you want to just kill buffers or delete their windows; ‘bury-buffer’ gives you nothing but annoying changes to the buffer stack. Unfortunately, some standard Emacs functions call ‘bury-buffer’ – this is one of the things that makes Emacs a bit unfriendly to frames.

See OneOnOneEmacs for enhancements to Emacs that facilitate using it in a one-window-per-frame fashion, including commands to kill buffers and delete associated windows – Delete Frames Easily - But Not Too Easily. – DrewAdams

But our GUI’s often give us an even faster shortcut, especially when switching back and forth between a few related documents. For example, Windows, MacOS, and many X11 window managers bind keys like C-tab and M-tab to switching between windows and/or applications. If one is accustomed to such things, it makes sense to do this in Emacs as well.

In looking through people’s .emacs files, it occurs to me that a lot of people have reinvented this wheel; for something this basic, I think most of us have very specific desires and like to implement this on our own.

A common and fast way of dealing with this problem is to bind C-tab or other key to bury-buffer like so:

    (global-set-key [(control tab)] 'bury-buffer)

This works very well for most people. Hit this key often enough and you will cycle all the way around the list of buffers available.

After a while you might notice some annoyances, though. Temporary buffers that get used by certain Emacs applications may always hover below the surface and get in your way (in my case, I ran across “KILL” quite frequently because Gnus uses that for the killfile, and looks at it while preparing every Summary group that is displayed). In my own quest to work around it, I came up with this:

    ; necessary support function for buffer burial
    (defun crs-delete-these (delete-these from-this-list)
      "Delete DELETE-THESE FROM-THIS-LIST."
      (cond
       ((car delete-these)
        (if (member (car delete-these) from-this-list)
            (crs-delete-these (cdr delete-these) (delete (car delete-these)
                                                     from-this-list))
          (crs-delete-these (cdr delete-these) from-this-list)))
       (t from-this-list)))
    ; this is the list of buffers I never want to see
    (defvar crs-hated-buffers
      '("KILL" "*Compile-Log*"))
    ; might as well use this for both
    (setq iswitchb-buffer-ignore (append '("^ " "*Buffer") crs-hated-buffers))
    (defun crs-hated-buffers ()
      "List of buffers I never want to see, converted from names to buffers."
      (delete nil
              (append
               (mapcar 'get-buffer crs-hated-buffers)
               (mapcar (lambda (this-buffer)
                         (if (string-match "^ " (buffer-name this-buffer))
                             this-buffer))
                       (buffer-list)))))
    ; I'm sick of switching buffers only to find KILL right in front of me
    (defun crs-bury-buffer (&optional n)
      (interactive)
      (unless n
        (setq n 1))
      (let ((my-buffer-list (crs-delete-these (crs-hated-buffers)
                                              (buffer-list (selected-frame)))))
        (switch-to-buffer
         (if (< n 0)
             (nth (+ (length my-buffer-list) n)
                  my-buffer-list)
           (bury-buffer)
           (nth n my-buffer-list)))))
    (global-set-key [(control tab)] 'crs-bury-buffer)
    (global-set-key [(control meta tab)] (lambda ()
                                           (interactive)
                                           (crs-bury-buffer -1)))

You might notice that using a negative number with crs-bury-buffer, as I have bound to C-M-tab, moves backwards on the list. This is nice; when cycling through the list, if you miss it by one, you can cycle backwards and find the buffer you missed.

Note that you will probably have to change things about your GUI to disable the built-in bindings of C-tab. You might want to use a different key for this if you find it easier.

I use Linux, and so the Windows key isn’t generally used. I’ve gone through and replaced Meta with Mod4 for all of my GUI manager’s key maps, that completely frees up Meta for use in Emacs. If you have this luxury, I recommend it. I took some code from TylerBerry? that seems to be based on this, and I’ve extended it to handle regexps. It’s nice especially if you use Tramp. – SamuelTesla

Stesla

 ;; Support functions for `stesla-rotate-buffers'.  From the EmacsWiki.
 (defvar stesla-hated-buffers '("KILL" "*Apropos*" "*Completions*" "*grep*"
                                ".newsrc-dribble" ".bbdb" "sent-mail" "*vc*"
                               "*Compile-Log*" "*Help*" "*Messages*"))       
 (defvar stesla-hated-buffer-regexps '("^ " "*Buffer" "^\\*trace" "^\\*tramp"))
 (setq iswitchb-buffer-ignore (append stesla-hated-buffer-regexps  stesla-hated-buffers))
 (defmacro stesla-buffer-regexp-mapcar (regexp buffers)
  "Find BUFFERS whose name matches REGEXP"
  `(mapcar (lambda (this-buffer)
             (if (string-match ,regexp (buffer-name this-buffer))
                 this-buffer))
           ,(if (symbolp buffers) (symbol-value buffers) buffers)))
 (defmacro stesla-hated-buffer-from-regexps (regexps)
  "Generate a one-dimensional list of buffers that match REGEXPS"
  (append
   '(append)
   (mapcar (lambda (regexp)
             `(delete nil (stesla-buffer-regexp-mapcar ,regexp
                                                       (buffer-list))))
           (if (symbolp regexps) (symbol-value regexps) regexps))))
 (defun stesla-delete-from-list (delete-these from-list)
  "Delete DELETE-THESE from FROM-LIST."
  (cond
   ((car delete-these)
    (if (member (car delete-these) from-list)
        (stesla-delete-from-list (cdr delete-these)
                                (delete (car delete-these) from-list))
      (stesla-delete-from-list (cdr delete-these) from-list)))
   (t from-list)))
 (defun stesla-hated-buffers ()
  "List of buffers I never want to see."
  (delete nil
          (append
           (mapcar 'get-buffer stesla-hated-buffers)
           (stesla-hated-buffer-from-regexps stesla-hated-buffer-regexps))))
 ;; `stesla-rotate-buffers': Like `bury-buffer' but with the capability to
 ;; exclude certain specified buffers.
 (defun stesla-rotate-buffers (&optional n)
  "Switch to the Nth next buffer.  Negative arguments move backwards."
  (interactive)
  (unless n
    (setq n 1))
  (let ((my-buffer-list
         (stesla-delete-from-list (stesla-hated-buffers)
                                 (buffer-list (selected-frame)))))
    (switch-to-buffer
     (if (< n 0)
         (nth (+ (length my-buffer-list) n)
              my-buffer-list)
       (bury-buffer)
       (nth n my-buffer-list)))))
 ;; Windows-style C-TAB and C-M-TAB to switch buffers.
 (global-set-key (kbd "C-<tab>") 'stesla-rotate-buffers)
 (global-set-key (kbd "C-M-<tab>") (lambda ()
                                    (interactive)
                                    (stesla-rotate-buffers -1)))
 ;; This is C-TAB and C-M-TAB for the Linux console.  This requires special
 ;; setup; namely, you need to load a keymap file with /usr/bin/loadkeys
 ;; containing the following lines:
 ;;
 ;; control keycode 15 = Macro
 ;; control alt keycode 15 = Pause
 ;;
 ;; If you actually -have- a key that generates the Macro or Pause keysyms,  you 
 ;; have a better keyboard than I.  For me, this makes Emacs DWIW.  Credit for
 ;; this hack goes to Alex Schroeder.
 (global-set-key (kbd "ESC [ M") 'stesla-rotate-buffers)
 (global-set-key (kbd "ESC [ P") (lambda ()
                                  (interactive)
                                  (stesla-rotate-buffers -1)))
SamuelTesla

Icicles

Command ‘icicle-buffer’ (bound by default to ‘C-x b’) in Icicles lets you use ‘C-next’ and ‘C-prior’ to cycle among your buffers. As the key is pressed, the next buffer appears.

By default, the buffers are cycled in alphabetical order. However, if you use `C-,’ after hitting ‘C-x b’, then you cycle to another sort order – several orders are available. You can alternatively impose a given order by default, by setting or binding user option ‘icicle-sort-comparer’ appropriately.

There are also several user options that control the behavior. For example, you can specify a predicate to satisfy or extra buffers to include as candidates. See Icicles - Buffer-Name Input.

SwBuff and SwBuff-x

With swbuff and swbuff-x together you can easily get a buffer switching that behaves like Alt-Tab in windows. An important addition by swbuff-x is that it reorders the buffers in the same way as Alt-Tab does.

For more info see SwBuff.

Cycbuf

This is a combination of some features of swbuff-x, which is a modification to swbuff and bs.

I really liked the nicely layouted and composed buffer-selection buffer of bs. However, also fast switching buffers with one key-stroke and showing a temporary buffer with a buffer list (with hide timeout) a la swbuff is nice. So I combined both’s advantages.

Ido buffer switching with Control-Tab

nXhtml combines ido-mode buffer switching with Control-Tab buffer cycling. You may also use the arrow keys in the MiniBuffer.

iflipb

iflipb is a lightweight and no-nonsense way of flipping through the most recently used buffers.

mybuffers

Yet another way to do it. It cycles only through the normal text buffers (i.e., excludes special buffers) and visits the most recently used first.

buffcycle

buffcycle.el is a simple Control-Tab way to switch only between file buffers


CategoryBufferSwitching