monaco-latex
Version:
LaTeX language support for Monaco Editor
139 lines (118 loc) • 4 kB
text/typescript
/**
* LaTeX Hover Provider for Monaco Editor.
* Provides documentation on hover for LaTeX commands and environments.
*/
import type * as Monaco from 'monaco-editor';
import {
COMMAND_MAP,
ENVIRONMENT_MAP,
type LaTeXCommand,
type LaTeXEnvironment,
} from './commands/data';
export class LaTeXHoverProvider implements Monaco.languages.HoverProvider {
constructor(private monaco: typeof Monaco) {}
provideHover(
model: Monaco.editor.ITextModel,
position: Monaco.Position,
token: Monaco.CancellationToken
): Monaco.languages.ProviderResult<Monaco.languages.Hover> {
const word = model.getWordAtPosition(position);
if (!word) return null;
const lineContent = model.getLineContent(position.lineNumber);
const beforeWord = lineContent.substring(0, word.startColumn - 1);
// Check if this is a LaTeX command (preceded by backslash)
if (beforeWord.endsWith('\\')) {
const command = COMMAND_MAP.get(word.word);
if (command) {
return this.createCommandHover(command, {
startLineNumber: position.lineNumber,
startColumn: word.startColumn - 1, // Include the backslash
endLineNumber: position.lineNumber,
endColumn: word.endColumn,
});
}
}
// Check if it's an environment name inside \begin{} or \end{}
const envMatch = lineContent.match(/\\(begin|end)\{(\w+\*?)\}/);
if (envMatch && word.word === envMatch[2]) {
const env = ENVIRONMENT_MAP.get(envMatch[2]);
if (env) {
return this.createEnvironmentHover(env, {
startLineNumber: position.lineNumber,
startColumn: word.startColumn,
endLineNumber: position.lineNumber,
endColumn: word.endColumn,
});
}
}
return null;
}
private createCommandHover(
cmd: LaTeXCommand,
range: Monaco.IRange
): Monaco.languages.Hover {
const contents: Monaco.IMarkdownString[] = [];
// Command signature
if (cmd.signature) {
contents.push({
value: `\`\\${cmd.name}${cmd.signature}\``,
});
} else {
contents.push({
value: `\`\\${cmd.name}\``,
});
}
// Description
contents.push({
value: cmd.description,
});
// Category
contents.push({
value: `*Category:* ${cmd.category}`,
});
// Package requirement
if (cmd.package) {
contents.push({
value: `*Requires:* \`\\usepackage{${cmd.package}}\``,
});
}
// Example
if (cmd.example) {
contents.push({
value: `**Example:**\n\`\`\`latex\n${cmd.example}\n\`\`\``,
});
}
return { contents, range };
}
private createEnvironmentHover(
env: LaTeXEnvironment,
range: Monaco.IRange
): Monaco.languages.Hover {
const contents: Monaco.IMarkdownString[] = [];
// Environment name
contents.push({
value: `\`\\begin{${env.name}}...\\end{${env.name}}\``,
});
// Description
contents.push({
value: env.description,
});
// Category
contents.push({
value: `*Category:* ${env.category}`,
});
// Package requirement
if (env.package) {
contents.push({
value: `*Requires:* \`\\usepackage{${env.package}}\``,
});
}
return { contents, range };
}
}
/**
* Creates a hover provider for LaTeX.
*/
export function createHoverProvider(monaco: typeof Monaco): LaTeXHoverProvider {
return new LaTeXHoverProvider(monaco);
}