3

I've enabled the macOS's terminal preference "Use Option as Meta key" but seem unable to have emacs behave in the terminal as it does when running the GUI.

I have the following use-package definition for drag-stuff:

(use-package drag-stuff
 :ensure t
 :bind (("M-<up>" . drag-stuff-up)
        ("M-<down>" . drag-stuff-down)))

When running the emacs GUI, option+shift+up/down correctly moves the line(s) up or down as expected.

However, in the terminal (emacs -nw) the commands are not recognised. The mini buffer says Esc <up> is undefined or Esc <down> is undefined.

When I look to describe the key sequence from the terminal I see this:

Esc <up> (translated from Esc M-O A) is undefined

Doing the same in the GUI I'm presented with the following **Help** window:

<M-up> (translated from <M-S-up>) runs the command drag-stuff-up
(found in global-map), which is an autoloaded interactive Lisp
function in ‘drag-stuff.el’.

It is bound to <M-up>.

[Arg list not available until function definition is loaded.]

Not documented.

I've seen that there are a number of questions on this kind of problem, but I've unfortunately come up short in finding something that works. It seems to be related to Shift+Up isn't recognized by Emacs in a terminal.

If I open the scratch buffer and attempt to see the escape sequence for shift+up (i.e., key sequence C+q S-up) I see ^[OA and similarly ^[OB for shift+down.

If I include the option (i.e., meta) key I see this for both option+shift+up and option+shift+down: ^[, which is weird.

Any helps on making things as consistent as possible between emacs GUI and NW would be much appreciated. Thanks!

Full emacs.nix config, for context, is defined here if that helps.

1 Answer 1

2

So it turns out that this is due to the macOS Terminal.app missing numerous keyboard text code settings that are present when running the emacs UI.

Let me firstly thank @timothy-basanov and his GitHub repo for terminal-app-function-keys which lists a number of good example key code mappings I needed.

The mappings I needed are included here (excluding basic up/down which are included to demonstrate the definition of "A"):

↑ \033[A
⇧↑ \033[1;2A
⌥↑ \033[1;3A
⌥⇧↑ \033[1;4A
↓ \033[B
⇧↓ \033[1;2B
⌥↓ \033[1;3B
⌥⇧↓ \033[1;4B

As you can see, there's a clear pattern here depending on which modifier keys are pressed.

In fact, 1 is implied if not specified. So \033[A is equivalent to \033[1A. Hence, you can see that the number n preceding A and B merely suggest a different hex code in sequence that happens to map to something that emacs (and other programs) understand.

I had originally thought that \033, \x1b and \e were all forms of CSI (Control Sequence Introducers), being in Octal, Hexadecimal and Escape sequence forms respectively.

But as @db48x points out \033 suffixed with [ forms a "Control Sequence Introducer" (CSI). \033 is the octal equivalent of the hexadecimal \x1b which is the decimal 27.

Thus a "Control Sequence Introducer" (i.e., CSI) is of the form prefix[ where prefix is one of (\033, \x1b, \e). I'm not sure on when you would choose one form or the other.

Similarly, my understanding is that the 1 (preceding the semi-colon) represents font-width.

The final character set denotes in ascii the character function to call.

I'm not completely clear on all the escape coding sequence formulae, but this answers the immediate question of why the default settings for Terminal.app were not allowing the same behaviour that was possible in the GUI and how to fix it.

An improvement on this would be to add this configuration as IaC (e.g., to my nix-home)

Helpful note from @db48x — "The control sequences you are describing here are documented in the XTerm Control Sequences document as well. They came from the VT510." Thanks!

References:

5
  • 1
    Some corrections you might want to make: \033, \e, and \x1b are all different ways of encoding the same escape character. 033 is in octal and 1b is in hexadecimal, but they both have the same value, which is 27 in decimal. CSI is actually the pair of characters \033[. The control sequences you are describing here are documented in the XTerm Control Sequences document as well. They came from the VT510.
    – db48x
    Commented Feb 10, 2022 at 14:34
  • 1
    I guess the modifier numbers come from terminal-app-function-keys—the choice of the numbers is a bit weird. Back in the day, single bits of the numbers would instead be assigned to each modifier, so combinations would be made from several bits set, and checking for modifiers could be done by bit-and'ing the number with a mask. E.g. if 1 is shift and 2 is alt, then 3 is them both together, and 7 would be shift-alt-control.
    – aaa
    Commented Feb 10, 2022 at 17:38
  • Thanks so much @db48x! That's very helpful. I've included your notes in the answer with all due attribution.
    – ldeck
    Commented Feb 10, 2022 at 20:01
  • Yes that makes sense @aaa. I'm not familiar enough as yet with what the conventions might be for the mapped function/character choices.
    – ldeck
    Commented Feb 10, 2022 at 20:04
  • No, the prefix is just character number 27, the escape character. The \033, \e, and \x1b syntaxes are just different styles of escaping. Different contexts have different support for different escape sequences. You may be more familiar with the escape sequence \n which is used to represent the newline character. These are used because the escape and newline characters are hard to type directly, and difficult to edit once included in a file.
    – db48x
    Commented Feb 10, 2022 at 20:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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