mirror of
https://github.com/strongdm/comply
synced 2024-11-24 16:44:53 +00:00
126 lines
2.3 KiB
Go
126 lines
2.3 KiB
Go
|
// +build windows
|
||
|
|
||
|
package readline
|
||
|
|
||
|
import "unsafe"
|
||
|
|
||
|
const (
|
||
|
VK_CANCEL = 0x03
|
||
|
VK_BACK = 0x08
|
||
|
VK_TAB = 0x09
|
||
|
VK_RETURN = 0x0D
|
||
|
VK_SHIFT = 0x10
|
||
|
VK_CONTROL = 0x11
|
||
|
VK_MENU = 0x12
|
||
|
VK_ESCAPE = 0x1B
|
||
|
VK_LEFT = 0x25
|
||
|
VK_UP = 0x26
|
||
|
VK_RIGHT = 0x27
|
||
|
VK_DOWN = 0x28
|
||
|
VK_DELETE = 0x2E
|
||
|
VK_LSHIFT = 0xA0
|
||
|
VK_RSHIFT = 0xA1
|
||
|
VK_LCONTROL = 0xA2
|
||
|
VK_RCONTROL = 0xA3
|
||
|
)
|
||
|
|
||
|
// RawReader translate input record to ANSI escape sequence.
|
||
|
// To provides same behavior as unix terminal.
|
||
|
type RawReader struct {
|
||
|
ctrlKey bool
|
||
|
altKey bool
|
||
|
}
|
||
|
|
||
|
func NewRawReader() *RawReader {
|
||
|
r := new(RawReader)
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
// only process one action in one read
|
||
|
func (r *RawReader) Read(buf []byte) (int, error) {
|
||
|
ir := new(_INPUT_RECORD)
|
||
|
var read int
|
||
|
var err error
|
||
|
next:
|
||
|
err = kernel.ReadConsoleInputW(stdin,
|
||
|
uintptr(unsafe.Pointer(ir)),
|
||
|
1,
|
||
|
uintptr(unsafe.Pointer(&read)),
|
||
|
)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
if ir.EventType != EVENT_KEY {
|
||
|
goto next
|
||
|
}
|
||
|
ker := (*_KEY_EVENT_RECORD)(unsafe.Pointer(&ir.Event[0]))
|
||
|
if ker.bKeyDown == 0 { // keyup
|
||
|
if r.ctrlKey || r.altKey {
|
||
|
switch ker.wVirtualKeyCode {
|
||
|
case VK_RCONTROL, VK_LCONTROL:
|
||
|
r.ctrlKey = false
|
||
|
case VK_MENU: //alt
|
||
|
r.altKey = false
|
||
|
}
|
||
|
}
|
||
|
goto next
|
||
|
}
|
||
|
|
||
|
if ker.unicodeChar == 0 {
|
||
|
var target rune
|
||
|
switch ker.wVirtualKeyCode {
|
||
|
case VK_RCONTROL, VK_LCONTROL:
|
||
|
r.ctrlKey = true
|
||
|
case VK_MENU: //alt
|
||
|
r.altKey = true
|
||
|
case VK_LEFT:
|
||
|
target = CharBackward
|
||
|
case VK_RIGHT:
|
||
|
target = CharForward
|
||
|
case VK_UP:
|
||
|
target = CharPrev
|
||
|
case VK_DOWN:
|
||
|
target = CharNext
|
||
|
}
|
||
|
if target != 0 {
|
||
|
return r.write(buf, target)
|
||
|
}
|
||
|
goto next
|
||
|
}
|
||
|
char := rune(ker.unicodeChar)
|
||
|
if r.ctrlKey {
|
||
|
switch char {
|
||
|
case 'A':
|
||
|
char = CharLineStart
|
||
|
case 'E':
|
||
|
char = CharLineEnd
|
||
|
case 'R':
|
||
|
char = CharBckSearch
|
||
|
case 'S':
|
||
|
char = CharFwdSearch
|
||
|
}
|
||
|
} else if r.altKey {
|
||
|
switch char {
|
||
|
case VK_BACK:
|
||
|
char = CharBackspace
|
||
|
}
|
||
|
return r.writeEsc(buf, char)
|
||
|
}
|
||
|
return r.write(buf, char)
|
||
|
}
|
||
|
|
||
|
func (r *RawReader) writeEsc(b []byte, char rune) (int, error) {
|
||
|
b[0] = '\033'
|
||
|
n := copy(b[1:], []byte(string(char)))
|
||
|
return n + 1, nil
|
||
|
}
|
||
|
|
||
|
func (r *RawReader) write(b []byte, char rune) (int, error) {
|
||
|
n := copy(b, []byte(string(char)))
|
||
|
return n, nil
|
||
|
}
|
||
|
|
||
|
func (r *RawReader) Close() error {
|
||
|
return nil
|
||
|
}
|