pi-better-btw-plus 1.3.0 → 1.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-better-btw-plus",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "pi extension: /btw side-chat overlay — maintained fork of @yceachan/pi-better-btw (+ right-click copy/paste, fork model switch, turn-level retry)",
5
5
  "type": "module",
6
6
  "keywords": [
package/srcs/shortcuts.ts CHANGED
@@ -6,6 +6,17 @@ export const SIDE_CHAT_SHORTCUT: KeyId = "alt+w";
6
6
  interface Keybinding {
7
7
  readonly keys: readonly KeyId[];
8
8
  readonly hint: string;
9
+ /**
10
+ * Raw terminal encodings that also trigger this action, besides the
11
+ * parser-recognizable `keys`. Needed because pi-tui's parser cannot express
12
+ * alt+shift+letter: its legacy branch only maps ESC+lowercase to alt+letter,
13
+ * and its modifyOtherKeys parse drops the shift bit. Terminals without the
14
+ * kitty keyboard protocol (Windows Terminal < 1.25) deliver Alt+Shift+C as
15
+ * the legacy ESC+'C' form (shift folded into case), which parseKey returns
16
+ * undefined for — so the binding must match the raw bytes too. Only
17
+ * copyInput needs this today.
18
+ */
19
+ readonly raw?: readonly string[];
9
20
  }
10
21
 
11
22
  /**
@@ -37,7 +48,7 @@ export const KEYBINDINGS = {
37
48
  /** Copy the last side-chat assistant message (pi `app.message.copy` parity). */
38
49
  copyLastMessage: { keys: ["ctrl+x"], hint: "C+x last" },
39
50
  /** Copy all input editor text (expanded paste markers — submit semantics). */
40
- copyInput: { keys: ["alt+shift+c"], hint: "A+⇧C all" },
51
+ copyInput: { keys: ["alt+shift+c"], raw: ["\x1bC", "\x1b[27;3;99~"], hint: "A+⇧C all" },
41
52
  /** Paste clipboard text (pi `app.clipboard.pasteImage` parity). */
42
53
  paste: { keys: ["ctrl+v", "alt+v"], hint: "C+v paste" },
43
54
  } as const satisfies Record<string, Keybinding>;
@@ -46,3 +57,9 @@ export const KEYBINDINGS = {
46
57
  export function matchesAnyKey(data: string, keys: readonly KeyId[]): boolean {
47
58
  return keys.some((key) => matchesKey(data, key));
48
59
  }
60
+
61
+ /** True when `data` matches a binding's keys or one of its raw encodings. */
62
+ export function matchesKeybinding(data: string, kb: Keybinding): boolean {
63
+ if (kb.raw?.includes(data)) return true;
64
+ return matchesAnyKey(data, kb.keys);
65
+ }
@@ -62,7 +62,7 @@ import {
62
62
  modelKey,
63
63
  type ModelChoice,
64
64
  } from "./model-switch.ts";
65
- import { KEYBINDINGS, matchesAnyKey } from "./shortcuts.ts";
65
+ import { KEYBINDINGS, matchesAnyKey, matchesKeybinding } from "./shortcuts.ts";
66
66
  import { wrapToolsWithOverlapDetection } from "./tool-wrapper.ts";
67
67
  import type { SideChatFeatures } from "./config.ts";
68
68
  import type { RetryPolicy } from "./retry.ts";
@@ -910,11 +910,13 @@ export class SideChatOverlay implements Component, Focusable {
910
910
  this.openModelPicker();
911
911
  return;
912
912
  }
913
- if (matchesAnyKey(data, KEYBINDINGS.copyInput.keys)) {
913
+ if (matchesKeybinding(data, KEYBINDINGS.copyInput)) {
914
914
  // Copy the whole input editor text (issue #23): expanded paste
915
915
  // markers — exactly what a submit would send. Read-only, unlike
916
916
  // Ctrl+C's clear lane it never touches the draft; an empty input
917
- // flashes a hint instead of copying.
917
+ // flashes a hint instead of copying. `matchesKeybinding` also accepts
918
+ // the raw legacy ESC+C form that terminals without the kitty protocol
919
+ // (Windows Terminal < 1.25) deliver for Alt+Shift+C.
918
920
  const text = this.editor.getExpandedText();
919
921
  if (!text) {
920
922
  this.status.flash(INPUT_EMPTY_STATUS, COPIED_STATUS_CLEAR_MS);