0

In xterm, when I press the HOME key on my keyboard, it normally sends ^[[H but when I open emacs -nw, it changes to ^[OH; those are home and khome respectively. I figured out while trying to build my own terminal that ^[[H doesn't work in emacs. However, I can't figure what causes xterm (or emacs) to change its behaviour.

Additionally

  • The keys that "should" correspond to home and khome (the home key I usually use, and 1 on the keypad with numlock off) - always do the same thing on every terminal I have tried even though xev shows they are different, so for the rest of the question, I will treat them as the same thing.
  • It doesn't seem to relate to pty settings. I have used stty -g to copy the settings with emacs on, and then applied them with cat -v running, and I still get the non emacs behaviour. (demo below)
  • bash's readline seems to be more accepting than emacs and/or read the TERM variable, because HOME always works in bash no matter what terminal I try

Here are my experiments:

xterm

get terminal info:

$ tty
/dev/pts/1
$ echo $TERM
xterm
$ infocmp $TERM | grep home
    el1=\E[1K, flash=\E[?5h$<100/>\E[?5l, home=\E[H,
    kf8=\E[19~, kf9=\E[20~, khome=\EOH, kich1=\E[2~,

try the HOME key, and then return with cat -v and then exit

$ cat -v
^[[H
^[[H
^C

open emacs

$ emacs -nw

try out behaviour of home key (it works - I won't post a video)

use C-q to see what the key is sending:

[^OH in emacs in xterm

meanwhile in a different terminal (that doesn't have to be xterm), copy the emacs pty settings:

$ emacs_settings=$(stty -F /dev/pts/1 -g)
$ echo $emacs_settings
4001:1:bf:a31:7:7:7f:15:4:0:1:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:

and then quit emacs and start cat -v again

$ cat -v

and then back to the second terminal - set the xterm pty back to the settings that emacs uses

$ stty -F /dev/pts/1 $emacs_settings

and press home again in xterm: (and then press return and quit)

$ cat -v
^[[H^M

It's the same as it always is outside of emacs, the home code, not the khome code that somebody is helpfully inserting inside emacs.

Now if you are trying this at home, and want to quit cat -v, you will need to use ctrl+G instead of ctrl+C because the emacs settings change some keys around. This proves the settings worked. You can also see there that there is no ^G at the end of the line from quitting, but there is a piece of carriage return - I guess because the echo settings changed, and it's in raw mode.

Here are the human readable emacs pty settings if you are curious.

$ stty -F /dev/pts/1 -a
speed 38400 baud; rows 24; columns 80; line = 0;
intr = ^G; quit = ^G; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = <undef>; stop = <undef>; susp = <undef>;
rprnt = <undef>; werase = <undef>; lnext = <undef>; discard = <undef>; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig -icanon -iexten -echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc

Other terminals

linux
$ infocmp linux | grep home
    home=\E[H, hpa=\E[%i%p1%dG, ht=^I, hts=\EH, ich=\E[%p1%d@,
    kf8=\E[19~, kf9=\E[20~, khome=\E[1~, kich1=\E[2~,

this one isn't easy to take a screenshot (I could photograph it but I haven't)

The summary is - whether you are in emacs or not, the HOME key sends khome from the terminal settings, and it always works in emacs.

MATE Terminal (xterm-256color)
$ echo $TERM
xterm-256color
$ infocmp $TERM | grep home
    el1=\E[1K, flash=\E[?5h$<100/>\E[?5l, home=\E[H,
    kf8=\E[19~, kf9=\E[20~, khome=\EOH, kich1=\E[2~,
$ cat -v
^[[H
^[[H
^C

but again it sends ^[OH inside emacs! So again they are different. I don't know how I missed this before. I guess MATE terminal implements exactly what xcode does, or uses some of the same components.

On the other hand:

Hyper (xterm-256color)

In this case, they just send khome all the time, and the HOME key still seems to work how you would expect it to work.

$ echo $TERM
xterm-256color
$ cat -v
^[OH
^[OH
^C
$ emacs -nw
$ # ... ^[OH again 
tmux (in MATE terminal) screen

I don't know when tmux sets TERM to screen and when it sets it to tmux, but today on this computer, in this host terminal, it's screen.

$ echo $TERM
screen
$ infocmp $TERM | grep home
        enacs=\E(B\E)0, flash=\Eg, home=\E[H, hpa=\E[%i%p1%dG,
        khome=\E[1~, kich1=\E[2~, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
$ cat -v
^[[1~
^[[1~
^C
$ emacs -nw
$ # also ^[[1~ with C-q inside emacs

round-up
  • Some terminals just send khome all the time, while others manage to send khome inside emacs and home the rest of the time.
  • khome and home both work for bash readline, but only khome works in emacs - or there is just a fixed list of home keys that work in emacs (I am talking about default config) - I am leaning toward the fixed list since I can't get emacs behaviour to change by changing TERM
the big question

How xterm (and MATE Terminal) manages to change which code it sends when emacs is open.

Here are some guesses I can think of:

a) xterm has a special rule emacs b) emacs has a special rule about xterm c) emacs does change the terminal settings to cause this, but whatever that setting is, cat continually changes back if you try to make cat use that setting

smaller questions worth mentioning
  • Why don't the keys that look like they correspond to home and khome send the corresponding values?
  • Does emacs (by default) change its behaviour based on TERM?
2
  • Note that stty involves tty settings, NOT terminal settings. The tty is the emulated serial line and includes cooked mode line editing characters, interrupt keys that send signals (like ctrl-c) and other stuff that emacs and shells with their own line editors bypass anyway. None of this affects or involves the graphical terminal emulator. Cat does see that stuff.
    – user10489
    Commented Apr 13 at 23:20
  • Yeah! I hadn't realised terminal settings existed until yesterday. I will update the question to say tty settings
    – Alex028502
    Commented Apr 14 at 5:14

1 Answer 1

5

You're referring to keypad application mode, which is documented in XTerm Control Sequences:

The home- and end-keys (unlike PageUp and other keys also on the 6-key
editing keypad) are considered "cursor keys" by xterm.  Their mode is
also controlled by the DECCKM escape sequence:

                    Key        Normal     Application
                    ---------+----------+-------------
                    Home     | CSI H    | SS3 H
                    End      | CSI F    | SS3 F
                    ---------+----------+-------------

and activated/deactivated with DECCKM:

CSI ? Pm h
          DEC Private Mode Set (DECSET).
            Ps = 1  ⇒  Application Cursor Keys (DECCKM), VT100.

via the smkx/rmkx capabilities in the terminal description (which you can see using infocmp):

        rmam=\E[?7l, rmir=\E[4l, rmkx=\E[?1l\E>, rmso=\E[27m,
        rmul=\E[24m, rs1=\Ec, rs2=\E[!p\E[?3;4l\E[4l\E>,
        setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
        setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}
             %=%t3%e%p1%d%;m,
        setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}
             %=%t3%e%p1%d%;m,
        sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;
            %?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m,
        sgr0=\E(B\E[m, smam=\E[?7h, smir=\E[4h, smkx=\E[?1h\E=,
        vpa=\E[%i%p1%dd, E3=\E[3J, use=ansi+csr, use=ansi+enq,
        use=ansi+idl, use=ansi+inittabs, use=ansi+local,
        use=ansi+pp, use=ansi+sgrbold, use=xterm+kbs,
        use=xterm+alt+title, use=att610+cvis, use=xterm+acs,
        use=xterm+meta,

(non-screen applications generally do not initialize the terminal, full-screen applications generally do -- ignoring hard-coded stuff in each case).

7
  • oh wow! Is there a straightforward "hello world" way of switching modes or initializing the terminal while cat -v is running so I can see it happen?
    – Alex028502
    Commented Apr 13 at 19:06
  • xterm has a menu item for this (other terminals generally not). Commented Apr 13 at 19:32
  • I found what I was looking for thanks to all your info - echo -e "\033[?1h\033=" can switch the mode without entering emacs, so cat -v after that shows the same sequence you see in emacs with C-q
    – Alex028502
    Commented Apr 13 at 20:43
  • if it's helpful, you may approve the answer Commented Apr 13 at 20:50
  • 1
    @Alex028502, on most systems, you can do tput smkx / tput rmkx to send those escape sequences. The zsh shell has a builtin interface to terminfo with its echoti builtin (see also its $terminfo special associative array). Commented Apr 14 at 12:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .