pi-better-btw-plus 1.1.1 → 1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-better-btw-plus",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
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
@@ -28,7 +28,12 @@ export const KEYBINDINGS = {
28
28
  /** Read-only / edit mode toggle (Ctrl+T freed for pi's thinking toggle). */
29
29
  toggleMode: { keys: ["alt+t"], hint: "A+t" },
30
30
  /** Copy the active mouse selection (pi `tui.input.copy` parity). */
31
- copySelection: { keys: ["ctrl+c", "ctrl+shift+c"], hint: "C+c copy" },
31
+ /**
32
+ * Copy the active mouse selection (pi `tui.input.copy` parity). Without
33
+ * one, bare Ctrl+C clears the input box (pi `app.clear` parity, spec #22);
34
+ * Ctrl+Shift+C stays a forced copy.
35
+ */
36
+ copySelection: { keys: ["ctrl+c", "ctrl+shift+c"], hint: "C+c copy/clear" },
32
37
  /** Copy the last side-chat assistant message (pi `app.message.copy` parity). */
33
38
  copyLastMessage: { keys: ["ctrl+x"], hint: "C+x last" },
34
39
  /** Paste clipboard text (pi `app.clipboard.pasteImage` parity). */
@@ -57,8 +57,9 @@ export class SideChatMessages implements Component {
57
57
  private totalLines = 0;
58
58
  /**
59
59
  * Active mouse selection over the visible chat lines ({@link CellPos} in
60
- * rendered-line coordinates). Cleared on scroll / content changes and on
61
- * the next press; kept after copy so Ctrl+C can copy again (B+C scheme).
60
+ * rendered-line coordinates). Cleared on scroll / content changes, on the
61
+ * next press, and after a successful copy (spec #22: Ctrl+C with no
62
+ * selection clears the input instead of re-copying).
62
63
  */
63
64
  private selection: { anchor: CellPos; focus: CellPos } | null = null;
64
65
  /** Plain (ANSI-stripped) text of the last rendered lines, for hit-testing and copy. */
@@ -269,14 +269,20 @@ export class SideChatOverlay implements Component, Focusable {
269
269
  * Copy the current mouse selection to the clipboard (native → wl-copy /
270
270
  * xclip → OSC 52 cascade via {@link copyToClipboard}, matching the main
271
271
  * app's tree selector) and show a transient status. Copying is hotkey-only:
272
- * `Ctrl+C` / `Ctrl+Shift+C` with an active mouse selection. The selection
273
- * stays highlighted so a second copy key press re-copies. Returns false when
274
- * there is nothing to copy.
272
+ * `Ctrl+C` / `Ctrl+Shift+C` with an active mouse selection. A successful
273
+ * copy consumes the selection (spec #22: Ctrl+C then returns to clearing
274
+ * the input); a failed copy keeps it so the user can retry. Returns false
275
+ * when there is nothing to copy.
275
276
  */
276
277
  async copySelectionToClipboard(): Promise<boolean> {
277
278
  const text = this.messages.getSelectedText();
278
279
  if (!text) return false;
279
- return this.copyTextWithFeedback(text);
280
+ const ok = await this.copyTextWithFeedback(text);
281
+ if (ok) {
282
+ this.messages.clearSelection();
283
+ this.options.tui.requestRender();
284
+ }
285
+ return ok;
280
286
  }
281
287
 
282
288
  /**
@@ -904,12 +910,18 @@ export class SideChatOverlay implements Component, Focusable {
904
910
  }
905
911
  if (matchesAnyKey(data, KEYBINDINGS.copySelection.keys)) {
906
912
  // Hotkey copy: with an active mouse selection, Ctrl+C / Ctrl+Shift+C
907
- // copies it. Without one, fall through so Ctrl+C keeps the editor's
908
- // own semantics.
913
+ // copies it. Without one, Ctrl+C clears the input box (pi `app.clear`
914
+ // parity, spec #22); Ctrl+Shift+C falls through — pi binds no such
915
+ // key, so it stays a forced copy (terminal habit).
909
916
  if (this.messages.hasSelection()) {
910
917
  void this.copySelectionToClipboard();
911
918
  return;
912
919
  }
920
+ if (matchesKey(data, KEYBINDINGS.copySelection.keys[0])) {
921
+ this.editor.setText("");
922
+ this.options.tui.requestRender();
923
+ return;
924
+ }
913
925
  }
914
926
  if (matchesAnyKey(data, KEYBINDINGS.copyLastMessage.keys)) {
915
927
  // app.message.copy parity: copy the last assistant message — no