@fractaal/pi-tui 0.86.9 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +7 -3
  2. package/dist/autocomplete.d.ts.map +1 -1
  3. package/dist/autocomplete.js +1 -4
  4. package/dist/autocomplete.js.map +1 -1
  5. package/dist/components/box.d.ts +1 -0
  6. package/dist/components/box.d.ts.map +1 -1
  7. package/dist/components/box.js +4 -0
  8. package/dist/components/box.js.map +1 -1
  9. package/dist/components/editor.d.ts +2 -0
  10. package/dist/components/editor.d.ts.map +1 -1
  11. package/dist/components/editor.js +11 -4
  12. package/dist/components/editor.js.map +1 -1
  13. package/dist/components/input.d.ts.map +1 -1
  14. package/dist/components/input.js +4 -4
  15. package/dist/components/input.js.map +1 -1
  16. package/dist/components/markdown.d.ts +6 -0
  17. package/dist/components/markdown.d.ts.map +1 -1
  18. package/dist/components/markdown.js +177 -59
  19. package/dist/components/markdown.js.map +1 -1
  20. package/dist/components/select-list.d.ts +1 -0
  21. package/dist/components/select-list.d.ts.map +1 -1
  22. package/dist/components/select-list.js +10 -1
  23. package/dist/components/select-list.js.map +1 -1
  24. package/dist/components/settings-list.d.ts +1 -0
  25. package/dist/components/settings-list.d.ts.map +1 -1
  26. package/dist/components/settings-list.js +8 -1
  27. package/dist/components/settings-list.js.map +1 -1
  28. package/dist/components/text.d.ts +1 -0
  29. package/dist/components/text.d.ts.map +1 -1
  30. package/dist/components/text.js +7 -0
  31. package/dist/components/text.js.map +1 -1
  32. package/dist/fuzzy.d.ts.map +1 -1
  33. package/dist/fuzzy.js +59 -44
  34. package/dist/fuzzy.js.map +1 -1
  35. package/dist/index.d.ts +4 -3
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +5 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/keybindings.d.ts +6 -0
  40. package/dist/keybindings.d.ts.map +1 -1
  41. package/dist/keybindings.js +15 -0
  42. package/dist/keybindings.js.map +1 -1
  43. package/dist/keys.d.ts.map +1 -1
  44. package/dist/keys.js +112 -26
  45. package/dist/keys.js.map +1 -1
  46. package/dist/layout.d.ts.map +1 -1
  47. package/dist/layout.js +18 -13
  48. package/dist/layout.js.map +1 -1
  49. package/dist/program-status.d.ts +23 -0
  50. package/dist/program-status.d.ts.map +1 -0
  51. package/dist/program-status.js +43 -0
  52. package/dist/program-status.js.map +1 -0
  53. package/dist/stdin-buffer.d.ts +4 -2
  54. package/dist/stdin-buffer.d.ts.map +1 -1
  55. package/dist/stdin-buffer.js +36 -1
  56. package/dist/stdin-buffer.js.map +1 -1
  57. package/dist/terminal-image.d.ts +2 -0
  58. package/dist/terminal-image.d.ts.map +1 -1
  59. package/dist/terminal-image.js +26 -1
  60. package/dist/terminal-image.js.map +1 -1
  61. package/dist/terminal.d.ts +23 -0
  62. package/dist/terminal.d.ts.map +1 -1
  63. package/dist/terminal.js +75 -6
  64. package/dist/terminal.js.map +1 -1
  65. package/dist/tui-alt-screen.d.ts +6 -1
  66. package/dist/tui-alt-screen.d.ts.map +1 -1
  67. package/dist/tui-alt-screen.js +26 -8
  68. package/dist/tui-alt-screen.js.map +1 -1
  69. package/dist/tui-main-screen.d.ts.map +1 -1
  70. package/dist/tui-main-screen.js +5 -1
  71. package/dist/tui-main-screen.js.map +1 -1
  72. package/dist/tui.d.ts +25 -0
  73. package/dist/tui.d.ts.map +1 -1
  74. package/dist/tui.js +53 -4
  75. package/dist/tui.js.map +1 -1
  76. package/dist/utils.d.ts +2 -0
  77. package/dist/utils.d.ts.map +1 -1
  78. package/dist/utils.js +79 -9
  79. package/dist/utils.js.map +1 -1
  80. package/package.json +4 -3
@@ -1 +1 @@
1
- {"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,UAAU,EAAE,MAAM,WAAW,CAAC;AAsEnD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B,qBAAqB,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAC3E,uBAAuB,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,EAAE;IACjF,4BAA4B,EAAE;QAC7B,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,sCAAsC;KACnD;IACD,wBAAwB,EAAE;QACzB,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,kCAAkC;KAC/C;IACD,uBAAuB,EAAE;QACxB,WAAW,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC/B,WAAW,EAAE,kBAAkB;KAC/B;IACD,wBAAwB,EAAE;QACzB,WAAW,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;QAChC,WAAW,EAAE,mBAAmB;KAChC;IACD,2BAA2B,EAAE;QAC5B,WAAW,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC;QAC/C,WAAW,EAAE,uBAAuB;KACpC;IACD,4BAA4B,EAAE;QAC7B,WAAW,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC;QACjD,WAAW,EAAE,wBAAwB;KACrC;IACD,4BAA4B,EAAE;QAC7B,WAAW,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC/B,WAAW,EAAE,oBAAoB;KACjC;IACD,0BAA0B,EAAE;QAC3B,WAAW,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;QAC9B,WAAW,EAAE,kBAAkB;KAC/B;IACD,wBAAwB,EAAE;QACzB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,2BAA2B;KACxC;IACD,yBAAyB,EAAE;QAC1B,WAAW,EAAE,YAAY;QACzB,WAAW,EAAE,4BAA4B;KACzC;IACD,mBAAmB,EAAE,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE;IACvF,qBAAqB,EAAE,EAAE,WAAW,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE;IAC/F,+BAA+B,EAAE;QAChC,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,2BAA2B;KACxC;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACjC,WAAW,EAAE,0BAA0B;KACvC;IACD,+BAA+B,EAAE;QAChC,WAAW,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC;QACxC,WAAW,EAAE,sBAAsB;KACnC;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;QACpC,WAAW,EAAE,qBAAqB;KAClC;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,sBAAsB;KACnC;IACD,4BAA4B,EAAE;QAC7B,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,oBAAoB;KACjC;IACD,iBAAiB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;IACjE,oBAAoB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE;IACvE,iBAAiB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;IACjE,mBAAmB,EAAE,EAAE,WAAW,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAC9F,kBAAkB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE;IACzE,eAAe,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE;IAC1E,gBAAgB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAC1E,eAAe,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACxE,iBAAiB,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,qBAAqB,EAAE;IAC9E,mBAAmB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAChF,qBAAqB,EAAE;QACtB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,qBAAqB;KAClC;IACD,oBAAoB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAChF,mBAAmB,EAAE;QACpB,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACjC,WAAW,EAAE,kBAAkB;KAC/B;IACD,gFAAgF;IAChF,sBAAsB,EAAE;QACvB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,6BAA6B;KAC1C;IACD,wBAAwB,EAAE;QACzB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,+BAA+B;KAC5C;IACD,0BAA0B,EAAE;QAC3B,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,gCAAgC;KAC7C;IACD,4BAA4B,EAAE;QAC7B,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,kCAAkC;KAC/C;IACD,sBAAsB,EAAE;QACvB,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,6BAA6B;KAC1C;IACD,wBAAwB,EAAE;QACzB,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,+BAA+B;KAC5C;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC;QACzC,WAAW,EAAE,kCAAkC;KAC/C;IACD,0BAA0B,EAAE;QAC3B,WAAW,EAAE,CAAC,iBAAiB,EAAE,WAAW,CAAC;QAC7C,WAAW,EAAE,8BAA8B;KAC3C;IACD,sBAAsB,EAAE;QACvB,WAAW,EAAE,cAAc;QAC3B,WAAW,EAAE,gCAAgC;KAC7C;IACD,0BAA0B,EAAE;QAC3B,WAAW,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;QAChC,WAAW,EAAE,8BAA8B;KAC3C;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC;QAC5C,WAAW,EAAE,kCAAkC;KAC/C;IACD,2BAA2B,EAAE;QAC5B,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,yBAAyB;KACtC;IACD,mBAAmB,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE;IACxF,sBAAsB,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,2BAA2B,EAAE;CACpD,CAAC;AAO3C,SAAS,aAAa,CAAC,IAAiC;IACvD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAS,CAAC;IAC9B,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,OAAO,kBAAkB;IACtB,WAAW,CAAwB;IACnC,YAAY,CAAoB;IAChC,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC1C,SAAS,GAAyB,EAAE,CAAC;IAE7C,YAAY,WAAkC,EAAE,YAAY,GAAsB,EAAE;QACnF,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAEO,OAAO;QACd,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAEpB,MAAM,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAC;QACrD,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YACpE,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC;gBAAE,SAAS;YAChD,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,EAAc,CAAC;gBAC/D,SAAS,CAAC,GAAG,CAAC,UAAwB,CAAC,CAAC;gBACxC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAChC,CAAC;QACF,CAAC;QAED,KAAK,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,UAAU,EAAE,CAAC;YAC7C,IAAI,WAAW,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;YAC7D,CAAC;QACF,CAAC;QAED,KAAK,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACvC,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACtG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAgB,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;IACF,CAAC;IAED,OAAO,CAAC,IAAY,EAAE,UAAsB;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,CAAC,UAAsB;QAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,aAAa,CAAC,UAAsB;QACnC,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAED,YAAY;QACX,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IACpG,CAAC;IAED,eAAe,CAAC,YAA+B;QAC9C,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAED,eAAe;QACd,OAAO,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IACjC,CAAC;IAED,mBAAmB;QAClB,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAgB,CAAC,IAAI,EAAE,CAAC;YACvD,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC;CACD;AAED,IAAI,iBAAiB,GAA8B,IAAI,CAAC;AAExD,MAAM,UAAU,cAAc,CAAC,WAA+B;IAC7D,iBAAiB,GAAG,WAAW,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc;IAC7B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxB,iBAAiB,GAAG,IAAI,kBAAkB,CAAC,eAAe,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC1B,CAAC","sourcesContent":["import { type KeyId, matchesKey } from \"./keys.ts\";\n\n/**\n * Global keybinding registry.\n * Downstream packages can add keybindings via declaration merging.\n */\nexport interface Keybindings {\n\t// Editor navigation and editing\n\t\"tui.editor.cursorUp\": true;\n\t\"tui.editor.cursorDown\": true;\n\t\"tui.editor.historyPrevious\": true;\n\t\"tui.editor.historyNext\": true;\n\t\"tui.editor.cursorLeft\": true;\n\t\"tui.editor.cursorRight\": true;\n\t\"tui.editor.cursorWordLeft\": true;\n\t\"tui.editor.cursorWordRight\": true;\n\t\"tui.editor.cursorLineStart\": true;\n\t\"tui.editor.cursorLineEnd\": true;\n\t\"tui.editor.jumpForward\": true;\n\t\"tui.editor.jumpBackward\": true;\n\t\"tui.editor.pageUp\": true;\n\t\"tui.editor.pageDown\": true;\n\t\"tui.editor.deleteCharBackward\": true;\n\t\"tui.editor.deleteCharForward\": true;\n\t\"tui.editor.deleteWordBackward\": true;\n\t\"tui.editor.deleteWordForward\": true;\n\t\"tui.editor.deleteToLineStart\": true;\n\t\"tui.editor.deleteToLineEnd\": true;\n\t\"tui.editor.yank\": true;\n\t\"tui.editor.yankPop\": true;\n\t\"tui.editor.undo\": true;\n\t// Generic input actions\n\t\"tui.input.newLine\": true;\n\t\"tui.input.submit\": true;\n\t\"tui.input.tab\": true;\n\t\"tui.input.copy\": true;\n\t// Generic selection actions\n\t\"tui.select.up\": true;\n\t\"tui.select.down\": true;\n\t\"tui.select.pageUp\": true;\n\t\"tui.select.pageDown\": true;\n\t\"tui.select.confirm\": true;\n\t\"tui.select.cancel\": true;\n\t// Alternate-screen viewport navigation\n\t\"tui.altScreen.pageUp\": true;\n\t\"tui.altScreen.pageDown\": true;\n\t\"tui.altScreen.halfPageUp\": true;\n\t\"tui.altScreen.halfPageDown\": true;\n\t\"tui.altScreen.lineUp\": true;\n\t\"tui.altScreen.lineDown\": true;\n\t\"tui.altScreen.previousPrompt\": true;\n\t\"tui.altScreen.nextPrompt\": true;\n\t\"tui.altScreen.search\": true;\n\t\"tui.altScreen.searchNext\": true;\n\t\"tui.altScreen.searchPrevious\": true;\n\t\"tui.altScreen.searchClose\": true;\n\t\"tui.altScreen.top\": true;\n\t\"tui.altScreen.bottom\": true;\n}\n\nexport type Keybinding = keyof Keybindings;\n\nexport interface KeybindingDefinition {\n\tdefaultKeys: KeyId | KeyId[];\n\tdescription?: string;\n}\n\nexport type KeybindingDefinitions = Record<string, KeybindingDefinition>;\nexport type KeybindingsConfig = Record<string, KeyId | KeyId[] | undefined>;\n\nexport const TUI_KEYBINDINGS = {\n\t\"tui.editor.cursorUp\": { defaultKeys: \"up\", description: \"Move cursor up\" },\n\t\"tui.editor.cursorDown\": { defaultKeys: \"down\", description: \"Move cursor down\" },\n\t\"tui.editor.historyPrevious\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Select previous prompt history entry\",\n\t},\n\t\"tui.editor.historyNext\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Select next prompt history entry\",\n\t},\n\t\"tui.editor.cursorLeft\": {\n\t\tdefaultKeys: [\"left\", \"ctrl+b\"],\n\t\tdescription: \"Move cursor left\",\n\t},\n\t\"tui.editor.cursorRight\": {\n\t\tdefaultKeys: [\"right\", \"ctrl+f\"],\n\t\tdescription: \"Move cursor right\",\n\t},\n\t\"tui.editor.cursorWordLeft\": {\n\t\tdefaultKeys: [\"alt+left\", \"ctrl+left\", \"alt+b\"],\n\t\tdescription: \"Move cursor word left\",\n\t},\n\t\"tui.editor.cursorWordRight\": {\n\t\tdefaultKeys: [\"alt+right\", \"ctrl+right\", \"alt+f\"],\n\t\tdescription: \"Move cursor word right\",\n\t},\n\t\"tui.editor.cursorLineStart\": {\n\t\tdefaultKeys: [\"home\", \"ctrl+a\"],\n\t\tdescription: \"Move to line start\",\n\t},\n\t\"tui.editor.cursorLineEnd\": {\n\t\tdefaultKeys: [\"end\", \"ctrl+e\"],\n\t\tdescription: \"Move to line end\",\n\t},\n\t\"tui.editor.jumpForward\": {\n\t\tdefaultKeys: \"ctrl+]\",\n\t\tdescription: \"Jump forward to character\",\n\t},\n\t\"tui.editor.jumpBackward\": {\n\t\tdefaultKeys: \"ctrl+alt+]\",\n\t\tdescription: \"Jump backward to character\",\n\t},\n\t\"tui.editor.pageUp\": { defaultKeys: [\"pageUp\", \"ctrl+pageUp\"], description: \"Page up\" },\n\t\"tui.editor.pageDown\": { defaultKeys: [\"pageDown\", \"ctrl+pageDown\"], description: \"Page down\" },\n\t\"tui.editor.deleteCharBackward\": {\n\t\tdefaultKeys: \"backspace\",\n\t\tdescription: \"Delete character backward\",\n\t},\n\t\"tui.editor.deleteCharForward\": {\n\t\tdefaultKeys: [\"delete\", \"ctrl+d\"],\n\t\tdescription: \"Delete character forward\",\n\t},\n\t\"tui.editor.deleteWordBackward\": {\n\t\tdefaultKeys: [\"ctrl+w\", \"alt+backspace\"],\n\t\tdescription: \"Delete word backward\",\n\t},\n\t\"tui.editor.deleteWordForward\": {\n\t\tdefaultKeys: [\"alt+d\", \"alt+delete\"],\n\t\tdescription: \"Delete word forward\",\n\t},\n\t\"tui.editor.deleteToLineStart\": {\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Delete to line start\",\n\t},\n\t\"tui.editor.deleteToLineEnd\": {\n\t\tdefaultKeys: \"ctrl+k\",\n\t\tdescription: \"Delete to line end\",\n\t},\n\t\"tui.editor.yank\": { defaultKeys: \"ctrl+y\", description: \"Yank\" },\n\t\"tui.editor.yankPop\": { defaultKeys: \"alt+y\", description: \"Yank pop\" },\n\t\"tui.editor.undo\": { defaultKeys: \"ctrl+-\", description: \"Undo\" },\n\t\"tui.input.newLine\": { defaultKeys: [\"shift+enter\", \"ctrl+j\"], description: \"Insert newline\" },\n\t\"tui.input.submit\": { defaultKeys: \"enter\", description: \"Submit input\" },\n\t\"tui.input.tab\": { defaultKeys: \"tab\", description: \"Tab / autocomplete\" },\n\t\"tui.input.copy\": { defaultKeys: \"ctrl+c\", description: \"Copy selection\" },\n\t\"tui.select.up\": { defaultKeys: \"up\", description: \"Move selection up\" },\n\t\"tui.select.down\": { defaultKeys: \"down\", description: \"Move selection down\" },\n\t\"tui.select.pageUp\": { defaultKeys: \"pageUp\", description: \"Selection page up\" },\n\t\"tui.select.pageDown\": {\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Selection page down\",\n\t},\n\t\"tui.select.confirm\": { defaultKeys: \"enter\", description: \"Confirm selection\" },\n\t\"tui.select.cancel\": {\n\t\tdefaultKeys: [\"escape\", \"ctrl+c\"],\n\t\tdescription: \"Cancel selection\",\n\t},\n\t// These intentionally shadow the unmodified editor bindings in fullscreen mode.\n\t\"tui.altScreen.pageUp\": {\n\t\tdefaultKeys: \"pageUp\",\n\t\tdescription: \"Scroll viewport up one page\",\n\t},\n\t\"tui.altScreen.pageDown\": {\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Scroll viewport down one page\",\n\t},\n\t\"tui.altScreen.halfPageUp\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport up half a page\",\n\t},\n\t\"tui.altScreen.halfPageDown\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport down half a page\",\n\t},\n\t\"tui.altScreen.lineUp\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport up one line\",\n\t},\n\t\"tui.altScreen.lineDown\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport down one line\",\n\t},\n\t\"tui.altScreen.previousPrompt\": {\n\t\tdefaultKeys: [\"ctrl+shift+up\", \"ctrl+up\"],\n\t\tdescription: \"Jump to previous semantic prompt\",\n\t},\n\t\"tui.altScreen.nextPrompt\": {\n\t\tdefaultKeys: [\"ctrl+shift+down\", \"ctrl+down\"],\n\t\tdescription: \"Jump to next semantic prompt\",\n\t},\n\t\"tui.altScreen.search\": {\n\t\tdefaultKeys: \"ctrl+shift+f\",\n\t\tdescription: \"Search the primary scroll view\",\n\t},\n\t\"tui.altScreen.searchNext\": {\n\t\tdefaultKeys: [\"enter\", \"ctrl+g\"],\n\t\tdescription: \"Select the next search match\",\n\t},\n\t\"tui.altScreen.searchPrevious\": {\n\t\tdefaultKeys: [\"shift+enter\", \"ctrl+shift+g\"],\n\t\tdescription: \"Select the previous search match\",\n\t},\n\t\"tui.altScreen.searchClose\": {\n\t\tdefaultKeys: \"escape\",\n\t\tdescription: \"Close transcript search\",\n\t},\n\t\"tui.altScreen.top\": { defaultKeys: \"ctrl+home\", description: \"Scroll viewport to top\" },\n\t\"tui.altScreen.bottom\": { defaultKeys: \"ctrl+end\", description: \"Scroll viewport to bottom\" },\n} as const satisfies KeybindingDefinitions;\n\nexport interface KeybindingConflict {\n\tkey: KeyId;\n\tkeybindings: string[];\n}\n\nfunction normalizeKeys(keys: KeyId | KeyId[] | undefined): KeyId[] {\n\tif (keys === undefined) return [];\n\tconst keyList = Array.isArray(keys) ? keys : [keys];\n\tconst seen = new Set<KeyId>();\n\tconst result: KeyId[] = [];\n\tfor (const key of keyList) {\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tresult.push(key);\n\t\t}\n\t}\n\treturn result;\n}\n\nexport class KeybindingsManager {\n\tprivate definitions: KeybindingDefinitions;\n\tprivate userBindings: KeybindingsConfig;\n\tprivate keysById = new Map<Keybinding, KeyId[]>();\n\tprivate conflicts: KeybindingConflict[] = [];\n\n\tconstructor(definitions: KeybindingDefinitions, userBindings: KeybindingsConfig = {}) {\n\t\tthis.definitions = definitions;\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.keysById.clear();\n\t\tthis.conflicts = [];\n\n\t\tconst userClaims = new Map<KeyId, Set<Keybinding>>();\n\t\tfor (const [keybinding, keys] of Object.entries(this.userBindings)) {\n\t\t\tif (!(keybinding in this.definitions)) continue;\n\t\t\tfor (const key of normalizeKeys(keys)) {\n\t\t\t\tconst claimants = userClaims.get(key) ?? new Set<Keybinding>();\n\t\t\t\tclaimants.add(keybinding as Keybinding);\n\t\t\t\tuserClaims.set(key, claimants);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [key, keybindings] of userClaims) {\n\t\t\tif (keybindings.size > 1) {\n\t\t\t\tthis.conflicts.push({ key, keybindings: [...keybindings] });\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, definition] of Object.entries(this.definitions)) {\n\t\t\tconst userKeys = this.userBindings[id];\n\t\t\tconst keys = userKeys === undefined ? normalizeKeys(definition.defaultKeys) : normalizeKeys(userKeys);\n\t\t\tthis.keysById.set(id as Keybinding, keys);\n\t\t}\n\t}\n\n\tmatches(data: string, keybinding: Keybinding): boolean {\n\t\tconst keys = this.keysById.get(keybinding) ?? [];\n\t\tfor (const key of keys) {\n\t\t\tif (matchesKey(data, key)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetKeys(keybinding: Keybinding): KeyId[] {\n\t\treturn [...(this.keysById.get(keybinding) ?? [])];\n\t}\n\n\tgetDefinition(keybinding: Keybinding): KeybindingDefinition {\n\t\treturn this.definitions[keybinding];\n\t}\n\n\tgetConflicts(): KeybindingConflict[] {\n\t\treturn this.conflicts.map((conflict) => ({ ...conflict, keybindings: [...conflict.keybindings] }));\n\t}\n\n\tsetUserBindings(userBindings: KeybindingsConfig): void {\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tgetUserBindings(): KeybindingsConfig {\n\t\treturn { ...this.userBindings };\n\t}\n\n\tgetResolvedBindings(): KeybindingsConfig {\n\t\tconst resolved: KeybindingsConfig = {};\n\t\tfor (const id of Object.keys(this.definitions)) {\n\t\t\tconst keys = this.keysById.get(id as Keybinding) ?? [];\n\t\t\tresolved[id] = keys.length === 1 ? keys[0]! : [...keys];\n\t\t}\n\t\treturn resolved;\n\t}\n}\n\nlet globalKeybindings: KeybindingsManager | null = null;\n\nexport function setKeybindings(keybindings: KeybindingsManager): void {\n\tglobalKeybindings = keybindings;\n}\n\nexport function getKeybindings(): KeybindingsManager {\n\tif (!globalKeybindings) {\n\t\tglobalKeybindings = new KeybindingsManager(TUI_KEYBINDINGS);\n\t}\n\treturn globalKeybindings;\n}\n"]}
1
+ {"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import { type KeyId, matchesKey } from \"./keys.ts\";\n\n/**\n * Global keybinding registry.\n * Downstream packages can add keybindings via declaration merging.\n */\nexport interface Keybindings {\n\t// Editor navigation and editing\n\t\"tui.editor.cursorUp\": true;\n\t\"tui.editor.cursorDown\": true;\n\t\"tui.editor.historyPrevious\": true;\n\t\"tui.editor.historyNext\": true;\n\t\"tui.editor.cursorLeft\": true;\n\t\"tui.editor.cursorRight\": true;\n\t\"tui.editor.cursorWordLeft\": true;\n\t\"tui.editor.cursorWordRight\": true;\n\t\"tui.editor.cursorLineStart\": true;\n\t\"tui.editor.cursorLineEnd\": true;\n\t\"tui.editor.jumpForward\": true;\n\t\"tui.editor.jumpBackward\": true;\n\t\"tui.editor.pageUp\": true;\n\t\"tui.editor.pageDown\": true;\n\t\"tui.editor.deleteCharBackward\": true;\n\t\"tui.editor.deleteCharForward\": true;\n\t\"tui.editor.deleteWordBackward\": true;\n\t\"tui.editor.deleteWordForward\": true;\n\t\"tui.editor.deleteToLineStart\": true;\n\t\"tui.editor.deleteToLineEnd\": true;\n\t\"tui.editor.yank\": true;\n\t\"tui.editor.yankPop\": true;\n\t\"tui.editor.undo\": true;\n\t// Generic input actions\n\t\"tui.input.newLine\": true;\n\t\"tui.input.submit\": true;\n\t\"tui.input.tab\": true;\n\t\"tui.input.copy\": true;\n\t// Generic selection actions\n\t\"tui.select.up\": true;\n\t\"tui.select.down\": true;\n\t\"tui.select.pageUp\": true;\n\t\"tui.select.pageDown\": true;\n\t\"tui.select.confirm\": true;\n\t\"tui.select.cancel\": true;\n\t// Alternate-screen viewport navigation\n\t\"tui.altScreen.pageUp\": true;\n\t\"tui.altScreen.pageDown\": true;\n\t\"tui.altScreen.halfPageUp\": true;\n\t\"tui.altScreen.halfPageDown\": true;\n\t\"tui.altScreen.lineUp\": true;\n\t\"tui.altScreen.lineDown\": true;\n\t\"tui.altScreen.previousPrompt\": true;\n\t\"tui.altScreen.nextPrompt\": true;\n\t\"tui.altScreen.search\": true;\n\t\"tui.altScreen.searchNext\": true;\n\t\"tui.altScreen.searchPrevious\": true;\n\t\"tui.altScreen.searchClose\": true;\n\t\"tui.altScreen.top\": true;\n\t\"tui.altScreen.bottom\": true;\n}\n\nexport type Keybinding = keyof Keybindings;\n\nexport interface KeybindingDefinition {\n\tdefaultKeys: KeyId | KeyId[];\n\tdescription?: string;\n}\n\nexport type KeybindingDefinitions = Record<string, KeybindingDefinition>;\nexport type KeybindingsConfig = Record<string, KeyId | KeyId[] | undefined>;\n\nexport const TUI_KEYBINDINGS = {\n\t\"tui.editor.cursorUp\": { defaultKeys: \"up\", description: \"Move cursor up\" },\n\t\"tui.editor.cursorDown\": { defaultKeys: \"down\", description: \"Move cursor down\" },\n\t\"tui.editor.historyPrevious\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Select previous prompt history entry\",\n\t},\n\t\"tui.editor.historyNext\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Select next prompt history entry\",\n\t},\n\t\"tui.editor.cursorLeft\": {\n\t\tdefaultKeys: [\"left\", \"ctrl+b\"],\n\t\tdescription: \"Move cursor left\",\n\t},\n\t\"tui.editor.cursorRight\": {\n\t\tdefaultKeys: [\"right\", \"ctrl+f\"],\n\t\tdescription: \"Move cursor right\",\n\t},\n\t\"tui.editor.cursorWordLeft\": {\n\t\tdefaultKeys: [\"alt+left\", \"ctrl+left\", \"alt+b\"],\n\t\tdescription: \"Move cursor word left\",\n\t},\n\t\"tui.editor.cursorWordRight\": {\n\t\tdefaultKeys: [\"alt+right\", \"ctrl+right\", \"alt+f\"],\n\t\tdescription: \"Move cursor word right\",\n\t},\n\t\"tui.editor.cursorLineStart\": {\n\t\tdefaultKeys: [\"home\", \"ctrl+a\"],\n\t\tdescription: \"Move to line start\",\n\t},\n\t\"tui.editor.cursorLineEnd\": {\n\t\tdefaultKeys: [\"end\", \"ctrl+e\"],\n\t\tdescription: \"Move to line end\",\n\t},\n\t\"tui.editor.jumpForward\": {\n\t\tdefaultKeys: \"ctrl+]\",\n\t\tdescription: \"Jump forward to character\",\n\t},\n\t\"tui.editor.jumpBackward\": {\n\t\tdefaultKeys: \"ctrl+alt+]\",\n\t\tdescription: \"Jump backward to character\",\n\t},\n\t\"tui.editor.pageUp\": { defaultKeys: [\"pageUp\", \"ctrl+pageUp\"], description: \"Page up\" },\n\t\"tui.editor.pageDown\": { defaultKeys: [\"pageDown\", \"ctrl+pageDown\"], description: \"Page down\" },\n\t\"tui.editor.deleteCharBackward\": {\n\t\tdefaultKeys: \"backspace\",\n\t\tdescription: \"Delete character backward\",\n\t},\n\t\"tui.editor.deleteCharForward\": {\n\t\tdefaultKeys: [\"delete\", \"ctrl+d\"],\n\t\tdescription: \"Delete character forward\",\n\t},\n\t\"tui.editor.deleteWordBackward\": {\n\t\tdefaultKeys: [\"ctrl+w\", \"alt+backspace\"],\n\t\tdescription: \"Delete word backward\",\n\t},\n\t\"tui.editor.deleteWordForward\": {\n\t\tdefaultKeys: [\"alt+d\", \"alt+delete\"],\n\t\tdescription: \"Delete word forward\",\n\t},\n\t\"tui.editor.deleteToLineStart\": {\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Delete to line start\",\n\t},\n\t\"tui.editor.deleteToLineEnd\": {\n\t\tdefaultKeys: \"ctrl+k\",\n\t\tdescription: \"Delete to line end\",\n\t},\n\t\"tui.editor.yank\": { defaultKeys: \"ctrl+y\", description: \"Yank\" },\n\t\"tui.editor.yankPop\": { defaultKeys: \"alt+y\", description: \"Yank pop\" },\n\t\"tui.editor.undo\": { defaultKeys: \"ctrl+-\", description: \"Undo\" },\n\t\"tui.input.newLine\": { defaultKeys: [\"shift+enter\", \"ctrl+j\"], description: \"Insert newline\" },\n\t\"tui.input.submit\": { defaultKeys: \"enter\", description: \"Submit input\" },\n\t\"tui.input.tab\": { defaultKeys: \"tab\", description: \"Tab / autocomplete\" },\n\t\"tui.input.copy\": { defaultKeys: \"ctrl+c\", description: \"Copy selection\" },\n\t\"tui.select.up\": { defaultKeys: \"up\", description: \"Move selection up\" },\n\t\"tui.select.down\": { defaultKeys: \"down\", description: \"Move selection down\" },\n\t\"tui.select.pageUp\": { defaultKeys: \"pageUp\", description: \"Selection page up\" },\n\t\"tui.select.pageDown\": {\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Selection page down\",\n\t},\n\t\"tui.select.confirm\": { defaultKeys: \"enter\", description: \"Confirm selection\" },\n\t\"tui.select.cancel\": {\n\t\tdefaultKeys: [\"escape\", \"ctrl+c\"],\n\t\tdescription: \"Cancel selection\",\n\t},\n\t// These intentionally shadow the unmodified editor bindings in fullscreen mode.\n\t\"tui.altScreen.pageUp\": {\n\t\tdefaultKeys: \"pageUp\",\n\t\tdescription: \"Scroll viewport up one page\",\n\t},\n\t\"tui.altScreen.pageDown\": {\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Scroll viewport down one page\",\n\t},\n\t\"tui.altScreen.halfPageUp\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport up half a page\",\n\t},\n\t\"tui.altScreen.halfPageDown\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport down half a page\",\n\t},\n\t\"tui.altScreen.lineUp\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport up one line\",\n\t},\n\t\"tui.altScreen.lineDown\": {\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport down one line\",\n\t},\n\t\"tui.altScreen.previousPrompt\": {\n\t\tdefaultKeys: [\"ctrl+shift+up\", \"ctrl+up\"],\n\t\tdescription: \"Jump to previous semantic prompt\",\n\t},\n\t\"tui.altScreen.nextPrompt\": {\n\t\tdefaultKeys: [\"ctrl+shift+down\", \"ctrl+down\"],\n\t\tdescription: \"Jump to next semantic prompt\",\n\t},\n\t\"tui.altScreen.search\": {\n\t\tdefaultKeys: \"ctrl+shift+f\",\n\t\tdescription: \"Search the primary scroll view\",\n\t},\n\t\"tui.altScreen.searchNext\": {\n\t\tdefaultKeys: [\"enter\", \"ctrl+g\"],\n\t\tdescription: \"Select the next search match\",\n\t},\n\t\"tui.altScreen.searchPrevious\": {\n\t\tdefaultKeys: [\"shift+enter\", \"ctrl+shift+g\"],\n\t\tdescription: \"Select the previous search match\",\n\t},\n\t\"tui.altScreen.searchClose\": {\n\t\tdefaultKeys: \"escape\",\n\t\tdescription: \"Close transcript search\",\n\t},\n\t\"tui.altScreen.top\": { defaultKeys: \"ctrl+home\", description: \"Scroll viewport to top\" },\n\t\"tui.altScreen.bottom\": { defaultKeys: \"ctrl+end\", description: \"Scroll viewport to bottom\" },\n} as const satisfies KeybindingDefinitions;\n\nexport interface KeybindingConflict {\n\tkey: KeyId;\n\tkeybindings: string[];\n}\n\nfunction normalizeKeys(keys: KeyId | KeyId[] | undefined): KeyId[] {\n\tif (keys === undefined) return [];\n\tconst keyList = Array.isArray(keys) ? keys : [keys];\n\tconst seen = new Set<KeyId>();\n\tconst result: KeyId[] = [];\n\tfor (const key of keyList) {\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tresult.push(key);\n\t\t}\n\t}\n\treturn result;\n}\n\nexport class KeybindingsManager {\n\tprivate definitions: KeybindingDefinitions;\n\tprivate userBindings: KeybindingsConfig;\n\tprivate keysById = new Map<Keybinding, KeyId[]>();\n\tprivate conflicts: KeybindingConflict[] = [];\n\n\tconstructor(definitions: KeybindingDefinitions, userBindings: KeybindingsConfig = {}) {\n\t\tthis.definitions = definitions;\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.keysById.clear();\n\t\tthis.conflicts = [];\n\n\t\tconst userClaims = new Map<KeyId, Set<Keybinding>>();\n\t\tfor (const [keybinding, keys] of Object.entries(this.userBindings)) {\n\t\t\tif (!(keybinding in this.definitions)) continue;\n\t\t\tfor (const key of normalizeKeys(keys)) {\n\t\t\t\tconst claimants = userClaims.get(key) ?? new Set<Keybinding>();\n\t\t\t\tclaimants.add(keybinding as Keybinding);\n\t\t\t\tuserClaims.set(key, claimants);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [key, keybindings] of userClaims) {\n\t\t\tif (keybindings.size > 1) {\n\t\t\t\tthis.conflicts.push({ key, keybindings: [...keybindings] });\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, definition] of Object.entries(this.definitions)) {\n\t\t\tconst userKeys = this.userBindings[id];\n\t\t\tconst keys = userKeys === undefined ? normalizeKeys(definition.defaultKeys) : normalizeKeys(userKeys);\n\t\t\tthis.keysById.set(id as Keybinding, keys);\n\t\t}\n\t}\n\n\tmatches(data: string, keybinding: Keybinding): boolean {\n\t\tconst keys = this.keysById.get(keybinding) ?? [];\n\t\tfor (const key of keys) {\n\t\t\tif (matchesKey(data, key)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetKeys(keybinding: Keybinding): KeyId[] {\n\t\treturn [...(this.keysById.get(keybinding) ?? [])];\n\t}\n\n\tgetDefinition(keybinding: Keybinding): KeybindingDefinition {\n\t\treturn this.definitions[keybinding];\n\t}\n\n\tgetConflicts(): KeybindingConflict[] {\n\t\treturn this.conflicts.map((conflict) => ({ ...conflict, keybindings: [...conflict.keybindings] }));\n\t}\n\n\tsetUserBindings(userBindings: KeybindingsConfig): void {\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tgetUserBindings(): KeybindingsConfig {\n\t\treturn { ...this.userBindings };\n\t}\n\n\tgetResolvedBindings(): KeybindingsConfig {\n\t\tconst resolved: KeybindingsConfig = {};\n\t\tfor (const id of Object.keys(this.definitions)) {\n\t\t\tconst keys = this.keysById.get(id as Keybinding) ?? [];\n\t\t\tresolved[id] = keys.length === 1 ? keys[0]! : [...keys];\n\t\t}\n\t\treturn resolved;\n\t}\n}\n\nlet globalKeybindings: KeybindingsManager | null = null;\n\nexport function setKeybindings(keybindings: KeybindingsManager): void {\n\tglobalKeybindings = keybindings;\n}\n\nexport function getKeybindings(): KeybindingsManager {\n\tif (!globalKeybindings) {\n\t\tglobalKeybindings = new KeybindingsManager(TUI_KEYBINDINGS);\n\t}\n\treturn globalKeybindings;\n}\n\n/**\n * Returns the selection index after a `tui.select.pageUp` or `tui.select.pageDown` key, moved by `pageSize` and\n * clamped to `0..itemCount - 1`. Returns undefined when `data` is not a selection page key, and 0 for a page key on\n * an empty list, so callers must still check that the list has items before selecting.\n */\nexport function getSelectPageIndex(\n\tkeybindings: KeybindingsManager,\n\tdata: string,\n\tselectedIndex: number,\n\titemCount: number,\n\tpageSize: number,\n): number | undefined {\n\tlet direction: number;\n\tif (keybindings.matches(data, \"tui.select.pageUp\")) direction = -1;\n\telse if (keybindings.matches(data, \"tui.select.pageDown\")) direction = 1;\n\telse return undefined;\n\treturn Math.max(0, Math.min(itemCount - 1, selectedIndex + direction * pageSize));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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"}
package/dist/keys.js CHANGED
@@ -165,6 +165,8 @@ const SYMBOL_KEYS = new Set([
165
165
  ">",
166
166
  "?",
167
167
  ]);
168
+ const SHIFTED_SYMBOL_KEYS = new Set("~!@#$%^&*()_+|{}:<>?");
169
+ const MODIFIER_NAMES = ["shift", "alt", "ctrl", "super"];
168
170
  const MODIFIERS = {
169
171
  shift: 1,
170
172
  alt: 2,
@@ -193,7 +195,23 @@ const FUNCTIONAL_CODEPOINTS = {
193
195
  pageDown: -13,
194
196
  home: -14,
195
197
  end: -15,
198
+ f1: -21,
199
+ f2: -22,
200
+ f3: -23,
201
+ f4: -24,
202
+ f5: -25,
203
+ f6: -26,
204
+ f7: -27,
205
+ f8: -28,
206
+ f9: -29,
207
+ f10: -30,
208
+ f11: -31,
209
+ f12: -32,
196
210
  };
211
+ // Kitty reserves this Private Use Area range for functional keys (F13-F35,
212
+ // media keys, modifier keys, ...). CSI-u codepoints in it are never text.
213
+ const KITTY_FUNCTIONAL_PUA_START = 57344;
214
+ const KITTY_FUNCTIONAL_PUA_END = 63743;
197
215
  const KITTY_FUNCTIONAL_KEY_EQUIVALENTS = new Map([
198
216
  [57399, 48], // KP_0 -> 0
199
217
  [57400, 49], // KP_1 -> 1
@@ -233,6 +251,14 @@ function normalizeShiftedLetterIdentityCodepoint(codepoint, modifier) {
233
251
  }
234
252
  return codepoint;
235
253
  }
254
+ function getLogicalShiftedSymbolCandidate(codepoint, modifier, allowedSymbols) {
255
+ if (codepoint === undefined || (modifier & MODIFIERS.shift) === 0)
256
+ return undefined;
257
+ const normalizedCodepoint = normalizeKittyFunctionalCodepoint(codepoint);
258
+ if (!allowedSymbols.has(String.fromCharCode(normalizedCodepoint)))
259
+ return undefined;
260
+ return { codepoint: normalizedCodepoint, modifier: modifier & ~MODIFIERS.shift };
261
+ }
236
262
  const LEGACY_KEY_SEQUENCES = {
237
263
  up: ["\x1b[A", "\x1bOA"],
238
264
  down: ["\x1b[B", "\x1bOB"],
@@ -377,7 +403,10 @@ export function isKeyRelease(data) {
377
403
  data.includes(":3C") ||
378
404
  data.includes(":3D") ||
379
405
  data.includes(":3H") ||
380
- data.includes(":3F")) {
406
+ data.includes(":3F") ||
407
+ data.includes(":3P") ||
408
+ data.includes(":3Q") ||
409
+ data.includes(":3S")) {
381
410
  return true;
382
411
  }
383
412
  return false;
@@ -399,7 +428,10 @@ export function isKeyRepeat(data) {
399
428
  data.includes(":2C") ||
400
429
  data.includes(":2D") ||
401
430
  data.includes(":2H") ||
402
- data.includes(":2F")) {
431
+ data.includes(":2F") ||
432
+ data.includes(":2P") ||
433
+ data.includes(":2Q") ||
434
+ data.includes(":2S")) {
403
435
  return true;
404
436
  }
405
437
  return false;
@@ -457,6 +489,18 @@ function parseKittySequence(data) {
457
489
  6: FUNCTIONAL_CODEPOINTS.pageDown,
458
490
  7: FUNCTIONAL_CODEPOINTS.home,
459
491
  8: FUNCTIONAL_CODEPOINTS.end,
492
+ 11: FUNCTIONAL_CODEPOINTS.f1,
493
+ 12: FUNCTIONAL_CODEPOINTS.f2,
494
+ 13: FUNCTIONAL_CODEPOINTS.f3,
495
+ 14: FUNCTIONAL_CODEPOINTS.f4,
496
+ 15: FUNCTIONAL_CODEPOINTS.f5,
497
+ 17: FUNCTIONAL_CODEPOINTS.f6,
498
+ 18: FUNCTIONAL_CODEPOINTS.f7,
499
+ 19: FUNCTIONAL_CODEPOINTS.f8,
500
+ 20: FUNCTIONAL_CODEPOINTS.f9,
501
+ 21: FUNCTIONAL_CODEPOINTS.f10,
502
+ 23: FUNCTIONAL_CODEPOINTS.f11,
503
+ 24: FUNCTIONAL_CODEPOINTS.f12,
460
504
  };
461
505
  const codepoint = funcCodes[keyNum];
462
506
  if (codepoint !== undefined) {
@@ -473,6 +517,20 @@ function parseKittySequence(data) {
473
517
  _lastEventType = eventType;
474
518
  return { codepoint, modifier: modValue - 1, eventType };
475
519
  }
520
+ // F1, F2, F4: \x1b[P/Q/S or \x1b[1;<mod>P/Q/S or \x1b[1;<mod>:<event>P/Q/S
521
+ // F3 is sent as \x1b[13~ because \x1b[1;<mod>R collides with cursor position reports.
522
+ const fKeyMatch = data.match(/^\x1b\[(?:1;(\d+)(?::(\d+))?)?([PQS])$/);
523
+ if (fKeyMatch) {
524
+ const modValue = fKeyMatch[1] ? parseInt(fKeyMatch[1], 10) : 1;
525
+ const eventType = parseEventType(fKeyMatch[2]);
526
+ const fKeyCodes = {
527
+ P: FUNCTIONAL_CODEPOINTS.f1,
528
+ Q: FUNCTIONAL_CODEPOINTS.f2,
529
+ S: FUNCTIONAL_CODEPOINTS.f4,
530
+ };
531
+ _lastEventType = eventType;
532
+ return { codepoint: fKeyCodes[fKeyMatch[3]], modifier: modValue - 1, eventType };
533
+ }
476
534
  return null;
477
535
  }
478
536
  function matchesKittySequence(data, expectedCodepoint, expectedModifier) {
@@ -481,14 +539,22 @@ function matchesKittySequence(data, expectedCodepoint, expectedModifier) {
481
539
  return false;
482
540
  const actualMod = parsed.modifier & ~LOCK_MASK;
483
541
  const expectedMod = expectedModifier & ~LOCK_MASK;
484
- // Check if modifiers match
485
- if (actualMod !== expectedMod)
486
- return false;
487
542
  const normalizedCodepoint = normalizeShiftedLetterIdentityCodepoint(normalizeKittyFunctionalCodepoint(parsed.codepoint), parsed.modifier);
488
543
  const normalizedExpectedCodepoint = normalizeShiftedLetterIdentityCodepoint(normalizeKittyFunctionalCodepoint(expectedCodepoint), expectedModifier);
489
- // Primary match: codepoint matches directly after normalizing functional keys
490
- if (normalizedCodepoint === normalizedExpectedCodepoint)
544
+ // Physical match: primary codepoint and every reported modifier match.
545
+ if (actualMod === expectedMod && normalizedCodepoint === normalizedExpectedCodepoint)
491
546
  return true;
547
+ // Logical match: Kitty reports symbols such as "+" as Shift plus the physical "=" key.
548
+ // Bindings name the produced symbol, so consume that implicit Shift while preserving
549
+ // Ctrl, Alt, and Super. The physical "shift+=" spelling remains valid through the match above.
550
+ const logicalShiftedSymbol = getLogicalShiftedSymbolCandidate(parsed.shiftedKey, actualMod, SYMBOL_KEYS);
551
+ if (logicalShiftedSymbol &&
552
+ (logicalShiftedSymbol.modifier & ~LOCK_MASK) === expectedMod &&
553
+ logicalShiftedSymbol.codepoint === normalizeKittyFunctionalCodepoint(expectedCodepoint)) {
554
+ return true;
555
+ }
556
+ if (actualMod !== expectedMod)
557
+ return false;
492
558
  // Alternate match: use base layout key for non-Latin keyboard layouts.
493
559
  // This allows Ctrl+С (Cyrillic) to match Ctrl+c (Latin) when terminal reports
494
560
  // the base layout key (the key in standard PC-101 layout).
@@ -576,13 +642,16 @@ function isDigitKey(key) {
576
642
  return key >= "0" && key <= "9";
577
643
  }
578
644
  function matchesPrintableModifyOtherKeys(data, expectedKeycode, expectedModifier) {
579
- if (expectedModifier === 0)
580
- return false;
581
645
  const parsed = parseModifyOtherKeysSequence(data);
582
- if (!parsed || parsed.modifier !== expectedModifier)
646
+ if (!parsed)
583
647
  return false;
584
- return (normalizeShiftedLetterIdentityCodepoint(parsed.codepoint, parsed.modifier) ===
585
- normalizeShiftedLetterIdentityCodepoint(expectedKeycode, expectedModifier));
648
+ const physicalMatch = parsed.modifier === expectedModifier &&
649
+ normalizeShiftedLetterIdentityCodepoint(parsed.codepoint, parsed.modifier) ===
650
+ normalizeShiftedLetterIdentityCodepoint(expectedKeycode, expectedModifier);
651
+ if (physicalMatch)
652
+ return true;
653
+ const logicalShiftedSymbol = getLogicalShiftedSymbolCandidate(parsed.codepoint, parsed.modifier, SHIFTED_SYMBOL_KEYS);
654
+ return logicalShiftedSymbol?.modifier === expectedModifier && logicalShiftedSymbol.codepoint === expectedKeycode;
586
655
  }
587
656
  function formatKeyNameWithModifiers(keyName, modifier) {
588
657
  const mods = [];
@@ -601,16 +670,25 @@ function formatKeyNameWithModifiers(keyName, modifier) {
601
670
  return mods.length > 0 ? `${mods.join("+")}+${keyName}` : keyName;
602
671
  }
603
672
  function parseKeyId(keyId) {
604
- const parts = keyId.toLowerCase().split("+");
605
- const key = parts[parts.length - 1];
606
- if (!key)
673
+ let key = keyId.toLowerCase();
674
+ const modifiers = new Set();
675
+ while (true) {
676
+ const modifier = MODIFIER_NAMES.find((name) => key.startsWith(`${name}+`));
677
+ if (!modifier)
678
+ break;
679
+ if (modifiers.has(modifier))
680
+ return null;
681
+ modifiers.add(modifier);
682
+ key = key.slice(modifier.length + 1);
683
+ }
684
+ if (!key || (key.includes("+") && key !== "+"))
607
685
  return null;
608
686
  return {
609
687
  key,
610
- ctrl: parts.includes("ctrl"),
611
- shift: parts.includes("shift"),
612
- alt: parts.includes("alt"),
613
- super: parts.includes("super"),
688
+ ctrl: modifiers.has("ctrl"),
689
+ shift: modifiers.has("shift"),
690
+ alt: modifiers.has("alt"),
691
+ super: modifiers.has("super"),
614
692
  };
615
693
  }
616
694
  /**
@@ -885,11 +963,11 @@ export function matchesKey(data, keyId) {
885
963
  case "f10":
886
964
  case "f11":
887
965
  case "f12": {
888
- if (modifier !== 0) {
889
- return false;
890
- }
891
966
  const functionKey = key;
892
- return matchesLegacySequence(data, LEGACY_KEY_SEQUENCES[functionKey]);
967
+ if (modifier === 0 && matchesLegacySequence(data, LEGACY_KEY_SEQUENCES[functionKey])) {
968
+ return true;
969
+ }
970
+ return matchesKittySequence(data, FUNCTIONAL_CODEPOINTS[functionKey], modifier);
893
971
  }
894
972
  }
895
973
  // Handle single letter/digit keys and symbols
@@ -933,7 +1011,7 @@ export function matchesKey(data, keyId) {
933
1011
  matchesPrintableModifyOtherKeys(data, codepoint, modifier));
934
1012
  }
935
1013
  // Check both raw char and Kitty sequence (needed for release events)
936
- return data === key || matchesKittySequence(data, codepoint, 0);
1014
+ return (data === key || matchesKittySequence(data, codepoint, 0) || matchesPrintableModifyOtherKeys(data, codepoint, 0));
937
1015
  }
938
1016
  return false;
939
1017
  }
@@ -978,6 +1056,8 @@ function formatParsedKey(codepoint, modifier, baseLayoutKey) {
978
1056
  keyName = "pageUp";
979
1057
  else if (effectiveCodepoint === FUNCTIONAL_CODEPOINTS.pageDown)
980
1058
  keyName = "pageDown";
1059
+ else if (effectiveCodepoint <= FUNCTIONAL_CODEPOINTS.f1 && effectiveCodepoint >= FUNCTIONAL_CODEPOINTS.f12)
1060
+ keyName = `f${FUNCTIONAL_CODEPOINTS.f1 - effectiveCodepoint + 1}`;
981
1061
  else if (effectiveCodepoint === ARROW_CODEPOINTS.up)
982
1062
  keyName = "up";
983
1063
  else if (effectiveCodepoint === ARROW_CODEPOINTS.down)
@@ -999,11 +1079,13 @@ function formatParsedKey(codepoint, modifier, baseLayoutKey) {
999
1079
  export function parseKey(data) {
1000
1080
  const kitty = parseKittySequence(data);
1001
1081
  if (kitty) {
1002
- return formatParsedKey(kitty.codepoint, kitty.modifier, kitty.baseLayoutKey);
1082
+ const logicalShiftedSymbol = getLogicalShiftedSymbolCandidate(kitty.shiftedKey, kitty.modifier, SYMBOL_KEYS);
1083
+ return formatParsedKey(logicalShiftedSymbol?.codepoint ?? kitty.codepoint, logicalShiftedSymbol?.modifier ?? kitty.modifier, kitty.baseLayoutKey);
1003
1084
  }
1004
1085
  const modifyOtherKeys = parseModifyOtherKeysSequence(data);
1005
1086
  if (modifyOtherKeys) {
1006
- return formatParsedKey(modifyOtherKeys.codepoint, modifyOtherKeys.modifier);
1087
+ const logicalShiftedSymbol = getLogicalShiftedSymbolCandidate(modifyOtherKeys.codepoint, modifyOtherKeys.modifier, SHIFTED_SYMBOL_KEYS);
1088
+ return formatParsedKey(logicalShiftedSymbol?.codepoint ?? modifyOtherKeys.codepoint, logicalShiftedSymbol?.modifier ?? modifyOtherKeys.modifier);
1007
1089
  }
1008
1090
  // Mode-aware legacy sequences
1009
1091
  // When Kitty protocol is active, ambiguous sequences are interpreted as custom terminal mappings:
@@ -1145,6 +1227,10 @@ export function decodeKittyPrintable(data) {
1145
1227
  // Drop control characters or invalid codepoints.
1146
1228
  if (!Number.isFinite(effectiveCodepoint) || effectiveCodepoint < 32)
1147
1229
  return undefined;
1230
+ // Drop unmapped Kitty functional keys (F13-F35, media keys, ...).
1231
+ if (effectiveCodepoint >= KITTY_FUNCTIONAL_PUA_START && effectiveCodepoint <= KITTY_FUNCTIONAL_PUA_END) {
1232
+ return undefined;
1233
+ }
1148
1234
  try {
1149
1235
  return String.fromCodePoint(effectiveCodepoint);
1150
1236
  }