Allow the Terminal.app to pass command key based keystrokes to terminal programs
I want to allow programs running in the terminal the ability to interpret the keyboard short cut Cmd + S
I have already Remapped the Terminals' default binding of Cmd + S to Ctrl + S via the Keyboard System Preferences in OS X Lion, so this has stopped the Terminal App itself from interpreting that key press, e.g. the save dialog no longer comes up when pressing Cmd + S . However something is still grabbing the key input before any terminal program can.
For example when running bash typing Cmd + S in the X11.app terminal results in:
$s
being printed to the screen.
When I perform the same Cmd + S in the Terminal.app nothing is printed and the OS plays an Error Sound. I am not really sure why the keystroke is not making it to the terminal as expected, how do I allow Cmd + S to pass thru.
For more information on what / why I am trying to do this see question Bind <Cmd-S> in Vim
I have similar desires to yours. I solved it using a system-level modifier-key re-bind.
(Of course, this is a mess; but I find it worth it to maintain my MacVim-trained hybrid of OS-wide controls (save, new, copy, paste) within command-line vim
s.)
Here's how I did it:
- Install Karabiner, which is a very, very powerful program (and an essential part of any poweruser's / programmer's OS X installation, IMHO)
-
Enable “Command_L to Control_L (only in Terminal)”:
-
Map ⌃-prefixed controls matching whichever MacVim commands you're most used-to in command-line
vim
. For instance, to support ⌘S,noremap <silent> <C-S> :update<CR> vnoremap <silent> <C-S> <C-C>:update<CR> inoremap <silent> <C-S> <C-O>:update<CR>
-
Restore expected ⌘-sequences for Terminal.app itself, by special-casing them in System Preferences. For instance, if you want ⌘N to still control Terminal tabs, instead of mapping it to
vim
files, try:Now, anything you don't add in this list, will be passed through verbatim to command-line
vim
(and, of course, any other command-line program you use.)
Caveats
This approach has several further subtle downsides, that I want to hilight for anyone considering taking it (as I do):
- ⌘␣ will no longer map to the system-wide Spotlight. (I've an open issue on Karabiner, and will come back here once I have a stopgap solution.)
- For reasons I can't ascertain, even with the ⌃W exclusions set up in System Preferences, the tab-closing behaviour of Terminal.app changes with this setup: ⌘W will close individual tabs in a window; but if the current tab is the last tab, it will not close the window. Instead, it has no effect. I've had to re-train myself to use ⇧⌘W to close the window if there's only one tab left.
- If you've trained yourself to use ⌃V in MacVim to do block-wise selection, then you'll have to re-train yourself to use the alternative, ⌃Q (or, now, ⌘Q). Additionally, you'll have to add
stty -ixon
in your shell's startup-script, as ⌃Q is consumed by default to preform an archaic shell-control function (one with no modern usage.)
Alternative ⌘W behaviour
In addition to the above, I decided to further override ⌘W as a universal ‘close this’ key, applicable to multiple applications.
Instead of mapping ⌘W to ‘Close Tab,’ as above; I personally map that to ⇧⌘W (to retain “immediately close this tab” semantics.) Then, in any given program, I map ⌃W to some sort of close-save-quit functionality.
For instance, in my .vimrc
:
noremap <C-W> :confirm quit<CR>
vnoremap <C-W> <C-C>:confirm quit<CR>
inoremap <C-W> <C-O>:confirm quit<CR>
… or my .zshrc
:
function close_tab { exit }
zle -N close_tab_widget close_tab
bindkey '' close_tab_widget
bindkey -M vicmd '' close_tab_widget
With those two snippets in place, and your Terminal configured to ‘Close if shell exits cleanly,’ a series of ⌘Ws will first quit vim, and then close the shell entirely.
In addition, now additional on-exit functionality of programs can be preserved: for instance, vim
will ask before quitting if files are unsaved (just like MacVim); and zsh
will ask before quitting if there are background jobs.
Postscript: Not directly related to your question; but you should also check out ‘Ubiquitous Vim Mode’ in Karabiner. It's “a bit much” for me to use everyday, but it's a very cool idea, and surprisingly-well implemented.