monaco-latex
Version:
LaTeX language support for Monaco Editor
113 lines (112 loc) • 4.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCompletionProvider = exports.LaTeXCompletionProvider = void 0;
const data_1 = require("./commands/data");
class LaTeXCompletionProvider {
constructor(monaco) {
this.monaco = monaco;
this.triggerCharacters = ['\\', '{', '['];
}
provideCompletionItems(model, position, context, token) {
const textUntilPosition = model.getValueInRange({
startLineNumber: position.lineNumber,
startColumn: 1,
endLineNumber: position.lineNumber,
endColumn: position.column,
});
const suggestions = [];
// Check if we're after a backslash (command completion)
const commandMatch = textUntilPosition.match(/\\([\w]*)$/);
if (commandMatch) {
// Calculate range for just the command name (after backslash)
const commandRange = {
startLineNumber: position.lineNumber,
startColumn: position.column - commandMatch[1].length,
endLineNumber: position.lineNumber,
endColumn: position.column,
};
suggestions.push(...this.getCommandCompletions(commandRange));
}
// Check if we're inside \begin{ or \end{ (environment completion)
const envMatch = textUntilPosition.match(/\\(begin|end)\{([\w*]*)$/);
if (envMatch) {
const envRange = {
startLineNumber: position.lineNumber,
startColumn: position.column - envMatch[2].length,
endLineNumber: position.lineNumber,
endColumn: position.column,
};
suggestions.push(...this.getEnvironmentCompletions(envRange));
}
// Check if we're inside \usepackage{ (package completion)
const pkgMatch = textUntilPosition.match(/\\usepackage(?:\[.*?\])?\{([\w,\s]*)$/);
if (pkgMatch) {
const pkgRange = {
startLineNumber: position.lineNumber,
startColumn: position.column - pkgMatch[1].length,
endLineNumber: position.lineNumber,
endColumn: position.column,
};
suggestions.push(...this.getPackageCompletions(pkgRange));
}
return { suggestions };
}
getCommandCompletions(range) {
return data_1.LATEX_COMMANDS.map((cmd, index) => ({
label: `\\${cmd.name}`,
kind: this.monaco.languages.CompletionItemKind.Function,
// insertText without backslash since we only replace the command name
insertText: cmd.snippet || cmd.name,
insertTextRules: cmd.snippet
? this.monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
: undefined,
detail: cmd.signature ? `\\${cmd.name}${cmd.signature}` : cmd.category,
documentation: this.formatDocumentation(cmd),
range,
sortText: String(index).padStart(4, '0'),
// Filter based on what user typed after backslash
filterText: cmd.name,
}));
}
getEnvironmentCompletions(range) {
return data_1.LATEX_ENVIRONMENTS.map((env, index) => ({
label: env.name,
kind: this.monaco.languages.CompletionItemKind.Snippet,
insertText: env.name,
detail: env.package ? `Requires: ${env.package}` : 'Base LaTeX',
documentation: {
value: env.description,
},
range,
sortText: String(index).padStart(4, '0'),
}));
}
getPackageCompletions(range) {
return data_1.LATEX_PACKAGES.map((pkg, index) => ({
label: pkg.name,
kind: this.monaco.languages.CompletionItemKind.Module,
insertText: pkg.name,
documentation: pkg.description,
range,
sortText: String(index).padStart(4, '0'),
}));
}
formatDocumentation(cmd) {
let doc = `**${cmd.description}**\n\n`;
if (cmd.package) {
doc += `*Requires:* \`\\usepackage{${cmd.package}}\`\n\n`;
}
if (cmd.example) {
doc += `**Example:**\n\`\`\`latex\n${cmd.example}\n\`\`\``;
}
return { value: doc };
}
}
exports.LaTeXCompletionProvider = LaTeXCompletionProvider;
/**
* Creates a completion provider for LaTeX.
*/
function createCompletionProvider(monaco) {
return new LaTeXCompletionProvider(monaco);
}
exports.createCompletionProvider = createCompletionProvider;