pi-edit-session-in-place 0.1.15 → 0.1.17
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/CHANGELOG.md +15 -0
- package/README.md +1 -1
- package/extensions/edit-session-in-place.ts +18 -170
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## [0.1.17] - 2026-06-04
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- fixed the editor hotkey command dispatch when duplicate installs suffix the command as `/edit-turn:1`, `/edit-turn:2`, etc.
|
|
11
|
+
- removed the local project package setting accidentally left by release verification so the repo no longer loads a duplicate project copy during local reloads
|
|
12
|
+
|
|
13
|
+
## [0.1.16] - 2026-06-04
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- fixed `Ctrl+Shift+E` after the Pi 0.78.1 update by removing the registered shortcut handler that consumed the key and only showed the placeholder notification
|
|
17
|
+
- added regression coverage that verifies the extension no longer registers a conflicting shortcut handler and still installs the custom editor hotkey path
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- removed the custom main-editor wrapper path and returned to the focused custom-editor hotkey path used by the working releases
|
|
21
|
+
|
|
7
22
|
## [0.1.15] - 2026-06-04
|
|
8
23
|
|
|
9
24
|
### Changed
|
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ If you clear the message and submit an empty value, the selected message is effe
|
|
|
81
81
|
- If the selected message contains images, the extension warns that re-editing or deleting it will drop the images and keep only text behavior
|
|
82
82
|
- The extension only offers text-bearing user messages for editing; image-only or whitespace-only user messages are skipped
|
|
83
83
|
- Queued messages must be cleared before using the command
|
|
84
|
-
-
|
|
84
|
+
- The `Ctrl+Shift+E` hotkey is handled by this extension's main-editor component so Pi's registered shortcut dispatcher does not consume it first
|
|
85
85
|
|
|
86
86
|
## Development
|
|
87
87
|
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
DynamicBorder,
|
|
16
16
|
keyHint,
|
|
17
17
|
rawKeyHint,
|
|
18
|
-
type AppKeybinding,
|
|
19
18
|
type ExtensionAPI,
|
|
20
19
|
type ExtensionCommandContext,
|
|
21
20
|
type KeybindingsManager,
|
|
@@ -30,8 +29,6 @@ import {
|
|
|
30
29
|
Spacer,
|
|
31
30
|
Text,
|
|
32
31
|
matchesKey,
|
|
33
|
-
type AutocompleteProvider,
|
|
34
|
-
type EditorComponent,
|
|
35
32
|
type EditorTheme,
|
|
36
33
|
type Focusable,
|
|
37
34
|
type TUI,
|
|
@@ -572,166 +569,32 @@ const handleEditTurn = async (ctx: ExtensionCommandContext) => {
|
|
|
572
569
|
);
|
|
573
570
|
};
|
|
574
571
|
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
572
|
+
export const getEditTurnCommandText = (commands: Array<{ name: string }>) => {
|
|
573
|
+
const candidates = commands
|
|
574
|
+
.map((command) => command.name)
|
|
575
|
+
.filter((name) => name === COMMAND_NAME || name.startsWith(`${COMMAND_NAME}:`));
|
|
576
|
+
return `/${candidates.at(-1) ?? COMMAND_NAME}`;
|
|
579
577
|
};
|
|
580
578
|
|
|
581
579
|
class EditSessionInPlaceEditor extends CustomEditor {
|
|
582
|
-
handleInput(data: string): void {
|
|
583
|
-
if (matchesKey(data, HOTKEY)) {
|
|
584
|
-
triggerEditTurnCommand(this);
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
super.handleInput(data);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
type AutocompleteAwareEditor = EditorComponent & {
|
|
593
|
-
isShowingAutocomplete?: () => boolean;
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
class EditSessionInPlaceEditorWrapper implements EditorComponent, Focusable {
|
|
597
|
-
public actionHandlers: Map<AppKeybinding, () => void> = new Map();
|
|
598
|
-
public onEscape?: () => void;
|
|
599
|
-
public onCtrlD?: () => void;
|
|
600
|
-
public onPasteImage?: () => void;
|
|
601
|
-
public onExtensionShortcut?: (data: string) => boolean | undefined;
|
|
602
|
-
|
|
603
580
|
constructor(
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
set focused(value: boolean) {
|
|
613
|
-
if ("focused" in this.base) {
|
|
614
|
-
(this.base as EditorComponent & Focusable).focused = value;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
get wantsKeyRelease(): boolean | undefined {
|
|
619
|
-
return this.base.wantsKeyRelease;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
set wantsKeyRelease(value: boolean | undefined) {
|
|
623
|
-
this.base.wantsKeyRelease = value;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
get onSubmit(): ((text: string) => void) | undefined {
|
|
627
|
-
return this.base.onSubmit;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
set onSubmit(value: ((text: string) => void) | undefined) {
|
|
631
|
-
this.base.onSubmit = value;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
get onChange(): ((text: string) => void) | undefined {
|
|
635
|
-
return this.base.onChange;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
set onChange(value: ((text: string) => void) | undefined) {
|
|
639
|
-
this.base.onChange = value;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
get borderColor(): ((str: string) => string) | undefined {
|
|
643
|
-
return this.base.borderColor;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
set borderColor(value: ((str: string) => string) | undefined) {
|
|
647
|
-
this.base.borderColor = value;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
render(width: number): string[] {
|
|
651
|
-
return this.base.render(width);
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
invalidate(): void {
|
|
655
|
-
this.base.invalidate();
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
getText(): string {
|
|
659
|
-
return this.base.getText();
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
setText(text: string): void {
|
|
663
|
-
this.base.setText(text);
|
|
581
|
+
tui: TUI,
|
|
582
|
+
theme: EditorTheme,
|
|
583
|
+
keybindings: KeybindingsManager,
|
|
584
|
+
private readonly getCommandText: () => string,
|
|
585
|
+
) {
|
|
586
|
+
super(tui, theme, keybindings);
|
|
664
587
|
}
|
|
665
588
|
|
|
666
589
|
handleInput(data: string): void {
|
|
667
590
|
if (matchesKey(data, HOTKEY)) {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
if (this.onExtensionShortcut?.(data)) {
|
|
591
|
+
draftBeforeHotkey = this.getText();
|
|
592
|
+
this.setText(this.getCommandText());
|
|
593
|
+
super.handleInput("\r");
|
|
673
594
|
return;
|
|
674
595
|
}
|
|
675
596
|
|
|
676
|
-
|
|
677
|
-
this.onPasteImage?.();
|
|
678
|
-
return;
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
if (this.keybindings.matches(data, "app.interrupt")) {
|
|
682
|
-
const isShowingAutocomplete = (this.base as AutocompleteAwareEditor).isShowingAutocomplete?.() ?? false;
|
|
683
|
-
if (!isShowingAutocomplete) {
|
|
684
|
-
const handler = this.onEscape ?? this.actionHandlers.get("app.interrupt");
|
|
685
|
-
if (handler) {
|
|
686
|
-
handler();
|
|
687
|
-
return;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
this.base.handleInput(data);
|
|
692
|
-
return;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
if (this.keybindings.matches(data, "app.exit") && this.base.getText().length === 0) {
|
|
696
|
-
const handler = this.onCtrlD ?? this.actionHandlers.get("app.exit");
|
|
697
|
-
if (handler) {
|
|
698
|
-
handler();
|
|
699
|
-
}
|
|
700
|
-
return;
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
for (const [action, handler] of this.actionHandlers) {
|
|
704
|
-
if (action !== "app.interrupt" && action !== "app.exit" && this.keybindings.matches(data, action)) {
|
|
705
|
-
handler();
|
|
706
|
-
return;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
this.base.handleInput(data);
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
addToHistory(text: string): void {
|
|
714
|
-
this.base.addToHistory?.(text);
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
insertTextAtCursor(text: string): void {
|
|
718
|
-
this.base.insertTextAtCursor?.(text);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
getExpandedText(): string {
|
|
722
|
-
return this.base.getExpandedText?.() ?? this.base.getText();
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
setAutocompleteProvider(provider: AutocompleteProvider): void {
|
|
726
|
-
this.base.setAutocompleteProvider?.(provider);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
setPaddingX(padding: number): void {
|
|
730
|
-
this.base.setPaddingX?.(padding);
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
setAutocompleteMaxVisible(maxVisible: number): void {
|
|
734
|
-
this.base.setAutocompleteMaxVisible?.(maxVisible);
|
|
597
|
+
super.handleInput(data);
|
|
735
598
|
}
|
|
736
599
|
}
|
|
737
600
|
|
|
@@ -743,27 +606,12 @@ export default function editSessionInPlace(pi: ExtensionAPI) {
|
|
|
743
606
|
},
|
|
744
607
|
});
|
|
745
608
|
|
|
746
|
-
// Shortcut handlers receive ExtensionContext, so the custom editor hotkey path performs
|
|
747
|
-
// the command execution while this registration keeps the hotkey discoverable.
|
|
748
|
-
pi.registerShortcut(HOTKEY, {
|
|
749
|
-
description: `Edit a previous user message (${HOTKEY_LABEL})`,
|
|
750
|
-
handler: (ctx) => {
|
|
751
|
-
if (!ctx.hasUI) {
|
|
752
|
-
return;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
ctx.ui.notify(`Press ${HOTKEY_LABEL} in the main editor to edit a previous message.`, "info");
|
|
756
|
-
},
|
|
757
|
-
});
|
|
758
|
-
|
|
759
609
|
pi.on("session_start", (_event, ctx) => {
|
|
760
610
|
clearSavedDraft();
|
|
761
611
|
if (ctx.mode === "tui") {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
return baseEditor ? new EditSessionInPlaceEditorWrapper(baseEditor, keybindings) : new EditSessionInPlaceEditor(tui, theme, keybindings);
|
|
766
|
-
});
|
|
612
|
+
ctx.ui.setEditorComponent((tui, theme, keybindings) =>
|
|
613
|
+
new EditSessionInPlaceEditor(tui, theme, keybindings, () => getEditTurnCommandText(pi.getCommands())),
|
|
614
|
+
);
|
|
767
615
|
}
|
|
768
616
|
});
|
|
769
617
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-edit-session-in-place",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "pi extension that lets you re-edit or delete an earlier user message in the current session branch",
|
|
5
5
|
"author": "Mitch Fultz (https://github.com/fitchmultz)",
|
|
6
6
|
"license": "MIT",
|