125 lines
4.1 KiB
TypeScript
125 lines
4.1 KiB
TypeScript
/**
|
|
* completion.ts
|
|
*
|
|
* @author CismonX <admin@cismon.net>
|
|
* @license MIT
|
|
*/
|
|
|
|
import * as vscode from 'vscode';
|
|
|
|
/**
|
|
* Texinfo language completion item provider.
|
|
*/
|
|
export class CompletionItemProvider implements vscode.CompletionItemProvider {
|
|
|
|
private readonly completionItems = [
|
|
command('c', 'Line comment'),
|
|
snippet('header', 'c', 'Declare header block', 1, '@c %**start of header\n\n@c %**end of header',
|
|
'c %**${1:start of header}\n$2\n@c %**${3:end of header}'),
|
|
command('setfilename', 'Set output file name'),
|
|
command('settitle', 'Set document title'),
|
|
command('copying', 'Declare copying permissions', { sortOrder: 1 }),
|
|
blockSnippet('copying', 'Declare copying permissions'),
|
|
command('copyright', 'The "©" symbol', { hasEmptyArguments: true }),
|
|
command('insertcopying', 'Include permissions text'),
|
|
command('titlepage', 'Declare title page', { sortOrder: 1 }),
|
|
blockSnippet('titlepage', 'Declare title page'),
|
|
];
|
|
|
|
provideCompletionItems(
|
|
document: vscode.TextDocument,
|
|
position: vscode.Position,
|
|
token: vscode.CancellationToken,
|
|
context: vscode.CompletionContext,
|
|
) {
|
|
if (context.triggerKind === vscode.CompletionTriggerKind.Invoke) {
|
|
const wordRange = document.getWordRangeAtPosition(position);
|
|
if (wordRange === undefined) {
|
|
return undefined;
|
|
}
|
|
position = wordRange.start;
|
|
if (document.getText(new vscode.Range(position.translate(0, -1), position)) !== '@') {
|
|
return undefined;
|
|
}
|
|
}
|
|
if (position.character === 1) {
|
|
return this.completionItems;
|
|
}
|
|
if (document.getText(new vscode.Range(position.translate(0, -2), position.translate(0, -1))) === '@') {
|
|
// The '@' character is escaped.
|
|
return undefined;
|
|
} else {
|
|
return this.completionItems;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the completion item for a Texinfo command.
|
|
*
|
|
* @param name The command name.
|
|
* @param detail The command description.
|
|
* @param extraArgs Extra arguments.
|
|
*/
|
|
function command(name: string, detail: string, extraArgs?: {
|
|
/**
|
|
* Sort order for this completion item when names collide.
|
|
*/
|
|
sortOrder?: number,
|
|
/**
|
|
* Whether this command takes no arguments and braces are required.
|
|
*/
|
|
hasEmptyArguments?: boolean,
|
|
}): vscode.CompletionItem {
|
|
return {
|
|
label: '@' + name,
|
|
kind: vscode.CompletionItemKind.Function,
|
|
detail: detail,
|
|
sortText: name + (extraArgs?.sortOrder?.toString() ?? ''),
|
|
filterText: name,
|
|
insertText: name + (extraArgs?.hasEmptyArguments ? '{}' : ''),
|
|
};
|
|
}
|
|
|
|
function blockSnippet(name: string, detail: string): vscode.CompletionItem {
|
|
return snippet(name, name, detail, 0, `@${name}\n\n@end ${name}`, `${name}\n$1\n@end ${name}`);
|
|
}
|
|
|
|
/**
|
|
* Build the completion item for a generic snippet.
|
|
*
|
|
* @param label The string showing up in the completion list.
|
|
* @param keyword The word typed by the user.
|
|
* @param detail The snippet description.
|
|
* @param sortOrder Sort order for this completion item when names collide.
|
|
* @param documentation The Markdown documentation for this snippet.
|
|
* @param insertText The text to replace current word when the item is selected.
|
|
*/
|
|
function snippet(
|
|
label: string,
|
|
keyword: string,
|
|
detail: string,
|
|
sortOrder: number,
|
|
documentation: string,
|
|
insertText: string,
|
|
): vscode.CompletionItem {
|
|
return {
|
|
label: label,
|
|
kind: vscode.CompletionItemKind.Snippet,
|
|
detail: detail + ' (snippet)',
|
|
documentation: snippetDocumentation(documentation),
|
|
sortText: keyword + sortOrder.toString(),
|
|
filterText: keyword,
|
|
insertText: new vscode.SnippetString(insertText),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Wraps Texinfo snippet code into a Markdown code block for documentation.
|
|
*
|
|
* @param snippet The snippet code
|
|
*/
|
|
function snippetDocumentation(snippet: string) {
|
|
return new vscode.MarkdownString('```texinfo\n' + snippet + '\n```');
|
|
}
|