telchars.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Useful telnet key detection.
  2. const compareBufStr = (buf, str) => {
  3. return buf.equals(Buffer.from(str.split('').map(c => c.charCodeAt(0))))
  4. }
  5. const telchars = {
  6. isSpace: buf => buf[0] === 0x20,
  7. isEnter: buf => buf[0] === 0x0d,
  8. isTab: buf => buf[0] === 0x09,
  9. isBackTab: buf => buf[0] === 0x1b && buf[2] === 0x5A,
  10. isBackspace: buf => buf[0] === 0x7F,
  11. // isEscape is hard because it's just send as ESC (the ANSI escape code),
  12. // so we need to make sure that the escape code is all on its own
  13. // (i.e. the length is 1)
  14. isEscape: buf => buf[0] === 0x1b && buf.length === 1,
  15. // Use this for when you'd like to detect the user confirming or issuing a
  16. // command, like the X button on your PlayStation controller, or the mouse
  17. // when you click on a button.
  18. isSelect: buf => telchars.isSpace(buf) || telchars.isEnter(buf),
  19. // Use this for when you'd like to detect the user cancelling an action,
  20. // like the O button on your PlayStation controller, or the Escape key on
  21. // your keyboard.
  22. isCancel: buf => telchars.isEscape(buf),
  23. isUp: buf => buf[0] === 0x1b && buf[2] === 0x41,
  24. isDown: buf => buf[0] === 0x1b && buf[2] === 0x42,
  25. isRight: buf => buf[0] === 0x1b && buf[2] === 0x43,
  26. isLeft: buf => buf[0] === 0x1b && buf[2] === 0x44,
  27. // Mouse constants!
  28. mapMouseActionNum: num => {
  29. let button = null
  30. if (num & 64) {
  31. if (num & 1) button = 'scroll-down'
  32. else button = 'scroll-up'
  33. } else {
  34. const drag = num & 32
  35. const bits = num & 3
  36. if (bits === 0) button = 'left'
  37. else if (bits === 1) button = 'middle'
  38. else if (bits === 2) button = 'right'
  39. else if (bits === 3) button = 'release'
  40. if (drag) {
  41. button = 'drag-' + button
  42. }
  43. }
  44. const shift = !!(num & 4)
  45. const ctrl = !!(num & 16)
  46. return {button, shift, ctrl}
  47. },
  48. isMouse: buf => buf[0] === 0x1b && buf[2] === 0x4d,
  49. parseMouse: buf => {
  50. if (!telchars.isMouse(buf)) {
  51. return null
  52. }
  53. const actionNum = buf[3] - 32
  54. const col = buf[4] - 32
  55. const line = buf[5] - 32
  56. const { button, shift, ctrl } = telchars.mapMouseActionNum(actionNum)
  57. return {button, shift, ctrl, col, line, actionNum}
  58. },
  59. isShiftUp: buf => compareBufStr(buf, '\x1b[1;2A'),
  60. isShiftDown: buf => compareBufStr(buf, '\x1b[1;2B'),
  61. isShiftRight: buf => compareBufStr(buf, '\x1b[1;2C'),
  62. isShiftLeft: buf => compareBufStr(buf, '\x1b[1;2D'),
  63. isMetaUp: buf => compareBufStr(buf, '\x1b[1;3A'),
  64. isMetaDown: buf => compareBufStr(buf, '\x1b[1;3B'),
  65. isMetaRight: buf => compareBufStr(buf, '\x1b[1;3C'),
  66. isMetaLeft: buf => compareBufStr(buf, '\x1b[1;3D'),
  67. isControlUp: buf => compareBufStr(buf, '\x1b[1;5A'),
  68. isControlDown: buf => compareBufStr(buf, '\x1b[1;5B'),
  69. isControlRight: buf => compareBufStr(buf, '\x1b[1;5C'),
  70. isControlLeft: buf => compareBufStr(buf, '\x1b[1;5D'),
  71. isHome: buf => compareBufStr(buf, '\x1b[1~'),
  72. isInsert: buf => compareBufStr(buf, '\x1b[2~'),
  73. isDelete: buf => compareBufStr(buf, '\x1b[3~'),
  74. isEnd: buf => compareBufStr(buf, '\x1b[4~'),
  75. isPageUp: buf => compareBufStr(buf, '\x1b[5~'),
  76. isPageDown: buf => compareBufStr(buf, '\x1b[6~'),
  77. isCaselessLetter: (buf, letter) => compareBufStr(buf, letter.toLowerCase()) || compareBufStr(buf, letter.toUpperCase()),
  78. isCharacter: (buf, char) => compareBufStr(buf, char),
  79. }
  80. export default telchars