vscode-texinfo/src/completion.ts

125 lines
4.1 KiB
TypeScript
Raw Normal View History

2020-10-05 22:31:40 +00:00
/**
* completion.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*/
import * as vscode from 'vscode';
2020-10-08 14:31:54 +00:00
/**
* Texinfo language completion item provider.
*/
2020-10-05 22:31:40 +00:00
export class CompletionItemProvider implements vscode.CompletionItemProvider {
2020-10-08 14:31:54 +00:00
private readonly completionItems = [
command('c', 'Line comment'),
2020-10-10 17:36:05 +00:00
snippet('header', 'c', 'Declare header block', 1, '@c %**start of header\n\n@c %**end of header',
2020-10-08 14:31:54 +00:00
'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'),
2020-10-10 17:36:05 +00:00
command('copyright', 'The "©" symbol', { hasEmptyArguments: true }),
2020-10-08 14:31:54 +00:00
command('insertcopying', 'Include permissions text'),
command('titlepage', 'Declare title page', { sortOrder: 1 }),
blockSnippet('titlepage', 'Declare title page'),
2020-10-07 23:09:21 +00:00
];
2020-10-05 22:31:40 +00:00
provideCompletionItems(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
2020-10-08 14:31:54 +00:00
context: vscode.CompletionContext,
2020-10-05 22:31:40 +00:00
) {
2020-10-07 23:09:21 +00:00
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;
}
2020-10-05 22:31:40 +00:00
}
}
2020-10-08 14:31:54 +00:00
/**
* 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,
2020-10-10 17:36:05 +00:00
sortText: name + (extraArgs?.sortOrder?.toString() ?? ''),
2020-10-08 14:31:54 +00:00
filterText: name,
2020-10-10 17:36:05 +00:00
insertText: name + (extraArgs?.hasEmptyArguments ? '{}' : ''),
};
2020-10-08 14:31:54 +00:00
}
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),
2020-10-10 17:36:05 +00:00
};
2020-10-08 14:31:54 +00:00
}
/**
* Wraps Texinfo snippet code into a Markdown code block for documentation.
*
* @param snippet The snippet code
*/
function snippetDocumentation(snippet: string) {
2020-10-10 17:36:05 +00:00
return new vscode.MarkdownString('```texinfo\n' + snippet + '\n```');
2020-10-08 14:31:54 +00:00
}