mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-28 22:03:16 -05:00
Use StringQuery and selectWord from @codemirror/search (#12828)
GitOrigin-RevId: 23b3e6a5db8583646f378cef52f41889a73a3672
This commit is contained in:
parent
db26446d76
commit
62533ace6d
4 changed files with 31 additions and 105 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -3384,8 +3384,8 @@
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/search": {
|
"node_modules/@codemirror/search": {
|
||||||
"version": "6.4.0",
|
"version": "6.4.0",
|
||||||
"resolved": "git+ssh://git@github.com/overleaf/codemirror-search.git#ea83364b22ad66455fc94babea7d576fa9f76a93",
|
"resolved": "git+ssh://git@github.com/overleaf/codemirror-search.git#6a09ea7eaad138d810f989753036eabce23cc969",
|
||||||
"integrity": "sha512-02UOFSNY7/FamUaRPNPwcjq58V2nsRbtXRIT85/AKgfEWv6tVHj5slobCeaRKCXb6hPSOEDMztR5ShmbuxLfEw==",
|
"integrity": "sha512-LblfUBGsW2+0U+orNGYcJHGKRnbUSU7V/tQDRNKlrw+hE0ZgAGW1B+dZAkcd+AITn6VwjFxKgERB1CzDkWmQWQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
|
@ -41260,7 +41260,7 @@
|
||||||
"@codemirror/lang-markdown": "^6.1.1",
|
"@codemirror/lang-markdown": "^6.1.1",
|
||||||
"@codemirror/language": "^6.6.0",
|
"@codemirror/language": "^6.6.0",
|
||||||
"@codemirror/lint": "^6.2.1",
|
"@codemirror/lint": "^6.2.1",
|
||||||
"@codemirror/search": "github:overleaf/codemirror-search#ea83364b22ad66455fc94babea7d576fa9f76a93",
|
"@codemirror/search": "github:overleaf/codemirror-search#6a09ea7eaad138d810f989753036eabce23cc969",
|
||||||
"@codemirror/state": "^6.2.0",
|
"@codemirror/state": "^6.2.0",
|
||||||
"@codemirror/view": "^6.14.0",
|
"@codemirror/view": "^6.14.0",
|
||||||
"@contentful/rich-text-html-renderer": "^16.0.2",
|
"@contentful/rich-text-html-renderer": "^16.0.2",
|
||||||
|
@ -45030,9 +45030,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@codemirror/search": {
|
"@codemirror/search": {
|
||||||
"version": "git+ssh://git@github.com/overleaf/codemirror-search.git#ea83364b22ad66455fc94babea7d576fa9f76a93",
|
"version": "git+ssh://git@github.com/overleaf/codemirror-search.git#6a09ea7eaad138d810f989753036eabce23cc969",
|
||||||
"integrity": "sha512-02UOFSNY7/FamUaRPNPwcjq58V2nsRbtXRIT85/AKgfEWv6tVHj5slobCeaRKCXb6hPSOEDMztR5ShmbuxLfEw==",
|
"integrity": "sha512-LblfUBGsW2+0U+orNGYcJHGKRnbUSU7V/tQDRNKlrw+hE0ZgAGW1B+dZAkcd+AITn6VwjFxKgERB1CzDkWmQWQ==",
|
||||||
"from": "@codemirror/search@github:overleaf/codemirror-search#ea83364b22ad66455fc94babea7d576fa9f76a93",
|
"from": "@codemirror/search@github:overleaf/codemirror-search#6a09ea7eaad138d810f989753036eabce23cc969",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.0.0",
|
"@codemirror/view": "^6.0.0",
|
||||||
|
@ -50242,7 +50242,7 @@
|
||||||
"@codemirror/lang-markdown": "^6.1.1",
|
"@codemirror/lang-markdown": "^6.1.1",
|
||||||
"@codemirror/language": "^6.6.0",
|
"@codemirror/language": "^6.6.0",
|
||||||
"@codemirror/lint": "^6.2.1",
|
"@codemirror/lint": "^6.2.1",
|
||||||
"@codemirror/search": "github:overleaf/codemirror-search#ea83364b22ad66455fc94babea7d576fa9f76a93",
|
"@codemirror/search": "github:overleaf/codemirror-search#6a09ea7eaad138d810f989753036eabce23cc969",
|
||||||
"@codemirror/state": "^6.2.0",
|
"@codemirror/state": "^6.2.0",
|
||||||
"@codemirror/view": "^6.14.0",
|
"@codemirror/view": "^6.14.0",
|
||||||
"@contentful/rich-text-html-renderer": "^16.0.2",
|
"@contentful/rich-text-html-renderer": "^16.0.2",
|
||||||
|
|
|
@ -1,91 +1,21 @@
|
||||||
import { EditorView } from '@codemirror/view'
|
import { EditorView } from '@codemirror/view'
|
||||||
import { EditorSelection, Text } from '@codemirror/state'
|
import { EditorSelection, EditorState, StateCommand } from '@codemirror/state'
|
||||||
import { selectNextOccurrence, SearchCursor } from '@codemirror/search'
|
import { SearchQuery, StringQuery, selectWord } from '@codemirror/search'
|
||||||
|
|
||||||
type Spec = {
|
export { selectNextOccurrence } from '@codemirror/search'
|
||||||
caseSensitive?: boolean
|
|
||||||
unquoted: string
|
const findPrevOccurence = (state: EditorState, search: string) => {
|
||||||
|
const searchQuery = new SearchQuery({ search, literal: true })
|
||||||
|
const query = new StringQuery(searchQuery)
|
||||||
|
const { from, to } = state.selection.main
|
||||||
|
return query.prevMatch(state, from, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
const stringCursor = (spec: Spec, doc: Text, from: number, to: number) => {
|
export const selectPrevOccurrence: StateCommand = ({ state, dispatch }) => {
|
||||||
return new SearchCursor(
|
|
||||||
doc,
|
|
||||||
spec.unquoted,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
spec.caseSensitive ? undefined : x => x.toLowerCase()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class QueryType {
|
|
||||||
protected spec
|
|
||||||
|
|
||||||
constructor(spec: Spec) {
|
|
||||||
this.spec = spec
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StringQuery extends QueryType {
|
|
||||||
// Searching in reverse is, rather than implementing inverted search
|
|
||||||
// cursor, done by scanning chunk after chunk forward.
|
|
||||||
prevMatchInRange(doc: Text, from: number, to: number) {
|
|
||||||
for (let pos = to; ; ) {
|
|
||||||
const start = Math.max(
|
|
||||||
from,
|
|
||||||
pos - 10000 /* ChunkSize */ - this.spec.unquoted.length
|
|
||||||
)
|
|
||||||
const cursor = stringCursor(this.spec, doc, start, pos)
|
|
||||||
let range = null
|
|
||||||
|
|
||||||
while (!cursor.nextOverlapping().done) {
|
|
||||||
range = cursor.value
|
|
||||||
}
|
|
||||||
|
|
||||||
if (range) {
|
|
||||||
return range
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start === from) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
pos -= 10000 /* ChunkSize */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prevMatch(doc: Text, curFrom: number, curTo: number) {
|
|
||||||
return (
|
|
||||||
this.prevMatchInRange(doc, 0, curFrom) ||
|
|
||||||
this.prevMatchInRange(doc, curTo, doc.length)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectWord = (view: EditorView) => {
|
|
||||||
const { selection } = view.state
|
|
||||||
const newSelection = EditorSelection.create(
|
|
||||||
selection.ranges.map(
|
|
||||||
range =>
|
|
||||||
view.state.wordAt(range.head) || EditorSelection.cursor(range.head)
|
|
||||||
),
|
|
||||||
selection.mainIndex
|
|
||||||
)
|
|
||||||
|
|
||||||
if (newSelection.eq(selection)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
view.dispatch(view.state.update({ selection: newSelection }))
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectPrevOccurrence = (view: EditorView) => {
|
|
||||||
const { state } = view
|
|
||||||
const { ranges } = state.selection
|
const { ranges } = state.selection
|
||||||
|
|
||||||
if (ranges.some(range => range.from === range.to)) {
|
if (ranges.some(range => range.from === range.to)) {
|
||||||
return selectWord(view)
|
return selectWord({ state, dispatch })
|
||||||
}
|
}
|
||||||
|
|
||||||
const searchedText = state.sliceDoc(ranges[0].from, ranges[0].to)
|
const searchedText = state.sliceDoc(ranges[0].from, ranges[0].to)
|
||||||
|
@ -98,23 +28,19 @@ const selectPrevOccurrence = (view: EditorView) => {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = new StringQuery({ unquoted: searchedText })
|
const range = findPrevOccurence(state, searchedText)
|
||||||
const { main } = state.selection
|
|
||||||
const range = query.prevMatch(state.doc, main.from, main.to)
|
|
||||||
|
|
||||||
if (!range) {
|
if (!range) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
view.dispatch({
|
dispatch(
|
||||||
selection: state.selection.addRange(
|
state.update({
|
||||||
EditorSelection.range(range.from, range.to)
|
selection: state.selection.addRange(
|
||||||
),
|
EditorSelection.range(range.from, range.to)
|
||||||
effects: EditorView.scrollIntoView(range.to),
|
),
|
||||||
})
|
effects: EditorView.scrollIntoView(range.to),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectOccurrence = (forward: boolean) => (view: EditorView) =>
|
|
||||||
forward ? selectNextOccurrence(view) : selectPrevOccurrence(view)
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
selectSyntaxRight,
|
selectSyntaxRight,
|
||||||
} from '@codemirror/commands'
|
} from '@codemirror/commands'
|
||||||
import { changeCase, duplicateSelection } from '../commands/ranges'
|
import { changeCase, duplicateSelection } from '../commands/ranges'
|
||||||
import { selectOccurrence } from '../commands/select'
|
import { selectNextOccurrence, selectPrevOccurrence } from '../commands/select'
|
||||||
import { cloneSelectionVertically } from '../commands/cursor'
|
import { cloneSelectionVertically } from '../commands/cursor'
|
||||||
import { dispatchEditorEvent } from './changes/change-manager'
|
import { dispatchEditorEvent } from './changes/change-manager'
|
||||||
import {
|
import {
|
||||||
|
@ -165,12 +165,12 @@ export const shortcuts = Prec.high(
|
||||||
{
|
{
|
||||||
key: 'Ctrl-Alt-ArrowLeft',
|
key: 'Ctrl-Alt-ArrowLeft',
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
run: selectOccurrence(false),
|
run: selectPrevOccurrence,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Ctrl-Alt-ArrowRight',
|
key: 'Ctrl-Alt-ArrowRight',
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
run: selectOccurrence(true),
|
run: selectNextOccurrence,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Mod-Shift-d',
|
key: 'Mod-Shift-d',
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
"@codemirror/lang-markdown": "^6.1.1",
|
"@codemirror/lang-markdown": "^6.1.1",
|
||||||
"@codemirror/language": "^6.6.0",
|
"@codemirror/language": "^6.6.0",
|
||||||
"@codemirror/lint": "^6.2.1",
|
"@codemirror/lint": "^6.2.1",
|
||||||
"@codemirror/search": "github:overleaf/codemirror-search#ea83364b22ad66455fc94babea7d576fa9f76a93",
|
"@codemirror/search": "github:overleaf/codemirror-search#6a09ea7eaad138d810f989753036eabce23cc969",
|
||||||
"@codemirror/state": "^6.2.0",
|
"@codemirror/state": "^6.2.0",
|
||||||
"@codemirror/view": "^6.14.0",
|
"@codemirror/view": "^6.14.0",
|
||||||
"@contentful/rich-text-html-renderer": "^16.0.2",
|
"@contentful/rich-text-html-renderer": "^16.0.2",
|
||||||
|
|
Loading…
Reference in a new issue