iTerm2 keymaps for tmux

UPDATE 17 March 2013: I am placing this post into the public domain
so people are free to incorporate it into their existing files which may
be in the public domain already.

UPDATE 16 July 2012: I have updated this post to reflect my current
keymaps, which I settled on after writing the original post.

As I’ve said before, I’m a huge fan of iTerm2. I am also
a huge fan of tmux, the terminal multiplexor. If you’re not familiar with
tmux, it’s conceptually the same thing as GNU screen, with some
differences, and (in my opinion) some advantages. For example:

In screen, each instance is its own completely separate process. With
tmux, the first time you run it, you start a server, but subsequent runs
will instantiate clients that connect to that existing server. Why does
that matter? Because it means you can lop a window off of one tmux
session and glue it onto another. It also means you can view the same
session from multiple clients simultaneously (say you left tmux attached
at the office, you can attach to that same session at home without
disrupting the session you left attached at work). You can even
share a session with someone else. All of that’s
possible because it’s all going on in the same server process.

tmux supports multiple panes within a window, where screen supports only
windows.

If you don’t set a window title, tmux will auto-set it for you based
on what you run in that window. So it might start as “bash” and change
automatically to “vim” or “top” or “tail” depending on what you run
inside. That is pretty handy to tell what’s going on in what window
even if you don’t take the time to set a name for it.

It so happens that the authors of iTerm2 are tmux users as well, and they have
integrated a tmux mode into iTerm2. It’s an early stage thing, so you have to
forgive it, but at this point it still has some drawbacks. I am not going to
talk about that integration much in this post, but I wanted to point out that
it exists, that I know about it, and explain why I don’t use it.

You can only connect iTerm2 to one iTerm2-aware tmux session at a time.

They communicate via a special protocol. In practical terms, this means
you “spend” a window for that channel. It sort of sits around lingering.
To be fair, they added an option to auto-hide it on connect so it goes
away by itself.

Because this is still under development, you currently have to run
the right version of iTerm2 with the right version of patched tmux.
That can be a headache if your server side is used by multiple people.
It also means an upgrade to iTerm2 sends you off to recompile tmux
before you can use it in integrated mode again.

For these reasons, I have set aside the iTerm2 tmux integration and I’m
just using regular tmux again. I’ll check it out again someday after it has
matured (and preferably been built into tmux mainline so I don’t have to
patch a copy myself).

But after using the integration, I found I was longing for easy hotkeys to
navigate around my windows and panes in tmux. (Using the integrated mode, you
use the iTerm-native hotkeys because it treats the tmux windows and panes as
native iTerm tabs and panes).

I was frustrated by this because in tmux you use a prefix key for everything,
so going to the next window means using Ctrl-B n and going to another pane
might be Ctrl-B H. You can remap a lot of things, but it’s never as easy as
native keys like Shift-Cmd-Right or similar that we are used to using on
Macs and PCs.

At first, I played with the tmux mouse mode. It’s actually pretty nice.
Assuming you send mouse events through to the server, tmux will recognize them
(if you turn on the appropriate options), allowing you to select windows and
panes using mouse clicks. You can even resize panes. Unfortunately, that comes
at a cost: it breaks using normal mouse selection to copy from iTerm2 window
into other programs on your Mac. Not good.

Send Hex Code is just an unassuming option in a pulldown in the iTerm key
mapping preferences. But when I saw it, I knew it was the solution to my
problem. The thing is, you can represent any ASCII character as a hex value,
and sending a sequence of ASCII characters is exactly what I needed to do.

Armed with all of my hex sequences, I headed to the iTerm2 preferences. Under
the “Keys” section, you can add new items to the global shortcut list. (You
can also do this in a profile’s key settings if you have a reason to not want
bindings to be available to all profiles.) I added the below sequences,
binding them to hotkeys.

Now I can move between tmux windows with Ctrl-Cmd-{direction}, move among
panes with Cmd-{direction}, and resize with Cmd-Opt-{direction}. It’s
really nice, and I can use Vim keys (H,J,K,L) or arrows.

(Yes, I am aware that this overrides certain keymaps. You will lose the
“Hide” hotkey, Cmd-H, but I never use that so I didn’t care. iTerm also
maps Cmd-{left,right} to navigate between tabs, but Cmd-{digit} and
Shift-Cmd-{left,right} will still work.)

Lastly, a few finishing touches for my tmux.conf. The colors I use
here assume Solarized Dark for the iTerm color scheme. They may
look awful with another color scheme (or they may look fine).