keymap.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. # Copyright 2022 The HuggingFace Team and Brian Chao. All rights reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """
  15. Utilities relating to parsing raw characters from the keyboard, based on https://github.com/bchao1/bullet
  16. """
  17. import os
  18. import string
  19. import sys
  20. ARROW_KEY_FLAG = 1 << 8
  21. KEYMAP = {
  22. "tab": ord("\t"),
  23. "newline": ord("\r"),
  24. "esc": 27,
  25. "up": 65 + ARROW_KEY_FLAG,
  26. "down": 66 + ARROW_KEY_FLAG,
  27. "right": 67 + ARROW_KEY_FLAG,
  28. "left": 68 + ARROW_KEY_FLAG,
  29. "mod_int": 91,
  30. "undefined": sys.maxsize,
  31. "interrupt": 3,
  32. "insert": 50,
  33. "delete": 51,
  34. "pg_up": 53,
  35. "pg_down": 54,
  36. }
  37. KEYMAP["arrow_begin"] = KEYMAP["up"]
  38. KEYMAP["arrow_end"] = KEYMAP["left"]
  39. if sys.platform == "win32":
  40. WIN_CH_BUFFER = []
  41. WIN_KEYMAP = {
  42. b"\xe0H": KEYMAP["up"] - ARROW_KEY_FLAG,
  43. b"\x00H": KEYMAP["up"] - ARROW_KEY_FLAG,
  44. b"\xe0P": KEYMAP["down"] - ARROW_KEY_FLAG,
  45. b"\x00P": KEYMAP["down"] - ARROW_KEY_FLAG,
  46. b"\xe0M": KEYMAP["right"] - ARROW_KEY_FLAG,
  47. b"\x00M": KEYMAP["right"] - ARROW_KEY_FLAG,
  48. b"\xe0K": KEYMAP["left"] - ARROW_KEY_FLAG,
  49. b"\x00K": KEYMAP["left"] - ARROW_KEY_FLAG,
  50. }
  51. for i in range(10):
  52. KEYMAP[str(i)] = ord(str(i))
  53. def get_raw_chars():
  54. "Gets raw characters from inputs"
  55. if os.name == "nt":
  56. import msvcrt
  57. encoding = "mbcs"
  58. # Flush the keyboard buffer
  59. while msvcrt.kbhit():
  60. msvcrt.getch()
  61. if len(WIN_CH_BUFFER) == 0:
  62. # Read the keystroke
  63. ch = msvcrt.getch()
  64. # If it is a prefix char, get second part
  65. if ch in (b"\x00", b"\xe0"):
  66. ch2 = ch + msvcrt.getch()
  67. # Translate actual Win chars to bullet char types
  68. try:
  69. chx = chr(WIN_KEYMAP[ch2])
  70. WIN_CH_BUFFER.append(chr(KEYMAP["mod_int"]))
  71. WIN_CH_BUFFER.append(chx)
  72. if ord(chx) in (
  73. KEYMAP["insert"] - 1 << 9,
  74. KEYMAP["delete"] - 1 << 9,
  75. KEYMAP["pg_up"] - 1 << 9,
  76. KEYMAP["pg_down"] - 1 << 9,
  77. ):
  78. WIN_CH_BUFFER.append(chr(126))
  79. ch = chr(KEYMAP["esc"])
  80. except KeyError:
  81. ch = ch2[1]
  82. else:
  83. ch = ch.decode(encoding)
  84. else:
  85. ch = WIN_CH_BUFFER.pop(0)
  86. elif os.name == "posix":
  87. import termios
  88. import tty
  89. fd = sys.stdin.fileno()
  90. old_settings = termios.tcgetattr(fd)
  91. try:
  92. tty.setraw(fd)
  93. ch = sys.stdin.read(1)
  94. finally:
  95. termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
  96. return ch
  97. def get_character():
  98. "Gets a character from the keyboard and returns the key code"
  99. char = get_raw_chars()
  100. if ord(char) in [KEYMAP["interrupt"], KEYMAP["newline"]]:
  101. return char
  102. elif ord(char) == KEYMAP["esc"]:
  103. combo = get_raw_chars()
  104. if ord(combo) == KEYMAP["mod_int"]:
  105. key = get_raw_chars()
  106. if ord(key) >= KEYMAP["arrow_begin"] - ARROW_KEY_FLAG and ord(key) <= KEYMAP["arrow_end"] - ARROW_KEY_FLAG:
  107. return chr(ord(key) + ARROW_KEY_FLAG)
  108. else:
  109. return KEYMAP["undefined"]
  110. else:
  111. return get_raw_chars()
  112. else:
  113. if char in string.printable:
  114. return char
  115. else:
  116. return KEYMAP["undefined"]