Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1641)

Side by Side Diff: ssh/terminal/terminal.go

Issue 92220043: code review 92220043: go.crypto/ssh/terminal: support ^U, ^D and ^L. (Closed)
Patch Set: diff -r fe6c00a82e55 https://code.google.com/p/go.crypto/ Created 9 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ssh/terminal/terminal_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package terminal 5 package terminal
6 6
7 import ( 7 import (
8 "io" 8 "io"
9 "sync" 9 "sync"
10 "unicode/utf8" 10 "unicode/utf8"
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 prompt: prompt, 101 prompt: prompt,
102 termWidth: 80, 102 termWidth: 80,
103 termHeight: 24, 103 termHeight: 24,
104 echo: true, 104 echo: true,
105 historyIndex: -1, 105 historyIndex: -1,
106 } 106 }
107 } 107 }
108 108
109 const ( 109 const (
110 keyCtrlD = 4 110 keyCtrlD = 4
111 keyCtrlU = 21
111 keyEnter = '\r' 112 keyEnter = '\r'
112 keyEscape = 27 113 keyEscape = 27
113 keyBackspace = 127 114 keyBackspace = 127
114 keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota 115 keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
115 keyUp 116 keyUp
116 keyDown 117 keyDown
117 keyLeft 118 keyLeft
118 keyRight 119 keyRight
119 keyAltLeft 120 keyAltLeft
120 keyAltRight 121 keyAltRight
121 keyHome 122 keyHome
122 keyEnd 123 keyEnd
123 keyDeleteWord 124 keyDeleteWord
124 keyDeleteLine 125 keyDeleteLine
126 keyClearScreen
125 ) 127 )
126 128
127 // bytesToKey tries to parse a key sequence from b. If successful, it returns 129 // bytesToKey tries to parse a key sequence from b. If successful, it returns
128 // the key and the remainder of the input. Otherwise it returns utf8.RuneError. 130 // the key and the remainder of the input. Otherwise it returns utf8.RuneError.
129 func bytesToKey(b []byte) (rune, []byte) { 131 func bytesToKey(b []byte) (rune, []byte) {
130 if len(b) == 0 { 132 if len(b) == 0 {
131 return utf8.RuneError, nil 133 return utf8.RuneError, nil
132 } 134 }
133 135
134 switch b[0] { 136 switch b[0] {
135 case 1: // ^A 137 case 1: // ^A
136 return keyHome, b[1:] 138 return keyHome, b[1:]
137 case 5: // ^E 139 case 5: // ^E
138 return keyEnd, b[1:] 140 return keyEnd, b[1:]
139 case 8: // ^H 141 case 8: // ^H
140 return keyBackspace, b[1:] 142 return keyBackspace, b[1:]
141 case 11: // ^K 143 case 11: // ^K
142 return keyDeleteLine, b[1:] 144 return keyDeleteLine, b[1:]
145 case 12: // ^L
146 return keyClearScreen, b[1:]
143 case 23: // ^W 147 case 23: // ^W
144 return keyDeleteWord, b[1:] 148 return keyDeleteWord, b[1:]
145 } 149 }
146 150
147 if b[0] != keyEscape { 151 if b[0] != keyEscape {
148 if !utf8.FullRune(b) { 152 if !utf8.FullRune(b) {
149 return utf8.RuneError, b 153 return utf8.RuneError, b
150 } 154 }
151 r, l := utf8.DecodeRune(b) 155 r, l := utf8.DecodeRune(b)
152 return r, b[l:] 156 return r, b[l:]
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 t.eraseNPreviousChars(t.countToLeftWord()) 450 t.eraseNPreviousChars(t.countToLeftWord())
447 case keyDeleteLine: 451 case keyDeleteLine:
448 // Delete everything from the current cursor position to the 452 // Delete everything from the current cursor position to the
449 // end of line. 453 // end of line.
450 for i := t.pos; i < len(t.line); i++ { 454 for i := t.pos; i < len(t.line); i++ {
451 t.queue(space) 455 t.queue(space)
452 t.cursorX++ 456 t.cursorX++
453 } 457 }
454 t.line = t.line[:t.pos] 458 t.line = t.line[:t.pos]
455 t.moveCursorToPos(t.pos) 459 t.moveCursorToPos(t.pos)
460 case keyCtrlD:
461 // Erase the charactor under the current position.
marios.nikolaou 2014/05/11 09:13:58 Should this be 'character'?
agl1 2014/05/13 03:21:05 Yep, thanks.
462 // The EOF case when the line is empty is handled in
463 // readLine().
464 if t.pos < len(t.line) {
465 t.pos++
466 t.eraseNPreviousChars(1)
467 }
468 case keyCtrlU:
469 t.eraseNPreviousChars(t.pos)
470 case keyClearScreen:
471 // Erases the screen and moves the cursor to the home position.
472 t.queue([]rune("\x1b[2J\x1b[H"))
473 t.queue([]rune(t.prompt))
474 t.cursorX = len(t.prompt)
475 t.cursorY = 0
476 t.setLine(t.line, t.pos)
456 default: 477 default:
457 if t.AutoCompleteCallback != nil { 478 if t.AutoCompleteCallback != nil {
458 prefix := string(t.line[:t.pos]) 479 prefix := string(t.line[:t.pos])
459 suffix := string(t.line[t.pos:]) 480 suffix := string(t.line[t.pos:])
460 481
461 t.lock.Unlock() 482 t.lock.Unlock()
462 newLine, newPos, completeOk := t.AutoCompleteCallback(pr efix+suffix, len(prefix), key) 483 newLine, newPos, completeOk := t.AutoCompleteCallback(pr efix+suffix, len(prefix), key)
463 t.lock.Lock() 484 t.lock.Lock()
464 485
465 if completeOk { 486 if completeOk {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 for { 618 for {
598 rest := t.remainder 619 rest := t.remainder
599 lineOk := false 620 lineOk := false
600 for !lineOk { 621 for !lineOk {
601 var key rune 622 var key rune
602 key, rest = bytesToKey(rest) 623 key, rest = bytesToKey(rest)
603 if key == utf8.RuneError { 624 if key == utf8.RuneError {
604 break 625 break
605 } 626 }
606 if key == keyCtrlD { 627 if key == keyCtrlD {
607 » » » » return "", io.EOF 628 » » » » if len(t.line) == 0 {
629 » » » » » return "", io.EOF
630 » » » » }
608 } 631 }
609 line, lineOk = t.handleKey(key) 632 line, lineOk = t.handleKey(key)
610 } 633 }
611 if len(rest) > 0 { 634 if len(rest) > 0 {
612 n := copy(t.inBuf[:], rest) 635 n := copy(t.inBuf[:], rest)
613 t.remainder = t.inBuf[:n] 636 t.remainder = t.inBuf[:n]
614 } else { 637 } else {
615 t.remainder = nil 638 t.remainder = nil
616 } 639 }
617 t.c.Write(t.outBuf) 640 t.c.Write(t.outBuf)
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { 713 func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
691 if n >= s.size { 714 if n >= s.size {
692 return "", false 715 return "", false
693 } 716 }
694 index := s.head - n 717 index := s.head - n
695 if index < 0 { 718 if index < 0 {
696 index += s.max 719 index += s.max
697 } 720 }
698 return s.entries[index], true 721 return s.entries[index], true
699 } 722 }
OLDNEW
« no previous file with comments | « no previous file | ssh/terminal/terminal_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b