This commit is contained in:
Jade (Rose) Rowland
2026-01-22 00:20:44 -05:00
parent f610965f43
commit 5cb2214d88
2 changed files with 157 additions and 10 deletions
+58 -3
View File
@@ -24,7 +24,12 @@ import { sliderPlugin, updateSliderWidgets } from './slider.mjs';
import { activateTheme, initTheme, theme } from './themes.mjs';
import { isTooltipEnabled } from './tooltip.mjs';
import { updateWidgets, widgetPlugin } from './widget.mjs';
import { jumpToCharacter } from './labelJump.mjs';
import {
deleteAllInlineBeforeCharacter,
jumpToCharacter,
jumpToNextCharacter,
ToggleCharBeforeChar,
} from './labelJump.mjs';
export { toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment } from '@codemirror/commands';
@@ -74,6 +79,10 @@ export const codemirrorSettings = persistentAtom('codemirror-settings', defaultS
decode: JSON.parse,
});
const ANON_LABEL = '$';
const SOLO_LABEL = 'S';
const MUTE_LABEL = '_';
// https://codemirror.net/docs/guide/
export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, root, mondo }) {
const settings = codemirrorSettings.get();
@@ -122,12 +131,58 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, roo
},
{
key: 'Alt-w',
run: (view) => jumpToCharacter(view, '$', 1),
run: (view) => jumpToNextCharacter(view, ANON_LABEL, 1),
},
{
key: 'Alt-q',
run: (view) => jumpToCharacter(view, '$', -1),
run: (view) => {
return jumpToNextCharacter(view, ANON_LABEL, -1);
},
},
// clear all muted
{
key: `Alt-Ctrl-0`,
run: (view) => {
return deleteAllInlineBeforeCharacter(view, MUTE_LABEL + ANON_LABEL);
},
},
// clear all solod
{
key: `Alt-Shift-0`,
run: (view) => {
return deleteAllInlineBeforeCharacter(view, SOLO_LABEL + ANON_LABEL);
},
},
...Array.from({ length: 9 }).map((_, i) => {
let num = i + 1;
return {
key: `Alt-${num}`,
run: (view) => {
return jumpToCharacter(view, ANON_LABEL, i);
},
};
}),
// handle solo toggles 1-9
...Array.from({ length: 9 }).map((_, i) => {
let num = i + 1;
return {
key: `Alt-Shift-${num}`,
run: (view) => {
return ToggleCharBeforeChar(view, ANON_LABEL, SOLO_LABEL, i);
},
};
}),
// handle mute toggles 1-9
...Array.from({ length: 9 }).map((_, i) => {
let num = i + 1;
return {
key: `Alt-Ctrl-${num}`,
run: (view) => {
return ToggleCharBeforeChar(view, ANON_LABEL, MUTE_LABEL, i);
},
};
}),
/* {
key: 'Ctrl-Shift-.',
run: () => (onPanic ? onPanic() : onStop?.()),
+99 -7
View File
@@ -1,16 +1,42 @@
import { EditorSelection } from '@codemirror/state';
import { SearchCursor } from '@codemirror/search';
import { EditorView } from '@codemirror/view';
export function jumpToCharacter(view, character, direction = 1) {
const { state, dispatch } = view;
const pos = state.selection.main.head;
function getCharacterPositions(state, character) {
const cursor = new SearchCursor(state.doc, character);
let characterPositions = [];
let jumpPos;
const characterPositions = [];
while (!cursor.next().done) {
characterPositions.push(cursor.value.to);
}
return characterPositions;
}
// 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 false;
// }
// 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 false;
// }
// const selection = EditorSelection.cursor(jumpPos - 1);
// }
const COMMENT_STRING = '//';
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 false;
}
@@ -23,9 +49,75 @@ export function jumpToCharacter(view, character, direction = 1) {
if (jumpPos == null) {
return false;
}
const selection = EditorSelection.cursor(jumpPos - 1);
dispatch({
selection: EditorSelection.cursor(jumpPos - 1),
selection,
scrollIntoView: true,
sequential: true,
});
return true;
}
export function jumpToCharacter(view, character, num) {
const { state, dispatch } = view;
const characterPositions = getCharacterPositions(state, character);
const pos = characterPositions.at(num) ?? characterPositions.at(-1);
if (pos == null) {
return false;
}
const selection = EditorSelection.cursor(pos - 1);
dispatch({
selection,
scrollIntoView: true,
});
return 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 + 1) === COMMENT_STRING) {
return;
}
changes.push({
from: line.from,
to: pos - 1,
insert: '',
});
});
dispatch({ changes });
return true;
}
export function ToggleCharBeforeChar(view, character, character2, num) {
const { state, dispatch } = view;
const changes = [];
const characterPositions = getCharacterPositions(state, character);
const labelpos = characterPositions.at(num) ?? characterPositions.at(-1);
const line = state.doc.lineAt(labelpos);
if (state.doc.sliceString(line.from, line.from + 1) === COMMENT_STRING) {
return false;
}
//delete preceeding characters
changes.push({
from: line.from,
to: labelpos - 1,
insert: '',
});
const preceedingLabelPos = labelpos - 2;
if (line.from === labelpos - 1 || state.doc.sliceString(preceedingLabelPos, labelpos - 1) !== character2) {
changes.push({
insert: character2,
from: line.from,
});
}
dispatch({ changes });
return true;
}