mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
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:
parent
59b3b9b933
commit
3bd174631a
5 changed files with 90 additions and 29 deletions
|
@ -731,6 +731,23 @@ export const atomicDecorations = (options: Options) => {
|
|||
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')) {
|
||||
// only decorate \item inside a list
|
||||
if (currentListEnvironment) {
|
||||
|
@ -823,23 +840,6 @@ export const atomicDecorations = (options: Options) => {
|
|||
widget: new TeXWidget(),
|
||||
}).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
|
||||
}
|
||||
} else if (hasCharacterSubstitution(commandName)) {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { EditorView, ViewPlugin } from '@codemirror/view'
|
||||
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 { extendForwardsOverEmptyLines } from './selection'
|
||||
export const skipPreambleWithCursor = ViewPlugin.define((view: EditorView) => {
|
||||
let checkedOnce = false
|
||||
return {
|
||||
|
@ -21,10 +22,16 @@ export const skipPreambleWithCursor = ViewPlugin.define((view: EditorView) => {
|
|||
)
|
||||
) {
|
||||
setTimeout(() => {
|
||||
const position = findDocumentEnvironment(view.state)
|
||||
const position =
|
||||
extendForwardsOverEmptyLines(
|
||||
update.state.doc,
|
||||
update.state.doc.lineAt(
|
||||
findStartOfDocumentContent(update.state) ?? 0
|
||||
)
|
||||
) + 1
|
||||
view.dispatch({
|
||||
selection: EditorSelection.cursor(
|
||||
Math.min(position ? position + 1 : 0, update.state.doc.length)
|
||||
Math.min(position, update.state.doc.length)
|
||||
),
|
||||
})
|
||||
}, 0)
|
||||
|
|
|
@ -84,7 +84,8 @@
|
|||
CenteringCtrlSeq,
|
||||
BibliographyCtrlSeq,
|
||||
BibliographyStyleCtrlSeq,
|
||||
AuthorCtrlSeq
|
||||
AuthorCtrlSeq,
|
||||
MaketitleCtrlSeq
|
||||
}
|
||||
|
||||
@external specialize {EnvName} specializeEnvName from "./tokens.mjs" {
|
||||
|
@ -310,6 +311,9 @@ KnownCommand {
|
|||
} |
|
||||
Item {
|
||||
ItemCtrlSeq optionalWhitespace?
|
||||
} |
|
||||
Maketitle {
|
||||
MaketitleCtrlSeq optionalWhitespace?
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ import {
|
|||
BibliographyStyleCtrlSeq,
|
||||
CenteringCtrlSeq,
|
||||
ListEnvName,
|
||||
MaketitleCtrlSeq,
|
||||
} from './latex.terms.mjs'
|
||||
|
||||
function nameChar(ch) {
|
||||
|
@ -635,6 +636,7 @@ const otherKnowncommands = {
|
|||
'\\centering': CenteringCtrlSeq,
|
||||
'\\bibliography': BibliographyCtrlSeq,
|
||||
'\\bibliographystyle': BibliographyStyleCtrlSeq,
|
||||
'\\maketitle': MaketitleCtrlSeq,
|
||||
}
|
||||
// specializer for control sequences
|
||||
// return new tokens for specific control sequences
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ensureSyntaxTree } from '@codemirror/language'
|
||||
import { EditorState } from '@codemirror/state'
|
||||
import { SyntaxNode, SyntaxNodeRef } from '@lezer/common'
|
||||
import { SyntaxNode, SyntaxNodeRef, Tree } from '@lezer/common'
|
||||
import { previousSiblingIs } from './common'
|
||||
import { NodeIntersectsChangeFn, ProjectionItem } from './projection'
|
||||
|
||||
|
@ -138,21 +138,69 @@ export const cursorIsAtEndEnvironment = (
|
|||
}
|
||||
}
|
||||
|
||||
export const findDocumentEnvironment = (state: EditorState): number | null => {
|
||||
const tree = ensureSyntaxTree(state, state.doc.length, HUNDRED_MS)
|
||||
let position: number | null = null
|
||||
const findStartOfDocumentEnvironment = (tree: Tree): number | null => {
|
||||
const docEnvironment = findNodeInDocument(tree, 'DocumentEnvironment')
|
||||
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({
|
||||
enter(nodeRef) {
|
||||
if (position !== null) {
|
||||
if (node !== null) {
|
||||
return false
|
||||
}
|
||||
if (nodeRef.type.is('DocumentEnvironment')) {
|
||||
position = nodeRef.node.getChild('Content')?.from || null
|
||||
if (predicateFn(nodeRef)) {
|
||||
node = nodeRef.node
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue