/** * 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 { 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); }