I should have been more clear -- emacs itself works fine, not
suffering from the issue I describe, but I don't use it very often.
I am talking just about the bindings like ctrl-e for "go to end of
line", which work across most of OSX, for example in TextEdit or in
this browser window where I am typing this reply. There are over a
dozen of them, and I refer to them as "emacs" bindings only because
the correspondence between keys and actions derives historically from
how the keys behaved in emacs. You can see a list of these bindings
in the lower right corner of the
http://www.danrodney.com/mac/ page.
My issue occurs because my keyboard uses regular unmodified alphabetic
characters, like "e", as dead keys. I do not know any system keyboard
with this feature, so I can't compare.
Your tip for fixing the command-key problem works perfectly, by the
way! Specifically, the command-key functionality works fine once I
set up the keyboard so that it provides a standard qwerty map when the
command key is pressed. This requires messing with the modifiers
drawer.
So my only remaining problem is that plain-alphabet dead keys cannot
have their control- version bound to anything in the
DefaultKeyBinding.dict file.
To reproduce my problem, set up "e" as a dead key. You can have its
terminator be the letter "e", and the dead key state can be an empty
keyboard, so that you can type normally. The only difference from
using a normal keyboard is that the "e" will be highlighted in orange
until you type the next character.
Now, using this keyboard, it seems to be the case that ctrl-e will
insert literally whatever the keyboard indicates for ctrl-e. Note
that this is completely abnormal behavior -- normally, pressing
control-this or control-that will either do nothing (beep) or perform
its defined emacs-style action. More specifically, it will perform
whatever action is defined in the DefaultKeyBinding.dict or
StandardKeyBinding.dict files (which is in fact where the system
defines the emacs-style bindings for us). Pressing control-something
certainly does not insert raw control characters into our text.
But when the plain (not control) "e" key is a dead key, then this
strange behavior occurs: The raw info from the keyboard's definition
of the control (not plain) "e" key is inserted into the document,
without ever passing through any of the *KeyBinding.dict files.
Examples:
For these examples, I set my DefaultKeyBindings.dict to contains the
following lines. (Which makes it very hard to type!) If you're not
familiar with the format, the string on the right doesn't have any
particular meaning to the system; it is simply inserted into the
document when the key on the left is received. These lines are not a
useful example to learn from -- the power of key bindings comes from
the fact that you can bind many different actions to keys besides
inserting text.
"e" = ("insertText:", "<plain e>");
"^e" = ("insertText:", "<ctrl-e>");
"~e" = ("insertText:", "<alt-e>");
"η" = ("insertText:", "<η>");
"^η" = ("insertText:", "<ctrl-η>");
"~η" = ("insertText:", "<alt-η>");
"€" = ("insertText:", "<€>");
"^€" = ("insertText:", "<ctrl-€>");
"~€" = ("insertText:", "<alt-€>");
"\U0005" = ("insertText:", "<enquiry>");
"^\U0005" = ("insertText:", "<ctrl-enquiry>");
"~\U0005" = ("insertText:", "<alt-enquiry>");
(note that \U0005 is a useless rare invisible ascii control code
character, "enquiry")
US keyboard:
plain e = "e", ctrl-e = "\U0005", alt-e = dead key for acute accent
behavior:
plain e = "<plain e>", ctrl-e = "<ctrl-e>", alt-e = dead key
behavior
my keyboard:
plain e = dead key for accented e, ctrl-e = "\U0005" (or "e"), alt-e
= "η"
behavior:
plain e = dead key behavior, ctrl-e = "\U0005" (or "e"), alt-e = "η"
Hungarian keyboard:
plain e = "e", ctrl-e = "\U0005", alt-e = "€"
behavior:
plain e = "<plain e>", ctrl-e = "<ctrl-e>", alt-e = "<alt-e>"
The thing that is weird:
Ctrl-e on my keyboard ignores the key bindings. My keyboard treats
ctrl-e just like every other keyboard does, but the behavior is
completely different. It is impossible for me to assign an action
(even the default OSX action) to ctrl-e. The difference stems from
the plain e being a dead key.
Why it is annoying:
Text navigation using the keyboard is very useful. I would like it
to work with my keyboard. But if my fingers try to navigate by
mistake, I wind up filling my document with invisible control code
characters. This doesn't happen with any other keyboard. My keyboard
doesn't have any invisible control code characters that the other
keyboards don't have. But with the other keyboards, these insidious
characters never get inserted into the text.
The Ukulele Manual (p. 66) says:
The way that the control key is handled appears to be this. When a key
stroke with the control key is sent to the system, if the option key
is not down, or if the quote key (normally ^q) has not just been sent,
the system reanalyses the key stroke. It does this by asking what
character would be generated by the same key stroke without the
control key.
The manual goes on to explain how you can compensate for this
weirdness via DefaultKeyBindings.dict. My experimentation shows that
this approach will only work when the non-control key is not a dead
key.
In fact the same process seems to apply for the alt (option) key as
well, considering the above data from the Hungarian keyboard: The
keyboard's definition for the unmodified key is sent, along with
modifier information, to the *KeyBinding.dict files. However, if the
keyboard has no definition for the unmodified key (for example because
it is a dead key), as is the case for my keyboard, then this binding
process can't do anything, and the keyboard's own definition of the
modified key is used.
As another comment, the Key Codes app reports absolutely no keys when
I press the dead "e" key on my keyboard. This contrasts with pressing
the dead key alt-e on the US keyboard, for which it reports that keys
= alt-e. This strangeness is in fact consistent with the process
described in the previous paragraph. The "keys" reported by Key Codes
is the same as what gets passed to the *KeyBinding.dict files.
At this point I believe my problem is unfixable. This is sad, because
the whole reason I made my own keyboard was to be able to type
diacritics *after* the letter, just like how we write them by hand.
But OSX seems to be unprepared for this approach.
I may try a pure DefaultKeyBinding.dict approach, since that can also
handle sequences of keys, but that approach will not allow switching
back and forth between DefaultKeyBinding.dict-defined keyboard
behaviors, whereas you can easily switch between actual keyboards. I
could define a keyboard to produce characters from an alphabet I
normally never use, and then a single DefaultKeyBinding.dict could
define one behavior for one keyboard and another behavior for the
other keyboard. A peculiar approach -- pressing the "a" key would
make that keyboard report an "alpha" key, and the
DefaultKeyBinding.dict file would then map the "alpha" back to "a", or
perhaps to a dead state waiting for diacritics to put on the "a",
without interfering with any ctrl-a functionality -- I think it would
work, but the dead keys (as defined in DefaultKeyBinding.dict) would
be invisible until completed, not even showing up in orange, and I
don't know of any way to set the equivalent of a terminator (to be
used if the next key pressed is not in the provided list), so the dead
key state would need to repeat the entire keyboard definition.