Left: | ||
Right: |
OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |