1// +build windows 2 3package readline 4 5import "unsafe" 6 7const ( 8 VK_CANCEL = 0x03 9 VK_BACK = 0x08 10 VK_TAB = 0x09 11 VK_RETURN = 0x0D 12 VK_SHIFT = 0x10 13 VK_CONTROL = 0x11 14 VK_MENU = 0x12 15 VK_ESCAPE = 0x1B 16 VK_LEFT = 0x25 17 VK_UP = 0x26 18 VK_RIGHT = 0x27 19 VK_DOWN = 0x28 20 VK_DELETE = 0x2E 21 VK_LSHIFT = 0xA0 22 VK_RSHIFT = 0xA1 23 VK_LCONTROL = 0xA2 24 VK_RCONTROL = 0xA3 25) 26 27// RawReader translate input record to ANSI escape sequence. 28// To provides same behavior as unix terminal. 29type RawReader struct { 30 ctrlKey bool 31 altKey bool 32} 33 34func NewRawReader() *RawReader { 35 r := new(RawReader) 36 return r 37} 38 39// only process one action in one read 40func (r *RawReader) Read(buf []byte) (int, error) { 41 ir := new(_INPUT_RECORD) 42 var read int 43 var err error 44next: 45 err = kernel.ReadConsoleInputW(stdin, 46 uintptr(unsafe.Pointer(ir)), 47 1, 48 uintptr(unsafe.Pointer(&read)), 49 ) 50 if err != nil { 51 return 0, err 52 } 53 if ir.EventType != EVENT_KEY { 54 goto next 55 } 56 ker := (*_KEY_EVENT_RECORD)(unsafe.Pointer(&ir.Event[0])) 57 if ker.bKeyDown == 0 { // keyup 58 if r.ctrlKey || r.altKey { 59 switch ker.wVirtualKeyCode { 60 case VK_RCONTROL, VK_LCONTROL: 61 r.ctrlKey = false 62 case VK_MENU: //alt 63 r.altKey = false 64 } 65 } 66 goto next 67 } 68 69 if ker.unicodeChar == 0 { 70 var target rune 71 switch ker.wVirtualKeyCode { 72 case VK_RCONTROL, VK_LCONTROL: 73 r.ctrlKey = true 74 case VK_MENU: //alt 75 r.altKey = true 76 case VK_LEFT: 77 target = CharBackward 78 case VK_RIGHT: 79 target = CharForward 80 case VK_UP: 81 target = CharPrev 82 case VK_DOWN: 83 target = CharNext 84 } 85 if target != 0 { 86 return r.write(buf, target) 87 } 88 goto next 89 } 90 char := rune(ker.unicodeChar) 91 if r.ctrlKey { 92 switch char { 93 case 'A': 94 char = CharLineStart 95 case 'E': 96 char = CharLineEnd 97 case 'R': 98 char = CharBckSearch 99 case 'S': 100 char = CharFwdSearch 101 } 102 } else if r.altKey { 103 switch char { 104 case VK_BACK: 105 char = CharBackspace 106 } 107 return r.writeEsc(buf, char) 108 } 109 return r.write(buf, char) 110} 111 112func (r *RawReader) writeEsc(b []byte, char rune) (int, error) { 113 b[0] = '\033' 114 n := copy(b[1:], []byte(string(char))) 115 return n + 1, nil 116} 117 118func (r *RawReader) write(b []byte, char rune) (int, error) { 119 n := copy(b, []byte(string(char))) 120 return n, nil 121} 122 123func (r *RawReader) Close() error { 124 return nil 125} 126