Skip to content

better function key support for rxvt-unicode #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: legacy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions terminfo/dynamic/dynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,22 +367,11 @@ func LoadTerminfo(name string) (*terminfo.Terminfo, string, error) {
// ALL XTerm sequences dynamically
if t.KeyShfHome == "\x1b[1;2H" && t.KeyShfEnd == "\x1b[1;2F" && t.KeyShfRight == "\x1b[1;2C" && t.KeyShfLeft == "\x1b[1;2D" {
t.Modifiers = terminfo.ModifiersXTerm
}

// And the same thing for rxvt and workalikes (Eterm, aterm, etc.)
// It seems that urxvt at least send escaped as ALT prefix for these,
// although some places seem to indicate a separate ALT key sesquence.
if t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" {
t.KeyShfUp = "\x1b[a"
t.KeyShfDown = "\x1b[b"
t.KeyCtrlUp = "\x1b[Oa"
t.KeyCtrlDown = "\x1b[Ob"
t.KeyCtrlRight = "\x1b[Oc"
t.KeyCtrlLeft = "\x1b[Od"
}
if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" {
t.KeyCtrlHome = "\x1b[7^"
t.KeyCtrlEnd = "\x1b[8^"
} else if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" && t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" {
t.Modifiers = terminfo.ModifiersUrxvt
}

// If the kmous entry is present, then we need to record the
Expand Down
26 changes: 8 additions & 18 deletions terminfo/mkinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ func getinfo(name string) (*terminfo.Terminfo, string, error) {
// keys, but it's nicer to match them to modifiers.
if tc.getstr("kRIT") == "\x1b[1;2C" {
t.Modifiers = terminfo.ModifiersXTerm
// And the same thing for rxvt
// It seems that urxvt at least send ESC as ALT prefix for these,
// although some places seem to indicate a separate ALT key sequence.
// Users are encouraged to update to an emulator that more closely
// matches xterm for better functionality.
} else if tc.getstr("kRIT") == "\x1b[c" && tc.getstr("kLFT") == "\x1b[d" &&
tc.getstr("kHOM") == "\x1b[7$" && tc.getstr("kEND") == "\x1b[8$" {
t.Modifiers = terminfo.ModifiersUrxvt
} else {
// Lookup high level function keys.
t.KeyShfInsert = tc.getstr("kIC")
Expand Down Expand Up @@ -346,24 +354,6 @@ func getinfo(name string) (*terminfo.Terminfo, string, error) {
t.KeyF64 = tc.getstr("kf64")
}

// And the same thing for rxvt.
// It seems that urxvt at least send ESC as ALT prefix for these,
// although some places seem to indicate a separate ALT key sequence.
// Users are encouraged to update to an emulator that more closely
// matches xterm for better functionality.
if t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" {
t.KeyShfUp = "\x1b[a"
t.KeyShfDown = "\x1b[b"
t.KeyCtrlUp = "\x1b[Oa"
t.KeyCtrlDown = "\x1b[Ob"
t.KeyCtrlRight = "\x1b[Oc"
t.KeyCtrlLeft = "\x1b[Od"
}
if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" {
t.KeyCtrlHome = "\x1b[7^"
t.KeyCtrlEnd = "\x1b[8^"
}

// Technically the RGB flag that is provided for xterm-direct is not
// quite right. The problem is that the -direct flag that was introduced
// with ncurses 6.1 requires a parsing for the parameters that we lack.
Expand Down
50 changes: 2 additions & 48 deletions terminfo/r/rxvt/term.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,31 +371,8 @@ func init() {
KeyF8: "\x1b[19~",
KeyF9: "\x1b[20~",
KeyF10: "\x1b[21~",
KeyF11: "\x1b[23~",
KeyF12: "\x1b[24~",
KeyF13: "\x1b[25~",
KeyF14: "\x1b[26~",
KeyF15: "\x1b[28~",
KeyF16: "\x1b[29~",
KeyF17: "\x1b[31~",
KeyF18: "\x1b[32~",
KeyF19: "\x1b[33~",
KeyF20: "\x1b[34~",
KeyBacktab: "\x1b[Z",
KeyShfLeft: "\x1b[d",
KeyShfRight: "\x1b[c",
KeyShfUp: "\x1b[a",
KeyShfDown: "\x1b[b",
KeyShfHome: "\x1b[7$",
KeyShfEnd: "\x1b[8$",
KeyShfInsert: "\x1b[2$",
KeyShfDelete: "\x1b[3$",
KeyCtrlUp: "\x1b[Oa",
KeyCtrlDown: "\x1b[Ob",
KeyCtrlRight: "\x1b[Oc",
KeyCtrlLeft: "\x1b[Od",
KeyCtrlHome: "\x1b[7^",
KeyCtrlEnd: "\x1b[8^",
Modifiers: 3,
})

// rxvt-unicode terminal with 256 colors (X Window System)
Expand Down Expand Up @@ -451,30 +428,7 @@ func init() {
KeyF8: "\x1b[19~",
KeyF9: "\x1b[20~",
KeyF10: "\x1b[21~",
KeyF11: "\x1b[23~",
KeyF12: "\x1b[24~",
KeyF13: "\x1b[25~",
KeyF14: "\x1b[26~",
KeyF15: "\x1b[28~",
KeyF16: "\x1b[29~",
KeyF17: "\x1b[31~",
KeyF18: "\x1b[32~",
KeyF19: "\x1b[33~",
KeyF20: "\x1b[34~",
KeyBacktab: "\x1b[Z",
KeyShfLeft: "\x1b[d",
KeyShfRight: "\x1b[c",
KeyShfUp: "\x1b[a",
KeyShfDown: "\x1b[b",
KeyShfHome: "\x1b[7$",
KeyShfEnd: "\x1b[8$",
KeyShfInsert: "\x1b[2$",
KeyShfDelete: "\x1b[3$",
KeyCtrlUp: "\x1b[Oa",
KeyCtrlDown: "\x1b[Ob",
KeyCtrlRight: "\x1b[Oc",
KeyCtrlLeft: "\x1b[Od",
KeyCtrlHome: "\x1b[7^",
KeyCtrlEnd: "\x1b[8^",
Modifiers: 3,
})
}
1 change: 1 addition & 0 deletions terminfo/terminfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ const (
ModifiersNone = 0
ModifiersXTerm = 1
ModifiersDynamic = 2
ModifiersUrxvt = 3
)

type stackElem struct {
Expand Down
48 changes: 48 additions & 0 deletions tscreen.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,52 @@ func (t *tScreen) prepareXtermModifiers() {
t.prepareKeyModXTerm(KeyF12, t.ti.KeyF12)
}

func (t *tScreen) prepareKeyModUrxvt(key Key, val string) {
val = val[:len(val)-1]
t.prepareKeyMod(key, ModShift, val+"$")
t.prepareKeyMod(key, ModCtrl, val+"^")
t.prepareKeyMod(key, ModCtrl|ModShift, val+"@")
}

func (t *tScreen) prepareUrxvtModifiers() {
if t.ti.Modifiers != terminfo.ModifiersUrxvt {
return
}
t.prepareKeyModUrxvt(KeyInsert, t.ti.KeyInsert)
t.prepareKeyModUrxvt(KeyDelete, t.ti.KeyDelete)
t.prepareKeyModUrxvt(KeyPgUp, t.ti.KeyPgUp)
t.prepareKeyModUrxvt(KeyPgDn, t.ti.KeyPgDn)
t.prepareKeyModUrxvt(KeyHome, t.ti.KeyHome)
t.prepareKeyModUrxvt(KeyEnd, t.ti.KeyEnd)
for i := 1; i <= 4; i++ {
key := Key(int(KeyUp)-1+i)
t.prepareKeyMod(key, ModShift, fmt.Sprintf("\x1b[%c", 96+i))
t.prepareKeyMod(key, ModCtrl, fmt.Sprintf("\x1bO%c", 96+i))
// we implement Ctrl-Shift as "application mode" for cursor keys
// in reality, urxvt treats Ctrl-Shift like Shift
t.prepareKeyMod(key, ModCtrl|ModShift, fmt.Sprintf("\x1bO%c", 64+i))
}
for i := 1; i <= 10; i++ {
key := Key(int(KeyF1)-1+i)
j := 10+i
if i >=6 { j++ }
t.prepareKeyModReplace(key, key+22, ModCtrl, fmt.Sprintf("\x1b[%d^", j))
j = 22+i
if i >=5 { j++ }
if i >=7 { j++ }
t.prepareKeyModReplace(key, key+10, ModShift, fmt.Sprintf("\x1b[%d~", j))
t.prepareKeyModReplace(key, key+32, ModCtrl|ModShift, fmt.Sprintf("\x1b[%d^", j))
key = Key(int(KeyF11)-1+i)
// urxvt treats F11 to F20 like Shift-F1 to Shift-F10, ditto plus Ctrl
// t.prepareKeyMod(key, ModNone, fmt.Sprintf("\x1b[%d~", j))
t.prepareKeyMod(key, ModNone, fmt.Sprintf("\x1b[%d#", j)) // non-standard!
t.prepareKeyModReplace(key, key+10, ModShift, fmt.Sprintf("\x1b[%d$", j))
// t.prepareKeyMod(key, ModCtrl, fmt.Sprintf("\x1b[%d^", j))
t.prepareKeyMod(key, ModCtrl, fmt.Sprintf("\x1b[%d&", j)) // non-standard!
t.prepareKeyModReplace(key, key+32, ModCtrl|ModShift, fmt.Sprintf("\x1b[%d@", j))
}
}

func (t *tScreen) prepareKey(key Key, val string) {
t.prepareKeyMod(key, ModNone, val)
}
Expand Down Expand Up @@ -471,6 +517,8 @@ func (t *tScreen) prepareKeys() {
t.prepareKeyMod(KeyEnd, ModMeta|ModShift, ti.KeyMetaShfEnd)
}

t.prepareUrxvtModifiers() // must be before application mode cursor keys below

// Sadly, xterm handling of keycodes is somewhat erratic. In
// particular, different codes are sent depending on application
// mode is in use or not, and the entries for many of these are
Expand Down