From f2f7f6b7d629f6ab7855fdc9da1d7c4fa128ffcb Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Fri, 5 May 2023 09:42:53 +0100 Subject: [PATCH] [cm6] Add beginEnvironmentCompletionSource (#12913) GitOrigin-RevId: eb4582606103268f1f2c90da7d372a0a33926e36 --- .../source-editor/languages/latex/complete.ts | 57 +++++++++++++++++++ .../source-editor/languages/latex/index.ts | 2 + 2 files changed, 59 insertions(+) diff --git a/services/web/frontend/js/features/source-editor/languages/latex/complete.ts b/services/web/frontend/js/features/source-editor/languages/latex/complete.ts index 9bbdf5031a..8f81695427 100644 --- a/services/web/frontend/js/features/source-editor/languages/latex/complete.ts +++ b/services/web/frontend/js/features/source-editor/languages/latex/complete.ts @@ -20,6 +20,12 @@ import { cursorIsAtBeginEnvironment, cursorIsAtEndEnvironment, } from '../../utils/tree-query' +import { + applySnippet, + extendOverUnpairedClosingBrace, +} from './completions/apply' +import { snippet } from './completions/data/environments' +import { syntaxTree } from '@codemirror/language' function blankCompletions(): Completions { return { @@ -373,3 +379,54 @@ export const inCommandCompletionSource: CompletionSource = ifInType( export const explicitCommandCompletionSource: CompletionSource = context => { return context.explicit ? commandCompletionSource(context) : null } + +/** + * An additional completion source that handles two situations: + * + * 1. Typing the environment name within an already-complete `\begin{…}` command. + * 2. After typing the closing brace of a complete `\begin{foo}` command, where the environment + * isn't previously known, leaving the cursor after the closing brace. + */ +export const beginEnvironmentCompletionSource: CompletionSource = context => { + const beginEnvToken = context.tokenBefore(['BeginEnv']) + if (!beginEnvToken) { + return null + } + + const beginEnv = syntaxTree(context.state).resolveInner( + beginEnvToken.from, + 1 + ).parent + if (!beginEnv?.type.is('BeginEnv')) { + return null + } + + const envNameGroup = beginEnv.getChild('EnvNameGroup') + if (!envNameGroup) { + return null + } + + // this completion source must only be active when the \begin command has a closing brace + const closeBrace = envNameGroup.getChild('CloseBrace') + if (!closeBrace) { + return null + } + + const envName = envNameGroup.getChild('$EnvName') + if (!envName) { + return null + } + + const name = context.state.sliceDoc(envName.from, envName.to) + + const completion = { + label: `\\begin{${name}} …`, + apply: applySnippet(snippet(name)), + extend: extendOverUnpairedClosingBrace, + } + + return { + from: beginEnvToken.from, + options: [completion], + } +} diff --git a/services/web/frontend/js/features/source-editor/languages/latex/index.ts b/services/web/frontend/js/features/source-editor/languages/latex/index.ts index b60a89ebd0..b2bc645906 100644 --- a/services/web/frontend/js/features/source-editor/languages/latex/index.ts +++ b/services/web/frontend/js/features/source-editor/languages/latex/index.ts @@ -9,6 +9,7 @@ import { argumentCompletionSources, explicitCommandCompletionSource, inCommandCompletionSource, + beginEnvironmentCompletionSource, } from './complete' import { documentCommands } from './document-commands' import importOverleafModules from '../../../../../macros/import-overleaf-module.macro' @@ -20,6 +21,7 @@ const completionSources: CompletionSource[] = [ ...argumentCompletionSources, inCommandCompletionSource, explicitCommandCompletionSource, + beginEnvironmentCompletionSource, ...importOverleafModules('sourceEditorCompletionSources').map( (item: any) => item.import.default ),