diff --git a/gui/input.go b/gui/input.go index fd37b66..f2f613b 100644 --- a/gui/input.go +++ b/gui/input.go @@ -7,68 +7,250 @@ func (gui *GUI) char(w *glfw.Window, r rune) { gui.terminal.Write([]byte(string(r))) } +func modsPressed(pressed glfw.ModifierKey, mods ...glfw.ModifierKey) bool { + for _, mod := range mods { + if pressed&mod == 0 { + return false + } + pressed ^= mod + } + return pressed == 0 +} + func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) { if action == glfw.Repeat || action == glfw.Press { gui.logger.Debugf("KEY PRESS: key=0x%X scan=0x%X", key, scancode) switch true { - case mods&glfw.ModControl > 0: - if mods&glfw.ModShift > 0 { - // ctrl + shift + - switch key { - case glfw.KeyV: - // todo handle both these errors - if buf, err := gui.window.GetClipboardString(); err == nil { - _ = gui.terminal.Write([]byte(buf)) - } - case glfw.KeySemicolon: - gui.config.Slomo = !gui.config.Slomo + case modsPressed(mods, glfw.ModControl, glfw.ModShift): + switch key { + case glfw.KeyV: + // todo handle both these errors + if buf, err := gui.window.GetClipboardString(); err == nil { + _ = gui.terminal.Write([]byte(buf)) } - } else { - // ctrl + - switch key { - case glfw.KeyC: // ctrl^c - gui.logger.Debugf("Sending CTRL^C") - gui.terminal.Write([]byte{0x3}) // send EOT + case glfw.KeySemicolon: + gui.config.Slomo = !gui.config.Slomo + } + case modsPressed(mods, glfw.ModControl): + switch key { + case glfw.KeyC: // ctrl^c + gui.logger.Debugf("Sending CTRL^C") + gui.terminal.Write([]byte{0x3}) // send EOT + } + default: // no mods + + switch key { + case glfw.KeyF1: + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'P', + }) + case glfw.KeyF2: + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'Q', + }) + case glfw.KeyF3: + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'R', + }) + case glfw.KeyF4: + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'S', + }) + case glfw.KeyF5: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '1', '5', '~', + }) + case glfw.KeyF6: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '1', '7', '~', + }) + case glfw.KeyF7: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '1', '8', '~', + }) + case glfw.KeyF8: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '1', '9', '~', + }) + case glfw.KeyF9: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '2', '0', '~', + }) + case glfw.KeyF10: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '2', '1', '~', + }) + case glfw.KeyF11: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '2', '3', '~', + }) + case glfw.KeyF12: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '2', '4', '~', + }) + case glfw.KeyInsert: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '2', '~', + }) + case glfw.KeyDelete: + gui.terminal.Write([]byte{ + 0x1b, + '[', + '3', '~', + }) + case glfw.KeyHome: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'H', + }) + } else { + gui.terminal.Write([]byte{ + 0x1b, + '[', + 'H', + }) + } + case glfw.KeyEnd: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'F', + }) + } else { + gui.terminal.Write([]byte{ + 0x1b, + '[', + 'F', + }) + } + case glfw.KeyEscape: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 0x1b, + }) + } else { + gui.terminal.Write([]byte{ + 0x1b, + '[', + 0x1b, + }) + } + case glfw.KeyTab: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'I', + }) + } else { + gui.terminal.Write([]byte{ + 0x09, + }) + } + case glfw.KeyEnter: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'M', + }) + } else { + gui.terminal.Write([]byte{0x0a}) + } + case glfw.KeyBackspace: + gui.terminal.Write([]byte{0x08}) + case glfw.KeyUp: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'A', + }) + } else { + gui.terminal.Write([]byte{ + 0x1b, + '[', + 'A', + }) + } + case glfw.KeyDown: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'B', + }) + } else { + gui.terminal.Write([]byte{ + 0x1b, + '[', + 'B', + }) + } + case glfw.KeyLeft: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'D', + }) + } else { + gui.terminal.Write([]byte{ + 0x1b, + '[', + 'D', + }) + } + case glfw.KeyRight: + if gui.terminal.IsApplicationCursorKeysModeEnabled() { + gui.terminal.Write([]byte{ + 0x1b, + 'O', + 'C', + }) + } else { + gui.terminal.Write([]byte{ + 0x1b, + '[', + 'C', + }) } } - } - switch key { - case glfw.KeyEnter: - gui.terminal.Write([]byte{0x0a}) - case glfw.KeyBackspace: - gui.terminal.Write([]byte{0x08}) - case glfw.KeyUp: - gui.terminal.Write([]byte{ - 0x1b, - '[', - 'A', - }) - case glfw.KeyDown: - gui.terminal.Write([]byte{ - 0x1b, - '[', - 'B', - }) - case glfw.KeyLeft: - gui.terminal.Write([]byte{ - 0x1b, - '[', - 'D', - }) - case glfw.KeyRight: - gui.terminal.Write([]byte{ - 0x1b, - '[', - 'C', - }) - case glfw.KeyTab: - gui.terminal.Write([]byte{ - 0x09, - }) } //gui.logger.Debugf("Key pressed: 0x%X %q", key, string([]byte{byte(key)})) diff --git a/terminal/output.go b/terminal/output.go index 0f4faf7..ba79ec6 100644 --- a/terminal/output.go +++ b/terminal/output.go @@ -41,7 +41,7 @@ func (terminal *Terminal) processInput(ctx context.Context, pty chan rune) { if ok { if err := handler(pty, terminal); err != nil { - terminal.logger.Errorf("Error handling escape sequence 0x%X: %s", b, err) + terminal.logger.Errorf("Error handling escape sequence: %s", err) } continue } @@ -49,18 +49,22 @@ func (terminal *Terminal) processInput(ctx context.Context, pty chan rune) { terminal.logger.Debugf("Received character 0x%X: %q", b, string(b)) switch b { - case 0x0a: + case 0x0a, 0x0c, 0x0b: // LF, FF, VT terminal.ActiveBuffer().NewLine() - case 0x0d: + case 0x0d: // CR terminal.ActiveBuffer().CarriageReturn() - case 0x08: + case 0x08: // BS // backspace terminal.ActiveBuffer().Backspace() - case 0x07: + case 0x07: // BEL // @todo ring bell - flash red or some shit? + case 0x05: // ENQ + terminal.logger.Errorf("Received ENQ!") + case 0xe, 0xf: + terminal.logger.Errorf("Received SI/SO") + case 0x09: + terminal.logger.Errorf("Received TAB") default: - // render character at current location - // fmt.Printf("%s\n", string([]byte{b})) if b >= 0x20 { terminal.ActiveBuffer().Write(b) } else { diff --git a/terminal/terminal.go b/terminal/terminal.go index 4410eac..a5f5fca 100644 --- a/terminal/terminal.go +++ b/terminal/terminal.go @@ -90,6 +90,10 @@ func New(pty *os.File, logger *zap.SugaredLogger, config *config.Config) *Termin } } +func (terminal *Terminal) IsApplicationCursorKeysModeEnabled() bool { + return terminal.modes.ApplicationCursorKeys +} + func (terminal *Terminal) SetMouseMode(mode MouseMode) { terminal.mouseMode = mode }