mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-13 14:26:58 -04:00
154 lines
3.8 KiB
JavaScript
154 lines
3.8 KiB
JavaScript
import { EditorSelection } from '@codemirror/state';
|
|
import { SearchCursor } from '@codemirror/search';
|
|
import { EditorView } from '@codemirror/view';
|
|
import { syntaxTree } from '@codemirror/language';
|
|
|
|
/**
|
|
* gets all of the positions of a character in a document, excluding commented out lines
|
|
* @param { EditorState} state
|
|
* @param {String} character
|
|
* @returns {number[]}
|
|
*/
|
|
function getCharacterPositions(state, character) {
|
|
const cursor = new SearchCursor(state.doc, character);
|
|
|
|
const characterPositions = [];
|
|
while (!cursor.next().done) {
|
|
|
|
const linestartpos = state.doc.lineAt(cursor.value.to).from
|
|
if (!isLineCommentedOut(state, linestartpos)) {
|
|
|
|
characterPositions.push(cursor.value.to);
|
|
}
|
|
}
|
|
return characterPositions;
|
|
}
|
|
|
|
function isLineCommentedOut(state, pos) {
|
|
|
|
const line = state.doc.lineAt(pos);
|
|
// remove white space
|
|
pos = line.from + line.text.search(/\S/)
|
|
|
|
const tree = syntaxTree(state);
|
|
const node = tree.resolveInner(pos, 1)
|
|
return node.name.includes("Comment")
|
|
}
|
|
|
|
/**
|
|
* jump to the next character in a document
|
|
* @param {EditorView} view
|
|
* @param {String} character
|
|
* @param {number} direction 0 or 1
|
|
* @returns {boolean}
|
|
*/
|
|
export function jumpToNextCharacter(view, character, direction = 1) {
|
|
const { state, dispatch } = view;
|
|
const pos = state.selection.main.head;
|
|
let jumpPos;
|
|
const characterPositions = getCharacterPositions(state, character);
|
|
if (!characterPositions.length) {
|
|
return true;
|
|
}
|
|
if (direction > 0) {
|
|
jumpPos = characterPositions.find((x) => x > pos + 1) ?? characterPositions.at(0); // Loop back around for convenience
|
|
} else {
|
|
jumpPos = characterPositions.reverse().find((x) => x < pos + 1) ?? characterPositions.at(0);
|
|
}
|
|
|
|
if (jumpPos == null) {
|
|
return true;
|
|
}
|
|
const selection = EditorSelection.cursor(jumpPos - 1);
|
|
dispatch({
|
|
selection,
|
|
effects: EditorView.scrollIntoView(
|
|
selection.head,
|
|
{ y: "start" }
|
|
)
|
|
});
|
|
return true;
|
|
}
|
|
/**
|
|
*
|
|
* @param {EditorView} view
|
|
* @param {String} character
|
|
* @param {number} index the instance of the character
|
|
* @returns
|
|
*/
|
|
export function jumpToCharacter(view, character, index) {
|
|
const { state, dispatch } = view;
|
|
const characterPositions = getCharacterPositions(state, character);
|
|
const pos = characterPositions.at(index) ?? characterPositions.at(-1);
|
|
if (pos == null) {
|
|
return true;
|
|
}
|
|
|
|
const selection = EditorSelection.cursor(pos - 1);
|
|
dispatch({
|
|
selection,
|
|
effects: EditorView.scrollIntoView(
|
|
selection.head,
|
|
{ y: "start" }
|
|
)
|
|
});
|
|
return true;
|
|
}
|
|
/**
|
|
*
|
|
* @param {EditorView} view
|
|
* @param {String} character
|
|
* @returns {true}
|
|
*/
|
|
export function deleteAllInlineBeforeCharacter(view, character) {
|
|
const { state, dispatch } = view;
|
|
const characterPositions = getCharacterPositions(state, character);
|
|
|
|
const changes = [];
|
|
characterPositions.forEach((pos) => {
|
|
const line = state.doc.lineAt(pos);
|
|
if (state.doc.sliceString(line.from, line.from + 2) === COMMENT_STRING) {
|
|
return;
|
|
}
|
|
changes.push({
|
|
from: line.from,
|
|
to: pos - 1,
|
|
insert: '',
|
|
});
|
|
});
|
|
dispatch({ changes });
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {EditorView} view
|
|
* @param {String} character
|
|
* @param {String} character2
|
|
* @param {number} index
|
|
* @returns
|
|
*/
|
|
export function InsertCharBeforeChar(view, character, character2, index) {
|
|
const { state, dispatch } = view;
|
|
|
|
const changes = [];
|
|
const characterPositions = getCharacterPositions(state, character);
|
|
const labelpos = characterPositions.at(index) ?? characterPositions.at(-1);
|
|
const line = state.doc.lineAt(labelpos);
|
|
|
|
//delete preceeding characters
|
|
changes.push({
|
|
from: line.from,
|
|
to: labelpos - 1,
|
|
insert: '',
|
|
});
|
|
|
|
changes.push({
|
|
insert: character2,
|
|
from: line.from,
|
|
});
|
|
|
|
dispatch({ changes });
|
|
return true;
|
|
}
|