From ad7e3013942c6960adee8bc9bdfa5bd3525a5f85 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 30 Jul 2026 12:13:47 +0100 Subject: [PATCH] repeat charactar --- packages/codemirror/codemirror.mjs | 3 +- packages/codemirror/repeatcharacter.mjs | 55 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 packages/codemirror/repeatcharacter.mjs diff --git a/packages/codemirror/codemirror.mjs b/packages/codemirror/codemirror.mjs index d84e8b33e..f3d37de6e 100644 --- a/packages/codemirror/codemirror.mjs +++ b/packages/codemirror/codemirror.mjs @@ -11,6 +11,7 @@ import { keymap, lineNumbers, } from '@codemirror/view'; +import {repeatCharKeymap} from './repeatcharacter.mjs'; import { persistentAtom } from '@nanostores/persistent'; import { logger, registerControl, repl } from '@strudel/core'; import { cleanupDraw, cleanupDrawContext, Drawer } from '@strudel/draw'; @@ -111,6 +112,7 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, roo syntaxHighlighting(defaultHighlightStyle), EditorView.updateListener.of((v) => onChange(v)), drawSelection({ cursorBlinkRate: 0 }), + repeatCharKeymap, Prec.highest( keymap.of([ { @@ -215,7 +217,6 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, roo }, }; }), - /* { key: 'Ctrl-Shift-.', run: () => (onPanic ? onPanic() : onStop?.()), diff --git a/packages/codemirror/repeatcharacter.mjs b/packages/codemirror/repeatcharacter.mjs new file mode 100644 index 000000000..527e71a40 --- /dev/null +++ b/packages/codemirror/repeatcharacter.mjs @@ -0,0 +1,55 @@ +import { Compartment } from "@codemirror/state"; +import { keymap } from "@codemirror/view"; + +const repeatMode = new Compartment(); + +function repeatPreviousChar(times) { + return ({ state, dispatch }) => { + const { from, empty } = state.selection.main; + if (!empty || from === 0) return false; + + const prevChar = state.doc.sliceString(from - 1, from); + const text = Array(times).fill(prevChar).join(" "); + + dispatch(state.update({ + changes: { + from, + insert: " " + text + } + })); + + return true; + }; +} + +function exitRepeatMode(view) { + view.dispatch({ + effects: repeatMode.reconfigure([]) + }); +} + +const digitBindings = Array.from({ length: 9 }, (_, i) => ({ + key: String(i + 1), + run(view) { + repeatPreviousChar(i + 1)(view); + exitRepeatMode(view); + return true; + } +})); + +export const repeatCharKeymap = [ + + repeatMode.of([]), + + keymap.of([ + { + key: "Alt-r", + run(view) { + view.dispatch({ + effects: repeatMode.reconfigure(keymap.of(digitBindings)) + }); + return true; + } + } + ]) +]; \ No newline at end of file