pi-sage 0.2.8 → 0.2.9
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/.pi/extensions/sage/index.ts +39 -65
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { DynamicBorder, type ExtensionAPI, type ExtensionCommandContext, type ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
import { Container, type SelectItem, SelectList, Text } from "@mariozechner/pi-tui";
|
|
2
3
|
import { Type } from "@sinclair/typebox";
|
|
3
4
|
import {
|
|
4
5
|
evaluateSoftBudget,
|
|
@@ -724,78 +725,51 @@ async function selectScrollable(
|
|
|
724
725
|
): Promise<string | undefined> {
|
|
725
726
|
if (options.length === 0) return undefined;
|
|
726
727
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
728
|
+
const items: SelectItem[] = options.map((option, index) => ({
|
|
729
|
+
value: String(index),
|
|
730
|
+
label: option
|
|
731
|
+
}));
|
|
732
|
+
|
|
733
|
+
const selectedValue = await ctx.ui.custom<string | undefined>((tui, theme, _keybindings, done) => {
|
|
734
|
+
const container = new Container();
|
|
735
|
+
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
|
|
736
|
+
container.addChild(new Text(theme.fg("accent", title), 1, 0));
|
|
737
|
+
container.addChild(new Text("", 0, 0));
|
|
738
|
+
|
|
739
|
+
const selectList = new SelectList(items, Math.max(3, Math.min(maxVisible, items.length)), {
|
|
740
|
+
selectedPrefix: (text) => theme.fg("accent", text),
|
|
741
|
+
selectedText: (text) => theme.fg("accent", text),
|
|
742
|
+
description: (text) => theme.fg("muted", text),
|
|
743
|
+
scrollInfo: (text) => theme.fg("dim", text),
|
|
744
|
+
noMatch: (text) => theme.fg("warning", text)
|
|
745
|
+
});
|
|
735
746
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
lines.push("");
|
|
747
|
+
selectList.onSelect = (item) => done(item.value);
|
|
748
|
+
selectList.onCancel = () => done(undefined);
|
|
749
|
+
container.addChild(selectList);
|
|
740
750
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
751
|
+
container.addChild(new Text("", 0, 0));
|
|
752
|
+
container.addChild(new Text(theme.fg("dim", "↑↓ navigate • enter select • esc back"), 1, 0));
|
|
753
|
+
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
|
|
744
754
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
755
|
+
return {
|
|
756
|
+
render: (width: number) => container.render(width),
|
|
757
|
+
invalidate: () => container.invalidate(),
|
|
758
|
+
handleInput: (data: string) => {
|
|
759
|
+
selectList.handleInput(data);
|
|
760
|
+
tui.requestRender();
|
|
750
761
|
}
|
|
751
|
-
|
|
752
|
-
lines.push("");
|
|
753
|
-
lines.push(theme.fg("muted", `(${selectedIndex + 1}/${options.length}) ↑↓ navigate • enter select • esc back`));
|
|
754
|
-
|
|
755
|
-
return lines.map((line) => (line.length > width ? `${line.slice(0, Math.max(0, width - 1))}…` : line));
|
|
756
762
|
};
|
|
763
|
+
});
|
|
757
764
|
|
|
758
|
-
|
|
759
|
-
const isUp = data.includes("\u001b[A") || data.includes("\u001bOA");
|
|
760
|
-
const isDown = data.includes("\u001b[B") || data.includes("\u001bOB");
|
|
761
|
-
const isEnter = data.includes("\r") || data.includes("\n") || data.includes("\u001bOM");
|
|
762
|
-
const isEscLike = data.startsWith("\u001b");
|
|
765
|
+
if (selectedValue === undefined) return undefined;
|
|
763
766
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
if (isDown) {
|
|
769
|
-
move(1);
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
if (data === "k" || data === "K") {
|
|
773
|
-
move(-1);
|
|
774
|
-
return;
|
|
775
|
-
}
|
|
776
|
-
if (data === "j" || data === "J") {
|
|
777
|
-
move(1);
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
if (isEnter) {
|
|
781
|
-
done(options[selectedIndex]);
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
if (data.includes("\u0003")) {
|
|
785
|
-
done(undefined);
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
if (isEscLike) {
|
|
789
|
-
done(undefined);
|
|
790
|
-
}
|
|
791
|
-
};
|
|
767
|
+
const selectedIndex = Number(selectedValue);
|
|
768
|
+
if (!Number.isInteger(selectedIndex) || selectedIndex < 0 || selectedIndex >= options.length) {
|
|
769
|
+
return undefined;
|
|
770
|
+
}
|
|
792
771
|
|
|
793
|
-
|
|
794
|
-
render,
|
|
795
|
-
invalidate: () => {},
|
|
796
|
-
handleInput
|
|
797
|
-
};
|
|
798
|
-
});
|
|
772
|
+
return options[selectedIndex];
|
|
799
773
|
}
|
|
800
774
|
|
|
801
775
|
function onOff(value: boolean): string {
|