Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

On my MacBook Pro running OS X Lion 10.7.4, there seems to be a keyboard issue. I first noticed this problem when I tried to use the default keybinding to execute mark-sexp and query-replace-regexp in emacs, which are bound respectively to C-M-@ and C-M-% by default. As I use emacs a lot, I really miss these two powerful features a lot.

As I don't have experience dealing with terminal types etc, I did some simple debugging within emacs:

  • C-M-f and C-M-b work as expected. So control and option work well together.
  • M-%, M-< and M-> work as expected. So option and shift work well together.
  • C-S-backspace does not work. (But I've never tried this command before; the first time I ran it was today when I found it in the emacs manual.) But C-@ works as expected. So control and shift probably work well together.
  • If I am not mistaken, the command digit-argument is bound to C-9, C-8, etc. These keys do not work as well. I have made sure that in System Preferences.app I have turned off these keys for switching spaces.

In Terminal.app preferences, I have selected "use option as meta key" as it eases typing the emacs keybindings. I also tried to disable this option and use ESC but still to no avail. Any ideas?

P.S. I launched X11.app and in the xterm window I started emacs. Using ESC as meta, C-M-% and C-M-@ work perfectly. In the Cocoa version of Emacs, these two work perfectly as well. So I guess it is a Terminal.app bug or probably there might be a setting or configuration switch I can tweak to make this work in Terminal.app?

And here is the output of stty -a from emacs shell, hopefully it's useful...

bash-3.2$ stty -a
speed 9600 baud; 0 rows; 0 columns;
lflags: icanon isig iexten -echo echoe -echok echoke -echonl echoctl
    -echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
    -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -iutf8
    -ignbrk brkint -inpck -ignpar -parmrk
oflags: opost -onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
    -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
    eol2 = <undef>; erase = <undef>; intr = ^C; kill = <undef>;
    lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
    status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
bash-3.2$ 

The same command directly from the shell:

$ stty -a
speed 9600 baud; 24 rows; 80 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
    -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
    -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
    -ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
    -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
    eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
    min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
    stop = ^S; susp = ^Z; time = 0; werase = ^W;
$

(Side-comment: It seems strange that the syntax for a code block is four preceding spaces. Are all StackExchange users expected to know how to use paste(1), sed(1) or rectangle edits?)

share|improve this question
    
To your side remark: Try the button marked {} in the toolbar of the StackExchange editor. Select your code snippet first. –  Harald Hanche-Olsen May 13 '12 at 6:01
1  
I don't know the answer to your question, but if you use emacs “a lot”, why on earth do you do it in a terminal window? You can get emacs to run with its own GUI, you know. You can get many versions here: emacsformacosx.com –  Harald Hanche-Olsen May 13 '12 at 6:05
    
@HaraldHanche-Olsen Yes, in the fourth paragraph I did mention that I have a Cocoa (GUI) version of emacs.app installed. But that version has some issues such as a corrupted linum column on OS X Lion, slow speed compared to terminal. Moreover, what if I needed to run emacs when I ssh to my machine from another computer? Or, when I am using mutt(1) to send emails or git(1) to commit changes? –  kccqzy May 13 '12 at 8:29
    
The cocoa version of emacs is ancient, isn't it? The one I pointed to is the nextstep version, from recent GNU emacs sources. You may want to try it out. When you log in from another computer, there is the option of using an X11 based emacs. Or, if you wish to run it in a terminal, how about an xterm? That gives you more direct control of the keybindings, I think. –  Harald Hanche-Olsen May 13 '12 at 9:12
add comment

2 Answers

up vote 2 down vote accepted

In general, Mac applications that are expecting text input from the keyboard do not handle C-S combinations or C-digit combinations. Programs that work with control-shift combos (like anything running under X11) do so by handling key events as events, not character input. This is how they can differentiate between Tab and Ctrl-i, which both generate the same ASCII character. (You can read in detail how Lion (really Cocoa) handles key events if you really want to know.)

Historically (back in the Teletype days), there were only uppercase letters on the keyboard, and there were no caret (^) or underscore (_) characters on the keyboard (instead there were up-arrow and back-arrow). The shift key worked by toggling the 16's bit and the control key worked by zeroing the 64's bit of the 7-bit ASCII codes the keyboard produced.

What this means is that the control key had no effect for the 32 characters on the keyboard that already had their 64's bit set to zero (most of the non-alphabetic characters, including digits), and since the teletype was purposefully limited to upper-case letters only, the shift key had no effect on most of the alphabetic characters (and where it did have an effect, it produced a special character like @).

Additional weirdness was added in the migration to supporting lower-case text, as the control key combos were all typed without using the shift key but now the letter typed without using the shift key had changed, so the decision was to map control-lower-case to what had been control-upper-case. But then what do you do with control-shift?

For a while the problem was handled by having the control key also zero out the 32's bit, which is what differentiated lower case letters from upper case letters. But eventually ASCII was replaced with Unicode and those kinds of duplicate key assignments were too much of a waste of keyboard space to be allowed to continue, so they got different mappings, and on the standard Mac US keyboard most C-S combos are unassigned.

So what you have run into is the legacy support for keyboard input running back to Teletype days. The characters Terminal (and other OS X apps) do not support are characters you could not type on the Teletype keyboard. As evidence of this, note that C-S-2 (C-@), C-S-6 (C-^), and C-S-- (C-_) all work, because those keys have been re-mapped since the ASR-33, where S-2 was " (and @ was S-P), S-6 was &, and S-- was =, but in general control-shift combos do not produce characters of any kind.

share|improve this answer
    
Great answer! In fact quite an enjoyable and educational read with historical details that clearly explained how all this came about. Although it doesn't provide a solution, I am quite satisfied with this answer. –  kccqzy May 14 '12 at 10:35
    
@kccqzy, I forgot to mention that digit-argument is bound to M-digit (and of course C-u), and you should check out iTerm2 as a replacement for Terminal. I haven't tried it, but I think it handles the keyboard the way Emacs wants. –  Old Pro May 14 '12 at 15:45
    
Yep, I guess most people are accustomed to invoking digit-argument by M-digit and so am I. I have used M-digit for a long time without realizing C-digit is also mentioned in the manual. iTerm2 seems promising. Using its default settings, ESC C-@ works but not ESC C-%, but I guess it should be possible to tweak this. Thanks! –  kccqzy May 15 '12 at 12:31
    
Found an excellent piece of article on the web, but written in Japanese: bit.ly/tLOFe1 Tried Google Translate and understood mostly what it was talking about. Using event-apply-modifier is truly a good idea. Combined with iTerm2's (thank you, it is a piece of great software) capability of sending arbitrary hex code with any key sequence, I could get C-M-% to work correctly (finally). But the strange thing is, C-M-@ doesn't work. Quite mysterious, as emacs told me C-M-@ is undefined when I used describe-key, but ESC C-@ works. –  kccqzy May 17 '12 at 15:38
add comment

Just sharing,

I've tried to customize those keys and by transposing option to command as meta but to no success.

What I realize is Terminal.app does not recognize 4 button simultaneously. Or at least i think it didn't.

However, this might help you to set your keybinding across software.

I also found out other discussions related to this as well.

(btw digit-argument works with M-{1..9}, doesnt with C-{1..9} like mentioned. weird)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.