@theia/core 1.77.0-next.49 → 1.77.0-next.57

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 (377) hide show
  1. package/lib/browser/breadcrumbs/breadcrumbs-renderer.js +1 -1
  2. package/lib/browser/breadcrumbs/breadcrumbs-renderer.js.map +1 -1
  3. package/lib/browser/catalog.json +81 -0
  4. package/lib/browser/color-application-contribution.d.ts +1 -1
  5. package/lib/browser/color-application-contribution.d.ts.map +1 -1
  6. package/lib/browser/color-registry.d.ts +1 -1
  7. package/lib/browser/color-registry.d.ts.map +1 -1
  8. package/lib/browser/common-frontend-contribution.d.ts +6 -1
  9. package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
  10. package/lib/browser/common-frontend-contribution.js +20 -3
  11. package/lib/browser/common-frontend-contribution.js.map +1 -1
  12. package/lib/browser/common-frontend-contribution.spec.js +2 -1
  13. package/lib/browser/common-frontend-contribution.spec.js.map +1 -1
  14. package/lib/browser/components/card.d.ts +1 -1
  15. package/lib/browser/components/card.d.ts.map +1 -1
  16. package/lib/browser/components/card.js +3 -2
  17. package/lib/browser/components/card.js.map +1 -1
  18. package/lib/browser/connection-status-service.spec.js +2 -1
  19. package/lib/browser/connection-status-service.spec.js.map +1 -1
  20. package/lib/browser/context-key-service.d.ts +11 -0
  21. package/lib/browser/context-key-service.d.ts.map +1 -1
  22. package/lib/browser/context-key-service.js +7 -0
  23. package/lib/browser/context-key-service.js.map +1 -1
  24. package/lib/browser/decorations-service.spec.js +2 -1
  25. package/lib/browser/decorations-service.spec.js.map +1 -1
  26. package/lib/browser/dialogs/react-dialog.spec.js +2 -1
  27. package/lib/browser/dialogs/react-dialog.spec.js.map +1 -1
  28. package/lib/browser/diff-uris.js +1 -1
  29. package/lib/browser/diff-uris.js.map +1 -1
  30. package/lib/browser/endpoint.js +2 -1
  31. package/lib/browser/endpoint.js.map +1 -1
  32. package/lib/browser/endpoint.spec.js +2 -1
  33. package/lib/browser/endpoint.spec.js.map +1 -1
  34. package/lib/browser/keybinding.d.ts +95 -17
  35. package/lib/browser/keybinding.d.ts.map +1 -1
  36. package/lib/browser/keybinding.js +406 -76
  37. package/lib/browser/keybinding.js.map +1 -1
  38. package/lib/browser/keybinding.spec.js +789 -33
  39. package/lib/browser/keybinding.spec.js.map +1 -1
  40. package/lib/browser/keyboard/browser-keyboard-frontend-contribution.js +1 -1
  41. package/lib/browser/keyboard/browser-keyboard-frontend-contribution.js.map +1 -1
  42. package/lib/browser/keyboard/browser-keyboard-layout-provider.d.ts +3 -4
  43. package/lib/browser/keyboard/browser-keyboard-layout-provider.d.ts.map +1 -1
  44. package/lib/browser/keyboard/browser-keyboard-layout-provider.js +3 -3
  45. package/lib/browser/keyboard/browser-keyboard-layout-provider.js.map +1 -1
  46. package/lib/browser/keyboard/browser-keyboard-layout-provider.spec.js +42 -3
  47. package/lib/browser/keyboard/browser-keyboard-layout-provider.spec.js.map +1 -1
  48. package/lib/browser/keyboard/keyboard-layout-service.d.ts +67 -15
  49. package/lib/browser/keyboard/keyboard-layout-service.d.ts.map +1 -1
  50. package/lib/browser/keyboard/keyboard-layout-service.js +309 -98
  51. package/lib/browser/keyboard/keyboard-layout-service.js.map +1 -1
  52. package/lib/browser/keyboard/keyboard-layout-service.spec.js +541 -15
  53. package/lib/browser/keyboard/keyboard-layout-service.spec.js.map +1 -1
  54. package/lib/browser/keyboard/keys.spec.js +187 -3
  55. package/lib/browser/keyboard/keys.spec.js.map +1 -1
  56. package/lib/browser/label-provider.d.ts.map +1 -1
  57. package/lib/browser/label-provider.js +5 -3
  58. package/lib/browser/label-provider.js.map +1 -1
  59. package/lib/browser/label-provider.spec.js +2 -1
  60. package/lib/browser/label-provider.spec.js.map +1 -1
  61. package/lib/browser/markdown-rendering/markdown-link-handler.js +2 -1
  62. package/lib/browser/markdown-rendering/markdown-link-handler.js.map +1 -1
  63. package/lib/browser/markdown-rendering/markdown-renderer.d.ts +1 -1
  64. package/lib/browser/markdown-rendering/markdown-renderer.d.ts.map +1 -1
  65. package/lib/browser/markdown-rendering/markdown-renderer.js +4 -4
  66. package/lib/browser/markdown-rendering/markdown-renderer.js.map +1 -1
  67. package/lib/browser/markdown-rendering/markdown.js +2 -1
  68. package/lib/browser/markdown-rendering/markdown.js.map +1 -1
  69. package/lib/browser/markdown-rendering/markdown.spec.js +2 -1
  70. package/lib/browser/markdown-rendering/markdown.spec.js.map +1 -1
  71. package/lib/browser/menu/action-menu-node.d.ts +5 -3
  72. package/lib/browser/menu/action-menu-node.d.ts.map +1 -1
  73. package/lib/browser/menu/action-menu-node.js +2 -11
  74. package/lib/browser/menu/action-menu-node.js.map +1 -1
  75. package/lib/browser/menu/action-menu-node.spec.d.ts +2 -0
  76. package/lib/browser/menu/action-menu-node.spec.d.ts.map +1 -0
  77. package/lib/browser/menu/action-menu-node.spec.js +54 -0
  78. package/lib/browser/menu/action-menu-node.spec.js.map +1 -0
  79. package/lib/browser/menu/browser-menu-plugin.js +1 -1
  80. package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
  81. package/lib/browser/menu/menu.spec.js +2 -1
  82. package/lib/browser/menu/menu.spec.js.map +1 -1
  83. package/lib/browser/opener-service.spec.js +3 -2
  84. package/lib/browser/opener-service.spec.js.map +1 -1
  85. package/lib/browser/perspective-service.spec.js +2 -1
  86. package/lib/browser/perspective-service.spec.js.map +1 -1
  87. package/lib/browser/preferences/preference-proxy.spec.js +2 -1
  88. package/lib/browser/preferences/preference-proxy.spec.js.map +1 -1
  89. package/lib/browser/preferences/preference-schema-provider.spec.js +2 -1
  90. package/lib/browser/preferences/preference-schema-provider.spec.js.map +1 -1
  91. package/lib/browser/preferences/preference-service.spec.js +2 -1
  92. package/lib/browser/preferences/preference-service.spec.js.map +1 -1
  93. package/lib/browser/preferences/preference-validation-service.spec.js +78 -77
  94. package/lib/browser/preferences/preference-validation-service.spec.js.map +1 -1
  95. package/lib/browser/quick-input/quick-command-service.d.ts +10 -1
  96. package/lib/browser/quick-input/quick-command-service.d.ts.map +1 -1
  97. package/lib/browser/quick-input/quick-command-service.js +31 -6
  98. package/lib/browser/quick-input/quick-command-service.js.map +1 -1
  99. package/lib/browser/quick-input/quick-command-service.spec.d.ts +2 -0
  100. package/lib/browser/quick-input/quick-command-service.spec.d.ts.map +1 -0
  101. package/lib/browser/quick-input/quick-command-service.spec.js +130 -0
  102. package/lib/browser/quick-input/quick-command-service.spec.js.map +1 -0
  103. package/lib/browser/quick-input/quick-help-service.js +1 -1
  104. package/lib/browser/quick-input/quick-help-service.js.map +1 -1
  105. package/lib/browser/quick-input/quick-input-service.spec.js +2 -1
  106. package/lib/browser/quick-input/quick-input-service.spec.js.map +1 -1
  107. package/lib/browser/quick-input/quick-pick-service-impl.d.ts +6 -6
  108. package/lib/browser/quick-input/quick-pick-service-impl.d.ts.map +1 -1
  109. package/lib/browser/quick-input/quick-view-service.spec.js +2 -1
  110. package/lib/browser/quick-input/quick-view-service.spec.js.map +1 -1
  111. package/lib/browser/secondary-window-handler.d.ts +4 -4
  112. package/lib/browser/secondary-window-handler.d.ts.map +1 -1
  113. package/lib/browser/shell/application-shell.js +1 -1
  114. package/lib/browser/shell/application-shell.js.map +1 -1
  115. package/lib/browser/shell/application-shell.spec.js +2 -1
  116. package/lib/browser/shell/application-shell.spec.js.map +1 -1
  117. package/lib/browser/shell/shell-layout-restorer.spec.js +2 -1
  118. package/lib/browser/shell/shell-layout-restorer.spec.js.map +1 -1
  119. package/lib/browser/shell/side-panel-toolbar.d.ts +1 -1
  120. package/lib/browser/shell/side-panel-toolbar.d.ts.map +1 -1
  121. package/lib/browser/shell/sidebar-menu-widget.js +1 -1
  122. package/lib/browser/shell/sidebar-menu-widget.js.map +1 -1
  123. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +1 -1
  124. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
  125. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +2 -1
  126. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
  127. package/lib/browser/shell/tab-bars.js +2 -1
  128. package/lib/browser/shell/tab-bars.js.map +1 -1
  129. package/lib/browser/status-bar/status-bar.js +1 -1
  130. package/lib/browser/status-bar/status-bar.js.map +1 -1
  131. package/lib/browser/storage-service.spec.js +2 -1
  132. package/lib/browser/storage-service.spec.js.map +1 -1
  133. package/lib/browser/test/jsdom.d.ts.map +1 -1
  134. package/lib/browser/test/jsdom.js +11 -0
  135. package/lib/browser/test/jsdom.js.map +1 -1
  136. package/lib/browser/tooltip-service.js +1 -1
  137. package/lib/browser/tooltip-service.js.map +1 -1
  138. package/lib/browser/tree/tree-consistency.spec.js +1 -1
  139. package/lib/browser/tree/tree-consistency.spec.js.map +1 -1
  140. package/lib/browser/tree/tree-container.spec.js +6 -5
  141. package/lib/browser/tree/tree-container.spec.js.map +1 -1
  142. package/lib/browser/tree/tree-iterator.js +1 -1
  143. package/lib/browser/tree/tree-iterator.js.map +1 -1
  144. package/lib/browser/tree/tree-model.js +2 -2
  145. package/lib/browser/tree/tree-model.js.map +1 -1
  146. package/lib/browser/tree/tree-view-welcome-widget.js +1 -1
  147. package/lib/browser/tree/tree-view-welcome-widget.js.map +1 -1
  148. package/lib/browser/tree/tree-widget.d.ts +2 -2
  149. package/lib/browser/tree/tree-widget.d.ts.map +1 -1
  150. package/lib/browser/tree/tree-widget.js +1 -1
  151. package/lib/browser/tree/tree-widget.js.map +1 -1
  152. package/lib/browser/tree/tree.spec.js +2 -1
  153. package/lib/browser/tree/tree.spec.js.map +1 -1
  154. package/lib/browser/user-working-directory-provider.js +1 -1
  155. package/lib/browser/user-working-directory-provider.js.map +1 -1
  156. package/lib/browser/widgets/react-renderer.js +1 -1
  157. package/lib/browser/widgets/react-renderer.js.map +1 -1
  158. package/lib/browser/widgets/react-widget.js +1 -1
  159. package/lib/browser/widgets/react-widget.js.map +1 -1
  160. package/lib/browser/widgets/select-component.js +4 -3
  161. package/lib/browser/widgets/select-component.js.map +1 -1
  162. package/lib/browser/widgets/select-component.spec.js +3 -2
  163. package/lib/browser/widgets/select-component.spec.js.map +1 -1
  164. package/lib/browser/widgets/widget.js +1 -1
  165. package/lib/browser/widgets/widget.js.map +1 -1
  166. package/lib/common/buffer.js +3 -2
  167. package/lib/common/buffer.js.map +1 -1
  168. package/lib/common/cancellation.js.map +1 -1
  169. package/lib/common/command.spec.js +2 -1
  170. package/lib/common/command.spec.js.map +1 -1
  171. package/lib/common/disposable.spec.js +3 -2
  172. package/lib/common/disposable.spec.js.map +1 -1
  173. package/lib/common/encoding-service.js +2 -2
  174. package/lib/common/encoding-service.js.map +1 -1
  175. package/lib/common/event.d.ts +1 -1
  176. package/lib/common/event.d.ts.map +1 -1
  177. package/lib/common/event.js +0 -1
  178. package/lib/common/event.js.map +1 -1
  179. package/lib/common/file-uri.js +2 -1
  180. package/lib/common/file-uri.js.map +1 -1
  181. package/lib/common/fuzzy-search.js +1 -1
  182. package/lib/common/fuzzy-search.js.map +1 -1
  183. package/lib/common/glob.d.ts.map +1 -1
  184. package/lib/common/glob.js +9 -15
  185. package/lib/common/glob.js.map +1 -1
  186. package/lib/common/index.js +1 -1
  187. package/lib/common/index.js.map +1 -1
  188. package/lib/common/keyboard/keyboard-layout-provider.d.ts +7 -0
  189. package/lib/common/keyboard/keyboard-layout-provider.d.ts.map +1 -1
  190. package/lib/common/keyboard/keyboard-layout-provider.js.map +1 -1
  191. package/lib/common/keys.d.ts +86 -3
  192. package/lib/common/keys.d.ts.map +1 -1
  193. package/lib/common/keys.js +263 -24
  194. package/lib/common/keys.js.map +1 -1
  195. package/lib/common/message-rpc/channel.spec.js +3 -2
  196. package/lib/common/message-rpc/channel.spec.js.map +1 -1
  197. package/lib/common/messaging/proxy-factory.js +2 -2
  198. package/lib/common/messaging/proxy-factory.js.map +1 -1
  199. package/lib/common/messaging/proxy-factory.spec.js +2 -1
  200. package/lib/common/messaging/proxy-factory.spec.js.map +1 -1
  201. package/lib/common/messaging/web-socket-channel.d.ts +1 -1
  202. package/lib/common/messaging/web-socket-channel.d.ts.map +1 -1
  203. package/lib/common/path.spec.js +2 -1
  204. package/lib/common/path.spec.js.map +1 -1
  205. package/lib/common/performance/stopwatch.spec.js +2 -1
  206. package/lib/common/performance/stopwatch.spec.js.map +1 -1
  207. package/lib/common/preferences/preference-schema-service.d.ts +2 -2
  208. package/lib/common/preferences/preference-schema-service.d.ts.map +1 -1
  209. package/lib/common/preferences/preference-service.js +1 -1
  210. package/lib/common/preferences/preference-service.js.map +1 -1
  211. package/lib/common/promise-util.spec.js +2 -1
  212. package/lib/common/promise-util.spec.js.map +1 -1
  213. package/lib/common/quick-pick-service.d.ts +5 -0
  214. package/lib/common/quick-pick-service.d.ts.map +1 -1
  215. package/lib/common/quick-pick-service.js +2 -1
  216. package/lib/common/quick-pick-service.js.map +1 -1
  217. package/lib/common/reference.spec.js +2 -1
  218. package/lib/common/reference.spec.js.map +1 -1
  219. package/lib/common/resource.js +1 -1
  220. package/lib/common/resource.js.map +1 -1
  221. package/lib/common/selection-service.spec.js +2 -1
  222. package/lib/common/selection-service.spec.js.map +1 -1
  223. package/lib/common/selection.js +2 -1
  224. package/lib/common/selection.js.map +1 -1
  225. package/lib/common/stream.d.ts.map +1 -1
  226. package/lib/common/stream.js +2 -1
  227. package/lib/common/stream.js.map +1 -1
  228. package/lib/common/strings.d.ts.map +1 -1
  229. package/lib/common/strings.js +1 -2
  230. package/lib/common/strings.js.map +1 -1
  231. package/lib/common/ternary-search-tree.js +2 -2
  232. package/lib/common/ternary-search-tree.js.map +1 -1
  233. package/lib/common/ternary-search-tree.spec.js +12 -0
  234. package/lib/common/ternary-search-tree.spec.js.map +1 -1
  235. package/lib/common/test/mock-resource-provider.js +1 -1
  236. package/lib/common/test/mock-resource-provider.js.map +1 -1
  237. package/lib/common/types.spec.js +2 -1
  238. package/lib/common/types.spec.js.map +1 -1
  239. package/lib/common/uri-command-handler.js +4 -3
  240. package/lib/common/uri-command-handler.js.map +1 -1
  241. package/lib/common/uri-command-handler.spec.js +3 -2
  242. package/lib/common/uri-command-handler.spec.js.map +1 -1
  243. package/lib/common/uri.spec.js +3 -2
  244. package/lib/common/uri.spec.js.map +1 -1
  245. package/lib/electron-browser/keyboard/electron-keyboard-module.d.ts +2 -0
  246. package/lib/electron-browser/keyboard/electron-keyboard-module.d.ts.map +1 -1
  247. package/lib/electron-browser/keyboard/electron-keyboard-module.js +8 -1
  248. package/lib/electron-browser/keyboard/electron-keyboard-module.js.map +1 -1
  249. package/lib/electron-browser/keyboard/electron-keyboard-module.spec.d.ts +2 -0
  250. package/lib/electron-browser/keyboard/electron-keyboard-module.spec.d.ts.map +1 -0
  251. package/lib/electron-browser/keyboard/electron-keyboard-module.spec.js +28 -0
  252. package/lib/electron-browser/keyboard/electron-keyboard-module.spec.js.map +1 -0
  253. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
  254. package/lib/electron-browser/menu/electron-main-menu-factory.js +3 -2
  255. package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
  256. package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
  257. package/lib/electron-browser/menu/electron-menu-contribution.js +3 -0
  258. package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
  259. package/lib/electron-browser/window/window-zoom-action-bar.js +2 -1
  260. package/lib/electron-browser/window/window-zoom-action-bar.js.map +1 -1
  261. package/lib/electron-common/electron-api.d.ts +5 -0
  262. package/lib/electron-common/electron-api.d.ts.map +1 -1
  263. package/lib/electron-common/electron-api.js +21 -0
  264. package/lib/electron-common/electron-api.js.map +1 -1
  265. package/lib/electron-common/electron-api.spec.d.ts +2 -0
  266. package/lib/electron-common/electron-api.spec.d.ts.map +1 -0
  267. package/lib/electron-common/electron-api.spec.js +40 -0
  268. package/lib/electron-common/electron-api.spec.js.map +1 -0
  269. package/lib/electron-main/electron-api-main.d.ts +0 -1
  270. package/lib/electron-main/electron-api-main.d.ts.map +1 -1
  271. package/lib/electron-main/electron-api-main.js +3 -14
  272. package/lib/electron-main/electron-api-main.js.map +1 -1
  273. package/lib/electron-main/electron-main-application.js +2 -2
  274. package/lib/electron-main/electron-main-application.js.map +1 -1
  275. package/lib/electron-node/hosting/electron-backend-hosting-module.spec.js +2 -1
  276. package/lib/electron-node/hosting/electron-backend-hosting-module.spec.js.map +1 -1
  277. package/lib/electron-node/keyboard/electron-keyboard-layout-provider.js +1 -1
  278. package/lib/electron-node/keyboard/electron-keyboard-layout-provider.js.map +1 -1
  279. package/lib/electron-node/token/electron-token-validator.js +2 -2
  280. package/lib/electron-node/token/electron-token-validator.js.map +1 -1
  281. package/lib/node/backend-application.d.ts +1 -1
  282. package/lib/node/backend-application.d.ts.map +1 -1
  283. package/lib/node/backend-application.js +7 -7
  284. package/lib/node/backend-application.js.map +1 -1
  285. package/lib/node/backend-application.spec.js +1 -1
  286. package/lib/node/backend-application.spec.js.map +1 -1
  287. package/lib/node/bundled-resource-provider.js +4 -4
  288. package/lib/node/bundled-resource-provider.js.map +1 -1
  289. package/lib/node/bundled-resource-provider.spec.js +5 -4
  290. package/lib/node/bundled-resource-provider.spec.js.map +1 -1
  291. package/lib/node/cli.d.ts +1 -1
  292. package/lib/node/cli.d.ts.map +1 -1
  293. package/lib/node/cli.js +2 -2
  294. package/lib/node/cli.js.map +1 -1
  295. package/lib/node/cli.spec.js +3 -2
  296. package/lib/node/cli.spec.js.map +1 -1
  297. package/lib/node/console-logger-server.js +1 -1
  298. package/lib/node/console-logger-server.js.map +1 -1
  299. package/lib/node/env-variables/env-variables-server.js +1 -1
  300. package/lib/node/env-variables/env-variables-server.js.map +1 -1
  301. package/lib/node/environment-utils.spec.js +2 -1
  302. package/lib/node/environment-utils.spec.js.map +1 -1
  303. package/lib/node/file-uri.spec.js +4 -3
  304. package/lib/node/file-uri.spec.js.map +1 -1
  305. package/lib/node/filesystem-locking.js +1 -1
  306. package/lib/node/filesystem-locking.js.map +1 -1
  307. package/lib/node/hosting/browser-connection-token.js +2 -2
  308. package/lib/node/hosting/browser-connection-token.js.map +1 -1
  309. package/lib/node/i18n/localization-contribution.js +1 -1
  310. package/lib/node/i18n/localization-contribution.js.map +1 -1
  311. package/lib/node/key-store-server.js +1 -1
  312. package/lib/node/key-store-server.js.map +1 -1
  313. package/lib/node/logger-cli-contribution.js +2 -2
  314. package/lib/node/logger-cli-contribution.js.map +1 -1
  315. package/lib/node/logger-cli-contribution.spec.js +17 -16
  316. package/lib/node/logger-cli-contribution.spec.js.map +1 -1
  317. package/lib/node/messaging/ipc-connection-provider.js +2 -2
  318. package/lib/node/messaging/ipc-connection-provider.js.map +1 -1
  319. package/lib/node/process-utils.js +1 -1
  320. package/lib/node/process-utils.js.map +1 -1
  321. package/lib/node/process-utils.spec.js +2 -1
  322. package/lib/node/process-utils.spec.js.map +1 -1
  323. package/lib/node/request/backend-request-facade.spec.js +2 -1
  324. package/lib/node/request/backend-request-facade.spec.js.map +1 -1
  325. package/lib/node/setting-service.spec.js +2 -1
  326. package/lib/node/setting-service.spec.js.map +1 -1
  327. package/package.json +4 -4
  328. package/src/browser/common-frontend-contribution.ts +17 -1
  329. package/src/browser/components/card.tsx +1 -1
  330. package/src/browser/context-key-service.ts +15 -0
  331. package/src/browser/keybinding.spec.ts +878 -34
  332. package/src/browser/keybinding.ts +470 -85
  333. package/src/browser/keyboard/browser-keyboard-frontend-contribution.ts +1 -1
  334. package/src/browser/keyboard/browser-keyboard-layout-provider.spec.ts +52 -1
  335. package/src/browser/keyboard/browser-keyboard-layout-provider.ts +5 -5
  336. package/src/browser/keyboard/keyboard-layout-service.spec.ts +640 -15
  337. package/src/browser/keyboard/keyboard-layout-service.ts +358 -106
  338. package/src/browser/keyboard/keys.spec.ts +206 -1
  339. package/src/browser/label-provider.ts +3 -1
  340. package/src/browser/markdown-rendering/markdown-renderer.ts +1 -1
  341. package/src/browser/menu/action-menu-node.spec.ts +60 -0
  342. package/src/browser/menu/action-menu-node.ts +8 -14
  343. package/src/browser/menu/browser-menu-plugin.ts +1 -1
  344. package/src/browser/preferences/preference-validation-service.spec.ts +1 -1
  345. package/src/browser/quick-input/quick-command-service.spec.ts +159 -0
  346. package/src/browser/quick-input/quick-command-service.ts +36 -9
  347. package/src/browser/quick-input/quick-help-service.ts +1 -1
  348. package/src/browser/test/jsdom.ts +11 -0
  349. package/src/browser/tree/tree-container.spec.ts +1 -1
  350. package/src/browser/tree/tree-iterator.ts +1 -1
  351. package/src/browser/tree/tree-model.ts +2 -2
  352. package/src/browser/tree/tree-widget.tsx +2 -2
  353. package/src/common/cancellation.ts +1 -1
  354. package/src/common/disposable.spec.ts +1 -1
  355. package/src/common/event.ts +1 -2
  356. package/src/common/glob.ts +13 -30
  357. package/src/common/json-schema.ts +1 -1
  358. package/src/common/keyboard/keyboard-layout-provider.ts +8 -0
  359. package/src/common/keys.ts +312 -27
  360. package/src/common/message-rpc/channel.spec.ts +1 -1
  361. package/src/common/messaging/proxy-factory.ts +2 -2
  362. package/src/common/quick-pick-service.ts +5 -0
  363. package/src/common/stream.ts +4 -3
  364. package/src/common/strings.ts +2 -5
  365. package/src/common/ternary-search-tree.spec.ts +14 -0
  366. package/src/common/ternary-search-tree.ts +3 -3
  367. package/src/common/uri-command-handler.ts +2 -2
  368. package/src/electron-browser/keyboard/electron-keyboard-module.spec.ts +29 -0
  369. package/src/electron-browser/keyboard/electron-keyboard-module.ts +9 -2
  370. package/src/electron-browser/menu/electron-main-menu-factory.ts +3 -3
  371. package/src/electron-browser/menu/electron-menu-contribution.ts +4 -0
  372. package/src/electron-common/electron-api.spec.ts +42 -0
  373. package/src/electron-common/electron-api.ts +23 -0
  374. package/src/electron-main/electron-api-main.ts +2 -13
  375. package/src/node/backend-application.ts +1 -1
  376. package/src/node/cli.ts +1 -1
  377. package/src/node/logger-cli-contribution.spec.ts +1 -1
@@ -47,7 +47,7 @@ export abstract class AbstractTreeIterator implements TreeIterator, Iterable<Tre
47
47
  this.delegate = this.iterator(this.root);
48
48
  }
49
49
 
50
- // tslint:disable-next-line:typedef
50
+ // eslint-disable-next-line @theia/explicit-return-type
51
51
  [Symbol.iterator]() {
52
52
  return this.delegate;
53
53
  }
@@ -263,12 +263,12 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
263
263
  return this.tree.refresh();
264
264
  }
265
265
 
266
- // tslint:disable-next-line:typedef
266
+ // eslint-disable-next-line @theia/explicit-return-type
267
267
  get selectedNodes() {
268
268
  return this.selectionService.selectedNodes;
269
269
  }
270
270
 
271
- // tslint:disable-next-line:typedef
271
+ // eslint-disable-next-line @theia/explicit-return-type
272
272
  get onSelectionChanged() {
273
273
  return this.selectionService.onSelectionChanged;
274
274
  }
@@ -120,7 +120,7 @@ export interface TreeProps {
120
120
  /**
121
121
  * Props that are forwarded to the virtuoso list rendered. Defaults to `{}`.
122
122
  */
123
- readonly viewProps?: VirtuosoProps<unknown, unknown>;
123
+ readonly viewProps?: Omit<VirtuosoProps<unknown, unknown>, 'width' | 'height' | 'rows'>;
124
124
  }
125
125
 
126
126
  /**
@@ -1602,7 +1602,7 @@ export namespace TreeWidget {
1602
1602
  /**
1603
1603
  * Representation of the tree view properties.
1604
1604
  */
1605
- export interface ViewProps extends VirtuosoProps<unknown, unknown> {
1605
+ export interface ViewProps extends Omit<VirtuosoProps<unknown, unknown>, 'width' | 'height' | 'rows'> {
1606
1606
  /**
1607
1607
  * The width property.
1608
1608
  */
@@ -128,7 +128,7 @@ export class CancellationTokenSource {
128
128
  // before someone asks for the token
129
129
  this._token = CancellationToken.Cancelled;
130
130
  } else if (this._token !== CancellationToken.Cancelled) {
131
- (<MutableToken>this._token).cancel();
131
+ (this._token as MutableToken).cancel();
132
132
  }
133
133
  }
134
134
 
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { expect, spy, use } from 'chai';
18
18
  import { DisposableCollection, Disposable } from './disposable';
19
- import * as spies from 'chai-spies';
19
+ import spies from 'chai-spies';
20
20
 
21
21
  use(spies);
22
22
 
@@ -166,8 +166,7 @@ class CallbackList implements Iterable<Callback> {
166
166
  }
167
167
  }
168
168
 
169
- // tslint:disable-next-line:typedef
170
- public [Symbol.iterator]() {
169
+ public [Symbol.iterator](): IterableIterator<Callback> {
171
170
  if (!this._callbacks) {
172
171
  return [][Symbol.iterator]();
173
172
  }
@@ -127,11 +127,8 @@ function parseRegExp(pattern: string): string {
127
127
  // Special case where we only have globstars
128
128
  if (segments.every(s => s === GLOBSTAR)) {
129
129
  regEx = '.*';
130
- }
131
-
132
- // Build regex over segments
133
- // tslint:disable-next-line:one-line
134
- else {
130
+ } else {
131
+ // Build regex over segments
135
132
  let previousSegmentWasGlobStar = false;
136
133
  segments.forEach((segment, index) => {
137
134
 
@@ -171,24 +168,15 @@ function parseRegExp(pattern: string): string {
171
168
  // range operator
172
169
  if (char === '-') {
173
170
  res = char;
174
- }
175
-
176
- // negation operator (only valid on first index in bracket)
177
- // tslint:disable-next-line:one-line
178
- else if ((char === '^' || char === '!') && !bracketVal) {
171
+ } else if ((char === '^' || char === '!') && !bracketVal) {
172
+ // negation operator (only valid on first index in bracket)
179
173
  res = '^';
180
- }
181
-
182
- // glob split matching is not allowed within character ranges
183
- // see http://man7.org/linux/man-pages/man7/glob.7.html
184
- // tslint:disable-next-line:one-line
185
- else if (char === GLOB_SPLIT) {
174
+ } else if (char === GLOB_SPLIT) {
175
+ // glob split matching is not allowed within character ranges
176
+ // see http://man7.org/linux/man-pages/man7/glob.7.html
186
177
  res = '';
187
- }
188
-
189
- // anything else gets escaped
190
- // tslint:disable-next-line:one-line
191
- else {
178
+ } else {
179
+ // anything else gets escaped
192
180
  res = strings.escapeRegExpCharacters(char);
193
181
  }
194
182
 
@@ -270,7 +258,7 @@ export type ParsedPattern = (path: string, basename?: string) => boolean;
270
258
 
271
259
  // The ParsedExpression returns a Promise iff hasSibling returns a Promise.
272
260
  // eslint-disable-next-line max-len
273
- export type ParsedExpression = (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise<boolean>) => string | Promise<string> /* the matching pattern */;
261
+ export type ParsedExpression = (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise<boolean>) => string | Promise<string>; // the matching pattern
274
262
 
275
263
  export interface IGlobOptions {
276
264
  /**
@@ -341,11 +329,8 @@ function parsePattern(arg1: string | IRelativePattern, options: IGlobOptions): P
341
329
  parsedPattern = trivia4and5(match[1].substring(1), pattern, true);
342
330
  } else if (match = T5.exec(trimForExclusions(pattern, options))!) { // common pattern: something/else just need equals check
343
331
  parsedPattern = trivia4and5(match[1], pattern, false);
344
- }
345
-
346
- // Otherwise convert to pattern
347
- // tslint:disable-next-line:one-line
348
- else {
332
+ } else {
333
+ // Otherwise convert to pattern
349
334
  parsedPattern = toRegExp(pattern);
350
335
  }
351
336
 
@@ -461,7 +446,7 @@ function toRegExp(pattern: string): ParsedStringPattern {
461
446
  * - character ranges (using [...])
462
447
  */
463
448
  export function match(pattern: string | IRelativePattern, path: string): boolean;
464
- export function match(expression: IExpression, path: string, hasSibling?: (name: string) => boolean): string /* the matching pattern */;
449
+ export function match(expression: IExpression, path: string, hasSibling?: (name: string) => boolean): string; // the matching pattern
465
450
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
466
451
  export function match(arg1: string | IExpression | IRelativePattern, path: string, hasSibling?: (name: string) => boolean): any {
467
452
  if (!arg1 || !path) {
@@ -593,7 +578,6 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse
593
578
  // eslint-disable-next-line @typescript-eslint/no-shadow
594
579
  const resultExpression: ParsedStringPattern = function (path: string, basename: string): string | Promise<string> {
595
580
  // eslint-disable-next-line @typescript-eslint/no-shadow
596
- // tslint:disable-next-line:one-variable-per-declaration
597
581
  for (let i = 0, n = parsedPatterns.length; i < n; i++) {
598
582
  // Pattern matches path
599
583
  const result = (<ParsedStringPattern>parsedPatterns[i])(path, basename);
@@ -707,7 +691,6 @@ function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedE
707
691
  let patterns: string[];
708
692
  if (result) {
709
693
  patterns = [];
710
- // tslint:disable-next-line:one-variable-per-declaration
711
694
  for (let i = 0, n = basenames.length; i < n; i++) {
712
695
  patterns.push(result);
713
696
  }
@@ -26,7 +26,7 @@ export type JsonType = 'string' | 'array' | 'number' | 'integer' | 'object' | 'b
26
26
  // copied from https://github.com/Microsoft/vscode/blob/d4edb9abcc261846cabee6702715fe2914ae42cb/src/vs/base/common/jsonSchema.ts
27
27
 
28
28
  // Keep tab indent for easier comparison with the original file.
29
- /* eslint-disable @typescript-eslint/indent */
29
+ /* eslint-disable @stylistic/indent */
30
30
 
31
31
  /**
32
32
  * extended JSON schema
@@ -21,8 +21,11 @@ export const keyboardPath = '/services/keyboard';
21
21
 
22
22
  export const KeyboardLayoutProvider = Symbol('KeyboardLayoutProvider');
23
23
 
24
+ export type KeyboardLayoutSource = 'navigator.keyboard' | 'user-choice' | 'pressed-keys' | 'native-keymap';
25
+
24
26
  export interface KeyboardLayoutProvider {
25
27
  getNativeLayout(): Promise<NativeKeyboardLayout>;
28
+ readonly layoutSource?: KeyboardLayoutSource;
26
29
  }
27
30
 
28
31
  export const KeyboardLayoutChangeNotifier = Symbol('KeyboardLayoutChangeNotifier');
@@ -37,6 +40,11 @@ export interface KeyValidationInput {
37
40
  shiftKey?: boolean;
38
41
  ctrlKey?: boolean;
39
42
  altKey?: boolean;
43
+ /**
44
+ * Whether the AltGr layer is active for the platform (Linux: AltGraph, macOS: Option, Windows: AltGraph or Ctrl+Alt),
45
+ * not the raw `AltGraph` modifier state.
46
+ */
47
+ altGraph?: boolean;
40
48
  }
41
49
 
42
50
  export const KeyValidator = Symbol('KeyValidator');
@@ -75,7 +75,7 @@ export namespace KeySequence {
75
75
 
76
76
  export function parse(keybinding: string): KeySequence {
77
77
  const keyCodes = [];
78
- const rawKeyCodes = keybinding.trim().split(/\s+/g);
78
+ const rawKeyCodes = splitKeySequence(keybinding.trim());
79
79
  for (const rawKeyCode of rawKeyCodes) {
80
80
  const keyCode = KeyCode.parse(rawKeyCode);
81
81
  if (keyCode !== undefined) {
@@ -97,6 +97,35 @@ export interface Keystroke {
97
97
  readonly modifiers?: KeyModifier[];
98
98
  }
99
99
 
100
+ /**
101
+ * The keyboard-layout modifier layer used to produce a logical character, ordered by resolution cost.
102
+ */
103
+ export type LayoutModifiers = 'none' | 'shift' | 'altGraph' | 'shiftAltGraph';
104
+
105
+ export function layoutModifiersIncludeShift(layoutModifiers: LayoutModifiers): boolean {
106
+ return layoutModifiers === 'shift' || layoutModifiers === 'shiftAltGraph';
107
+ }
108
+
109
+ export function layoutModifiersIncludeAltGraph(layoutModifiers: LayoutModifiers): boolean {
110
+ return layoutModifiers === 'altGraph' || layoutModifiers === 'shiftAltGraph';
111
+ }
112
+
113
+ export function isPrintableKey(key: Key): boolean {
114
+ return isPrintableCharacter(key.easyString);
115
+ }
116
+
117
+ export function isPrintableCharacter(character: string | undefined): character is string {
118
+ return !!character && character !== ' ' && isSingleCharacter(character);
119
+ }
120
+
121
+ /**
122
+ * Identifies how a key code was derived for runtime matching.
123
+ * `authored` is the constructor default and represents an authored binding, even for manually constructed instances.
124
+ * `commandModifiers` preserves the event's modifiers as command modifiers, while `layoutModifiers` attributes them to
125
+ * the keyboard layout's character-producing layer.
126
+ */
127
+ export type KeyCodeInterpretation = 'authored' | 'commandModifiers' | 'layoutModifiers';
128
+
100
129
  export interface KeyCodeSchema {
101
130
  key?: Partial<Key>;
102
131
  ctrl?: boolean;
@@ -104,6 +133,180 @@ export interface KeyCodeSchema {
104
133
  alt?: boolean;
105
134
  meta?: boolean;
106
135
  character?: string;
136
+ layoutModifiers?: LayoutModifiers;
137
+ interpretation?: KeyCodeInterpretation;
138
+ supportedByLayout?: boolean;
139
+ authoredToken?: string;
140
+ physical?: boolean;
141
+ }
142
+
143
+ /**
144
+ * Plain keyboard input data used by keybinding dispatch and diagnostics.
145
+ */
146
+ export interface NormalizedKeyboardInput {
147
+ key?: string;
148
+ code?: string;
149
+ keyCode?: number;
150
+ charCode?: number;
151
+ ctrlKey?: boolean;
152
+ shiftKey?: boolean;
153
+ altKey?: boolean;
154
+ metaKey?: boolean;
155
+ altGraph?: boolean;
156
+ repeat?: boolean;
157
+ isComposing?: boolean;
158
+ location?: number;
159
+ timeStamp?: number;
160
+ keyIdentifier?: string;
161
+ getModifierState?(keyArg: string): boolean;
162
+ }
163
+
164
+ /**
165
+ * Read AltGraph state, preferring explicitly transported state over native event state.
166
+ */
167
+ export function readAltGraph(input: NormalizedKeyboardInput): boolean {
168
+ if (input.altGraph !== undefined) {
169
+ return input.altGraph;
170
+ }
171
+ return input.getModifierState?.('AltGraph') ?? false;
172
+ }
173
+
174
+ /**
175
+ * Copy native or transported keyboard input into a normalized, transport-independent representation.
176
+ * The parameter and result share this type because a native `KeyboardEvent` structurally satisfies the permissive input
177
+ * shape. The returned data always has AltGraph resolved even though the field is optional in the input type.
178
+ * `getModifierState` is retained for local diagnostics only and must not be relied on after transport.
179
+ */
180
+ export function normalizeKeyboardInput(input: NormalizedKeyboardInput): NormalizedKeyboardInput {
181
+ return {
182
+ key: input.key,
183
+ code: input.code,
184
+ keyCode: input.keyCode,
185
+ charCode: input.charCode,
186
+ ctrlKey: input.ctrlKey,
187
+ shiftKey: input.shiftKey,
188
+ altKey: input.altKey,
189
+ metaKey: input.metaKey,
190
+ altGraph: readAltGraph(input),
191
+ repeat: input.repeat,
192
+ isComposing: input.isComposing,
193
+ location: input.location,
194
+ timeStamp: input.timeStamp,
195
+ keyIdentifier: input.keyIdentifier,
196
+ getModifierState: input.getModifierState?.bind(input)
197
+ };
198
+ }
199
+
200
+ function splitKeySequence(keybinding: string): string[] {
201
+ const result: string[] = [];
202
+ let current = '';
203
+ let bracketed = false;
204
+ for (let index = 0; index < keybinding.length; index++) {
205
+ const character = keybinding[index];
206
+ if (character === '[') {
207
+ const closingBracket = keybinding.indexOf(']', index + 1);
208
+ const nextWhitespace = keybinding.slice(index + 1).search(/\s/);
209
+ bracketed = closingBracket !== -1 && (nextWhitespace === -1 || closingBracket < index + 1 + nextWhitespace);
210
+ } else if (character === ']' && bracketed) {
211
+ bracketed = false;
212
+ }
213
+ if (/\s/.test(character) && !bracketed) {
214
+ if (current) {
215
+ result.push(current);
216
+ current = '';
217
+ }
218
+ } else {
219
+ current += character;
220
+ }
221
+ }
222
+ if (current) {
223
+ result.push(current);
224
+ }
225
+ return result;
226
+ }
227
+
228
+ function splitKeyCode(keybinding: string): string[] {
229
+ const result: string[] = [];
230
+ let current = '';
231
+ let bracketed = false;
232
+ for (let index = 0; index < keybinding.length; index++) {
233
+ const character = keybinding[index];
234
+ if (character === '[' && keybinding.indexOf(']', index + 1) !== -1) {
235
+ bracketed = true;
236
+ } else if (character === ']' && bracketed) {
237
+ bracketed = false;
238
+ }
239
+ if (!bracketed && current && (character === '+' || character === '-')) {
240
+ result.push(current);
241
+ current = '';
242
+ } else if (!bracketed && character === '+') {
243
+ continue;
244
+ } else {
245
+ current += character;
246
+ }
247
+ }
248
+ if (current) {
249
+ result.push(current);
250
+ }
251
+ return result;
252
+ }
253
+
254
+ function parseScanCode(token: string): Key | undefined {
255
+ const match = /^\[([^\]]+)\]$/.exec(token);
256
+ if (!match || match[1].toLocaleLowerCase().startsWith('char:')) {
257
+ return undefined;
258
+ }
259
+ const key = Key.getKey(match[1]) ?? Object.values(CODE_TO_KEY).find(candidate => candidate.code.toLocaleLowerCase() === match[1].toLocaleLowerCase());
260
+ if (!key) {
261
+ throw new Error(nls.localize('theia/core/keybinding/unknownScanCode', 'Unknown scan code {0}. Use a supported KeyboardEvent.code name.', match[1]));
262
+ }
263
+ return key;
264
+ }
265
+
266
+ /** Parse a logical-character token, rejecting bare grammar delimiters. */
267
+ function parseCharacterToken(token: string): string | undefined {
268
+ const match = /^\[char:(.*)\]$/i.exec(token);
269
+ if (match) {
270
+ const payload = match[1];
271
+ let character: string;
272
+ if (/^0x[0-9a-f]+$/i.test(payload)) {
273
+ const value = Number.parseInt(payload.slice(2), 16);
274
+ if (value > 0x10ffff || value >= 0xd800 && value <= 0xdfff) {
275
+ throw new Error(nls.localize('theia/core/keybinding/invalidCharacter', 'Invalid Unicode character {0}.', payload));
276
+ }
277
+ character = String.fromCodePoint(value);
278
+ } else {
279
+ character = payload;
280
+ }
281
+ if (!isSingleCharacter(character) || !/^0x/i.test(payload) && RESERVED_BARE_CHARACTERS.has(character)) {
282
+ throw new Error(nls.localize('theia/core/keybinding/invalidCharacter', 'Invalid Unicode character {0}.', payload));
283
+ }
284
+ return character;
285
+ }
286
+ return isSingleCharacter(token) && !RESERVED_BARE_CHARACTERS.has(token) ? token : undefined;
287
+ }
288
+
289
+ function isSingleCharacter(value: string): boolean {
290
+ return Array.from(value).length === 1;
291
+ }
292
+
293
+ /** Characters reserved by the keybinding grammar and therefore unavailable as bare logical-character tokens. */
294
+ const RESERVED_BARE_CHARACTERS = new Set([' ', '+', '-', '[', ']']);
295
+
296
+ /**
297
+ * Serialize a logical character for the keybinding grammar.
298
+ * `+` and `-` are excluded from legacy bare spelling because they delimit key-code tokens. Uppercase ASCII letters are
299
+ * escaped so their case is not lost by case-insensitive legacy key lookup.
300
+ */
301
+ export function characterToken(character: string): string {
302
+ if (!isSingleCharacter(character)) {
303
+ throw new Error(nls.localize('theia/core/keybinding/invalidCharacter', 'Invalid Unicode character {0}.', character));
304
+ }
305
+ const legacyCharacter = !!EASY_TO_KEY[character] && character !== '+' && character !== '-';
306
+ const requiresEscape = /^[A-Z]$/.test(character) || RESERVED_BARE_CHARACTERS.has(character) && !legacyCharacter;
307
+ return requiresEscape
308
+ ? `[char:0x${character.codePointAt(0)!.toString(16).toUpperCase()}]`
309
+ : character;
107
310
  }
108
311
 
109
312
  /**
@@ -117,6 +320,13 @@ export class KeyCode {
117
320
  public readonly alt: boolean;
118
321
  public readonly meta: boolean;
119
322
  public readonly character: string | undefined;
323
+ public readonly layoutModifiers: LayoutModifiers;
324
+ public readonly interpretation: KeyCodeInterpretation;
325
+ /** Whether the authored logical character is available on the active keyboard layout. */
326
+ public readonly supportedByLayout: boolean;
327
+ public readonly authoredToken: string | undefined;
328
+ /** Whether the authored token denotes a physical scan code rather than a logical character. */
329
+ public readonly physical: boolean;
120
330
 
121
331
  public constructor(schema: KeyCodeSchema) {
122
332
  const key = schema.key;
@@ -134,13 +344,18 @@ export class KeyCode {
134
344
  this.alt = !!schema.alt;
135
345
  this.meta = !!schema.meta;
136
346
  this.character = schema.character;
347
+ this.layoutModifiers = schema.layoutModifiers ?? 'none';
348
+ this.interpretation = schema.interpretation ?? 'authored';
349
+ this.supportedByLayout = schema.supportedByLayout !== false;
350
+ this.authoredToken = schema.authoredToken;
351
+ this.physical = !!schema.physical;
137
352
  }
138
353
 
139
354
  /**
140
355
  * Return true if this KeyCode only contains modifiers.
141
356
  */
142
357
  public isModifierOnly(): boolean {
143
- return this.key === undefined;
358
+ return this.key === undefined && this.character === undefined;
144
359
  }
145
360
 
146
361
  /**
@@ -150,11 +365,11 @@ export class KeyCode {
150
365
  if (this.key && (!other.key || this.key.code !== other.key.code) || !this.key && other.key) {
151
366
  return false;
152
367
  }
153
- return this.ctrl === other.ctrl && this.alt === other.alt && this.shift === other.shift && this.meta === other.meta;
368
+ return this.dispatchString() === other.dispatchString();
154
369
  }
155
370
 
156
- /*
157
- * Return a keybinding string compatible with the `Keybinding.keybinding` property.
371
+ /**
372
+ * Return a keybinding string that round-trips the authored spelling through {@link authoredToken}.
158
373
  */
159
374
  toString(): string {
160
375
  const result = [];
@@ -170,8 +385,69 @@ export class KeyCode {
170
385
  if (this.ctrl) {
171
386
  result.push(Key.CONTROL_LEFT.easyString);
172
387
  }
388
+ if (this.authoredToken) {
389
+ result.push(this.authoredToken);
390
+ } else if (this.key) {
391
+ result.push(this.key.easyString);
392
+ }
393
+ return result.join('+');
394
+ }
395
+
396
+ /**
397
+ * Return the runtime match identity used for keybinding dispatch.
398
+ * The interpretation is diagnostic metadata and does not affect this identity.
399
+ */
400
+ dispatchString(): string {
401
+ const result: string[] = [];
402
+ if (this.meta) {
403
+ result.push(SpecialCases.META);
404
+ }
405
+ if (this.shift) {
406
+ result.push(Key.SHIFT_LEFT.easyString);
407
+ }
408
+ if (this.alt) {
409
+ result.push(Key.ALT_LEFT.easyString);
410
+ }
411
+ if (this.ctrl) {
412
+ result.push(Key.CONTROL_LEFT.easyString);
413
+ }
173
414
  if (this.key) {
174
415
  result.push(this.key.easyString);
416
+ } else if (this.character) {
417
+ result.push(characterToken(this.character));
418
+ }
419
+ const suffix = this.layoutModifiers === 'shift' ? '@shift'
420
+ : this.layoutModifiers === 'altGraph' ? '@altgraph'
421
+ : this.layoutModifiers === 'shiftAltGraph' ? '@shift@altgraph' : '';
422
+ return result.join('+') + suffix;
423
+ }
424
+
425
+ /**
426
+ * Derive an authored keybinding stroke from a key event for recorder persistence.
427
+ * This cannot use {@link toString}: event-derived key codes have no {@link authoredToken}, so `toString` would persist
428
+ * the physical US key name instead of the committed logical character. Non-printable keys, Space and numpad keys are
429
+ * persisted by name; printable keys without a committed character are persisted as scan codes.
430
+ */
431
+ toAuthoredKeybindingString(): string {
432
+ const result: string[] = [];
433
+ if (this.meta) {
434
+ result.push(SpecialCases.META);
435
+ }
436
+ const character = isPrintableCharacter(this.character) && !this.key?.code.startsWith('Numpad') ? this.character : undefined;
437
+ const shiftedLetter = !!character && /^[A-Z]$/.test(character);
438
+ if (this.shift && (!character || shiftedLetter)) {
439
+ result.push(Key.SHIFT_LEFT.easyString);
440
+ }
441
+ if (this.alt) {
442
+ result.push(Key.ALT_LEFT.easyString);
443
+ }
444
+ if (this.ctrl) {
445
+ result.push(Key.CONTROL_LEFT.easyString);
446
+ }
447
+ if (character) {
448
+ result.push(characterToken(shiftedLetter ? character.toLocaleLowerCase() : character));
449
+ } else if (this.key) {
450
+ result.push(isPrintableKey(this.key) ? `[${this.key.code}]` : this.key.easyString);
175
451
  }
176
452
  return result.join('+');
177
453
  }
@@ -179,7 +455,7 @@ export class KeyCode {
179
455
  /**
180
456
  * Create a KeyCode from one of several input types.
181
457
  */
182
- public static createKeyCode(input: KeyboardEvent | Keystroke | KeyCodeSchema | string, eventDispatch: 'code' | 'keyCode' = 'code'): KeyCode {
458
+ public static createKeyCode(input: KeyboardEvent | NormalizedKeyboardInput | Keystroke | KeyCodeSchema | string, eventDispatch: 'code' | 'keyCode' = 'code'): KeyCode {
183
459
  if (typeof input === 'string') {
184
460
  const parts = input.split('+');
185
461
  if (!KeyCode.isModifierString(parts[0])) {
@@ -189,7 +465,7 @@ export class KeyCode {
189
465
  });
190
466
  }
191
467
  return KeyCode.createKeyCode({ modifiers: parts as KeyModifier[] });
192
- } else if (KeyCode.isKeyboardEvent(input)) {
468
+ } else if (KeyCode.isKeyboardEvent(input) || KeyCode.isNormalizedKeyboardInput(input)) {
193
469
  const key = KeyCode.toKey(input, eventDispatch);
194
470
  return new KeyCode({
195
471
  key: Key.isModifier(key.code) ? undefined : key,
@@ -238,25 +514,14 @@ export class KeyCode {
238
514
  }
239
515
 
240
516
  const schema: KeyCodeSchema = {};
241
- const keys = [];
242
- let currentKey = '';
243
- for (const character of keybinding.trim().toLowerCase()) {
244
- if (currentKey && (character === '-' || character === '+')) {
245
- keys.push(currentKey);
246
- currentKey = '';
247
- } else if (character !== '+') {
248
- currentKey += character;
249
- }
250
- }
251
- if (currentKey) {
252
- keys.push(currentKey);
253
- }
517
+ const keys = splitKeyCode(keybinding.trim());
254
518
  /* If duplicates i.e ctrl+ctrl+a or alt+alt+b or b+alt+b it is invalid */
255
- if (keys.length !== new Set(keys).size) {
519
+ if (keys.length !== new Set(keys.map(key => key.toLocaleLowerCase())).size) {
256
520
  throw new Error(nls.localize('theia/core/keybinding/duplicateModifierError', "Can't parse keybinding {0} Duplicate modifiers", keybinding));
257
521
  }
258
522
 
259
- for (let keyString of keys) {
523
+ for (const token of keys) {
524
+ let keyString = token.toLocaleLowerCase();
260
525
  if (SPECIAL_ALIASES[keyString] !== undefined) {
261
526
  keyString = SPECIAL_ALIASES[keyString];
262
527
  }
@@ -289,7 +554,20 @@ export class KeyCode {
289
554
  schema.key = key;
290
555
  }
291
556
  } else {
292
- throw new Error(nls.localize('theia/core/keybinding/unrecognizedKeyError', 'Unrecognized key {0} in {1}', keyString, keybinding));
557
+ const scanCode = parseScanCode(token);
558
+ if (scanCode) {
559
+ schema.key = scanCode;
560
+ schema.authoredToken = `[${scanCode.code}]`;
561
+ schema.physical = true;
562
+ continue;
563
+ }
564
+ const character = parseCharacterToken(token);
565
+ if (character) {
566
+ schema.character = character;
567
+ schema.authoredToken = characterToken(character);
568
+ continue;
569
+ }
570
+ throw new Error(nls.localize('theia/core/keybinding/unrecognizedKeyError', 'Unrecognized key {0} in {1}', token, keybinding));
293
571
  }
294
572
  }
295
573
 
@@ -339,6 +617,13 @@ export namespace KeyCode {
339
617
  return false;
340
618
  }
341
619
 
620
+ /**
621
+ * Return true if the given object carries normalized keyboard input fields.
622
+ */
623
+ export function isNormalizedKeyboardInput(input: object): input is NormalizedKeyboardInput {
624
+ return 'code' in input || 'keyCode' in input || 'charCode' in input || 'keyIdentifier' in input;
625
+ }
626
+
342
627
  /**
343
628
  * Determine the pressed key of a keyboard event. This key should correspond to the physical key according
344
629
  * to a standard US keyboard layout. International keyboard layouts are handled by `KeyboardLayoutService`.
@@ -346,7 +631,7 @@ export namespace KeyCode {
346
631
  * `keyIdentifier` is used to access this deprecated field:
347
632
  * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyIdentifier
348
633
  */
349
- export function toKey(event: KeyboardEvent, dispatch: 'code' | 'keyCode' = 'code'): Key {
634
+ export function toKey(event: NormalizedKeyboardInput, dispatch: 'code' | 'keyCode' = 'code'): Key {
350
635
  const code = event.code;
351
636
  if (code && dispatch === 'code') {
352
637
  if (isOSX) {
@@ -373,7 +658,7 @@ export namespace KeyCode {
373
658
  }
374
659
  }
375
660
 
376
- // tslint:disable-next-line: deprecation
661
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
377
662
  const keyCode = event.keyCode;
378
663
  if (keyCode) {
379
664
  const key = Key.getKey(keyCode);
@@ -382,7 +667,7 @@ export namespace KeyCode {
382
667
  }
383
668
  }
384
669
 
385
- const keyIdentifier = (event as KeyboardEvent & { keyIdentifier?: string }).keyIdentifier;
670
+ const keyIdentifier = event.keyIdentifier;
386
671
  if (keyIdentifier) {
387
672
  const key = Key.getKey(keyIdentifier);
388
673
  if (key) {
@@ -397,7 +682,7 @@ export namespace KeyCode {
397
682
  * If the key does not correspond to a printable character, `undefined` is returned.
398
683
  * The result may be altered by modifier keys.
399
684
  */
400
- export function toCharacter(event: KeyboardEvent): string | undefined {
685
+ export function toCharacter(event: NormalizedKeyboardInput): string | undefined {
401
686
  const key = event.key;
402
687
  // Use the key property if it contains exactly one unicode character
403
688
  if (key && Array.from(key).length === 1) {
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { assert, expect, spy, use } from 'chai';
18
- import * as spies from 'chai-spies';
18
+ import spies from 'chai-spies';
19
19
  import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from './uint8-array-message-buffer';
20
20
  import { ChannelMultiplexer, ForwardingChannel, MessageProvider } from './channel';
21
21
  import { RpcProtocol } from './rpc-protocol';