@@ -4,12 +4,10 @@
|
||||
|
||||
### Added
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- Added `areExperimentalFeaturesEnabled` feature guard to allow users to opt-in to early features.
|
||||
- Added `ctx.isProjectTrusted()` for extensions to observe the effective project trust decision, including temporary trust decisions ([#5523](https://github.com/earendil-works/pi/issues/5523)).
|
||||
=======
|
||||
- Added a global `defaultProjectTrust` setting to choose whether unresolved project trust asks, always trusts, or never trusts by default.
|
||||
>>>>>>> Stashed changes
|
||||
- Added extension autocomplete trigger character support for `ctx.ui.addAutocompleteProvider()` wrappers ([#4703](https://github.com/earendil-works/pi/issues/4703)).
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -2281,6 +2281,7 @@ ctx.ui.pasteToEditor("pasted content");
|
||||
|
||||
// Stack custom autocomplete behavior on top of the built-in provider
|
||||
ctx.ui.addAutocompleteProvider((current) => ({
|
||||
triggerCharacters: ["#"],
|
||||
async getSuggestions(lines, line, col, options) {
|
||||
const beforeCursor = (lines[line] ?? "").slice(0, col);
|
||||
const match = beforeCursor.match(/(?:^|[ \t])#([^\s#]*)$/);
|
||||
@@ -2329,7 +2330,7 @@ Custom working-indicator frames are rendered verbatim. If you want colors, add t
|
||||
|
||||
### Autocomplete Providers
|
||||
|
||||
Use `ctx.ui.addAutocompleteProvider()` to stack custom autocomplete logic on top of the built-in slash-command and path provider.
|
||||
Use `ctx.ui.addAutocompleteProvider()` to stack custom autocomplete logic on top of the built-in slash-command and path provider. Set `triggerCharacters` for custom natural triggers such as `$`.
|
||||
|
||||
Typical pattern:
|
||||
|
||||
@@ -2341,6 +2342,7 @@ Typical pattern:
|
||||
```typescript
|
||||
pi.on("session_start", (_event, ctx) => {
|
||||
ctx.ui.addAutocompleteProvider((current) => ({
|
||||
triggerCharacters: ["#"],
|
||||
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
||||
const line = lines[cursorLine] ?? "";
|
||||
const beforeCursor = line.slice(0, cursorCol);
|
||||
|
||||
@@ -555,8 +555,13 @@ export class InteractiveMode {
|
||||
|
||||
private setupAutocompleteProvider(): void {
|
||||
let provider = this.createBaseAutocompleteProvider();
|
||||
const triggerCharacters: string[] = [];
|
||||
for (const wrapProvider of this.autocompleteProviderWrappers) {
|
||||
provider = wrapProvider(provider);
|
||||
triggerCharacters.push(...(provider.triggerCharacters ?? []));
|
||||
}
|
||||
if (triggerCharacters.length > 0) {
|
||||
provider.triggerCharacters = [...new Set(triggerCharacters)];
|
||||
}
|
||||
|
||||
this.autocompleteProvider = provider;
|
||||
|
||||
@@ -324,6 +324,36 @@ describe("InteractiveMode.setupAutocompleteProvider", () => {
|
||||
expect(provider.shouldTriggerFileCompletion?.(["foo"], 0, 3)).toBe(true);
|
||||
expect(calls).toEqual(["shouldTrigger:wrap2", "shouldTrigger:wrap1"]);
|
||||
});
|
||||
|
||||
test("merges triggerCharacters from wrapper factories", () => {
|
||||
const defaultEditor = { setAutocompleteProvider: vi.fn() };
|
||||
const customEditor = { setAutocompleteProvider: vi.fn() };
|
||||
const passThrough =
|
||||
(triggerCharacters: string[]): AutocompleteProviderFactory =>
|
||||
(current) => ({
|
||||
triggerCharacters,
|
||||
getSuggestions: (lines, cursorLine, cursorCol, options) =>
|
||||
current.getSuggestions(lines, cursorLine, cursorCol, options),
|
||||
applyCompletion: (lines, cursorLine, cursorCol, item, prefix) =>
|
||||
current.applyCompletion(lines, cursorLine, cursorCol, item, prefix),
|
||||
});
|
||||
|
||||
const fakeThis = {
|
||||
createBaseAutocompleteProvider: () => new CombinedAutocompleteProvider([], "/tmp/project", undefined),
|
||||
defaultEditor,
|
||||
editor: customEditor,
|
||||
autocompleteProviderWrappers: [passThrough(["$"]), passThrough(["!"])],
|
||||
};
|
||||
|
||||
(
|
||||
InteractiveMode as unknown as {
|
||||
prototype: { setupAutocompleteProvider: (this: typeof fakeThis) => void };
|
||||
}
|
||||
).prototype.setupAutocompleteProvider.call(fakeThis);
|
||||
|
||||
const provider = defaultEditor.setAutocompleteProvider.mock.calls[0]?.[0] as AutocompleteProvider;
|
||||
expect(provider.triggerCharacters).toEqual(["$", "!"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("InteractiveMode.showLoadedResources", () => {
|
||||
|
||||
Reference in New Issue
Block a user