Преглед изворни кода

go.crypto/ssh/terminal: support ^U, ^D and ^L.

LGTM=bradfitz
R=bradfitz, marios.nikolaou
CC=golang-codereviews
https://golang.org/cl/92220043
Adam Langley пре 11 година
родитељ
комит
9fb3568646
2 измењених фајлова са 40 додато и 1 уклоњено
  1. 24 1
      ssh/terminal/terminal.go
  2. 16 0
      ssh/terminal/terminal_test.go

+ 24 - 1
ssh/terminal/terminal.go

@@ -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)
 		}

+ 16 - 0
ssh/terminal/terminal_test.go

@@ -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) {