Skip to content

Commit

Permalink
Handle keypad mode cursor key escape sequences. (#203)
Browse files Browse the repository at this point in the history
Normally the terminal uses CSI escape sequences when the UP, DOWN,
LEFT, RIGHT and HOME, END keys are pressed. These look like the
following ESC [ A etc, where ESC [ is the CSI sequence.

xterm and other terminals however can generate an alternative
escape sequence called SS3 if in the application keypad mode.
This sequence is ESC O A etc.

Bash readline understands both modes so nowadays you rarely
see OA being printed when you press the up arrow while the terminal
is using the keypad mode. readline currently does not understand
these sequences.

To test this fix, I used an xterm and put it in keypad mode
using the command "tput smkx". Then I started the readline-demo
and tried using arrow keys. Without this fix, OA is printed when
I press up. With this fix, readline fetches the previous command
as per regular mode. After testing you can escape back to
regular mode using "tput rmkx".
  • Loading branch information
tpodowd committed May 20, 2022
1 parent 80e2d19 commit 8e4bd41
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
16 changes: 16 additions & 0 deletions terminal.go
Expand Up @@ -125,6 +125,7 @@ func (t *Terminal) ioloop() {
var (
isEscape bool
isEscapeEx bool
isEscapeSS3 bool
expectNextChar bool
)

Expand Down Expand Up @@ -152,9 +153,15 @@ func (t *Terminal) ioloop() {
if isEscape {
isEscape = false
if r == CharEscapeEx {
// ^][
expectNextChar = true
isEscapeEx = true
continue
} else if r == CharO {
// ^]O
expectNextChar = true
isEscapeSS3 = true
continue
}
r = escapeKey(r, buf)
} else if isEscapeEx {
Expand All @@ -177,6 +184,15 @@ func (t *Terminal) ioloop() {
expectNextChar = true
continue
}
} else if isEscapeSS3 {
isEscapeSS3 = false
if key := readEscKey(r, buf); key != nil {
r = escapeSS3Key(key)
}
if r == 0 {
expectNextChar = true
continue
}
}

expectNextChar = true
Expand Down
22 changes: 22 additions & 0 deletions utils.go
Expand Up @@ -43,6 +43,7 @@ const (
CharCtrlY = 25
CharCtrlZ = 26
CharEsc = 27
CharO = 79
CharEscapeEx = 91
CharBackspace = 127
)
Expand Down Expand Up @@ -123,6 +124,27 @@ func escapeExKey(key *escapeKeyPair) rune {
return r
}

// translate EscOX SS3 codes for up/down/etc.
func escapeSS3Key(key *escapeKeyPair) rune {
var r rune
switch key.typ {
case 'D':
r = CharBackward
case 'C':
r = CharForward
case 'A':
r = CharPrev
case 'B':
r = CharNext
case 'H':
r = CharLineStart
case 'F':
r = CharLineEnd
default:
}
return r
}

type escapeKeyPair struct {
attr string
typ rune
Expand Down

0 comments on commit 8e4bd41

Please sign in to comment.