diff --git a/services/web/frontend/js/features/source-editor/languages/latex/close-bracket-config.ts b/services/web/frontend/js/features/source-editor/languages/latex/close-bracket-config.ts index 1c13487ea8..f86bedbafd 100644 --- a/services/web/frontend/js/features/source-editor/languages/latex/close-bracket-config.ts +++ b/services/web/frontend/js/features/source-editor/languages/latex/close-bracket-config.ts @@ -1,5 +1,14 @@ -import { EditorState, SelectionRange, Text } from '@codemirror/state' -import { CloseBracketConfig, prevChar } from '@codemirror/autocomplete' +import { + CharCategory, + EditorState, + SelectionRange, + Text, +} from '@codemirror/state' +import { + CloseBracketConfig, + nextChar, + prevChar, +} from '@codemirror/autocomplete' export const closeBracketConfig: CloseBracketConfig = { brackets: ['$', '$$', '[', '{', '('], @@ -22,6 +31,21 @@ export const closeBracketConfig: CloseBracketConfig = { // don't auto-close \$ return open } + + const next = nextChar(state.doc, range.head) + if (next === '\\') { + // avoid auto-closing $ before a TeX command + const pos = range.head + prev.length + const postnext = nextChar(state.doc, pos) + + if (state.charCategorizer(pos)(postnext) !== CharCategory.Word) { + return open + '$' + } + + // don't auto-close $\command + return open + } + // avoid creating an odd number of dollar signs const count = countSurroundingCharacters(state.doc, range.from, open) if (count % 2 !== 0) { diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-close-brackets.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-close-brackets.spec.tsx index a9be4d90db..5b4ef5c647 100644 --- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-close-brackets.spec.tsx +++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-close-brackets.spec.tsx @@ -138,6 +138,18 @@ describe('close brackets', { scrollBehavior: false }, function () { cy.get('@active-line').should('have.text', '2$') }) + it('does not auto-close a dollar sign before a command', function () { + cy.get('@active-line').type('\\nu') + cy.get('@active-line').type('{leftArrow}{leftArrow}{leftArrow}$') + cy.get('@active-line').should('have.text', '$\\nu') + }) + + it('does auto-close a dollar sign before a newline', function () { + cy.get('@active-line').type('\\\\') + cy.get('@active-line').type('{leftArrow}{leftArrow}$') + cy.get('@active-line').should('have.text', '$$\\\\') + }) + it('does auto-close a curly bracket before punctuation', function () { cy.get('@active-line').type(':2') cy.get('@active-line').type('{leftArrow}{leftArrow}{{}')