Add documentation to completion item (#238391)

pull/238398/head
Megan Rogge 2025-01-21 14:03:42 -06:00 committed by GitHub
parent 0ac5cce008
commit ac0f552f56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 32 additions and 10 deletions

View File

@ -7,6 +7,7 @@ import code from './code';
const codeInsidersCompletionSpec: Fig.Spec = {
...code,
name: 'code-insiders',
description: 'Visual Studio Code Insiders',
};
export default codeInsidersCompletionSpec;

View File

@ -198,7 +198,12 @@ export async function resolveCwdFromPrefix(prefix: string, currentCwd?: vscode.U
// If the prefix is not a folder, return the current cwd
return currentCwd;
}
function getDescription(spec: Fig.Spec): string {
if ('description' in spec) {
return spec.description ?? '';
}
return '';
}
function getLabel(spec: Fig.Spec | Fig.Arg | Fig.Suggestion | string): string[] | undefined {
if (typeof spec === 'string') {
@ -213,12 +218,13 @@ function getLabel(spec: Fig.Spec | Fig.Arg | Fig.Suggestion | string): string[]
return spec.name;
}
function createCompletionItem(cursorPosition: number, prefix: string, commandResource: ICompletionResource, description?: string, kind?: vscode.TerminalCompletionItemKind): vscode.TerminalCompletionItem {
function createCompletionItem(cursorPosition: number, prefix: string, commandResource: ICompletionResource, detail?: string, documentation?: string | vscode.MarkdownString, kind?: vscode.TerminalCompletionItemKind): vscode.TerminalCompletionItem {
const endsWithSpace = prefix.endsWith(' ');
const lastWord = endsWithSpace ? '' : prefix.split(' ').at(-1) ?? '';
return {
label: commandResource.label,
detail: description ?? commandResource.detail ?? '',
detail: detail ?? commandResource.detail ?? '',
documentation,
replacementIndex: cursorPosition - lastWord.length,
replacementLength: lastWord.length,
kind: kind ?? vscode.TerminalCompletionItemKind.Method
@ -327,7 +333,8 @@ export async function getCompletionItemsFromSpecs(
}
for (const specLabel of specLabels) {
if (!availableCommands.find(command => command.label === specLabel) || (token && token.isCancellationRequested)) {
const availableCommand = availableCommands.find(command => command.label === specLabel);
if (!availableCommand || (token && token.isCancellationRequested)) {
continue;
}
@ -338,7 +345,7 @@ export async function getCompletionItemsFromSpecs(
|| !!firstCommand && specLabel.startsWith(firstCommand)
) {
// push it to the completion items
items.push(createCompletionItem(terminalContext.cursorPosition, prefix, { label: specLabel }));
items.push(createCompletionItem(terminalContext.cursorPosition, prefix, { label: specLabel }, availableCommand.detail, getDescription(spec)));
}
if (!terminalContext.commandLine.startsWith(specLabel)) {
@ -374,7 +381,7 @@ export async function getCompletionItemsFromSpecs(
const labels = new Set(items.map((i) => i.label));
for (const command of availableCommands) {
if (!labels.has(command.label)) {
items.push(createCompletionItem(terminalContext.cursorPosition, prefix, command));
items.push(createCompletionItem(terminalContext.cursorPosition, prefix, command, command.detail));
}
}
}
@ -445,6 +452,7 @@ function handleOptions(specLabel: string, spec: Fig.Spec, terminalContext: { com
prefix,
{ label: optionLabel },
option.description,
undefined,
vscode.TerminalCompletionItemKind.Flag
)
);
@ -505,7 +513,7 @@ function getCompletionItemsFromArgs(args: Fig.SingleOrArray<Fig.Arg> | undefined
}
if (suggestionLabel && suggestionLabel.startsWith(currentPrefix.trim())) {
const description = typeof suggestion !== 'string' ? suggestion.description : '';
items.push(createCompletionItem(terminalContext.cursorPosition, wordBefore ?? '', { label: suggestionLabel }, description, vscode.TerminalCompletionItemKind.Argument));
items.push(createCompletionItem(terminalContext.cursorPosition, wordBefore ?? '', { label: suggestionLabel }, description, undefined, vscode.TerminalCompletionItemKind.Argument));
}
}
}

View File

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { FuzzyScore } from '../../../../base/common/filters.js';
import { MarkdownString } from '../../../../base/common/htmlContent.js';
import { isWindows } from '../../../../base/common/platform.js';
import { ThemeIcon } from '../../../../base/common/themables.js';
@ -24,6 +25,12 @@ export interface ISimpleCompletion {
* 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;
/**
* Whether the completion is a file. Files with the same score will be sorted against each other
* first by extension length and then certain extensions will get a boost based on the OS.

View File

@ -18,7 +18,7 @@ import { MarkdownRenderer } from '../../../../editor/browser/widget/markdownRend
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
export function canExpandCompletionItem(item: SimpleCompletionItem | undefined): boolean {
return !!item && Boolean(item.completion.detail && item.completion.detail !== item.completion.label);
return !!item && Boolean(item.completion.documentation || item.completion.detail && item.completion.detail !== item.completion.label);
}
export const SuggestDetailsClassName = 'suggest-details';
@ -104,10 +104,10 @@ export class SimpleSuggestDetailsWidget {
renderItem(item: SimpleCompletionItem, explainMode: boolean): void {
this._renderDisposeable.clear();
let { detail } = item.completion;
let { detail, documentation } = item.completion;
let md = '';
let documentation;
if (explainMode) {
md += `score: ${item.score[0]}\n`;
md += `prefix: ${item.word ?? '(no prefix)'}\n`;

View File

@ -40,6 +40,12 @@ declare module 'vscode' {
*/
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.
*/