mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-29 09:43:49 +01:00
finalize terminal completion provider API (#271338)
This commit is contained in:
@@ -13,8 +13,7 @@ export function createCompletionItem(cursorPosition: number, currentCommandStrin
|
||||
label: commandResource.label,
|
||||
detail: detail ?? commandResource.detail ?? '',
|
||||
documentation,
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length,
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition],
|
||||
kind: kind ?? commandResource.kind ?? vscode.TerminalCompletionItemKind.Method
|
||||
};
|
||||
}
|
||||
|
||||
@@ -495,13 +495,9 @@ export async function getCompletionItemsFromSpecs(
|
||||
}
|
||||
showFiles = true;
|
||||
showFolders = true;
|
||||
}
|
||||
// For arguments when no fig suggestions are found these are fallback suggestions
|
||||
else if (!items.length && !showFiles && !showFolders && !hasCurrentArg) {
|
||||
if (terminalContext.allowFallbackCompletions) {
|
||||
showFiles = true;
|
||||
showFolders = true;
|
||||
}
|
||||
} else if (!items.length && !showFiles && !showFolders && !hasCurrentArg) {
|
||||
showFiles = true;
|
||||
showFolders = true;
|
||||
}
|
||||
|
||||
let cwd: vscode.Uri | undefined;
|
||||
@@ -509,7 +505,7 @@ export async function getCompletionItemsFromSpecs(
|
||||
cwd = await resolveCwdFromCurrentCommandString(currentCommandString, shellIntegrationCwd);
|
||||
}
|
||||
|
||||
return { items, showFiles: showFiles, showFolders: showFolders, fileExtensions, cwd };
|
||||
return { items, showFiles, showFolders, fileExtensions, cwd };
|
||||
}
|
||||
|
||||
function getEnvAsRecord(shellIntegrationEnv: ITerminalEnvironment): Record<string, string> {
|
||||
|
||||
@@ -95,7 +95,7 @@ suite('Terminal Suggest', () => {
|
||||
const currentCommandString = getCurrentCommandAndArgs(commandLine, cursorIndex, undefined);
|
||||
const showFiles = testSpec.expectedResourceRequests?.type === 'files' || testSpec.expectedResourceRequests?.type === 'both';
|
||||
const showFolders = testSpec.expectedResourceRequests?.type === 'folders' || testSpec.expectedResourceRequests?.type === 'both';
|
||||
const terminalContext = { commandLine, cursorIndex, allowFallbackCompletions: true };
|
||||
const terminalContext = { commandLine, cursorIndex };
|
||||
const result = await getCompletionItemsFromSpecs(
|
||||
completionSpecs,
|
||||
terminalContext,
|
||||
|
||||
@@ -394,9 +394,6 @@ const _allApiProposals = {
|
||||
telemetry: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.telemetry.d.ts',
|
||||
},
|
||||
terminalCompletionProvider: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts',
|
||||
},
|
||||
terminalDataWriteEvent: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.terminalDataWriteEvent.d.ts',
|
||||
},
|
||||
|
||||
@@ -277,8 +277,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
public $registerCompletionProvider(id: string, extensionIdentifier: string, ...triggerCharacters: string[]): void {
|
||||
this._completionProviders.set(id, this._terminalCompletionService.registerTerminalCompletionProvider(extensionIdentifier, id, {
|
||||
id,
|
||||
provideCompletions: async (commandLine, cursorPosition, allowFallbackCompletions, token) => {
|
||||
const completions = await this._proxy.$provideTerminalCompletions(id, { commandLine, cursorIndex: cursorPosition, allowFallbackCompletions }, token);
|
||||
provideCompletions: async (commandLine, cursorIndex, token) => {
|
||||
const completions = await this._proxy.$provideTerminalCompletions(id, { commandLine, cursorIndex }, token);
|
||||
if (!completions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -878,7 +878,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostTerminalService.registerProfileProvider(extension, id, provider);
|
||||
},
|
||||
registerTerminalCompletionProvider(provider: vscode.TerminalCompletionProvider<vscode.TerminalCompletionItem>, ...triggerCharacters: string[]): vscode.Disposable {
|
||||
checkProposedApiEnabled(extension, 'terminalCompletionProvider');
|
||||
return extHostTerminalService.registerTerminalCompletionProvider(extension, provider, ...triggerCharacters);
|
||||
},
|
||||
registerTerminalQuickFixProvider(id: string, provider: vscode.TerminalQuickFixProvider): vscode.Disposable {
|
||||
|
||||
@@ -2498,7 +2498,6 @@ export interface ITerminalCommandDto {
|
||||
export interface ITerminalCompletionContextDto {
|
||||
commandLine: string;
|
||||
cursorIndex: number;
|
||||
allowFallbackCompletions: boolean;
|
||||
}
|
||||
|
||||
export interface ITerminalCompletionItemDto {
|
||||
@@ -2509,8 +2508,7 @@ export interface ITerminalCompletionItemDto {
|
||||
isFile?: boolean | undefined;
|
||||
isDirectory?: boolean | undefined;
|
||||
isKeyword?: boolean | undefined;
|
||||
replacementIndex: number;
|
||||
replacementLength: number;
|
||||
replacementRange: readonly [number, number];
|
||||
}
|
||||
|
||||
export interface ITerminalCompletionProvider {
|
||||
|
||||
@@ -940,25 +940,23 @@ export enum TerminalCompletionItemKind {
|
||||
|
||||
export class TerminalCompletionItem implements vscode.TerminalCompletionItem {
|
||||
label: string | CompletionItemLabel;
|
||||
replacementRange: readonly [number, number];
|
||||
icon?: ThemeIcon | undefined;
|
||||
detail?: string | undefined;
|
||||
documentation?: string | vscode.MarkdownString | undefined;
|
||||
isFile?: boolean | undefined;
|
||||
isDirectory?: boolean | undefined;
|
||||
isKeyword?: boolean | undefined;
|
||||
replacementIndex: number;
|
||||
replacementLength: number;
|
||||
|
||||
constructor(label: string | CompletionItemLabel, icon?: ThemeIcon, detail?: string, documentation?: string | vscode.MarkdownString, isFile?: boolean, isDirectory?: boolean, isKeyword?: boolean, replacementIndex?: number, replacementLength?: number) {
|
||||
constructor(label: string | CompletionItemLabel, replacementRange: readonly [number, number], icon?: ThemeIcon, detail?: string, documentation?: string | vscode.MarkdownString, isFile?: boolean, isDirectory?: boolean, isKeyword?: boolean) {
|
||||
this.label = label;
|
||||
this.replacementRange = replacementRange;
|
||||
this.icon = icon;
|
||||
this.detail = detail;
|
||||
this.documentation = documentation;
|
||||
this.isFile = isFile;
|
||||
this.isDirectory = isDirectory;
|
||||
this.isKeyword = isKeyword;
|
||||
this.replacementIndex = replacementIndex ?? 0;
|
||||
this.replacementLength = replacementLength ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-12
@@ -38,7 +38,7 @@ export class LspCompletionProviderAddon extends Disposable implements ITerminalA
|
||||
// console.log('activate');
|
||||
}
|
||||
|
||||
async provideCompletions(value: string, cursorPosition: number, allowFallbackCompletions: false, token: CancellationToken): Promise<ITerminalCompletion[] | TerminalCompletionList<ITerminalCompletion> | undefined> {
|
||||
async provideCompletions(value: string, cursorPosition: number, token: CancellationToken): Promise<ITerminalCompletion[] | TerminalCompletionList<ITerminalCompletion> | undefined> {
|
||||
|
||||
// Apply edit for non-executed current commandline --> Pretend we are typing in the real-document.
|
||||
this._lspTerminalModelContentProvider.trackPromptInputToVirtualFile(value);
|
||||
@@ -65,8 +65,7 @@ export class LspCompletionProviderAddon extends Disposable implements ITerminalA
|
||||
detail: item.detail,
|
||||
documentation: item.documentation,
|
||||
kind: convertedKind,
|
||||
replacementIndex: completionItemTemp.replacementIndex,
|
||||
replacementLength: completionItemTemp.replacementLength,
|
||||
replacementRange: completionItemTemp.replacementRange,
|
||||
};
|
||||
|
||||
// Store unresolved item and provider for lazy resolution if needed
|
||||
@@ -95,8 +94,7 @@ export function createCompletionItemPython(
|
||||
return {
|
||||
label,
|
||||
detail: detail ?? '',
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length,
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition],
|
||||
kind: kind ?? TerminalCompletionItemKind.Method
|
||||
};
|
||||
}
|
||||
@@ -133,14 +131,9 @@ export interface TerminalCompletionItem {
|
||||
label: string | CompletionItemLabel;
|
||||
|
||||
/**
|
||||
* The index of the start of the range to replace.
|
||||
* Selection range (inclusive start, exclusive end) to replace when this completion is applied.
|
||||
*/
|
||||
replacementIndex: number;
|
||||
|
||||
/**
|
||||
* The length of the range to replace.
|
||||
*/
|
||||
replacementLength: number;
|
||||
replacementRange: readonly [number, number] | undefined;
|
||||
|
||||
/**
|
||||
* The completion's detail which appears on the right of the list.
|
||||
|
||||
+17
-22
@@ -55,7 +55,7 @@ export class TerminalCompletionList<ITerminalCompletion> {
|
||||
|
||||
export interface TerminalCompletionResourceOptions {
|
||||
showFiles?: boolean;
|
||||
showFolders?: boolean;
|
||||
showDirectories?: boolean;
|
||||
globPattern?: string | IRelativePattern;
|
||||
cwd: UriComponents;
|
||||
pathSeparator: string;
|
||||
@@ -65,7 +65,7 @@ export interface TerminalCompletionResourceOptions {
|
||||
export interface ITerminalCompletionProvider {
|
||||
id: string;
|
||||
shellTypes?: TerminalShellType[];
|
||||
provideCompletions(value: string, cursorPosition: number, allowFallbackCompletions: boolean, token: CancellationToken): Promise<ITerminalCompletion[] | TerminalCompletionList<ITerminalCompletion> | undefined>;
|
||||
provideCompletions(value: string, cursorPosition: number, token: CancellationToken): Promise<ITerminalCompletion[] | TerminalCompletionList<ITerminalCompletion> | undefined>;
|
||||
triggerCharacters?: string[];
|
||||
isBuiltin?: boolean;
|
||||
}
|
||||
@@ -190,7 +190,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
let completions;
|
||||
try {
|
||||
completions = await Promise.race([
|
||||
provider.provideCompletions(promptValue, cursorPosition, allowFallbackCompletions, token).then(result => {
|
||||
provider.provideCompletions(promptValue, cursorPosition, token).then(result => {
|
||||
this._logService.trace(`TerminalCompletionService#_collectCompletions provider ${provider.id} finished`);
|
||||
return result;
|
||||
}),
|
||||
@@ -211,7 +211,8 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
this._logService.trace(`TerminalCompletionService#_collectCompletions amend ${completionItems.length} completion items`);
|
||||
if (shellType === GeneralShellType.PowerShell) {
|
||||
for (const completion of completionItems) {
|
||||
completion.isFileOverride ??= completion.kind === TerminalCompletionItemKind.Method && completion.replacementIndex === 0;
|
||||
const start = completion.replacementRange ? completion.replacementRange[0] : 0;
|
||||
completion.isFileOverride ??= completion.kind === TerminalCompletionItemKind.Method && start === 0;
|
||||
}
|
||||
}
|
||||
if (provider.isBuiltin) {
|
||||
@@ -256,11 +257,11 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
|
||||
// Files requested implies folders requested since the file could be in any folder. We could
|
||||
// provide diagnostics when a folder is provided where a file is expected.
|
||||
const showFolders = (resourceOptions.showFolders || resourceOptions.showFiles) ?? false;
|
||||
const showDirectories = (resourceOptions.showDirectories || resourceOptions.showFiles) ?? false;
|
||||
const showFiles = resourceOptions.showFiles ?? false;
|
||||
const globPattern = resourceOptions.globPattern ?? undefined;
|
||||
|
||||
if (!showFolders && !showFiles) {
|
||||
if (!showDirectories && !showFiles) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -350,8 +351,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
provider,
|
||||
kind: TerminalCompletionItemKind.Folder,
|
||||
detail: lastWordFolderResource,
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition]
|
||||
});
|
||||
return resourceCompletions;
|
||||
}
|
||||
@@ -374,7 +374,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
// - (tilde) `~/|` -> `~/`
|
||||
// - (tilde) `~/src/|` -> `~/src/`
|
||||
this._logService.trace(`TerminalCompletionService#resolveResources cwd`);
|
||||
if (showFolders) {
|
||||
if (showDirectories) {
|
||||
let label: string;
|
||||
switch (type) {
|
||||
case 'tilde': {
|
||||
@@ -398,8 +398,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
provider,
|
||||
kind: TerminalCompletionItemKind.Folder,
|
||||
detail: getFriendlyPath(this._labelService, lastWordFolderResource, resourceOptions.pathSeparator, TerminalCompletionItemKind.Folder, shellType),
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -412,7 +411,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
await Promise.all(stat.children.map(child => (async () => {
|
||||
let kind: TerminalCompletionItemKind | undefined;
|
||||
let detail: string | undefined = undefined;
|
||||
if (showFolders && child.isDirectory) {
|
||||
if (showDirectories && child.isDirectory) {
|
||||
if (child.isSymbolicLink) {
|
||||
kind = TerminalCompletionItemKind.SymbolicLinkFolder;
|
||||
} else {
|
||||
@@ -468,8 +467,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
provider,
|
||||
kind,
|
||||
detail: detail ?? getFriendlyPath(this._labelService, child.resource, resourceOptions.pathSeparator, kind, shellType),
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition]
|
||||
});
|
||||
})()));
|
||||
|
||||
@@ -477,7 +475,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
//
|
||||
// - (relative) `|` -> `/foo/vscode` (CDPATH has /foo which contains vscode folder)
|
||||
this._logService.trace(`TerminalCompletionService#resolveResources CDPATH`);
|
||||
if (type === 'relative' && showFolders) {
|
||||
if (type === 'relative' && showDirectories) {
|
||||
if (promptValue.startsWith('cd ')) {
|
||||
const config = this._configurationService.getValue(TerminalSuggestSettingId.CdPath);
|
||||
if (config === 'absolute' || config === 'relative') {
|
||||
@@ -507,8 +505,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
provider,
|
||||
kind,
|
||||
detail,
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition]
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -524,7 +521,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
// - (relative) `|` -> `../`
|
||||
// - (relative) `./src/|` -> `./src/../`
|
||||
this._logService.trace(`TerminalCompletionService#resolveResources parent dir`);
|
||||
if (type === 'relative' && showFolders) {
|
||||
if (type === 'relative' && showDirectories) {
|
||||
let label = `..${resourceOptions.pathSeparator}`;
|
||||
if (lastWordFolder.length > 0) {
|
||||
label = addPathRelativePrefix(lastWordFolder + label, resourceOptions, lastWordFolderHasDotPrefix);
|
||||
@@ -535,8 +532,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
provider,
|
||||
kind: TerminalCompletionItemKind.Folder,
|
||||
detail: getFriendlyPath(this._labelService, parentDir, resourceOptions.pathSeparator, TerminalCompletionItemKind.Folder, shellType),
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -561,8 +557,7 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
|
||||
provider,
|
||||
kind: TerminalCompletionItemKind.Folder,
|
||||
detail: typeof homeResource === 'string' ? homeResource : getFriendlyPath(this._labelService, homeResource, resourceOptions.pathSeparator, TerminalCompletionItemKind.Folder, shellType),
|
||||
replacementIndex: cursorPosition - lastWord.length,
|
||||
replacementLength: lastWord.length
|
||||
replacementRange: [cursorPosition - lastWord.length, cursorPosition]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -156,8 +156,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest
|
||||
// Right arrow is used to accept the completion. This is a common keybinding in pwsh, zsh
|
||||
// and fish.
|
||||
inputData: '\x1b[C',
|
||||
replacementIndex: 0,
|
||||
replacementLength: 0,
|
||||
replacementRange: [0, 0],
|
||||
provider: 'core:inlineSuggestion',
|
||||
detail: 'Inline suggestion',
|
||||
kind: TerminalCompletionItemKind.InlineSuggestion,
|
||||
@@ -650,10 +649,9 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest
|
||||
const replacementIndex = spaceIndex === -1 ? 0 : spaceIndex + 1;
|
||||
const suggestion = this._currentPromptInputState.value.substring(replacementIndex);
|
||||
this._inlineCompletion.label = suggestion;
|
||||
this._inlineCompletion.replacementIndex = replacementIndex;
|
||||
// Note that the cursor index delta must be taken into account here, otherwise filtering
|
||||
// wont work correctly.
|
||||
this._inlineCompletion.replacementLength = this._currentPromptInputState.cursorIndex - replacementIndex - this._cursorIndexDelta;
|
||||
// Update replacementRange (inclusive start, exclusive end) for replacement
|
||||
const end = this._currentPromptInputState.cursorIndex - this._cursorIndexDelta;
|
||||
this._inlineCompletion.replacementRange = [replacementIndex, end];
|
||||
// Reset the completion item as the object reference must remain the same but its
|
||||
// contents will differ across syncs. This is done so we don't need to reassign the
|
||||
// model and the slowdown/flickering that could potentially cause.
|
||||
@@ -928,7 +926,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest
|
||||
// The replacement text is any text after the replacement index for the completions, this
|
||||
// includes any text that was there before the completions were requested and any text added
|
||||
// since to refine the completion.
|
||||
const replacementText = currentPromptInputState.value.substring(suggestion.item.completion.replacementIndex, currentPromptInputState.cursorIndex);
|
||||
const startIndex = suggestion.item.completion.replacementRange?.[0] ?? currentPromptInputState.cursorIndex;
|
||||
const replacementText = currentPromptInputState.value.substring(startIndex, currentPromptInputState.cursorIndex);
|
||||
|
||||
// Right side of replacement text in the same word
|
||||
let rightSideReplacementText = '';
|
||||
|
||||
+2
-4
@@ -15,8 +15,7 @@ function createItem(options: Partial<ITerminalCompletion>): TerminalCompletionIt
|
||||
kind: options.kind ?? TerminalCompletionItemKind.Method,
|
||||
label: options.label || 'defaultLabel',
|
||||
provider: options.provider || 'defaultProvider',
|
||||
replacementIndex: options.replacementIndex || 0,
|
||||
replacementLength: options.replacementLength || 1,
|
||||
replacementRange: options.replacementRange || [0, 1],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -254,8 +253,7 @@ suite('TerminalCompletionModel', function () {
|
||||
new TerminalCompletionItem({
|
||||
label: 'ab',
|
||||
provider: 'core',
|
||||
replacementIndex: 0,
|
||||
replacementLength: 0,
|
||||
replacementRange: [0, 0],
|
||||
kind
|
||||
})
|
||||
];
|
||||
|
||||
+56
-64
@@ -33,8 +33,7 @@ interface IAssertionTerminalCompletion {
|
||||
}
|
||||
|
||||
interface IAssertionCommandLineConfig {
|
||||
replacementIndex: number;
|
||||
replacementLength: number;
|
||||
replacementRange: [number, number];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,14 +46,12 @@ function assertCompletions(actual: ITerminalCompletion[] | undefined, expected:
|
||||
label: e.label,
|
||||
detail: e.detail ?? '',
|
||||
kind: e.kind ?? TerminalCompletionItemKind.Folder,
|
||||
replacementIndex: e.replacementIndex,
|
||||
replacementLength: e.replacementLength,
|
||||
replacementRange: e.replacementRange,
|
||||
})), expected.map(e => ({
|
||||
label: e.label.replaceAll('/', sep),
|
||||
detail: e.detail ? e.detail.replaceAll('/', sep) : '',
|
||||
kind: e.kind ?? TerminalCompletionItemKind.Folder,
|
||||
replacementIndex: expectedConfig.replacementIndex,
|
||||
replacementLength: expectedConfig.replacementLength,
|
||||
replacementRange: expectedConfig.replacementRange,
|
||||
}))
|
||||
);
|
||||
}
|
||||
@@ -70,16 +67,14 @@ function assertPartialCompletionsExist(actual: ITerminalCompletion[] | undefined
|
||||
label: e.label.replaceAll('/', pathSeparator),
|
||||
detail: e.detail ? e.detail.replaceAll('/', pathSeparator) : '',
|
||||
kind: e.kind ?? TerminalCompletionItemKind.Folder,
|
||||
replacementIndex: expectedConfig.replacementIndex,
|
||||
replacementLength: expectedConfig.replacementLength,
|
||||
replacementRange: expectedConfig.replacementRange,
|
||||
}));
|
||||
for (const expectedItem of expectedMapped) {
|
||||
assert.deepStrictEqual(actual.map(e => ({
|
||||
label: e.label,
|
||||
detail: e.detail ?? '',
|
||||
kind: e.kind ?? TerminalCompletionItemKind.Folder,
|
||||
replacementIndex: e.replacementIndex,
|
||||
replacementLength: e.replacementLength,
|
||||
replacementRange: e.replacementRange,
|
||||
})).find(e => e.detail === expectedItem.detail), expectedItem);
|
||||
}
|
||||
}
|
||||
@@ -170,7 +165,7 @@ suite('TerminalCompletionService', () => {
|
||||
test('| should return root-level completions', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
const result = await terminalCompletionService.resolveResources(resourceOptions, '', 1, provider, capabilities);
|
||||
@@ -180,13 +175,13 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './folder1/', detail: '/test/folder1/' },
|
||||
{ label: '../', detail: '/' },
|
||||
standardTidleItem,
|
||||
], { replacementIndex: 1, replacementLength: 0 });
|
||||
], { replacementRange: [1, 1] });
|
||||
});
|
||||
|
||||
test('./| should return folder completions', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
const result = await terminalCompletionService.resolveResources(resourceOptions, './', 3, provider, capabilities);
|
||||
@@ -195,13 +190,13 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './', detail: '/test/' },
|
||||
{ label: './folder1/', detail: '/test/folder1/' },
|
||||
{ label: './../', detail: '/' },
|
||||
], { replacementIndex: 1, replacementLength: 2 });
|
||||
], { replacementRange: [1, 3] });
|
||||
});
|
||||
|
||||
test('cd ./| should return folder completions', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
const result = await terminalCompletionService.resolveResources(resourceOptions, 'cd ./', 5, provider, capabilities);
|
||||
@@ -210,12 +205,12 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './', detail: '/test/' },
|
||||
{ label: './folder1/', detail: '/test/folder1/' },
|
||||
{ label: './../', detail: '/' },
|
||||
], { replacementIndex: 3, replacementLength: 2 });
|
||||
], { replacementRange: [3, 5] });
|
||||
});
|
||||
test('cd ./f| should return folder completions', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
const result = await terminalCompletionService.resolveResources(resourceOptions, 'cd ./f', 6, provider, capabilities);
|
||||
@@ -224,7 +219,7 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './', detail: '/test/' },
|
||||
{ label: './folder1/', detail: '/test/folder1/' },
|
||||
{ label: './../', detail: '/' },
|
||||
], { replacementIndex: 3, replacementLength: 3 });
|
||||
], { replacementRange: [3, 6] });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -242,7 +237,7 @@ suite('TerminalCompletionService', () => {
|
||||
test('./| should handle hidden files and folders', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator
|
||||
};
|
||||
@@ -255,13 +250,13 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './folder1/', detail: '/test/folder1/' },
|
||||
{ label: './file1.txt', detail: '/test/file1.txt', kind: TerminalCompletionItemKind.File },
|
||||
{ label: './../', detail: '/' },
|
||||
], { replacementIndex: 0, replacementLength: 2 });
|
||||
], { replacementRange: [0, 2] });
|
||||
});
|
||||
|
||||
test('./h| should handle hidden files and folders', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator
|
||||
};
|
||||
@@ -274,7 +269,7 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './folder1/', detail: '/test/folder1/' },
|
||||
{ label: './file1.txt', detail: '/test/file1.txt', kind: TerminalCompletionItemKind.File },
|
||||
{ label: './../', detail: '/' },
|
||||
], { replacementIndex: 0, replacementLength: 3 });
|
||||
], { replacementRange: [0, 3] });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -293,7 +288,7 @@ suite('TerminalCompletionService', () => {
|
||||
resourceOptions = {
|
||||
cwd: URI.parse('file:///test/folder1'),// Updated to reflect home directory
|
||||
showFiles: true,
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [
|
||||
@@ -314,14 +309,14 @@ suite('TerminalCompletionService', () => {
|
||||
test('~| should return completion for ~', async () => {
|
||||
assertPartialCompletionsExist(await terminalCompletionService.resolveResources(resourceOptions, '~', 1, provider, capabilities), [
|
||||
{ label: '~', detail: '/home/' },
|
||||
], { replacementIndex: 0, replacementLength: 1 });
|
||||
], { replacementRange: [0, 1] });
|
||||
});
|
||||
|
||||
test('~/| should return folder completions relative to $HOME', async () => {
|
||||
assertCompletions(await terminalCompletionService.resolveResources(resourceOptions, '~/', 2, provider, capabilities), [
|
||||
{ label: '~/', detail: '/home/' },
|
||||
{ label: '~/vscode/', detail: '/home/vscode/' },
|
||||
], { replacementIndex: 0, replacementLength: 2 });
|
||||
], { replacementRange: [0, 2] });
|
||||
});
|
||||
|
||||
test('~/vscode/| should return folder completions relative to $HOME/vscode', async () => {
|
||||
@@ -329,7 +324,7 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: '~/vscode/', detail: '/home/vscode/' },
|
||||
{ label: '~/vscode/foo/', detail: '/home/vscode/foo/' },
|
||||
{ label: '~/vscode/bar.txt', detail: '/home/vscode/bar.txt', kind: TerminalCompletionItemKind.File },
|
||||
], { replacementIndex: 0, replacementLength: 9 });
|
||||
], { replacementRange: [0, 9] });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -343,7 +338,7 @@ suite('TerminalCompletionService', () => {
|
||||
test('C:/Foo/| absolute paths on Windows', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///C:'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [URI.parse('file:///C:/Foo')];
|
||||
@@ -356,12 +351,12 @@ suite('TerminalCompletionService', () => {
|
||||
assertCompletions(result, [
|
||||
{ label: 'C:/Foo/', detail: 'C:/Foo/' },
|
||||
{ label: 'C:/Foo/Bar/', detail: 'C:/Foo/Bar/' },
|
||||
], { replacementIndex: 0, replacementLength: 7 });
|
||||
], { replacementRange: [0, 7] });
|
||||
});
|
||||
test('c:/foo/| case insensitivity on Windows', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///c:'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [URI.parse('file:///c:/foo')];
|
||||
@@ -374,13 +369,13 @@ suite('TerminalCompletionService', () => {
|
||||
// Note that the detail is normalizes drive letters to capital case intentionally
|
||||
{ label: 'c:/foo/', detail: 'C:/foo/' },
|
||||
{ label: 'c:/foo/Bar/', detail: 'C:/foo/Bar/' },
|
||||
], { replacementIndex: 0, replacementLength: 7 });
|
||||
], { replacementRange: [0, 7] });
|
||||
});
|
||||
} else {
|
||||
test('/foo/| absolute paths NOT on Windows', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [URI.parse('file:///foo')];
|
||||
@@ -393,7 +388,7 @@ suite('TerminalCompletionService', () => {
|
||||
assertCompletions(result, [
|
||||
{ label: '/foo/', detail: '/foo/' },
|
||||
{ label: '/foo/Bar/', detail: '/foo/Bar/' },
|
||||
], { replacementIndex: 0, replacementLength: 5 });
|
||||
], { replacementRange: [0, 5] });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -401,7 +396,7 @@ suite('TerminalCompletionService', () => {
|
||||
test('.\\folder | Case insensitivity should resolve correctly on Windows', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///C:/test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator: '\\'
|
||||
};
|
||||
|
||||
@@ -418,13 +413,13 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: '.\\FolderA\\', detail: 'C:\\test\\FolderA\\' },
|
||||
{ label: '.\\anotherFolder\\', detail: 'C:\\test\\anotherFolder\\' },
|
||||
{ label: '.\\..\\', detail: 'C:\\' },
|
||||
], { replacementIndex: 0, replacementLength: 8 });
|
||||
], { replacementRange: [0, 8] });
|
||||
});
|
||||
} else {
|
||||
test('./folder | Case sensitivity should resolve correctly on Mac/Unix', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator: '/'
|
||||
};
|
||||
validResources = [URI.parse('file:///test')];
|
||||
@@ -440,14 +435,14 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './FolderA/', detail: '/test/FolderA/' },
|
||||
{ label: './foldera/', detail: '/test/foldera/' },
|
||||
{ label: './../', detail: '/' }
|
||||
], { replacementIndex: 0, replacementLength: 8 });
|
||||
], { replacementRange: [0, 8] });
|
||||
});
|
||||
|
||||
}
|
||||
test('| Empty input should resolve to current directory', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [URI.parse('file:///test')];
|
||||
@@ -463,13 +458,13 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './folder2/', detail: '/test/folder2/' },
|
||||
{ label: '../', detail: '/' },
|
||||
standardTidleItem,
|
||||
], { replacementIndex: 0, replacementLength: 0 });
|
||||
], { replacementRange: [0, 0] });
|
||||
});
|
||||
|
||||
test('./| should handle large directories with many results gracefully', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [URI.parse('file:///test')];
|
||||
@@ -489,7 +484,7 @@ suite('TerminalCompletionService', () => {
|
||||
test('./folder| should include current folder with trailing / is missing', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [URI.parse('file:///test')];
|
||||
@@ -504,20 +499,18 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './folder1/', detail: '/test/folder1/' },
|
||||
{ label: './folder2/', detail: '/test/folder2/' },
|
||||
{ label: './../', detail: '/' }
|
||||
], { replacementIndex: 1, replacementLength: 9 });
|
||||
], { replacementRange: [1, 10] });
|
||||
});
|
||||
|
||||
test('folder/| should normalize current and parent folders', async () => {
|
||||
test('test/| should normalize current and parent folders', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
pathSeparator
|
||||
};
|
||||
validResources = [
|
||||
URI.parse('file:///'),
|
||||
URI.parse('file:///test'),
|
||||
URI.parse('file:///test/folder1'),
|
||||
URI.parse('file:///test/folder2'),
|
||||
URI.parse('file:///test/folder2')
|
||||
];
|
||||
childResources = [
|
||||
{ resource: URI.parse('file:///test/folder1/'), isDirectory: true },
|
||||
@@ -530,7 +523,7 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './test/folder1/', detail: '/test/folder1/' },
|
||||
{ label: './test/folder2/', detail: '/test/folder2/' },
|
||||
{ label: './test/../', detail: '/' }
|
||||
], { replacementIndex: 0, replacementLength: 5 });
|
||||
], { replacementRange: [0, 5] });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -553,7 +546,7 @@ suite('TerminalCompletionService', () => {
|
||||
configurationService.setUserConfiguration('terminal.integrated.suggest.cdPath', 'relative');
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator
|
||||
};
|
||||
@@ -561,14 +554,14 @@ suite('TerminalCompletionService', () => {
|
||||
|
||||
assertPartialCompletionsExist(result, [
|
||||
{ label: 'folder1', detail: 'CDPATH /cdpath_value/folder1/' },
|
||||
], { replacementIndex: 3, replacementLength: 0 });
|
||||
], { replacementRange: [3, 3] });
|
||||
});
|
||||
|
||||
test('cd | should show paths from $CDPATH (absolute)', async () => {
|
||||
configurationService.setUserConfiguration('terminal.integrated.suggest.cdPath', 'absolute');
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator
|
||||
};
|
||||
@@ -576,7 +569,7 @@ suite('TerminalCompletionService', () => {
|
||||
|
||||
assertPartialCompletionsExist(result, [
|
||||
{ label: '/cdpath_value/folder1/', detail: 'CDPATH' },
|
||||
], { replacementIndex: 3, replacementLength: 0 });
|
||||
], { replacementRange: [3, 3] });
|
||||
});
|
||||
|
||||
test('cd | should support pulling from multiple paths in $CDPATH', async () => {
|
||||
@@ -604,7 +597,7 @@ suite('TerminalCompletionService', () => {
|
||||
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse(`${uriPathPrefix}test`),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator
|
||||
};
|
||||
@@ -616,7 +609,7 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: 'folder2', detail: `CDPATH ${finalPrefix}cdpath1_value/folder2/` },
|
||||
{ label: 'folder1', detail: `CDPATH ${finalPrefix}cdpath2_value/inner_dir/folder1/` },
|
||||
{ label: 'folder2', detail: `CDPATH ${finalPrefix}cdpath2_value/inner_dir/folder2/` },
|
||||
], { replacementIndex: 3, replacementLength: 0 });
|
||||
], { replacementRange: [3, 3] });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -639,7 +632,7 @@ suite('TerminalCompletionService', () => {
|
||||
test('resolveResources with c:/ style absolute path for Git Bash', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.file('C:\\Users\\foo'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator: '/'
|
||||
};
|
||||
@@ -657,12 +650,12 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: 'C:/Users/foo/', detail: 'C:\\Users\\foo\\' },
|
||||
{ label: 'C:/Users/foo/bar/', detail: 'C:\\Users\\foo\\bar\\' },
|
||||
{ label: 'C:/Users/foo/baz.txt', detail: 'C:\\Users\\foo\\baz.txt', kind: TerminalCompletionItemKind.File },
|
||||
], { replacementIndex: 0, replacementLength: 13 }, '/');
|
||||
], { replacementRange: [0, 13] }, '/');
|
||||
});
|
||||
test('resolveResources with cwd as Windows path (relative)', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.file('C:\\Users\\foo'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator: '/'
|
||||
};
|
||||
@@ -681,13 +674,13 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './bar/', detail: 'C:\\Users\\foo\\bar\\' },
|
||||
{ label: './baz.txt', detail: 'C:\\Users\\foo\\baz.txt', kind: TerminalCompletionItemKind.File },
|
||||
{ label: './../', detail: 'C:\\Users\\' }
|
||||
], { replacementIndex: 0, replacementLength: 2 }, '/');
|
||||
], { replacementRange: [0, 2] }, '/');
|
||||
});
|
||||
|
||||
test('resolveResources with cwd as Windows path (absolute)', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.file('C:\\Users\\foo'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator: '/'
|
||||
};
|
||||
@@ -705,7 +698,7 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: '/c/Users/foo/', detail: 'C:\\Users\\foo\\' },
|
||||
{ label: '/c/Users/foo/bar/', detail: 'C:\\Users\\foo\\bar\\' },
|
||||
{ label: '/c/Users/foo/baz.txt', detail: 'C:\\Users\\foo\\baz.txt', kind: TerminalCompletionItemKind.File },
|
||||
], { replacementIndex: 0, replacementLength: 13 }, '/');
|
||||
], { replacementRange: [0, 13] }, '/');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -716,7 +709,7 @@ suite('TerminalCompletionService', () => {
|
||||
cwd: URI.parse('file:///test'),
|
||||
pathSeparator,
|
||||
showFiles: true,
|
||||
showFolders: true
|
||||
showDirectories: true
|
||||
};
|
||||
|
||||
validResources = [URI.parse('file:///test')];
|
||||
@@ -743,7 +736,7 @@ suite('TerminalCompletionService', () => {
|
||||
test('| should escape special characters in file/folder names for POSIX shells', async () => {
|
||||
const resourceOptions: TerminalCompletionResourceOptions = {
|
||||
cwd: URI.parse('file:///test'),
|
||||
showFolders: true,
|
||||
showDirectories: true,
|
||||
showFiles: true,
|
||||
pathSeparator
|
||||
};
|
||||
@@ -764,7 +757,7 @@ suite('TerminalCompletionService', () => {
|
||||
{ label: './\!special\$chars2\&', detail: '/test/\!special\$chars2\&', kind: TerminalCompletionItemKind.File },
|
||||
{ label: '../', detail: '/' },
|
||||
standardTidleItem,
|
||||
], { replacementIndex: 0, replacementLength: 0 });
|
||||
], { replacementRange: [0, 0] });
|
||||
});
|
||||
|
||||
});
|
||||
@@ -790,8 +783,7 @@ suite('TerminalCompletionService', () => {
|
||||
provideCompletions: async () => [{
|
||||
label: `completion-from-${id}`,
|
||||
kind: TerminalCompletionItemKind.Method,
|
||||
replacementIndex: 0,
|
||||
replacementLength: 0,
|
||||
replacementRange: [0, 0],
|
||||
provider: id
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -45,14 +45,10 @@ export interface ISimpleCompletion {
|
||||
documentation?: string | IMarkdownString;
|
||||
|
||||
/**
|
||||
* The start of the replacement.
|
||||
* Replacement range (inclusive start, exclusive end) of text in the line to be replaced when
|
||||
* this completion is applied.
|
||||
*/
|
||||
replacementIndex: number;
|
||||
|
||||
/**
|
||||
* The length of the replacement.
|
||||
*/
|
||||
replacementLength: number;
|
||||
replacementRange: readonly [number, number] | undefined;
|
||||
}
|
||||
|
||||
export class SimpleCompletionItem {
|
||||
|
||||
@@ -112,9 +112,9 @@ export class SimpleCompletionModel<T extends SimpleCompletionItem> {
|
||||
// 'word' is that remainder of the current line that we
|
||||
// filter and score against. In theory each suggestion uses a
|
||||
// different word, but in practice not - that's why we cache
|
||||
// TODO: Fix
|
||||
const overwriteBefore = item.completion.replacementLength; // item.position.column - item.editStart.column;
|
||||
const wordLen = overwriteBefore + characterCountDelta; // - (item.position.column - this._column);
|
||||
|
||||
const overwriteBefore = item.completion.replacementRange ? (item.completion.replacementRange[1] - item.completion.replacementRange[0]) : 0;
|
||||
const wordLen = overwriteBefore + characterCountDelta;
|
||||
if (word.length !== wordLen) {
|
||||
word = wordLen === 0 ? '' : leadingLineContent.slice(-wordLen);
|
||||
wordLow = word.toLowerCase();
|
||||
|
||||
@@ -134,8 +134,8 @@ export class SimpleSuggestDetailsWidget {
|
||||
if (explainMode) {
|
||||
md += `score: ${item.score[0]}\n`;
|
||||
md += `prefix: ${item.word ?? '(no prefix)'}\n`;
|
||||
md += `replacementIndex: ${item.completion.replacementIndex}\n`;
|
||||
md += `replacementLength: ${item.completion.replacementLength}\n`;
|
||||
const vs = item.completion.replacementRange;
|
||||
md += `valueSelection: ${vs ? `[${vs[0]}, ${vs[1]}]` : 'undefined'}\\n`;
|
||||
md += `index: ${item.idx}\n`;
|
||||
if (this._getAdvancedExplainModeDetails) {
|
||||
const advancedDetails = this._getAdvancedExplainModeDetails();
|
||||
|
||||
Vendored
+265
@@ -8192,6 +8192,256 @@ declare module 'vscode' {
|
||||
constructor(options: TerminalOptions | ExtensionTerminalOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* A provider that supplies terminal completion items.
|
||||
*
|
||||
* Implementations of this interface should return an array of {@link TerminalCompletionItem} or a
|
||||
* {@link TerminalCompletionList} describing completions for the current command line.
|
||||
*
|
||||
* @example <caption>Simple provider returning a single completion</caption>
|
||||
* window.registerTerminalCompletionProvider('extension-provider-id', {
|
||||
* provideTerminalCompletions(terminal, context) {
|
||||
* return [{ label: '--help', replacementRange: [Math.max(0, context.cursorPosition - 2), context.cursorPosition] }];
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
export interface TerminalCompletionProvider<T extends TerminalCompletionItem> {
|
||||
/**
|
||||
* Provide completions for the given terminal and context.
|
||||
* @param terminal The terminal for which completions are being provided.
|
||||
* @param context Information about the terminal's current state.
|
||||
* @param token A cancellation token.
|
||||
* @return A list of completions.
|
||||
*/
|
||||
provideTerminalCompletions(terminal: Terminal, context: TerminalCompletionContext, token: CancellationToken): ProviderResult<T[] | TerminalCompletionList<T>>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents a completion suggestion for a terminal command line.
|
||||
*
|
||||
* @example <caption>Completion item for `ls -|`</caption>
|
||||
* const item = {
|
||||
* label: '-A',
|
||||
* replacementRange: [3, 4], // replace the single character at index 3
|
||||
* detail: 'List all entries except for . and .. (always set for the super-user)',
|
||||
* kind: TerminalCompletionItemKind.Flag
|
||||
* };
|
||||
*
|
||||
* The fields on a completion item describe what text should be shown to the user
|
||||
* and which portion of the command line should be replaced when the item is accepted.
|
||||
*/
|
||||
export class TerminalCompletionItem {
|
||||
/**
|
||||
* The label of the completion.
|
||||
*/
|
||||
label: string | CompletionItemLabel;
|
||||
|
||||
/**
|
||||
* The range in the command line to replace when the completion is accepted. Defined
|
||||
* as a tuple where the first entry is the inclusive start index and the second entry is the
|
||||
* exclusive end index. When `undefined` the completion will be inserted at the cursor
|
||||
* position. When the two numbers are equal only the cursor position changes (insertion).
|
||||
*
|
||||
*/
|
||||
replacementRange: readonly [number, number];
|
||||
|
||||
/**
|
||||
* The completion's detail which appears on the right of the list.
|
||||
*/
|
||||
detail?: string;
|
||||
|
||||
/**
|
||||
* A human-readable string that represents a doc-comment.
|
||||
*/
|
||||
documentation?: string | MarkdownString;
|
||||
|
||||
/**
|
||||
* The completion's kind. Note that this will map to an icon.
|
||||
*/
|
||||
kind?: TerminalCompletionItemKind;
|
||||
|
||||
/**
|
||||
* Creates a new terminal completion item.
|
||||
*
|
||||
* @param label The label of the completion.
|
||||
* @param replacementRange The inclusive start and exclusive end index of the text to replace.
|
||||
* @param kind The completion's kind.
|
||||
*/
|
||||
constructor(
|
||||
label: string | CompletionItemLabel,
|
||||
replacementRange: readonly [number, number],
|
||||
kind?: TerminalCompletionItemKind
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The kind of an individual terminal completion item.
|
||||
*
|
||||
* The kind is used to render an appropriate icon in the suggest list and to convey the semantic
|
||||
* meaning of the suggestion (file, folder, flag, commit, branch, etc.).
|
||||
*/
|
||||
export enum TerminalCompletionItemKind {
|
||||
/**
|
||||
* A file completion item.
|
||||
* Example: `README.md`
|
||||
*/
|
||||
File = 0,
|
||||
/**
|
||||
* A folder completion item.
|
||||
* Example: `src/`
|
||||
*/
|
||||
Folder = 1,
|
||||
/**
|
||||
* A method completion item.
|
||||
* Example: `git commit`
|
||||
*/
|
||||
Method = 2,
|
||||
/**
|
||||
* An alias completion item.
|
||||
* Example: `ll` as an alias for `ls -l`
|
||||
*/
|
||||
Alias = 3,
|
||||
/**
|
||||
* An argument completion item.
|
||||
* Example: `origin` in `git push origin master`
|
||||
*/
|
||||
Argument = 4,
|
||||
/**
|
||||
* An option completion item. An option value is expected to follow.
|
||||
* Example: `--locale` in `code --locale en`
|
||||
*/
|
||||
Option = 5,
|
||||
/**
|
||||
* The value of an option completion item.
|
||||
* Example: `en-US` in `code --locale en-US`
|
||||
*/
|
||||
OptionValue = 6,
|
||||
/**
|
||||
* A flag completion item.
|
||||
* Example: `--amend` in `git commit --amend`
|
||||
*/
|
||||
Flag = 7,
|
||||
/**
|
||||
* A symbolic link file completion item.
|
||||
* Example: `link.txt` (symlink to a file)
|
||||
*/
|
||||
SymbolicLinkFile = 8,
|
||||
/**
|
||||
* A symbolic link folder completion item.
|
||||
* Example: `node_modules/` (symlink to a folder)
|
||||
*/
|
||||
SymbolicLinkFolder = 9,
|
||||
/**
|
||||
* A source control commit completion item.
|
||||
* Example: `abc1234` (commit hash)
|
||||
*/
|
||||
ScmCommit = 10,
|
||||
/**
|
||||
* A source control branch completion item.
|
||||
* Example: `main`
|
||||
*/
|
||||
ScmBranch = 11,
|
||||
/**
|
||||
* A source control tag completion item.
|
||||
* Example: `v1.0.0`
|
||||
*/
|
||||
ScmTag = 12,
|
||||
/**
|
||||
* A source control stash completion item.
|
||||
* Example: `stash@{0}`
|
||||
*/
|
||||
ScmStash = 13,
|
||||
/**
|
||||
* A source control remote completion item.
|
||||
* Example: `origin`
|
||||
*/
|
||||
ScmRemote = 14,
|
||||
/**
|
||||
* A pull request completion item.
|
||||
* Example: `#42 Add new feature`
|
||||
*/
|
||||
PullRequest = 15,
|
||||
/**
|
||||
* A closed pull request completion item.
|
||||
* Example: `#41 Fix bug (closed)`
|
||||
*/
|
||||
PullRequestDone = 16,
|
||||
}
|
||||
|
||||
/**
|
||||
* Context information passed to {@link TerminalCompletionProvider.provideTerminalCompletions}.
|
||||
*
|
||||
* It contains the full command line, the current cursor position, and a flag indicating whether
|
||||
* completions were explicitly invoked.
|
||||
*/
|
||||
export interface TerminalCompletionContext {
|
||||
/**
|
||||
* The complete terminal command line.
|
||||
*/
|
||||
readonly commandLine: string;
|
||||
/**
|
||||
* The index of the cursor in the command line.
|
||||
*/
|
||||
readonly cursorIndex: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a collection of {@link TerminalCompletionItem completion items} to be presented
|
||||
* in the terminal.
|
||||
*
|
||||
* @example <caption>Create a completion list that requests files for the terminal cwd</caption>
|
||||
* const list = new TerminalCompletionList([
|
||||
* { label: 'ls', replacementRange: [0, 0], kind: TerminalCompletionItemKind.Method }
|
||||
* ], { showFiles: true, cwd: Uri.file('/home/user') });
|
||||
*/
|
||||
export class TerminalCompletionList<T extends TerminalCompletionItem = TerminalCompletionItem> {
|
||||
|
||||
/**
|
||||
* Resources that should be shown in the completions list for the cwd of the terminal.
|
||||
*/
|
||||
resourceOptions?: TerminalCompletionResourceOptions;
|
||||
|
||||
/**
|
||||
* The completion items.
|
||||
*/
|
||||
items: T[];
|
||||
|
||||
/**
|
||||
* Creates a new completion list.
|
||||
*
|
||||
* @param items The completion items.
|
||||
* @param resourceOptions Indicates which resources should be shown as completions for the cwd of the terminal.
|
||||
*/
|
||||
constructor(items: T[], resourceOptions?: TerminalCompletionResourceOptions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configuration for requesting file and folder resources to be shown as completions.
|
||||
*
|
||||
* When a provider indicates that it wants file/folder resources, the terminal will surface completions for files and
|
||||
* folders that match {@link globPattern} from the provided {@link cwd}.
|
||||
*/
|
||||
export interface TerminalCompletionResourceOptions {
|
||||
/**
|
||||
* Show files as completion items.
|
||||
*/
|
||||
showFiles: boolean;
|
||||
/**
|
||||
* Show folders as completion items.
|
||||
*/
|
||||
showDirectories: boolean;
|
||||
/**
|
||||
* A glob pattern string that controls which files suggest should surface. Note that this will only apply if {@param showFiles} or {@param showDirectories} is set to true.
|
||||
*/
|
||||
globPattern?: string;
|
||||
/**
|
||||
* The cwd from which to request resources.
|
||||
*/
|
||||
cwd: Uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* A file decoration represents metadata that can be rendered with a file.
|
||||
*/
|
||||
@@ -11768,6 +12018,21 @@ declare module 'vscode' {
|
||||
* @returns A {@link Disposable disposable} that unregisters the provider.
|
||||
*/
|
||||
export function registerTerminalProfileProvider(id: string, provider: TerminalProfileProvider): Disposable;
|
||||
/**
|
||||
* Register a completion provider for terminals.
|
||||
* @param provider The completion provider.
|
||||
* @returns A {@link Disposable} that unregisters this provider when being disposed.
|
||||
*
|
||||
* @example <caption>Register a provider for an extension</caption>
|
||||
* window.registerTerminalCompletionProvider('extension-provider-id', {
|
||||
* provideTerminalCompletions(terminal, context) {
|
||||
* return new TerminalCompletionList([
|
||||
* { label: '--version', replacementRange: [Math.max(0, context.cursorPosition - 2), 2] }
|
||||
* ]);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
export function registerTerminalCompletionProvider<T extends TerminalCompletionItem>(provider: TerminalCompletionProvider<T>, ...triggerCharacters: string[]): Disposable;
|
||||
/**
|
||||
* Register a file decoration provider.
|
||||
*
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/226562
|
||||
|
||||
/**
|
||||
* A provider that supplies terminal completion items.
|
||||
*
|
||||
* Implementations of this interface should return an array of {@link TerminalCompletionItem} or a
|
||||
* {@link TerminalCompletionList} describing completions for the current command line.
|
||||
*
|
||||
* @example <caption>Simple provider returning a single completion</caption>
|
||||
* window.registerTerminalCompletionProvider('extension-provider-id', {
|
||||
* provideTerminalCompletions(terminal, context) {
|
||||
* return [{ label: '--help', replacementIndex: Math.max(0, context.cursorPosition - 2), replacementLength: 2 }];
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
export interface TerminalCompletionProvider<T extends TerminalCompletionItem> {
|
||||
/**
|
||||
* Provide completions for the given terminal and context.
|
||||
* @param terminal The terminal for which completions are being provided.
|
||||
* @param context Information about the terminal's current state.
|
||||
* @param token A cancellation token.
|
||||
* @return A list of completions.
|
||||
*/
|
||||
provideTerminalCompletions(terminal: Terminal, context: TerminalCompletionContext, token: CancellationToken): ProviderResult<T[] | TerminalCompletionList<T>>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents a completion suggestion for a terminal command line.
|
||||
*
|
||||
* @example <caption>Completion item for `ls -|`</caption>
|
||||
* const item = {
|
||||
* label: '-A',
|
||||
* replacementIndex: 3,
|
||||
* replacementLength: 1,
|
||||
* detail: 'List all entries except for . and .. (always set for the super-user)',
|
||||
* kind: TerminalCompletionItemKind.Flag
|
||||
* };
|
||||
*
|
||||
* The fields on a completion item describe what text should be shown to the user
|
||||
* and which portion of the command line should be replaced when the item is accepted.
|
||||
*/
|
||||
export interface TerminalCompletionItem {
|
||||
/**
|
||||
* The label of the completion.
|
||||
*/
|
||||
label: string | CompletionItemLabel;
|
||||
|
||||
/**
|
||||
* The index of the start of the range to replace.
|
||||
*/
|
||||
replacementIndex: number;
|
||||
|
||||
/**
|
||||
* The length of the range to replace.
|
||||
*/
|
||||
replacementLength: number;
|
||||
|
||||
/**
|
||||
* The completion's detail which appears on the right of the list.
|
||||
*/
|
||||
detail?: string;
|
||||
|
||||
/**
|
||||
* A human-readable string that represents a doc-comment.
|
||||
*/
|
||||
documentation?: string | MarkdownString;
|
||||
|
||||
/**
|
||||
* The completion's kind. Note that this will map to an icon.
|
||||
*/
|
||||
kind?: TerminalCompletionItemKind;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The kind of an individual terminal completion item.
|
||||
*
|
||||
* The kind is used to render an appropriate icon in the suggest list and to convey the semantic
|
||||
* meaning of the suggestion (file, folder, flag, commit, branch, etc.).
|
||||
*
|
||||
*/
|
||||
export enum TerminalCompletionItemKind {
|
||||
File = 0,
|
||||
Folder = 1,
|
||||
Method = 2,
|
||||
Alias = 3,
|
||||
Argument = 4,
|
||||
/**
|
||||
* An option, for example in `code --locale`, `--locale` is the option
|
||||
*/
|
||||
Option = 5,
|
||||
/**
|
||||
* The value of an option, for example in `code --locale en-US`, `en-US` is the option value
|
||||
*/
|
||||
OptionValue = 6,
|
||||
/**
|
||||
* A flag, for example in `git commit --amend"`, `--amend` is the flag
|
||||
*/
|
||||
Flag = 7,
|
||||
SymbolicLinkFile = 8,
|
||||
SymbolicLinkFolder = 9,
|
||||
ScmCommit = 10,
|
||||
ScmBranch = 11,
|
||||
ScmTag = 12,
|
||||
ScmStash = 13,
|
||||
ScmRemote = 14,
|
||||
PullRequest = 15,
|
||||
/**
|
||||
* The pull request has been closed
|
||||
*/
|
||||
PullRequestDone = 16,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Context information passed to {@link TerminalCompletionProvider.provideTerminalCompletions}.
|
||||
*
|
||||
* It contains the full command line, the current cursor position, and a flag indicating whether
|
||||
* fallback completions are allowed when the exact completion type cannot be determined.
|
||||
*/
|
||||
export interface TerminalCompletionContext {
|
||||
/**
|
||||
* The complete terminal command line.
|
||||
*/
|
||||
readonly commandLine: string;
|
||||
/**
|
||||
* The index of the cursor in the command line.
|
||||
*/
|
||||
readonly cursorIndex: number;
|
||||
/**
|
||||
* Whether completions should be provided when none are explicitly suggested. This will display
|
||||
* fallback suggestions like files and folders.
|
||||
*/
|
||||
readonly allowFallbackCompletions: boolean;
|
||||
}
|
||||
|
||||
export namespace window {
|
||||
/**
|
||||
* Register a completion provider for terminals.
|
||||
* @param provider The completion provider.
|
||||
* @returns A {@link Disposable} that unregisters this provider when being disposed.
|
||||
*
|
||||
* @example <caption>Register a provider for an extension</caption>
|
||||
* window.registerTerminalCompletionProvider('extension-provider-id', {
|
||||
* provideTerminalCompletions(terminal, context) {
|
||||
* return new TerminalCompletionList([
|
||||
* { label: '--version', replacementIndex: Math.max(0, context.cursorPosition - 2), replacementLength: 2 }
|
||||
* ]);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
export function registerTerminalCompletionProvider<T extends TerminalCompletionItem>(provider: TerminalCompletionProvider<T>, ...triggerCharacters: string[]): Disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a collection of {@link TerminalCompletionItem completion items} to be presented
|
||||
* in the terminal.
|
||||
*
|
||||
* @example <caption>Create a completion list that requests files for the terminal cwd</caption>
|
||||
* const list = new TerminalCompletionList([
|
||||
* { label: 'ls', replacementIndex: 0, replacementLength: 0, kind: TerminalCompletionItemKind.Method }
|
||||
* ], { showFiles: true, cwd: Uri.file('/home/user') });
|
||||
*/
|
||||
export class TerminalCompletionList<T extends TerminalCompletionItem = TerminalCompletionItem> {
|
||||
|
||||
/**
|
||||
* Resources that should be shown in the completions list for the cwd of the terminal.
|
||||
*/
|
||||
resourceOptions?: TerminalCompletionResourceOptions;
|
||||
|
||||
/**
|
||||
* The completion items.
|
||||
*/
|
||||
items: T[];
|
||||
|
||||
/**
|
||||
* Creates a new completion list.
|
||||
*
|
||||
* @param items The completion items.
|
||||
* @param resourceOptions Indicates which resources should be shown as completions for the cwd of the terminal.
|
||||
*/
|
||||
constructor(items: T[], resourceOptions?: TerminalCompletionResourceOptions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configuration for requesting file and folder resources to be shown as completions.
|
||||
*
|
||||
* When a provider indicates that it wants file/folder resources, the terminal will surface completions for files and
|
||||
* folders that match {@link globPattern} from the provided {@link cwd}.
|
||||
*/
|
||||
export interface TerminalCompletionResourceOptions {
|
||||
/**
|
||||
* Show files as completion items.
|
||||
*/
|
||||
showFiles?: boolean;
|
||||
/**
|
||||
* Show folders as completion items.
|
||||
*/
|
||||
showDirectories?: boolean;
|
||||
/**
|
||||
* A glob pattern string that controls which files suggest should surface. Note that this will only apply if {@param showFiles} or {@param showDirectories} is set to true.
|
||||
*/
|
||||
globPattern?: string;
|
||||
/**
|
||||
* The cwd from which to request resources.
|
||||
*/
|
||||
cwd: Uri;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user