diff --git a/terminal.go b/terminal.go index 9255449..5fdfff0 100644 --- a/terminal.go +++ b/terminal.go @@ -160,6 +160,7 @@ const ( keyEnd keyDeleteWord keyDeleteLine + keyDelete keyClearScreen keyPasteStart keyPasteEnd @@ -228,6 +229,10 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { } } + if !pasteActive && len(b) >= 4 && b[0] == keyEscape && b[1] == '[' && b[2] == '3' && b[3] == '~' { + return keyDelete, b[4:] + } + if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { switch b[5] { case 'C': @@ -590,7 +595,7 @@ func (t *Terminal) handleKey(key rune) (line string, ok bool) { } t.line = t.line[:t.pos] t.moveCursorToPos(t.pos) - case keyCtrlD: + case keyCtrlD, keyDelete: // Erase the character under the current position. // The EOF case when the line is empty is handled in // readLine(). diff --git a/terminal_test.go b/terminal_test.go index 5d35cc5..45aeffa 100644 --- a/terminal_test.go +++ b/terminal_test.go @@ -238,6 +238,31 @@ var keyPressTests = []struct { in: "a\003\r", err: io.EOF, }, + { + // Delete at EOL: nothing + in: "abc\x1b[3~\r", + line: "abc", + }, + { + // Delete in empty string: nothing + in: "\x1b[3~\r", + line: "", + }, + { + // Move left, delete: delete 'c' + in: "abc\x1b[D\x1b[3~\r", + line: "ab", + }, + { + // Home, delete: delete 'a' + in: "abc\x1b[H\x1b[3~\r", + line: "bc", + }, + { + // Home, delete twice: delete 'a' and 'b' + in: "abc\x1b[H\x1b[3~\x1b[3~\r", + line: "c", + }, } func TestKeyPresses(t *testing.T) { @@ -387,7 +412,7 @@ func TestReadPasswordLineEnd(t *testing.T) { input string want string } - var tests = []testType{ + tests := []testType{ {"\r\n", ""}, {"test\r\n", "test"}, {"test\r", "test"},