3 Answers
3

I finally sorted out the various issues to come up with a solution. The problem seems to be that if the Control key is part of the keyboard shortcut then no other modifier keys that are also pressed will change the code that is sent by that keypress. If Control + i produces the ^i (tab) character then adding more modifiers to the shortcut will still produce the same ^i code, at least when using iTerm2. This may be occurring at the OSX level or perhaps at the Unix level where a termcap table handles the translation of "terminal keys" to "output codes." It can be observed with iTerm2 by using "cat -v" or "vis -o" to see the output being generated and is also seen when using Key Codes (without iTerm2 running) which makes OSX the more likely culprit. That conclusion is supported by noting that the general user is not able to redefine certain keyboard shortcuts (without difficulty) that are reserved for basic OSX functions (such as Command-Tab for program switching).

It is possible to programmatically differentiate any set of modifiers pressed with a character key but those modifier flags are accessible programmatically within OSX and by a totally unique set of codes for every different set of keys pressed. To witness this, use Key Codes and while holding the Control key and pressing a character key and then doing the same while pressing additional modifier keys at the same time, note that it is always the same character code that is produced. Yet Key Codes has access to the various keys being held and is able to display them to us in the "modifier" field that it reveals. And, if iTerm2 could only see the standard codes produced from various key presses and not also see the modifier flags then iTerm2 itself wouldn’t be able to define the range of shortcut keys that it is actually able to define. On the other hand, after identifying each set differently modified keys in a unique manner, iTerm2 appears to pass it’s generated codes to OSX where they are handled in the same way as if they’d been keyed on a keyboard, resulting in identical output for groups distinguishable keystrokes. So, for example, iTerm2 may pass the unique Control + Alt + i determined code(s) out for the use of tmux but OSX takes them and tosses out a few details before delivery, making the code appear to be just ^i when it finally arrives for tmux to handle. The shortcut binding in tmux expects to receive the code we thought we were sending but along the way OSX has removed the information about the Alt (Meta) key, the same as it would do if the keyboard shortcut had been typed on a keyboard.

The solution is to find a key combination that won’t be used for something else and that can be transmitted without being changed to another key combination that you do want to use. That’s where Key Codes is useful since it let's you test many key combinations and find what the key presses are translated to be "unique enough." Here’s the process I used to make it work for me:

Goal: Running tmux in iTerm2, I want to be able to press Command-Control-i and have tmux execute the "select-pane -U"command.

Choose an esoteric key press that you won’t be using. Consider a multi-key sequence with the tmux escape character followed by another unusual key press making it much less likely to be needed. I’m choosing to send the standard tmux escape character (0x02 = ^b) followed by the ansi code sequence for F1 (0x1b 0x4f 0x50). Good keys to look at are the less used characters generated on a Mac by holding down Alt (Option) and Shift with another character key.

Within iTerm2 open Preferences and define the Command+Control+i shortcut in either the global key shortcuts or as a keyboard shortcut for a specific profile.

Press the + button to add a new shortcut.

Click in the Keyboard Shortcut field and hold down the Command and Control keys while you press the "i" key.

Use the mouse to select "Send Hex Code" in the Action drop-down. (Trying to use Tab to leave the Shortcut field will change the value for the shortcut.)

Type the string "0x02 0x1b 0x4f 0x50" (without the quotes and assuming that you are using the default tmux escape character, ^b = 0x02).

Press the OK button to commit your shortcut. Close Preferences.

Within iTerm2, invoke a tmux session and define the key binding for the codes iTerm2 will send.

Test it by splitting your tmux window into several appropriate panes and try using Command+Control+i to move through panes vertically. If successful, you'll probably want to record your key-binding with the start-up bindings invoked by tmux on startup.

This method worked fine for me and should work well unless you have somehow used all the possible keyboard combinations for other uses. Methods like this one combined with practice and experience guessing the inner workings of a system should can help work around situations like this one that may feel foreign and overwhelming. Some parts of the above explanation are reasonable guesses as to what is occurring or that may assign blame to the wrong process but I hope that it’s helpful as a guide to how problems like this can be approached with less than a complete understanding of the whole system.

(The theory is in the following 3 paragraphs and the best guess answer is developed in the remainder of this long winded explanation. The spoiler is our educated guess of 0x89 as the answer to the given question. If not then you'll probably need to read much of the rest and do some searching on your own to see exactly what you should send and how. I do hope this helps.)

To sort this out the first thing is to realize that C-M-i is not the same as Control + Command + I except when (in a specific context such as an OS or a program) the Command key is set to be the Meta key. In iTerm the choices for the Meta key are one or the other of the Option (Alt) keys. In iTerm one can't speak of the Command key as the Meta key although it's possible to capture the Command key press by defining it as an iTerm keyboard shortcut. So what does it mean in iTerm to press Control + Command + i? It's not defined; it sends no visible or invisible characters at all. (This is best seen by invoking cat -v, vis -o or another program that will visibly display invisible codes and trying various keystrokes.)\

But the idea of pressing C-M-i is somewhat defined and often including the Meta key with another key combination is equivalent to pressing the ESCape key followed by the same key combination. That appears to be what you were trying to do by setting a key to output the escape sequence: ESC + ^i. If that didn't work then we need to know what string of characters/bytes is actually wanted by whatever program you are trying to control. Following the example you pointed to I created a hex sequence of 0x1B 0x09 which produced the same output as your ESC sequence. (Hex 1B or 0x1B = Binary 000110111 = Octal 033 or \033 = Decimal 27…value of 27not2 followed by 7; after a while these particular numbers all start to mean ESCape character when one sees them.)

Now, Key Codes was a good try being the same sort of idea as using cat or vis to visualize the characters that get sent. The problem is that Key Codes is not running within iTerm but is running within OS X. One could say the Command key is OS X'sMeta key but that train of thought isn't useful since OS X defines the function of its Meta key quite differently from how iTerm defines its Meta key. If you go into Key Codes and try pressing Control + i with and without the Command key you'll see that the difference is in the resulting modifiers; but the modifiers are internal flags within OS X that OS X creates by examining what keys are pressed. The actual output code is closest to the Unicode character shown (0x09) and you'll see that both with and without the Command key you receive the same character. But that's illusory anyway since what actually happens is that OS X gets the Key Code and the Modifers values and interprets those codes as it wants. Control + i comes closest to "sending" a ^i but add the Command key and, if the Finder is the receiving the results, you get one of the various Get Info commands; another program may interpret it as it likes. It's turtles on turtles on turtles all the way down, i.e., what you begin with may end up doing many different things depending on what is re-interpreting what, and so on.

Now I have to try to give you an answer that will work for you, but the preceding was necessary to show why I can't say for sure. But I can make an educated guess. First, the context is iTerm and I assume you are running a program in iTerm that does something in response to what is said to be C-M-i. If, in iTerm I set one Option/Alt key to be the Meta key and then press that key with the ^i keys we will expect that we will get what we want to happen to happen. So let's find out what gets sent by doing that. If you use Key Caps it won't say anything different since you're back outside of iTerm. But when I use the cat -v command which does it's best to make the invisible visible on the screen and press C-M-i, then along with a strange diamond shape character I get the string M-^i which seems to be a way to say M-C-i. That looks good.

Now I get out of the cat program and go to the vis -o program which will try to give me some octal values for some of the invisible characters. Now pressing C-M-i gives me an octal value (after pressing return) of \211 as well as that funny diamond. (Octal 211 or \211 = Binary 10001001 = Hex 89 or 0x89; which is encouraging since when I earlier turned on the Meta key in iTerm it gave me a warning a that Meta was usually used on older systems and new systems generally use the +ESC code sequence…back to where you started! I also have seen that what the Meta key often did was to output the ASCII 7-bit printable character with its high-order bit (leftmost bit usually set to zero) set to 1. If you strip the leftmost 1 from the binary coding of what we received you're left with a 1001 binary = Decimal 9! 9 is the character that pressing ^i "sends out." That looks good.

Just to go full circle and check it out further I can go back to iTerm, make sure I've turned off my Meta key options (just in case) and define a new keyboard shortcut to some key that sends a 0x89 (Hex 89). Then open a new window so that the changes are active and press the key you assigned the 0x89 with vis -o running to interpret your characters. Out comes the same funny diamond shape and the octal string \211. So it appears we have set up a shortcut key to produce C-M-i to the best of what we know.

Whether that key will do what you want depends on whether the program that wants that keyboard code handles what we gave it. Not knowing more this is a best educated guess. If it fails then it's necessary to delve further into the end program that is being controlled [I'd venture Emacs but, hey, I use vi so what do I know ;-] Hopefully some of the techniques and ideas presented here would help you determine how to send the correct codes once you found them. I hope that this works for you. Note that without all the fuss you can get a pretty good idea that it will or won't work by turning on a Meta key in iTerm and pressing C-M-i to see if that works; if so then proceed to define your shortcut key.

Thanks a lot Zhora. This is extremely helpful, although unfortunately 0X89 didn't do it. The receiving program is actually tmux where I have .tmux.conf listening to bind-key -n C-M-i select-pane -U (i.e. the shortcut C-M-i is supposed to call select-pane -U. I am able to do this get this to work if I set it to M-i (and ask iTerm to send the appropiate Esc+i, but not with C-M-i.
– Amelio Vazquez-ReinaSep 9 '14 at 21:53

To be clear, yes I am running Tmux on the shell, even though iTerm technically itself relies on Tmux. This shouldn't matter. I have been doing this for years. I do this because (1) I don't like relying exclusively relying on iTerm2 for multiplexing, and because (2) this allows me to detach from remote sessions.
– Amelio Vazquez-ReinaSep 9 '14 at 21:54

I once wrote up a brief for small claims court and the rigid deadline for filing prevented me from sleeping for 3 days and nights; the result was an absolute mess to say the least. As I look back at your question and my answer I’m reminded of that experience (but to a lesser degree by far). In rereading it I think I may have confused and switched around parts of the question with parts of my intended solution. I do hope it helped somewhat and I think my newer answer will clarify things and provide a definite solution.
– ZhoraSep 11 '14 at 12:24