go.crypto/ssh/terminal: support ^U, ^D and ^L.
LGTM=bradfitz R=bradfitz, marios.nikolaou CC=golang-codereviews https://golang.org/cl/92220043
This commit is contained in:
@@ -108,6 +108,7 @@ func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
|
||||
|
||||
const (
|
||||
keyCtrlD = 4
|
||||
keyCtrlU = 21
|
||||
keyEnter = '\r'
|
||||
keyEscape = 27
|
||||
keyBackspace = 127
|
||||
@@ -122,6 +123,7 @@ const (
|
||||
keyEnd
|
||||
keyDeleteWord
|
||||
keyDeleteLine
|
||||
keyClearScreen
|
||||
)
|
||||
|
||||
// bytesToKey tries to parse a key sequence from b. If successful, it returns
|
||||
@@ -140,6 +142,8 @@ func bytesToKey(b []byte) (rune, []byte) {
|
||||
return keyBackspace, b[1:]
|
||||
case 11: // ^K
|
||||
return keyDeleteLine, b[1:]
|
||||
case 12: // ^L
|
||||
return keyClearScreen, b[1:]
|
||||
case 23: // ^W
|
||||
return keyDeleteWord, b[1:]
|
||||
}
|
||||
@@ -453,6 +457,23 @@ func (t *Terminal) handleKey(key rune) (line string, ok bool) {
|
||||
}
|
||||
t.line = t.line[:t.pos]
|
||||
t.moveCursorToPos(t.pos)
|
||||
case keyCtrlD:
|
||||
// Erase the character under the current position.
|
||||
// The EOF case when the line is empty is handled in
|
||||
// readLine().
|
||||
if t.pos < len(t.line) {
|
||||
t.pos++
|
||||
t.eraseNPreviousChars(1)
|
||||
}
|
||||
case keyCtrlU:
|
||||
t.eraseNPreviousChars(t.pos)
|
||||
case keyClearScreen:
|
||||
// Erases the screen and moves the cursor to the home position.
|
||||
t.queue([]rune("\x1b[2J\x1b[H"))
|
||||
t.queue([]rune(t.prompt))
|
||||
t.cursorX = len(t.prompt)
|
||||
t.cursorY = 0
|
||||
t.setLine(t.line, t.pos)
|
||||
default:
|
||||
if t.AutoCompleteCallback != nil {
|
||||
prefix := string(t.line[:t.pos])
|
||||
@@ -604,7 +625,9 @@ func (t *Terminal) readLine() (line string, err error) {
|
||||
break
|
||||
}
|
||||
if key == keyCtrlD {
|
||||
return "", io.EOF
|
||||
if len(t.line) == 0 {
|
||||
return "", io.EOF
|
||||
}
|
||||
}
|
||||
line, lineOk = t.handleKey(key)
|
||||
}
|
||||
|
||||
@@ -163,6 +163,22 @@ var keyPressTests = []struct {
|
||||
line: "£",
|
||||
throwAwayLines: 1,
|
||||
},
|
||||
{
|
||||
// Ctrl-D at the end of the line should be ignored.
|
||||
in: "a\004\r",
|
||||
line: "a",
|
||||
},
|
||||
{
|
||||
// a, b, left, Ctrl-D should erase the b.
|
||||
in: "ab\x1b[D\004\r",
|
||||
line: "a",
|
||||
},
|
||||
{
|
||||
// a, b, c, d, left, left, ^U should erase to the beginning of
|
||||
// the line.
|
||||
in: "abcd\x1b[D\x1b[D\025\r",
|
||||
line: "cd",
|
||||
},
|
||||
}
|
||||
|
||||
func TestKeyPresses(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user