2023-04-13 04:21:25 -04:00
|
|
|
import { EditorView } from '@codemirror/view'
|
2023-06-29 04:52:38 -04:00
|
|
|
import { EditorSelection, EditorState, StateCommand } from '@codemirror/state'
|
|
|
|
import { SearchQuery, StringQuery, selectWord } from '@codemirror/search'
|
2023-04-13 04:21:25 -04:00
|
|
|
|
2023-06-29 04:52:38 -04:00
|
|
|
export { selectNextOccurrence } from '@codemirror/search'
|
2023-04-13 04:21:25 -04:00
|
|
|
|
2023-06-29 04:52:38 -04:00
|
|
|
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)
|
2023-04-13 04:21:25 -04:00
|
|
|
}
|
|
|
|
|
2023-06-29 04:52:38 -04:00
|
|
|
export const selectPrevOccurrence: StateCommand = ({ state, dispatch }) => {
|
2023-04-13 04:21:25 -04:00
|
|
|
const { ranges } = state.selection
|
|
|
|
|
|
|
|
if (ranges.some(range => range.from === range.to)) {
|
2023-06-29 04:52:38 -04:00
|
|
|
return selectWord({ state, dispatch })
|
2023-04-13 04:21:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const searchedText = state.sliceDoc(ranges[0].from, ranges[0].to)
|
|
|
|
|
|
|
|
if (
|
|
|
|
state.selection.ranges.some(
|
|
|
|
range => state.sliceDoc(range.from, range.to) !== searchedText
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-06-29 04:52:38 -04:00
|
|
|
const range = findPrevOccurence(state, searchedText)
|
2023-04-13 04:21:25 -04:00
|
|
|
if (!range) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-06-29 04:52:38 -04:00
|
|
|
dispatch(
|
|
|
|
state.update({
|
|
|
|
selection: state.selection.addRange(
|
|
|
|
EditorSelection.range(range.from, range.to)
|
|
|
|
),
|
|
|
|
effects: EditorView.scrollIntoView(range.to),
|
|
|
|
})
|
|
|
|
)
|
2023-04-13 04:21:25 -04:00
|
|
|
|
|
|
|
return true
|
|
|
|
}
|