132

How do I switch between windows quickly?

I often have multiple windows open and need to switch between them. Right now, I use C-x o to get to the one I want. Is there a more efficient workflow available for this?

1

14 Answers 14

81

I obviously prefer ace-window for this. You can switch between visible windows and frames. It's in MELPA, you can install it quickly. The only thing left to do is to bind it:

(global-set-key (kbd "C-x o") 'ace-window)

Or maybe use a shorter key chord, since switching windows is a common task:

(global-set-key (kbd "M-p") 'ace-window)

Summary of ace-window

It's a drop-in replacement for other-window. Unlike the latter, you never have to call ace-window two or more times to select a window: you select a window you want in one call (possibly across multiple frames).

Besides switching windows, ace-window can do more (delete or swap windows, etc), see README.

6
  • 2
    This is interesting. I used ace-window and then saw switch-window which seems to do roughly the same thing, except that the letters are more pronounced. seems funny we have both packages. Commented Jan 23, 2015 at 17:16
  • You're right. There are only small differences between them. This is an issue that we have to face when we have a repository with 2000 packages. I wasn't aware of switch-window until I submitted ace-window to MELPA.
    – abo-abo
    Commented Jan 23, 2015 at 17:25
  • 1
    thanks for ace-window, it has more customization than other packages I guess. Still one might be of help in the future is a key binding to a function that would in a similar way to the smart swap action but eat up that window resulting in having a larger window at point and a smaller in size chosen window (the eaten up window). The ratio should be determined in this case as one half, one fourth, or one third may be.
    – doctorate
    Commented Feb 16, 2016 at 17:37
  • 5
    Please consider adding a description. You just say that you like it, and you link to it. That makes this essentially a link-only answer.
    – Drew
    Commented Feb 20, 2016 at 2:45
  • 5
    What's the benefit of ace-window? Why should I use it over the 14 other solutions proposed on this page? Commented Oct 15, 2017 at 17:17
152

One way is to use windmove. With its default keybindings, it allows switching to the window next to the currently active one.

It's built in Emacs, so there is no need to install anything; just activate it with the following minimal setup in your init file:

(windmove-default-keybindings)

You can then switch to neighbouring windows using the following keys (where the arrow used intuitively defines the direction in which you move): S-<left>, S-<right>, S-<up>, S-<down>.


If you'd prefer using another modifier instead of shift, you can provide it as an argument to windmove-default-keybindings. For example:

(windmove-default-keybindings 'meta)

or

(windmove-default-keybindings 'control)

More info at Emacs Wiki.

9
  • 28
    This should be the accepted answer !
    – rowman
    Commented Feb 17, 2015 at 10:26
  • 2
    OMG, why does no tutorial mention shift + arrow keys to move around window! Its so much better then ctrl + o
    – Didier A.
    Commented Mar 7, 2018 at 2:33
  • I'd say some of the other answers here contain redundant windmove configuration. Perhaps it's worth updating the answer to mention that the function accepts the modifier key as an argument e.g. (windmove-default-keybindings 'meta) as suggested on EmacsWiki.
    – user66
    Commented Aug 9, 2018 at 0:07
  • 1
    This creates lot of conflict with other keybinding (or with window managers). I prefer ace-window.
    – azzamsa
    Commented Sep 22, 2018 at 3:11
  • I'm using something alike (I'm moving around with Shift-arrow), but when you have a big monitor with lots of splits, such a movement quickly becomes unwieldy. It'd be more interesting to somehow enumerate windows/splits. Like ace-window, but with less key-presses, and an obvious algorithm to immediately figure out the number you want.
    – Hi-Angel
    Commented Oct 22, 2018 at 13:45
33

You can bind other-window to an easier-to-type key sequence.

For example, I have C-. bound to other-window, and C-, bound to go to the previous window.

(global-set-key (kbd "C-.") #'other-window)
(global-set-key (kbd "C-,") #'prev-window)

(defun prev-window ()
  (interactive)
  (other-window -1))

This is especially useful for moving multiple windows; once you hold down Control, you only have to press a single button to move to the next window. This is much easier than three keypresses per move.

9
  • 4
    +1 C-x o for other-window is one of a few solid contenders for the title of "worst default emacs shortcut". My solution (similar to zck) was to rebind other window to a (way) easier key sequence - I have it bound to C-; (and my Caps-Lock is swapped with Ctrl so all it takes is a quick tap of the pinkies). Btw, I'm totally dependent on certain features of helm and icicles (i.e., I'm not "anti-packages" or anything); I just think that a simple solution works best here.
    – iceman
    Commented Nov 13, 2014 at 3:43
  • 3
    +1 This should be the accepted answer AND the most simple answer too (alas, no such thing yet exists on StEx). Works out of the box, scales perfectly, simple to memorize. The latter I found especially important in the Emacs jungle. After surviving there 20+ years, sometimes I find myself yearningly lurking at the vi desert... Commented Jul 4, 2015 at 8:20
  • Simple, easy to use, easy to implement. This needs more votes. Commented Feb 3, 2016 at 16:39
  • 3
    This is also what I do. I use M-o for other-window. Some modes already have M-o binding, notably diff-mode, ggtag-mode, and ibuffer-mode. You have to manually unbind it in each mode map. unbind-key provided by bind-key.el is very useful. Commented Dec 6, 2016 at 3:56
  • I use M-o as well, and have M-O bound to ace-window for when I need the additional power.
    – glucas
    Commented Sep 15, 2017 at 13:13
15

Some people may remember the editor Brief (funnily enough produced by a company called Underware).

It had a neat way to switch between visible windows. M-arrow would move the cursor into the window directly in line with the direction of the arrow key.

So, I mapped the winmove-left, winmove-right, winmove-up and winmove-down functions to M-left, M-right, M-up and M-down keys as follows in my .emacs file -

(global-set-key [M-left] 'windmove-left)          ; move to left window
(global-set-key [M-right] 'windmove-right)        ; move to right window
(global-set-key [M-up] 'windmove-up)              ; move to upper window
(global-set-key [M-down] 'windmove-down)          ; move to lower window

Now I can move with ease between windows, regardless of how cluttered I have the configuration... And it can get quite cluttered with the size of displays nowadays...

3
  • Isn't this more or less @Francesco's answer?
    – Dan
    Commented Nov 13, 2014 at 11:16
  • I agree. I did not notice before I posted mine.
    – user2542
    Commented Nov 13, 2014 at 11:21
  • 5
    A much shorter way to get those keybindings is (windmove-default-keybindings 'meta)!
    – Omar
    Commented Aug 4, 2018 at 6:28
14

window-numbering.el !

I assign the hotkey ",1", ",2", ",3" to switch specific window (please note I use evil-mode)

besides, I display the window number at the mode line in PINK color, underlined.

It's a visual hint you can never ignore,

That's quickest way to switch window.

check https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-evil.el and https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-modeline.el for my setup.

Sylvain Benner adopted my idea in spacemacs but keybindings are different. So if you use spacemacs, you get the quickest solution out of the box.

3
  • 2
    Yup. This concept is great. I use package window-number with M-<num> to quickly switch b/w windows. Similar concept to this one
    – mike3996
    Commented Nov 13, 2014 at 10:14
  • 1
    Note that window-numbering.el is deprecated in favor of winum, which is here. FWIW the window-numering for me didn't even work.
    – Hi-Angel
    Commented Oct 23, 2018 at 7:58
  • I might switch to winum soon. But window-numbering still works fine on emacs24/25/26.
    – chen bin
    Commented Oct 24, 2018 at 4:17
13

Without using any additional add-ons, you can continue to use C-x o with an optional prefix to skip over that many windows. Eg: C-u 1 C-x o will go to the next window in the order (ie, what you would get with plain C-x o), C-u 2 C-x o goes two windows over, C-u 3 C-x o goes three windows over, and so on.

An excerpt from the other-window docstring (the function called by C-x o:

COUNT specifies the number of windows to skip, starting with the selected window, before making the selection. If COUNT is positive, skip COUNT windows forwards. If COUNT is negative, skip -COUNT windows backwards. COUNT zero means do not skip any window, so select the selected window. In an interactive call, COUNT is the numeric prefix argument. Return nil.

4
  • When you have multiple windows what order do they follow?
    – stsquad
    Commented Nov 12, 2014 at 22:10
  • The order is the cyclic window ordering.
    – Dan
    Commented Nov 12, 2014 at 23:11
  • 4
    hmm "The ordering is determined by a depth-first traversal of the frame's window tree, retrieving the live windows which are the leaf nodes of the tree" isn't the most helpful description for the human brain trying to guess which window is next or how many to skip. I guess this is why I use ace-window.
    – stsquad
    Commented Nov 13, 2014 at 10:52
  • 2
    @stsquad: oh, I agree with you -- it makes my head spin, too. I put this answer up here for the sake of completeness.
    – Dan
    Commented Nov 13, 2014 at 11:03
7

If you use Icicles then C-x o lets you select windows by name (or by cycling).

  • With no prefix arg, C-x o is the same as usual, other-window, unless the frame has only one window, in which case it is other-frame.

  • With a prefix arg, C-x o is a multi-command that lets you navigate among windows or frames by name (or by cycling). Navigating among windows uses multi-command icicle-select-window; navigating among frames uses icicle-select-frame.

Which navigation is used depends on the prefix arg:

  • Zero prefix arg (e.g. C-0): If the selected frame has multiple windows, then this is icicle-select-window, with windows in the same frame as candidates. Otherwise (single-window frame), this is icicle-select-frame.

  • C-u: If the selected frame has multiple windows, then this is icicle-select-window, with windows from all visible frames as candidates. Otherwise, this is icicle-select-frame.

  • C-u C-u: icicle-select-window, with windows from all frames as candidates (including iconified or hidden frames).

As always in Icicles, you can combine (a) completion, typing text to narrow the set of matching candidates (window or frame names, in this case), with (b) cycling (among matching candidates).

4

Consider using a key-chord for quickly jumping between windows. I find it much quicker than reaching for a modifier key(and less straining on my hands, as well).

My choice of package to use is ace-window, which lets you navigate multiple windows easier than just other-window.

(require 'key-chord)
(key-chord-define-global "xo" 'ace-window)
(key-chord-mode +1)

Obviously to use this you need key-chord and ace-window, both are available in melpa.

5
  • 2
    Isn't this more or less @abo-abo's answer?
    – Dan
    Commented Nov 13, 2014 at 11:06
  • 1
    @Dan his doesn't use key-chord, note the lack of meta or super keys in the chord. Wether you use ace-window/something else is a bit irrelevant, the point was to give an answer that doesn't use modifier keys for so commonly used operation.
    – Zavior
    Commented Nov 13, 2014 at 11:54
  • 1
    I saw that, but I raised the question because ace-window is doing the work as in @abo-abo's answer. It strikes me that, in this context, the specific keybinding to use would make more sense as a comment rather than an answer. Just my two cents.
    – Dan
    Commented Nov 13, 2014 at 12:03
  • @Dan, overall the question was about quickly switching the windows, and I do not think this solution has been brought up yet. Clarified the answer a bit in regards to that.
    – Zavior
    Commented Nov 13, 2014 at 12:19
  • @Zavior raises an important point. The question is about switching windows quickly- for which the form of the binding is very important. Regardless of the library you prefer key-chord allows binding very accessible combinations of keys. The example binding of xo is faster than C-x o (depth of one versus two). This answer could be reworded to emphasize that the answer is orthogonal to the other answers about function selection (and ace-window is just one of many choices that could be bound in the described fashion). Keep this answer as distinct!
    – ebpa
    Commented Jan 6, 2016 at 2:51
4

Some good answers here, I also am a fan of WinMove, but I bind it to C- because org-mode uses M- for manipulating headings

(define-key global-map (kbd "C-<up>") 'windmove-up)
(define-key global-map (kbd "C-<down>") 'windmove-down)
(define-key global-map (kbd "C-<left>") 'windmove-left)
(define-key global-map (kbd "C-<right>") 'windmove-right)

Where it gets really good is if you combine it with Hydra. Following the examples on their wiki I created my own monster:

(defhydra hydra-windows ()
  "C-arrow = switch, S-arrow = size, M-arrow = move"
  ("C-<left>" windmove-left nil)
  ("C-<right>" windmove-right nil)
  ("C-<up>" windmove-up nil)
  ("C-<down>" windmove-down nil)
  ("S-<left>" hydra-move-splitter-left nil)
  ("S-<right>" hydra-move-splitter-right  nil)
  ("S-<up>" hydra-move-splitter-up nil)
  ("S-<down>" hydra-move-splitter-down nil)
  ("M-<left>" buf-move-left nil)
  ("M-<right>" buf-move-right nil)
  ("M-<up>" buf-move-up nil)
  ("M-<down>" buf-move-down nil)
  ("p" previous-buffer "prev-buf")
  ("n" next-buffer "next-buf")
  ("1" delete-other-windows "1")
  ("d" delete-window "del")
  ("k" kill-buffer "kill")
  ("s" save-buffer "save")
  ("u" (progn (winner-undo) (setq this-command 'winner-undo)) "undo")
  ("r" winner-redo "redo")
  ("b" helm-mini "helm-mini" :exit t)
  ("f" helm-find-files "helm-find" :exit t)
  ("|" (lambda () (interactive) (split-window-right) (windmove-right)))
  ("_" (lambda () (interactive) (split-window-below) (windmove-down)))
  ("q" nil "cancel")
  )

(global-set-key (kbd "M-#") 'hydra-windows/body)

This lets me change windows, resize them, move buffers from window to window, cycle buffers, kill buffers and even undo window configurations via winner-mode, and it also integrates helm. To exit the hydra, just press arrow or some other key not in the hydra. You can find the "hydra-move" functions on the hydra examples The great thing about hydra is I don't have to remember all those keybindings and its "modeful", so once you are in the hydra everything is available as a single key press.

2
  • 2
    A shorter way to get the keybindings you mention at the beginning is (windmove-default-keybindings 'control).
    – Omar
    Commented Aug 4, 2018 at 6:30
  • Nice answer and @Omar comment is nice also.
    – NAND
    Commented Apr 20, 2020 at 4:51
3

If you use evil-mode, you can just use a numeric prefix with C-w C-w (evil-window-next) to pick the window you want. So: 1 C-w C-w picks the first window in cyclic order, 3 C-w C-w picks the third window in cyclic order, and so forth.

1
  • This seems like it should just be combined with your other answer: it's the same thing, just with evil-specific bindings.
    – npostavs
    Commented May 5, 2019 at 14:06
1

Ace Jump lets you navigate your pointer to all words on a screen, regardless of what window or frame they're in, so it's not so different from using Ace Window or Switch Window.

An advantage could be that while jumping windows you can also place your pointer with some precision.

I still find it a little cumbersome or distracting, and find I'm using windmove more, because it's very simple, but still use Ace Jump when I've been reading in another window or frame and want to move to a spot there.

1

As usual there are a hundred different ways to accomplish this. My preferred way is using NumberedWindows. I then set the following keybind using Super and keys 1-9.

(global-set-key (kbd "s-1") (lambda() (interactive) (window-number-select 1)))

I go into a little more detail on this exact subject with a recent post of mine which you can read on Afternoon Coder.

2
1

Windows are given by window-list. Use select-window to select a window. For example, assuming there are at least 3 windows, use `M-:` to run the following:

;; Select the 3rd window in the `window-list'
(select-window (nth 2 (window-list)))

It's fundamentally as simple as that :)

Obviously, raw calls to window-list and select-window don't make for a great user experience. We probably want the following properties (at least):

  1. regularity
  2. interactivity
  3. visual cues

1. Regularity

The window-list function returns a list of windows in some unspecified order (as of this writing). It would be nice if the list had the same order every time we referenced it.

Use the WINDOW parameter to start the list at a specific window. Here, we use window-at to make the list always relative to the top left window.

;; Create a window list ordered from the top left window
(window-list nil nil (window-at 1 1))

This allows us to create direct key-bindings, assuming the layout is always the same. For example, if you always do C-x 3 C-x 2 M-x other-window M-x other-window C-x 2 to get 4 windows then the following jump directly to each window.

;; Select the 1st window counter clock-wise from the top left
(global-set-key (kbd "C-x w 1") '(lambda () (interactive) 
  (select-window (nth 0 (window-list nil nil (window-at 1 1))))))

;; Select the 2nd window counter clock-wise from the top left
(global-set-key (kbd "C-x w 2") '(lambda () (interactive) 
  (select-window (nth 1 (window-list nil nil (window-at 1 1))))))

;; Select the 3rd window counter clock-wise from the top left
(global-set-key (kbd "C-x w 3") '(lambda () (interactive) 
  (select-window (nth 2 (window-list nil nil (window-at 1 1))))))

;; Select the 4th window counter clock-wise from the top left
(global-set-key (kbd "C-x w 4") '(lambda () (interactive) 
  (select-window (nth 3 (window-list nil nil (window-at 1 1))))))

2. Interactivity

Maybe you use several layouts. We can use interactive to make the command callable with M-x. When the prompt starts with an n, it expects a number:

(defun my-select-window (n)
  "Select window N from the list of windows ordered
counter-clockwise from the top left starting with 0."
  (interactive "nSelect window: ")
  (select-window (nth n (window-list nil nil (window-at 1 1)))))

This isn't the most user friendly. However, it's version 2.0 of our Minimal Viable Product. Maybe it's good enough.

3. Visual cues

Lists in Emacs Lisp are indexed starting at 0. The first window listed by window-list is (nth 0 (window-list)). The second window is (nth 1 (window-list)). And so on.

Using window-list directly requires knowing that windows are indexed starting with 0 and that they proceed counter-clockwise from the top left.

We can give users a visual cue about which window is which by creating a buffer over each window that shows the corresponding number. This function does that.

(defun my-select-window--display-number-buffer (win num)
  "Create a new buffer in WIN displaying NUM."
  (let ((buf (get-buffer-create (format "*%s*" num))))
    (with-current-buffer buf
      (insert (number-to-string num)))
    (set-window-buffer win buf)
    buf))

You can try it out like this:

(my-select-window--display-number-buffer
 (select-window (nth 0 (window-list)))  ; get the 0th window
 0                                      ; display 0 in a buffer there
 )

Unfortunately for us, the interactive function is the first thing called in a function. This prevents us from displaying the number buffers before the prompt is given.

We can work around this by using read-number (which is what interactive uses behind the scenes).

(defun my-select-window--ordered-window-list ()
  "Return `window-list' ordered according to top left window."
  (window-list nil nil (window-at 1 1)))

(defun my-select-window--display-number-buffer (win num)
  "Create a new buffer in WIN displaying NUM."
  (let ((buf (get-buffer-create (format "*%s*" num))))
    (with-current-buffer buf
      (insert (number-to-string num)))
    (set-window-buffer win buf)
    buf))

(defun my-select-window (&optional n)
  "Select Nth window from the list of windows ordered
counter-clockwise from the top left starting with 0."
  (interactive)
  (let ((num 1)
        overlay-buffers)
    ;; display visual cues
    (dolist (win (my-select-window--ordered-window-list))
      (push (my-select-window--display-number win num) overlay-buffers)
      (setq num (1+ num)))

    ;; prompt user for selection
    (select-window
     (nth
      (1- (or n (read-number "Select window: "))) ; correct index
      (my-select-window--ordered-window-list)))
    ;; remove visual cues
    (mapc 'kill-buffer overlay-buffers)))

Note: An expression like (or n 2) says, "If n exists, use it, otherwise, use 2". This is because or stops and returns its first non-nil argument.

Conclusion

This is a minimal, yet surprisingly useful way to switch windows. Some features you might also want would be:

  • reset windows on cancel (with C-g)
  • the ability to call from Lisp without drawing the overlays
  • act like other-window when there are only two windows
  • select the window immediately, without needing to press return

The following does these:

(defun my-select-window--ordered-window-list ()
  "Return `window-list' ordered according to top left window."
  (window-list nil nil (window-at 1 1)))

(defun my-select-window--display-number (win num)
  "Create a new buffer in WIN displaying NUM."
  (let ((buf (get-buffer-create (format " *%s*" num))))  ; space intentional, see documentation
    (with-current-buffer buf
      (insert (concat "\n\n    " (number-to-string num)))
      (text-scale-increase 5))
    (set-window-buffer win buf)
    buf))

(defun my-select-window-1 (n)
  "Select window N from the list of windows ordered
counter-clockwise from the top left starting with 1."
  (cond ((< n (length (window-list)))
         (select-window (nth n (my-select-window--ordered-window-list))))))

(defun my-select-window (&optional n display-numbers)
  "Select Nth window numbered 1 through 9.

Windows are numbered starting at 1 and increase
counter-clockwise.

Show window numbers when DISPLAY-NUMBERS t (default).  If N is
given, window numbers are not displayed."
  (interactive)
  (let ((display-numbers (if n nil (or display-numbers t)))
        (num 1)
        (n (if n (1- n))) ; convert base-1 to base-0
        overlay-buffers)

    (if (< (length (window-list)) 3)
        (other-window 1)
      (unwind-protect
          (progn
            (if display-numbers
                (dolist (win (my-select-window--ordered-window-list))
                  (push (my-select-window--display-number win num) overlay-buffers)
                  (setq num (1+ num))))

            ;; read event to avoid needing to press return
            (while (not n)
              (let ((input (read-event "Select window: " nil 5)))
                (unless (symbolp input)
                  (if (and (<= 47 input) (>= 57 input))  ; 1 to 9 in ASCII
                      ;; convert ASCII to corresponding number and
                      ;; convert to base-0
                      (setq n (- (- input 48) 1)))))))

        (if display-numbers
            (mapc 'kill-buffer overlay-buffers)))
      (my-select-window-1 n))))

You can then map that C-x o:

(global-set-key (kbd "C-x o") 'my-select-window)

Since we made the function callable from Lisp, we can create keys for each window:

(global-set-key (kbd "C-x w 1") '(lambda () (interactive) (my-select-window 1)))

PS: To give credit where due, this is basically how switch-window.el works. This post is based off commit 4a19d5b8 with my own modifications.

PPS: In case you don't know, use Control+h f (C-h f) to see the documentation for a function and Control+h v (C-h v) for variable documentation.

Happy hacking! :)

-1

You can also decide to use switch-window as a visual replacement for C-x o

3
  • 1
    What's the benefit of switch-window? Why should I use it over the 14 other solutions proposed on this page? Commented Oct 15, 2017 at 17:20
  • How says you should ? Emacs is all about alternatives, customisation and freedom to decide.
    – csantosb
    Commented Feb 14, 2018 at 8:35
  • 2
    That's neither here nor there. Why would someone pick this particular alternative? Why would one decide to use switch-window over all the others? Commented Feb 14, 2018 at 19:51

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