getch.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Public Domain Software
  3. *
  4. * I (Matthias Ladkau) am the author of the source code in this file.
  5. * I have placed the source code in this file in the public domain.
  6. *
  7. * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. /*
  10. Package getch implements a platform agnostic character-wise input capture.
  11. Things which work on all platforms:
  12. - Detection of special keys F1-F12, Esc, Enter, Cursor keys, etc.
  13. - Key combinations: CTRL+<Letter>, Shift+<Letter>
  14. - Normal character input via KeyEvent.Rune
  15. Example code:
  16. func main() {
  17. var err error
  18. var e *getch.KeyEvent
  19. if err = getch.Start(); err != nil {
  20. fmt.Println(err)
  21. return
  22. }
  23. defer getch.Stop()
  24. for e == nil || e.Code != getch.KeyTab {
  25. e, err = getch.Getch()
  26. fmt.Println("==>", e, err)
  27. }
  28. }
  29. */
  30. package getch
  31. import (
  32. "errors"
  33. "fmt"
  34. )
  35. // Static errors
  36. /*
  37. ErrNotImplemented is returned if the platform is not supported by getch
  38. */
  39. var ErrNotImplemented = errors.New("Not implemented")
  40. // Detail specific (dynamic) errors
  41. /*
  42. ErrUnknownEscapeSequence is returned if an unknown escape sequence was retrieved.
  43. The sequence in question is located in the Detail byte slice.
  44. */
  45. type ErrUnknownEscapeSequence struct {
  46. Detail []byte
  47. }
  48. /*
  49. Error returns a string representation of this error.
  50. */
  51. func (e *ErrUnknownEscapeSequence) Error() string {
  52. return fmt.Sprintf("Unknown escape sequence: %v", e.Detail)
  53. }
  54. /*
  55. KeyCode is a platform-independent key code
  56. */
  57. type KeyCode string
  58. /*
  59. Key codes for the KeyEvent object
  60. */
  61. const (
  62. // Function keys
  63. KeyF1 = "Key_F1"
  64. KeyF2 = "Key_F2"
  65. KeyF3 = "Key_F3"
  66. KeyF4 = "Key_F4"
  67. KeyF5 = "Key_F5"
  68. KeyF6 = "Key_F6"
  69. KeyF7 = "Key_F7"
  70. KeyF8 = "Key_F8"
  71. KeyF9 = "Key_F9"
  72. KeyF10 = "Key_F10"
  73. KeyF11 = "Key_F11"
  74. KeyF12 = "Key_F12"
  75. // Control keys
  76. KeyEnter = "Key_ENTER"
  77. KeyBackspace = "Key_BACKSPACE"
  78. KeyEsc = "Key_ESC"
  79. KeyTab = "Key_TAB"
  80. KeyInsert = "Key_INSERT"
  81. KeyDelete = "Key_DELETE"
  82. KeyHome = "Key_HOME"
  83. KeyEnd = "Key_END"
  84. KeyPgup = "Key_PAGE_UP"
  85. KeyPgdn = "Key_PAGE_DOWN"
  86. KeyArrowUp = "Key_ARROW_UP"
  87. KeyArrowDown = "Key_ARROW_DOWN"
  88. KeyArrowLeft = "Key_ARROW_LEFT"
  89. KeyArrowRight = "Key_ARROW_RIGHT"
  90. KeyCommand = "Key_CMD" // "Windows" key
  91. // Normal letters
  92. KeyA = "Key_A"
  93. KeyB = "Key_B"
  94. KeyC = "Key_C"
  95. KeyD = "Key_D"
  96. KeyE = "Key_E"
  97. KeyF = "Key_F"
  98. KeyG = "Key_G"
  99. KeyH = "Key_H"
  100. KeyI = "Key_I"
  101. KeyJ = "Key_J"
  102. KeyK = "Key_K"
  103. KeyL = "Key_L"
  104. KeyM = "Key_M"
  105. KeyN = "Key_N"
  106. KeyO = "Key_O"
  107. KeyP = "Key_P"
  108. KeyQ = "Key_Q"
  109. KeyR = "Key_R"
  110. KeyS = "Key_S"
  111. KeyT = "Key_T"
  112. KeyU = "Key_U"
  113. KeyV = "Key_V"
  114. KeyW = "Key_W"
  115. KeyX = "Key_X"
  116. KeyY = "Key_Y"
  117. KeyZ = "Key_Z"
  118. // Normal numbers
  119. Key1 = "Key_1"
  120. Key2 = "Key_2"
  121. Key3 = "Key_3"
  122. Key4 = "Key_4"
  123. Key5 = "Key_5"
  124. Key6 = "Key_6"
  125. Key7 = "Key_7"
  126. Key8 = "Key_8"
  127. Key9 = "Key_9"
  128. Key0 = "Key_0"
  129. // Normal Symbols
  130. KeyBacktick = "Key_BACKTICK"
  131. KeyMinus = "Key_MINUS"
  132. KeyEqual = "Key_EQUAL"
  133. KeyBracketOpen = "Key_BRACKET_OPEN"
  134. KeyBracketClose = "Key_BRACKET_CLOSE"
  135. KeySemiColon = "Key_SEMICOLON"
  136. KeyQuote = "Key_QUOTE"
  137. KeyHash = "Key_HASH"
  138. KeyBackslash = "Key_BACKSLASH"
  139. KeyComma = "Key_COMMA"
  140. KeyDot = "Key_DOT"
  141. KeySlash = "Key_SLASH"
  142. // Special states
  143. KeyUnknown = "Key_UNKNOWN"
  144. )
  145. /*
  146. KeyEvent objects are produced by an input reader.
  147. */
  148. type KeyEvent struct {
  149. Code KeyCode // Code of the pressed key
  150. Ctrl bool // Flag if the ctrl key is also pressed
  151. Alt bool // Flag if the alt key is also pressed
  152. Shift bool // Flag if the shift key is also pressed
  153. Rune rune // Produced rune if the key is printable
  154. RawBuf []byte // Raw input buffer since the last key event
  155. }
  156. func (k *KeyEvent) String() string {
  157. ret := fmt.Sprintf("%v %c [%#v - 0x%x]", k.Code, k.Rune, k.Rune, k.Rune)
  158. if k.Shift {
  159. ret += " + SHIFT"
  160. }
  161. if k.Ctrl {
  162. ret += " + CTRL"
  163. }
  164. if k.Alt {
  165. ret += " + ALT"
  166. }
  167. return ret
  168. }
  169. /*
  170. internalKeyEvent is used to pass additional information to the getch function
  171. */
  172. type internalKeyEvent struct {
  173. *KeyEvent
  174. err error
  175. }
  176. /*
  177. getch is a platform-native single character input reader object.
  178. */
  179. type getch interface {
  180. /*
  181. GetKey returns the next key event or an error. This function blocks if no key
  182. event is available.
  183. */
  184. GetKey() *internalKeyEvent
  185. /*
  186. GetKeyAsync returns the next key event or an error. This function does not block if no key
  187. event is available - in this case nil is returned.
  188. */
  189. GetKeyAsync() *internalKeyEvent
  190. /*
  191. CursorPosition returns the current cursor position.
  192. */
  193. CursorPosition() (int, int, error)
  194. /*
  195. SetCursorPosition sets the current cursor position
  196. */
  197. SetCursorPosition(int, int) error
  198. /*
  199. Close detaches the character reader.
  200. */
  201. Close()
  202. }
  203. /*
  204. Singleton getch instance.
  205. */
  206. var g getch
  207. /*
  208. Start starts the character reader.
  209. */
  210. func Start() error {
  211. var err error
  212. if g == nil {
  213. g, err = attachReader()
  214. }
  215. return err
  216. }
  217. /*
  218. CursorPosition returns the current cursor position.
  219. */
  220. func CursorPosition() (int, int, error) {
  221. var x, y int
  222. var err error
  223. if g != nil {
  224. x, y, err = g.CursorPosition()
  225. }
  226. return x, y, err
  227. }
  228. /*
  229. SetCursorPosition sets the current cursor position.
  230. */
  231. func SetCursorPosition(x, y int) error {
  232. var err error
  233. if g != nil {
  234. err = g.SetCursorPosition(x, y)
  235. }
  236. return err
  237. }
  238. /*
  239. Getch reads a single character.
  240. */
  241. func Getch() (*KeyEvent, error) {
  242. var ret *KeyEvent
  243. var err error
  244. if g != nil {
  245. ke := g.GetKey()
  246. if err = ke.err; err == nil {
  247. ret = ke.KeyEvent
  248. }
  249. }
  250. return ret, err
  251. }
  252. /*
  253. Stop stops the character reader.
  254. */
  255. func Stop() {
  256. if g != nil {
  257. g.Close()
  258. g = nil
  259. }
  260. }