mulmoterminal 5.0.1 → 5.2.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.
- package/common/agentTitle.ts +23 -0
- package/common/keymap.ts +45 -3
- package/dist/assets/{AllPackages-B1YCJRYB-4WQ_EIrl.js → AllPackages-B1YCJRYB-Byv5Y2l8.js} +1 -1
- package/dist/assets/{BaseConfiguration-B6s_tKOW-CuXGj6gD.js → BaseConfiguration-B6s_tKOW-D-gjoRXo.js} +1 -1
- package/dist/assets/{Element-BMI7Nj5w-Bik3AfgD.js → Element-BMI7Nj5w-pmadKN44.js} +1 -1
- package/dist/assets/{Entities-C8p_0jCn-CjiJEF3r.js → Entities-C8p_0jCn-DOze-aLz.js} +1 -1
- package/dist/assets/{FunctionList-YWk54TCy-Dq1GQL-M.js → FunctionList-YWk54TCy-ChT_85FS.js} +1 -1
- package/dist/assets/{InputJax-C5dj-ntL-DEjnMcSa.js → InputJax-C5dj-ntL-QDnGDgyA.js} +1 -1
- package/dist/assets/{MathItem-YJvQL-XJ-pMaMH7Pe.js → MathItem-YJvQL-XJ-C1WmSlqG.js} +1 -1
- package/dist/assets/{MmlFactory-DSoKkE7s-BTFYdeyR.js → MmlFactory-DSoKkE7s-BSods9g3.js} +1 -1
- package/dist/assets/{Options-oARQeeuT-DN-QpMwi.js → Options-oARQeeuT-BezHG2DV.js} +1 -1
- package/dist/assets/{OutputJax-DfUZNNCu-0eNVVspA.js → OutputJax-DfUZNNCu-CiGZyFkj.js} +1 -1
- package/dist/assets/{PrioritizedList-6lun1Xqd-B3xDwkAm.js → PrioritizedList-6lun1Xqd-1YFOP2UD.js} +1 -1
- package/dist/assets/{Styles-5NmwS-3M-CYH8SIw8.js → Styles-5NmwS-3M-CckuzfVu.js} +1 -1
- package/dist/assets/{TeXAtom-B5ni9myz-B2Lg1OeP.js → TeXAtom-B5ni9myz-czpsshhI.js} +1 -1
- package/dist/assets/{abnfDiagram-VCTEODGH-BGhi-oVb-rfnIw5mF.js → abnfDiagram-VCTEODGH-BGhi-oVb-CxSD522K.js} +1 -1
- package/dist/assets/{arc-CK5ru50N-CpwYDtFh.js → arc-CK5ru50N-DKCl2r1T.js} +1 -1
- package/dist/assets/architecture-7GRP2DOG-otSkCkT5-YabtMIbr.js +1 -0
- package/dist/assets/{architectureDiagram-5GKGNRK7-ELuPYMlf-jRFBK2xY.js → architectureDiagram-5GKGNRK7-ELuPYMlf-Dopud1bd.js} +1 -1
- package/dist/assets/{assistive-mml-CdU3rUpx-CfM4F5jW.js → assistive-mml-CdU3rUpx-CBXDqBb7.js} +1 -1
- package/dist/assets/{blockDiagram-I7D4REHJ-BZ7-OGWQ-GPkhdnf1.js → blockDiagram-I7D4REHJ-BZ7-OGWQ-o5hOntDX.js} +1 -1
- package/dist/assets/{c4Diagram-7LVT6UL2-DCovPZ_4-DlgnltG1.js → c4Diagram-7LVT6UL2-DCovPZ_4-DmxXKUN2.js} +1 -1
- package/dist/assets/channel-Bmu_OOc6-LXxQltDk.js +1 -0
- package/dist/assets/{chunk-4HAMMTFA-DqpzLmar-BYwab83k.js → chunk-4HAMMTFA-DqpzLmar-DiA8EWSJ.js} +1 -1
- package/dist/assets/{chunk-75Z2AOVW-CT5TYzp5-BRr2sap2.js → chunk-75Z2AOVW-CT5TYzp5-lldrjFxV.js} +1 -1
- package/dist/assets/{chunk-DU6HZSFF-BVf-rtdf-BiTD5bH2.js → chunk-DU6HZSFF-BVf-rtdf-CwUL1NFa.js} +1 -1
- package/dist/assets/{chunk-F27PBJKO-rP8pUsk3-jZL8tnaO.js → chunk-F27PBJKO-rP8pUsk3-CzNXy7AU.js} +1 -1
- package/dist/assets/{chunk-IMKFNOWR-D_IT0r3G-4Na8DCGZ.js → chunk-IMKFNOWR-D_IT0r3G-B9KUwB52.js} +1 -1
- package/dist/assets/{chunk-POPQ4Y6H-C5YURnHe-BtvIAZQ9.js → chunk-POPQ4Y6H-C5YURnHe-BSqsqkgY.js} +1 -1
- package/dist/assets/{chunk-SHT3W25Y-CfF0J8Qh-CSKY6pei.js → chunk-SHT3W25Y-CfF0J8Qh-5fHXXkh7.js} +1 -1
- package/dist/assets/{chunk-SVP7TREG-CTZbRIbX-DXmyUlG6.js → chunk-SVP7TREG-CTZbRIbX-CWrs29Kz.js} +1 -1
- package/dist/assets/{chunk-TICWLB2K-DP1lYmZm-2WQGl4am.js → chunk-TICWLB2K-DP1lYmZm-DDcA7wX4.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-vg0kfC73-BNbpCBp8.js → chunk-XXDRQBXY-vg0kfC73-B9m3UCLq.js} +1 -1
- package/dist/assets/classDiagram-ZZMXUADV-BDQOAOBf-BUvThf0-.js +1 -0
- package/dist/assets/classDiagram-v2-VYDZK3BY-CwPXtzoF-BUvThf0-.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-qIiD3RGD-glIzrMsu.js → cose-bilkent-JH36ORCC-qIiD3RGD-8iqUd8fN.js} +1 -1
- package/dist/assets/cynefin-OW5HDTMX-Xr6IPdZG-BzdrGHCp.js +1 -0
- package/dist/assets/{cynefinDiagram-5FMLGOSQ-BZrUCS-v-BP9iYDiL.js → cynefinDiagram-5FMLGOSQ-BZrUCS-v-BjGdpO1b.js} +1 -1
- package/dist/assets/{dagre-C2SZ8h4o-Cvn7MMN8.js → dagre-C2SZ8h4o-Bv8J8VUz.js} +1 -1
- package/dist/assets/{dagre-GXQ25YYZ-CQcLM4na-CUPIues9.js → dagre-GXQ25YYZ-CQcLM4na-BEUkvakq.js} +1 -1
- package/dist/assets/{diagram-S7CK7UJ4-BdmcmUQh-BzmDaJl4.js → diagram-S7CK7UJ4-BdmcmUQh-C17Q-TTS.js} +1 -1
- package/dist/assets/{diagram-UQ7AKVKN-BtvmEiYl-C-SDkeQT.js → diagram-UQ7AKVKN-BtvmEiYl-sOGBhdh3.js} +1 -1
- package/dist/assets/{diagram-VSXAHHWV-qEG6N0bV-BBEGoVq0.js → diagram-VSXAHHWV-qEG6N0bV-D-F3WtOn.js} +1 -1
- package/dist/assets/{diagram-VX7I27RA-BA8is49N-C_RijuTO.js → diagram-VX7I27RA-BA8is49N-DDC2KnwX.js} +1 -1
- package/dist/assets/{diagram-Z3DM3KII-XPcU7IOQ-CxOwdwHR.js → diagram-Z3DM3KII-XPcU7IOQ-DnNwyEbY.js} +1 -1
- package/dist/assets/{dist-uQlE_JYp.js → dist-B3WvX9Mu.js} +1 -1
- package/dist/assets/{dist-BvG2w_9k.js → dist-B_fklXwV.js} +1 -1
- package/dist/assets/{dist-DBRVDw9D.js → dist-BfgqBdfY.js} +1 -1
- package/dist/assets/{dist-CWF1S7vL.js → dist-CqavRLcS.js} +1 -1
- package/dist/assets/{dist-DeiyD9Ki-BDcmanZh.js → dist-DeiyD9Ki-CTmQI5BY.js} +1 -1
- package/dist/assets/{ebnfDiagram-PWID7BFC-CTHIHdBS-BGwyAx_X.js → ebnfDiagram-PWID7BFC-CTHIHdBS-BUK0gvW3.js} +1 -1
- package/dist/assets/{erDiagram-RLTQ6QDP-DVpWTNZj-CpwnuTPx.js → erDiagram-RLTQ6QDP-DVpWTNZj-WczcFdQ5.js} +1 -1
- package/dist/assets/eventmodeling-NTZA5JFV-B7bRrpt_-izWjOGe8.js +1 -0
- package/dist/assets/flowDiagram-HODETNUW-r-3T5g30-D06E2Yur.js +1 -0
- package/dist/assets/{ganttDiagram-EL5Y4UJY-BfAgk15F-CuhMMDMU.js → ganttDiagram-EL5Y4UJY-BfAgk15F-DTGMCrLj.js} +1 -1
- package/dist/assets/gitGraph-4MIJSDKK-BhzSx5wq-HItyG1D5.js +1 -0
- package/dist/assets/{gitGraphDiagram-WWUBYQGX-DEVVZ6wt-Bh_VaB4G.js → gitGraphDiagram-WWUBYQGX-DEVVZ6wt-HdaEqyjq.js} +1 -1
- package/dist/assets/{graphlib-BYLhHyYO-BCQclP1Y.js → graphlib-BYLhHyYO-DQGQ3Hua.js} +1 -1
- package/dist/assets/{html-Z7dGbczU-UIlR1xAp.js → html-Z7dGbczU-CrSYt5SB.js} +1 -1
- package/dist/assets/{index-sxsMmFcI.js → index-CFCwHCAC.js} +322 -322
- package/dist/assets/index-ZQzSIgvD.css +1 -0
- package/dist/assets/info-A6RAGUB7-fR2SUJmJ-CCp3Pve-.js +1 -0
- package/dist/assets/{infoDiagram-27XIBGKW-CvHUhAHd-DigY259e.js → infoDiagram-27XIBGKW-CvHUhAHd-Bqc9FCJv.js} +1 -1
- package/dist/assets/{ishikawaDiagram-5VMMS53U-CeqyKdwk-ACmU-Jzv.js → ishikawaDiagram-5VMMS53U-CeqyKdwk-BTaokajf.js} +1 -1
- package/dist/assets/{journeyDiagram-3NMN7TZE-Jfi7MPDi-YIFwpJyP.js → journeyDiagram-3NMN7TZE-Jfi7MPDi-DG9WVFfp.js} +1 -1
- package/dist/assets/{kanban-definition-UXKFOSKX-yOrlojns-0RXVl3u9.js → kanban-definition-UXKFOSKX-yOrlojns-B5-MNvAZ.js} +1 -1
- package/dist/assets/{lengths-CvmPfBid-BAfNjGrF.js → lengths-CvmPfBid-Ccc3uBwx.js} +1 -1
- package/dist/assets/{linear-jdmEy-qs-Djjlqhox.js → linear-jdmEy-qs-BRxqk9pe.js} +1 -1
- package/dist/assets/{liteAdaptor-pH5MXTG0-pAc8cmKr.js → liteAdaptor-pH5MXTG0-D2DVKbJh.js} +1 -1
- package/dist/assets/material-symbols-outlined-DhPLOrnb.woff2 +0 -0
- package/dist/assets/{mathjax-DVEo4UYj-Cnj1zcS1.js → mathjax-DVEo4UYj-z2lf4I_o.js} +1 -1
- package/dist/assets/{mermaid-parser.core-CzBW8Fof-s3bWPn0O.js → mermaid-parser.core-CzBW8Fof-kR4f_D21.js} +2 -2
- package/dist/assets/{mermaid.core-Dv4uylek-DqGXjOPu.js → mermaid.core-Dv4uylek-Ddm4KdK9.js} +4 -4
- package/dist/assets/{mindmap-definition-YA3MSWOX-DP_2R9Ga-KrOUlEvG.js → mindmap-definition-YA3MSWOX-DP_2R9Ga-BamcFU30.js} +1 -1
- package/dist/assets/{mo-Xv_6CC7A-5T19MjVl.js → mo-Xv_6CC7A-C4qQoXD7.js} +1 -1
- package/dist/assets/packet-AYTQ26CC-B_oKR9KZ-P1h4UNRU.js +1 -0
- package/dist/assets/{pegDiagram-XKGWAZYB-BsBWryhi-DYwgFu60.js → pegDiagram-XKGWAZYB-BsBWryhi-BPOLi_DS.js} +1 -1
- package/dist/assets/pie-WAS4IAKB-D1ZXrN1W-BejuFjHy.js +1 -0
- package/dist/assets/{pieDiagram-E7YTZNPT-OugkS2pU-CitvFGku.js → pieDiagram-E7YTZNPT-OugkS2pU-BxJPZt-m.js} +1 -1
- package/dist/assets/{quadrantDiagram-AXDQQJYC-DXEAAaUE-BJz-5fWN.js → quadrantDiagram-AXDQQJYC-DXEAAaUE-CeLGIG_l.js} +1 -1
- package/dist/assets/radar-RG4KPBEZ-BmUgDkiH-Wu_t-Az-.js +1 -0
- package/dist/assets/railroad-74A4TZTK-6lEXVJo8-DJe4dT-U.js +1 -0
- package/dist/assets/railroad-abnf-HS5TGJTU-BG28Qiz1-M9sfPaQt.js +1 -0
- package/dist/assets/railroad-ebnf-LZEXJU2U-DzpHhtTH-C1RD0jlr.js +1 -0
- package/dist/assets/railroad-peg-WCYAUIDC-B2CHCTyG-CsDICDaK.js +1 -0
- package/dist/assets/{railroadDiagram-O6MQD6OU-BJys8O96-8S8j18MZ.js → railroadDiagram-O6MQD6OU-BJys8O96-CXO-wle8.js} +1 -1
- package/dist/assets/{requirementDiagram-BXWQKSXE-BaDgCtM5-D0sLbDHs.js → requirementDiagram-BXWQKSXE-BaDgCtM5-Dt4Cfr6O.js} +1 -1
- package/dist/assets/{sankeyDiagram-P5KCCOFB-puZsr_vK-C1OX3N7F.js → sankeyDiagram-P5KCCOFB-puZsr_vK-CMC9fgwz.js} +1 -1
- package/dist/assets/{sequenceDiagram-WJ2MYXX4-D1ziEryC-CvoJhcsM.js → sequenceDiagram-WJ2MYXX4-D1ziEryC-DB5eVRRY.js} +1 -1
- package/dist/assets/{src-CLC0ddSd-D-EBSy-7.js → src-CLC0ddSd-ByF0JTrb.js} +1 -1
- package/dist/assets/{stateDiagram-D77RDMKH-HSEurT6h-DWNnPlrT.js → stateDiagram-D77RDMKH-HSEurT6h-BwSqvh1q.js} +1 -1
- package/dist/assets/stateDiagram-v2-MP3YSRHH-DnOa-Otc-DgFYwvfo.js +1 -0
- package/dist/assets/{svg-D_RYJvQC-xxS_UOMd.js → svg-D_RYJvQC-BPJwglJJ.js} +1 -1
- package/dist/assets/{swimlanes-42K2YHIH-umBsuvsI-BE4MiInp.js → swimlanes-42K2YHIH-umBsuvsI-BAnYSTii.js} +1 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-ZLUyNmnU-CM3sLR6V.js +8 -0
- package/dist/assets/{tex-Dx2UJ3VU-Bvt244KZ.js → tex-Dx2UJ3VU-CCsHHGCD.js} +1 -1
- package/dist/assets/{timeline-definition-24CTP7MA-D9plt22Y-DHwEP0-q.js → timeline-definition-24CTP7MA-D9plt22Y-BX4CiOEk.js} +1 -1
- package/dist/assets/treeView-Q6P3EWNA-BdvZ0_C5-Ce03QaRO.js +1 -0
- package/dist/assets/treemap-WGGIJYW6-CIJLPQlC-sLYXmnbr.js +1 -0
- package/dist/assets/{vennDiagram-4TSXK5OY-DZe7wY85-BzqCxOQu.js → vennDiagram-4TSXK5OY-DZe7wY85-BRytU48n.js} +1 -1
- package/dist/assets/wardley-WFR3VGLG-CKqtFD8V-CR-W1Hkl.js +1 -0
- package/dist/assets/{wardleyDiagram-VM6X3IG4-DK9yytWx-FK9bW_eQ.js → wardleyDiagram-VM6X3IG4-DK9yytWx-DVNY3c-A.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-CLSO4Pc9-BGF6axe4.js → xychartDiagram-S5SC5T6Z-CLSO4Pc9-XnrHm8Bf.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/server/agents/agent-session-title.ts +227 -0
- package/server/agents/antigravity-sessions.ts +12 -3
- package/server/agents/bounded-cache.ts +30 -0
- package/server/agents/codex-sessions.ts +40 -1
- package/server/agents/copilot-sessions.ts +21 -0
- package/server/agents/cursor-sessions.ts +49 -1
- package/server/agents/muse-session.ts +23 -1
- package/server/agents/sqlite-read.ts +19 -2
- package/server/config/keymap-check.ts +4 -2
- package/server/routes/session-routes.ts +65 -16
- package/server/skills/mulmoterminal-keys/SKILL.md +19 -2
- package/dist/assets/architecture-7GRP2DOG-otSkCkT5-BXYe9Y4x.js +0 -1
- package/dist/assets/channel-Bmu_OOc6-Byl1e1Rn.js +0 -1
- package/dist/assets/classDiagram-ZZMXUADV-BDQOAOBf-DGA1_qS0.js +0 -1
- package/dist/assets/classDiagram-v2-VYDZK3BY-CwPXtzoF-DGA1_qS0.js +0 -1
- package/dist/assets/cynefin-OW5HDTMX-Xr6IPdZG-DCyyQmwN.js +0 -1
- package/dist/assets/eventmodeling-NTZA5JFV-B7bRrpt_-DWVjLwmJ.js +0 -1
- package/dist/assets/flowDiagram-HODETNUW-r-3T5g30-CjAJJOoL.js +0 -1
- package/dist/assets/gitGraph-4MIJSDKK-BhzSx5wq-CmU_NC2u.js +0 -1
- package/dist/assets/index-DgdW3UkV.css +0 -1
- package/dist/assets/info-A6RAGUB7-fR2SUJmJ-Dc6y50d4.js +0 -1
- package/dist/assets/material-symbols-outlined-Dp0GkOHZ.woff2 +0 -0
- package/dist/assets/packet-AYTQ26CC-B_oKR9KZ-DzcrK2qY.js +0 -1
- package/dist/assets/pie-WAS4IAKB-D1ZXrN1W-EXLeDSJc.js +0 -1
- package/dist/assets/radar-RG4KPBEZ-BmUgDkiH-CYsT6Q2i.js +0 -1
- package/dist/assets/railroad-74A4TZTK-6lEXVJo8-CGKkcPl-.js +0 -1
- package/dist/assets/railroad-abnf-HS5TGJTU-BG28Qiz1-CX4pHVjI.js +0 -1
- package/dist/assets/railroad-ebnf-LZEXJU2U-DzpHhtTH-DuFCuwxK.js +0 -1
- package/dist/assets/railroad-peg-WCYAUIDC-B2CHCTyG-BZCRCTz5.js +0 -1
- package/dist/assets/stateDiagram-v2-MP3YSRHH-DnOa-Otc-jwvolGHy.js +0 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-ZLUyNmnU-DNoFZykH.js +0 -8
- package/dist/assets/treeView-Q6P3EWNA-BdvZ0_C5-Cw7gALPI.js +0 -1
- package/dist/assets/treemap-WGGIJYW6-CIJLPQlC-BuBwqHqi.js +0 -1
- package/dist/assets/wardley-WFR3VGLG-CKqtFD8V-Ds6_n_M_.js +0 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// The cap on what an agent's own store label may be, shipped to the roster.
|
|
2
|
+
//
|
|
3
|
+
// In `common/` because BOTH sides decide from it: the server cuts the title here, and the client has
|
|
4
|
+
// to know that a title of exactly this length may be a TRUNCATION of the prompt beneath it rather
|
|
5
|
+
// than the whole of it. Without that, the roster cannot tell "the summary is the entire prompt, cut
|
|
6
|
+
// by us" from "the summary is a shorter, different sentence that happens to start the same way", and
|
|
7
|
+
// suppressing the second hides a real opening (#2123, Codex round 4).
|
|
8
|
+
export const AGENT_TITLE_MAX = 200;
|
|
9
|
+
|
|
10
|
+
/** What an `agentTitle` IS, which the roster cannot work out from the string itself.
|
|
11
|
+
*
|
|
12
|
+
* Four agents answer with the person's OPENING PROMPT; two answer with a summary the agent wrote
|
|
13
|
+
* for itself. The difference decides whether a title that is exactly `AGENT_TITLE_MAX` long may be
|
|
14
|
+
* treated as our own truncation of the prompt beneath it — for an opening prompt it is, for an
|
|
15
|
+
* agent's own summary it may simply be a long sentence that happens to start the same way.
|
|
16
|
+
*
|
|
17
|
+
* Sent per response rather than derived on the client, so the two cannot drift: the server states
|
|
18
|
+
* what it just read. */
|
|
19
|
+
export type AgentTitleKind = "opening-prompt" | "agent-summary";
|
|
20
|
+
|
|
21
|
+
/** Which kind each agent's store answers with. copilot and muse write their own summary — and are
|
|
22
|
+
* also the two the reader never caches, because they REWRITE it as the conversation goes. */
|
|
23
|
+
export const agentTitleKind = (agent: string): AgentTitleKind => (agent === "copilot" || agent === "muse" ? "agent-summary" : "opening-prompt");
|
package/common/keymap.ts
CHANGED
|
@@ -16,6 +16,8 @@ export const KEYMAP_ACTIONS = [
|
|
|
16
16
|
"zoom-toggle",
|
|
17
17
|
"zoom-next",
|
|
18
18
|
"zoom-prev",
|
|
19
|
+
"focus-next",
|
|
20
|
+
"focus-prev",
|
|
19
21
|
"next-attention",
|
|
20
22
|
"terminal-new",
|
|
21
23
|
"terminal-new-here",
|
|
@@ -62,6 +64,18 @@ export const NEEDS_A_CURRENT_TERMINAL: readonly KeymapAction[] = [
|
|
|
62
64
|
"files-find",
|
|
63
65
|
];
|
|
64
66
|
|
|
67
|
+
// The mirror of the list above: actions that walk the TILED grid, and so need nothing enlarged.
|
|
68
|
+
// While a cell is, every other cell is either off-screen or parked in the roster, and moving the
|
|
69
|
+
// cursor into one would put it somewhere the user cannot see.
|
|
70
|
+
//
|
|
71
|
+
// This is deliberately NOT one key meaning two things by state. An action has ONE meaning and
|
|
72
|
+
// declines where it has none — exactly as NEEDS_A_CURRENT_TERMINAL does in the other state. Binding
|
|
73
|
+
// one keystroke to `zoom-prev` AND `focus-prev` still resolves to a single action, because
|
|
74
|
+
// `actionForKey` stops at the first bound one, and validateKeymap reports that. Picking the action
|
|
75
|
+
// by state would mean an ordered-candidates resolver plus action-to-action collision reporting; see
|
|
76
|
+
// plans/feat-2106-focus-prev-next.md for why that is a change of its own.
|
|
77
|
+
export const NEEDS_NOTHING_ENLARGED: readonly KeymapAction[] = ["focus-next", "focus-prev"];
|
|
78
|
+
|
|
65
79
|
// A key that puts BYTES into the focused terminal instead of running an app action (#1005) —
|
|
66
80
|
// Cmd+Right as Ctrl+E for end-of-line, say, or Alt+B for word-back.
|
|
67
81
|
//
|
|
@@ -80,7 +94,8 @@ export type Keymap = Partial<Record<KeymapAction, string>> & { send?: SendBindin
|
|
|
80
94
|
|
|
81
95
|
// A parsed binding. `key` is matched against `KeyboardEvent.key` exactly as the browser
|
|
82
96
|
// reports it, so it is case-sensitive for printable characters ("a" and "A" differ, the
|
|
83
|
-
// latter implying Shift)
|
|
97
|
+
// latter implying Shift) — except while Cmd is held on macOS, where the browser reports the
|
|
98
|
+
// UNSHIFTED character and an uppercase letter is unreachable (validateKeymap warns, #2125).
|
|
84
99
|
export interface KeyBinding {
|
|
85
100
|
key: string;
|
|
86
101
|
shift: boolean;
|
|
@@ -213,11 +228,35 @@ export function validateKeymap(input: unknown): KeymapProblem[] {
|
|
|
213
228
|
return [{ action, binding, reason: 'unparseable key binding — expected e.g. "PageDown" or "Shift+PageUp"', fatal: true }];
|
|
214
229
|
}
|
|
215
230
|
claim(parsed, { label: action, binding, rank: KEYMAP_ACTIONS.indexOf(action), kind: "action" });
|
|
216
|
-
return
|
|
231
|
+
return unshiftedUnderCmdWarnings(action, binding, parsed);
|
|
217
232
|
});
|
|
218
233
|
return [...problems, ...duplicateWarnings(bound)];
|
|
219
234
|
}
|
|
220
235
|
|
|
236
|
+
// A binding that says one keystroke and waits for another. While Cmd is held, a macOS browser puts
|
|
237
|
+
// the UNSHIFTED character in `KeyboardEvent.key` — Cmd+Shift+P arrives as `"p"` — so a binding
|
|
238
|
+
// written `"Cmd+Shift+P"` waits for a `"P"` that never comes, and nothing downstream can see the
|
|
239
|
+
// difference between that and a shortcut the user has not pressed yet (#2125).
|
|
240
|
+
//
|
|
241
|
+
// Safari and Chrome both do this and w3c/uievents#169 is still open, so it is the platform, not a
|
|
242
|
+
// bug to route around: matching stays case-sensitive (`"a"` and `"A"` are different keystrokes,
|
|
243
|
+
// pinned by the specs) and this only says so out loud.
|
|
244
|
+
//
|
|
245
|
+
// A WARNING, not an error: the deviation is macOS's, so a browser following the spec reports `"P"`
|
|
246
|
+
// and the identical entry is correct there — and the server cannot know which one will connect.
|
|
247
|
+
const UPPERCASE_ASCII_LETTER = /^[A-Z]$/;
|
|
248
|
+
const unshiftedUnderCmdWarnings = (action: string, binding: string, parsed: KeyBinding): KeymapProblem[] =>
|
|
249
|
+
parsed.meta && parsed.shift && UPPERCASE_ASCII_LETTER.test(parsed.key)
|
|
250
|
+
? [
|
|
251
|
+
{
|
|
252
|
+
action,
|
|
253
|
+
binding,
|
|
254
|
+
reason: `never fires in a macOS browser — with Cmd held it reports the unshifted letter, so write the key lowercase ("${parsed.key.toLowerCase()}")`,
|
|
255
|
+
fatal: false,
|
|
256
|
+
},
|
|
257
|
+
]
|
|
258
|
+
: [];
|
|
259
|
+
|
|
221
260
|
interface Claim {
|
|
222
261
|
label: string;
|
|
223
262
|
binding: string;
|
|
@@ -248,7 +287,7 @@ function sendProblems(input: unknown, claim: (parsed: KeyBinding, entry: Claim)
|
|
|
248
287
|
}
|
|
249
288
|
// Ranked after every action, matching who actually wins (see the `bound` comment above).
|
|
250
289
|
claim(parsed, { label, binding: entry.key, rank: KEYMAP_ACTIONS.length + i, kind: "send" });
|
|
251
|
-
return
|
|
290
|
+
return unshiftedUnderCmdWarnings(label, entry.key, parsed);
|
|
252
291
|
});
|
|
253
292
|
}
|
|
254
293
|
|
|
@@ -280,6 +319,7 @@ function duplicateWarnings(bound: Map<string, Claim[]>): KeymapProblem[] {
|
|
|
280
319
|
//
|
|
281
320
|
// - `copy` with no selection (clipboardActionFor), deliberately, so Ctrl+C stays interrupt.
|
|
282
321
|
// - NEEDS_A_CURRENT_TERMINAL with nothing enlarged (gridShortcutFor).
|
|
322
|
+
// - NEEDS_NOTHING_ENLARGED with something enlarged (gridShortcutFor), the mirror of it.
|
|
283
323
|
//
|
|
284
324
|
// `acts` and `otherwise` are the two halves of what the user is told.
|
|
285
325
|
interface StandsAside {
|
|
@@ -287,8 +327,10 @@ interface StandsAside {
|
|
|
287
327
|
otherwise: string;
|
|
288
328
|
}
|
|
289
329
|
const WHILE_ENLARGED: StandsAside = { acts: "only while a terminal is enlarged", otherwise: "when none is" };
|
|
330
|
+
const WHILE_NOT_ENLARGED: StandsAside = { acts: "only while no terminal is enlarged", otherwise: "when one is" };
|
|
290
331
|
const standsAside = (label: string): StandsAside | null => {
|
|
291
332
|
if (label === "copy") return { acts: "only while text is selected", otherwise: "when nothing is" };
|
|
333
|
+
if (NEEDS_NOTHING_ENLARGED.some((action) => action === label)) return WHILE_NOT_ENLARGED;
|
|
292
334
|
return NEEDS_A_CURRENT_TERMINAL.some((action) => action === label) ? WHILE_ENLARGED : null;
|
|
293
335
|
};
|
|
294
336
|
|