Merge pull request #12696 from overleaf/mj-rt-skip-more-preamble

[cm6+rt] Update skip-preamble-cursor to skip \maketitle and abstract

GitOrigin-RevId: 3c54d8159bfdb431763872790a2b82ac4cffc09f
This commit is contained in:
Mathias Jakobsen
2023-04-20 10:59:43 +01:00
committed by Copybot
parent 59b3b9b933
commit 3bd174631a
5 changed files with 90 additions and 29 deletions
@@ -731,6 +731,23 @@ export const atomicDecorations = (options: Options) => {
return false return false
} }
} }
} else if (nodeRef.type.is('Maketitle')) {
if (shouldDecorate(state, nodeRef)) {
const line = state.doc.lineAt(nodeRef.from)
const from = extendBackwardsOverEmptyLines(state.doc, line)
const to = extendForwardsOverEmptyLines(state.doc, line)
if (shouldDecorate(state, { from, to })) {
decorations.push(
Decoration.replace({
widget: new MakeTitleWidget(preamble),
block: true,
}).range(from, to)
)
}
return false
}
} else if (nodeRef.type.is('Item')) { } else if (nodeRef.type.is('Item')) {
// only decorate \item inside a list // only decorate \item inside a list
if (currentListEnvironment) { if (currentListEnvironment) {
@@ -823,23 +840,6 @@ export const atomicDecorations = (options: Options) => {
widget: new TeXWidget(), widget: new TeXWidget(),
}).range(nodeRef.from, nodeRef.to) }).range(nodeRef.from, nodeRef.to)
) )
return false
}
} else if (commandName === '\\maketitle') {
if (shouldDecorate(state, nodeRef)) {
const line = state.doc.lineAt(nodeRef.from)
const from = extendBackwardsOverEmptyLines(state.doc, line)
const to = extendForwardsOverEmptyLines(state.doc, line)
if (shouldDecorate(state, { from, to })) {
decorations.push(
Decoration.replace({
widget: new MakeTitleWidget(preamble),
block: true,
}).range(from, to)
)
}
return false return false
} }
} else if (hasCharacterSubstitution(commandName)) { } else if (hasCharacterSubstitution(commandName)) {
@@ -1,7 +1,8 @@
import { EditorView, ViewPlugin } from '@codemirror/view' import { EditorView, ViewPlugin } from '@codemirror/view'
import { EditorSelection } from '@codemirror/state' import { EditorSelection } from '@codemirror/state'
import { findDocumentEnvironment } from '../../utils/tree-operations/environments' import { findStartOfDocumentContent } from '../../utils/tree-operations/environments'
import { syntaxTree } from '@codemirror/language' import { syntaxTree } from '@codemirror/language'
import { extendForwardsOverEmptyLines } from './selection'
export const skipPreambleWithCursor = ViewPlugin.define((view: EditorView) => { export const skipPreambleWithCursor = ViewPlugin.define((view: EditorView) => {
let checkedOnce = false let checkedOnce = false
return { return {
@@ -21,10 +22,16 @@ export const skipPreambleWithCursor = ViewPlugin.define((view: EditorView) => {
) )
) { ) {
setTimeout(() => { setTimeout(() => {
const position = findDocumentEnvironment(view.state) const position =
extendForwardsOverEmptyLines(
update.state.doc,
update.state.doc.lineAt(
findStartOfDocumentContent(update.state) ?? 0
)
) + 1
view.dispatch({ view.dispatch({
selection: EditorSelection.cursor( selection: EditorSelection.cursor(
Math.min(position ? position + 1 : 0, update.state.doc.length) Math.min(position, update.state.doc.length)
), ),
}) })
}, 0) }, 0)
@@ -84,7 +84,8 @@
CenteringCtrlSeq, CenteringCtrlSeq,
BibliographyCtrlSeq, BibliographyCtrlSeq,
BibliographyStyleCtrlSeq, BibliographyStyleCtrlSeq,
AuthorCtrlSeq AuthorCtrlSeq,
MaketitleCtrlSeq
} }
@external specialize {EnvName} specializeEnvName from "./tokens.mjs" { @external specialize {EnvName} specializeEnvName from "./tokens.mjs" {
@@ -310,6 +311,9 @@ KnownCommand {
} | } |
Item { Item {
ItemCtrlSeq optionalWhitespace? ItemCtrlSeq optionalWhitespace?
} |
Maketitle {
MaketitleCtrlSeq optionalWhitespace?
} }
} }
@@ -65,6 +65,7 @@ import {
BibliographyStyleCtrlSeq, BibliographyStyleCtrlSeq,
CenteringCtrlSeq, CenteringCtrlSeq,
ListEnvName, ListEnvName,
MaketitleCtrlSeq,
} from './latex.terms.mjs' } from './latex.terms.mjs'
function nameChar(ch) { function nameChar(ch) {
@@ -635,6 +636,7 @@ const otherKnowncommands = {
'\\centering': CenteringCtrlSeq, '\\centering': CenteringCtrlSeq,
'\\bibliography': BibliographyCtrlSeq, '\\bibliography': BibliographyCtrlSeq,
'\\bibliographystyle': BibliographyStyleCtrlSeq, '\\bibliographystyle': BibliographyStyleCtrlSeq,
'\\maketitle': MaketitleCtrlSeq,
} }
// specializer for control sequences // specializer for control sequences
// return new tokens for specific control sequences // return new tokens for specific control sequences
@@ -1,6 +1,6 @@
import { ensureSyntaxTree } from '@codemirror/language' import { ensureSyntaxTree } from '@codemirror/language'
import { EditorState } from '@codemirror/state' import { EditorState } from '@codemirror/state'
import { SyntaxNode, SyntaxNodeRef } from '@lezer/common' import { SyntaxNode, SyntaxNodeRef, Tree } from '@lezer/common'
import { previousSiblingIs } from './common' import { previousSiblingIs } from './common'
import { NodeIntersectsChangeFn, ProjectionItem } from './projection' import { NodeIntersectsChangeFn, ProjectionItem } from './projection'
@@ -138,21 +138,69 @@ export const cursorIsAtEndEnvironment = (
} }
} }
export const findDocumentEnvironment = (state: EditorState): number | null => { const findStartOfDocumentEnvironment = (tree: Tree): number | null => {
const tree = ensureSyntaxTree(state, state.doc.length, HUNDRED_MS) const docEnvironment = findNodeInDocument(tree, 'DocumentEnvironment')
let position: number | null = null return docEnvironment?.getChild('Content')?.from || null
}
const findStartOfAbstractEnvironment = (
tree: Tree,
state: EditorState
): number | null => {
const abstractEnvironment = findNodeInDocument(
tree,
(nodeRef: SyntaxNodeRef) => {
return Boolean(
nodeRef.type.is('$Environment') &&
getEnvironmentName(nodeRef.node, state) === 'abstract'
)
}
)
return abstractEnvironment?.getChild('Content')?.from || null
}
const findMaketitleCommand = (tree: Tree): number | null => {
const maketitle = findNodeInDocument(tree, 'Maketitle')
return maketitle?.to ?? null
}
const findNodeInDocument = (
tree: Tree,
predicate: number | string | ((node: SyntaxNodeRef) => boolean)
): SyntaxNode | null => {
let node: SyntaxNode | null = null
const predicateFn =
typeof predicate !== 'function'
? (nodeRef: SyntaxNodeRef) => {
return nodeRef.type.is(predicate)
}
: predicate
tree?.iterate({ tree?.iterate({
enter(nodeRef) { enter(nodeRef) {
if (position !== null) { if (node !== null) {
return false return false
} }
if (nodeRef.type.is('DocumentEnvironment')) { if (predicateFn(nodeRef)) {
position = nodeRef.node.getChild('Content')?.from || null node = nodeRef.node
return false return false
} }
}, },
}) })
return position return node
}
export const findStartOfDocumentContent = (
state: EditorState
): number | null => {
const tree = ensureSyntaxTree(state, state.doc.length, HUNDRED_MS)
if (!tree) {
return null
}
return (
findStartOfAbstractEnvironment(tree, state) ??
findMaketitleCommand(tree) ??
findStartOfDocumentEnvironment(tree)
)
} }
/** /**