You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
2.3 KiB

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