When window switching mode is on, window movement and resizing commands are bound to simple keys that can be quickly pressed with one hand. (Additional keys allow resizing, splitting, and deleting windows.) Any other key sequence ends window switching and executes its original function. (Window switching is also exited with an explicit command key or after a preset idle time.) With this in place, navigating among complicated window configurations can happen seamlessly with minimal movement or fuss.
One wonderful efficiency feature in Emacs is the ability to divide the current view into disjoint rectangular panels (called windows in Emacs terminology) that can be seen and manipulated simultaneously.fn1 Taken together, Emacs windows and buffers provide a much more versatile and efficient interface than tabbed browsing or similar designs.
It is not uncommon for people to keep four to six or more windows in a frame. But when you use multiple windows in this way, you may frequently find yourself moving among the windows using
C-x o) again and again – an unpleasantly large number of keystrokes for so common a maneuver. And because the order of windows in the window list need not relate intuitively to windows’ visual positions, moving more efficiently requires context-specific prefix arguments along the way. The tiring outcome is that navigation through a complex window configuration demands many keystrokes and/or nontrivial attention. This package is designed to solve that problem.
‘windmove’ package provides functions for moving intuitively among windows, the natural key bindings for these functions (e.g., the arrow keys with some modifier) require a distant and thus inefficient hand movement. Moreover, one often wants to mix a variety of window-based operations (other-window, previous-window, directional movement, resizing) in rapid succession, which windmove does not easily support.
This package builds on the windmove functionality by defining a command
win-switch-dispatch that engages a dynamic, transient keyboard override, allowing one to efficiently move among defined windows (and frames) – and even resize, split, delete them – with minimal fuss and effort. When the override is engaged, the movement and resizing commands are bound to simple keys that can be pressed quickly with one hand. The override ends either when the user exits explicitly or after a configurable idle time threshold. The happy outcome is fast and seamless navigation.
To use the package, download Lisp:win-switch.el and place it somewhere in your load path.fn2 (You can also obtain the package through
package.el from the Marmalade repository.) Then, execute the following code either directly or from in your .emacs file:
(require 'win-switch) (global-set-key "\C-xo" 'win-switch-dispatch)
or use whatever keybinding you ordinarily have set to
‘other-window’. Alternatively, you can use one of a variety of predefined configuration commands, as in
(require 'win-switch) (win-switch-setup-keys-ijkl "\C-xo")
which has the same effect as the above. In fact, the latter approach is preferred somewhat as it makes it easier to explore other configurations or bindings. See WinSwitchConfig below.
At this point, when you execute a window switch (i.e., hit C-x o), Emacs will (typically) enter window switching mode allowing you to navigate among the windows (and frames). This is described in more detail in the next section.
When executing the
win-switch-dispatch command, Emacs’s behavior depends on the win-switch parameter settings and the current window configuration. Under the default settings, when there are three or more windows, Emacs will enter window switching mode. This temporarily overrides all key bindings, with selected keys moving among the windows (or frames) and resizing, splitting, or deleting the current window. Window switching lasts until either the user exits explicitly (in one of two ways) or idle time exceeds the threshold in the variable
win-switch-idle-time. Whenever possible, visual feedback is provided to indicate the window switching state. The following keys are bound by default during window switching mode:
win-switch-idle-timewill exit window switching mode (like u does)
*C-M-g*is an “emergency” exit fn3
These keys are chosen to make one-handed navigation fast and easy. It is worth re-emphasizing that any key not bound to a win-switch command exits window switching mode and executes its original function. This is the most common way to exit window switching mode: just do what you want to do in the current window and it will be done. An explicit exit is only required when the first key in the current window is one of the win-switch commands, which should be relatively rare.
By default, window selection wraps around when moving across a frame edge and window switching mode is forgone when there are only two windows. But these features, the key bindings, and other parameters can all be customized, either with the customization facility or with defvar and setter functions, as described in the next section.
The default keybindings are designed for fast and intuitve, one-handed operation, but if desired the key bindings can be easily adjusted or reset. There are several pre-defined key configurations; the key-bindings can be set via the customization mechanism; and there are several functions for modifying the keys associated with particular commands.
win-switch-dispatch, as in
(win-switch-setup-keys-ijkl "\C-xo" "\C-x\C-o")
The command keys also can be rebound in groups via the variables with names =win-switch-<name>-keys= where =<name>= can be one of up, down, left, right, next-window, previous-window, enlarge-vertically, shrink-vertically, enlarge-horizontally, shrink-horizontally, other-frame, exit, split-vertically, split-horizontally, delete-window, or emergency-exit. These variables should not be set directly, but rather should be set either by the customize mechanism, or by using the functions described below.
Several functions are available for adjusting the key lists associated with a particular win-switch command. These are
win-switch-set-keys, which as the names suggest add and delete a key and set the key list, respectively. These functions take a key (or key-list in the latter case) and a command symbol, where the command symbol is one of up, down, left, right, next-window, previous-window, enlarge-vertically, shrink-vertically, enlarge-horizontally, shrink-horizontally, other-frame, exit, split-vertically, split-horizontally, delete-window, or emergency-exit. They are used as follows:
(win-switch-add-key "O" 'previous-window) (win-switch-delete-key "p" 'previous-window) (win-switch-set-keys '(" " "," "m") 'other-frame)
Note that the last arguments here are win-switch commands not elisp functions. At least one exit key must always be defined.
win-switch-define-key is also available for setting general commands in the win-switch keymap, but the other key setting functions and methods are certainly preferred when applicable.
If key bindings are not set by the customize mechanism, they can be set in in the hook
win-switch-load-hook before loading the package.
win-switch-dispatch-once is a prefix command/keymap that can be used in place of the standard
win-switch-dispatch command. This accepts a single win-switch command, by default using the same keybindings as standard win-switch (excluding the exit keys), and gives one switch. There are two additional groups of keys
double-previous-window which cycle forward and backward two windows in the list. While not as flexible as window switching mode, the once-dispatch allows easy maneuvering in up to five windows with a single key stroke. The once command keys can be set with either the customize mechanism or the
win-switch-dispatch-with accepts an elisp command and produces a new command that first executes the given command and then
win-switch-dispatch. It can be used to create dispatch commands with customized initial behavior. See
win-switch-setup-keys-arrows for an example.
Besides key bindings, the most important customization options are the following:
win-switch-dispatchenters window-switching mode unconditionally; otherwise, it acts like
win-switch-authors-configurationfor an example.
other-window. One application of this parameter is when win-switch is used with packages like icicles that remap the other-window function (see
icicle-other-window-or-frame). If nil, the default,
The other customizable parameters control how win-switch mode gives feedback indicating whether window switching is engaged.
The feedback mechanisms are intended to make it salient when window switching mode is on or off and can be customized at several scales. The default method changes the colors on the mode line in the current window during window switching mode (restoring them after), along with transient messages in the echo area.
Finally, three hooks are available to change settings or behavior at load time, when window switching turns on, and when window switching turns off. Extra care should be taken to handle errors properly in the latter two, if they are used.
The associated package Lisp:ws-tests.el in the same repository contains a framework for automated testing of win-switch. Load the package and execute the comand
ws-test-run-all within emacs, i.e. do
M-x ws-test-run-all. (There are other ways to run tests in the framework but that is the simplest.) It might be a good idea to manually increase the frame size above the small default initial size before running the tests. A report on the test results will then come up, typically in its own frame. If there are any failures, instructions for reporting tne tests will be given. Please copy the test report and provide as much information as you can about your platform, emacs setup, and ideally your emacs init file. New tests will be added over time.
If when using Lisp:win-switch.el, you encounter any problems, anomalies, or curiosities, please report them to me at
*firstname.lastname@example.org*, along with information about your platform, emacs version, and emacs initialization. In addition, feel free to send me feature requests to the same address. In both cases, I would appreciate if you would include “win-switch” on the subject line.
win-switch is not a formal major or minor mode, more of an overriding mode. This started as a way to explore dynamic keybindings, an idea that is generalized considerably in my packages
power-keys. The latter introduces some programming abstractions that can be used to easily install dynamic keymaps of several flavors. I plan to use the
power-keys.el mechanisms for this package in a later version.
The code is also available from github.
fn1 There is an unfortunate conflict in terminology between Emacs and traditional window systems. An Emacs frame corresponds to a window in a traditional window system. An Emacs window is a panel within a frame that displays a buffer. There is no direct analog to windows and buffers in standard window systems, though tabbed browsing is perhaps the closest common approach. I will use Emacs terminology in what follows. fn1Back
fn3 The emergency exit key causes a no-frills escape from window switching mode in case of an unexpected error during a user defined function or hook (as a customization option) called during window switching mode. This is a paranoid precaution only, and you are very unlikely to need this. Use only as a last resort because it does not handle feedback or other clean up mechanisms. This functionality may be removed in future versions. fn3Back