Homepage: http://www.stat.cmu.edu/~genovese/emacs/win-switch
Author: Christopher Genovese
Updated:
Fast, dynamic bindings for window-switching/resizing
If you use multiple windows in an Emacs frame, you may find yourself moving through the window configuration using `other-window' (C-x o) again and again. Because the order of windows in the window list need not relate intuitively to windows' positions, moving efficiently can require context-specific prefix arguments along the way. The tiring outcome is that navigation through a complex window configuration demands many keystrokes and nontrivial attention. This package is designed to solve that problem. While the `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. 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, execute the following code either directly or 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. Now, when executing a window switch (i.e., hitting C-xo), Emacs enters window switching mode, which lasts until either the user exits the mode or the idle time exceeds the threshold `win-switch-idle-time'. During this override, selected keys move among windows (or frames) or resize the windows. The following keys are bound by default: + i select the window above the current window. + k select the window below the current window. + j select the window left of the current window. + l select the window right of the current window. + o cycle forward through the window list in the current frame. + p cycle backward through the window list in the current frame. + SPACE cycles among existing frames. + u (and RETURN) exit window switching mode. + I and K vertically enlarge and shrink the current window, respectively. + L and J horizontally enlarge and shrink the current window, respectively. + h and ; split the current window, horizontally and vertically, respectively. + ESCAPE acts as an "emergency" exit All other keys exit window switching mode and execute their original function. 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. The default keybindings are designed for fast and intuitve, one-handed operation, but if desired the key bindings can be easily adjusted or reset. Several alternative key configurations are pre-defined (see `win-switch-setup-keys-ijkl', `win-switch-setup-keys-arrow-ctrl', `win-switch-setup-keys-arrow-meta', and `win-switch-setup-keys-esdf' below). The keys also can be rebound in groups via the variables `win-switch--keys' where 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 customize or by using the functions `win-switch-add-key', `win-switch-delete-key', and `win-switch-set-keys'. For example: (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. (Note also that the emergency-exit keys do a hard exit in case of an unexpected error in user-defined code such as in customized feedback functions. This command may be removed in future versions.) At least one exit key must always be defined. Revised bindings can be set in in the hook `win-switch-load-hook' before loading the package. (Also see `win-switch-define-key' for setting general commands in the win-switch keymap, and `win-switch-set-once-key' for setting commands in the once only keymap used by `win-switch-dispatch-once'.) Besides key bindings, the most important customization options are the following: + `win-switch-idle-time' + `win-switch-window-threshold' + `win-switch-other-window-first' + `win-switch-wrap-around' (set via `win-switch-set-wrap-around') The idle time should be set so that one does not have to either rush or wait. (While explicit exit always works, it is nice to have window-switching mode end on its own at just the right time.) This may require some personalized fiddling to find a comfortable value, though the default should be pretty good. The window-threshold and other-window-first control when and if window switching mode is entered. And wrap-around determines if moving across the edge of the frame wraps around to the window on the other side. The other customizable parameters are as follows: + `win-switch-provide-visual-feedback' + `win-switch-feedback-background-color' + `win-switch-feedback-foreground-color' + `win-switch-on-feedback-function' + `win-switch-off-feedback-function' + `win-switch-other-window-function' 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 other-window-function replaces `other-window' for moving between window; the primary motivation is to allow `icicle-other-window-or-frame' under icicles. And four hooks can be set as well: + `win-switch-load-hook' + `win-switch-on-hook' + `win-switch-off-hook' + `win-switch-abort-hook' The following functions are used to set options: + `win-switch-set-wrap-around' + `win-switch-add-key' + `win-switch-delete-key' + `win-switch-set-keys' There are three main entry points for using this functionality + `win-switch-dispatch' (alias `win-switch-mode') + `win-switch-dispatch-once' + `win-switch-dispatch-with' The first is the main function, the second is a prefix command that gives one switch only but allows easy maneuvering in up to five windows with a single keystroke. (The `once' keys can be set using the `win-switch-set-once-keys' command.) The last constructs commands for keybindings that dispatch after some other command. (See `win-switch-setup-keys-arrow' for a nice example of its use.) NOTE: 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 `quick-nav' and `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' mechanisms for this package in a later version. Code Contents 1. (@> "User-Configurable Parameters") 2. (@> "User-Configurable Key Bindings") 3. (@> "Preventing Default Shadowing") 4. (@> "Internal Configuration Data") 5. (@> "Internal Functions and Macros") 6. (@> "Actions and Key Commands") 7. (@> "Customization Initializers and Option Setters") 8. (@> "User Entry Points") 9. (@> "Pre-defined Configurations")