diff --git a/packages/codemirror/codemirror.mjs b/packages/codemirror/codemirror.mjs index 0eec08d1..4470173b 100644 --- a/packages/codemirror/codemirror.mjs +++ b/packages/codemirror/codemirror.mjs @@ -2,7 +2,7 @@ import { closeBrackets } from '@codemirror/autocomplete'; // import { search, highlightSelectionMatches } from '@codemirror/search'; import { history } from '@codemirror/commands'; import { javascript } from '@codemirror/lang-javascript'; -import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language'; +import { defaultHighlightStyle, syntaxHighlighting, bracketMatching } from '@codemirror/language'; import { Compartment, EditorState, Prec } from '@codemirror/state'; import { EditorView, @@ -24,6 +24,7 @@ import { persistentAtom } from '@nanostores/persistent'; const extensions = { isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []), + isBracketMatchingEnabled: (on) => (on ? bracketMatching({ brackets: '()[]{}<>' }) : []), isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []), theme, isAutoCompletionEnabled, @@ -37,6 +38,7 @@ const compartments = Object.fromEntries(Object.keys(extensions).map((key) => [ke export const defaultSettings = { keybindings: 'codemirror', + isBracketMatchingEnabled: false, isLineNumbersDisplayed: true, isActiveLineHighlighted: false, isAutoCompletionEnabled: false, @@ -290,6 +292,9 @@ export class StrudelMirror { setLineWrappingEnabled(enabled) { this.reconfigureExtension('isLineWrappingEnabled', enabled); } + setBracketMatchingEnabled(enabled) { + this.reconfigureExtension('isBracketMatchingEnabled', enabled); + } setLineNumbersDisplayed(enabled) { this.reconfigureExtension('isLineNumbersDisplayed', enabled); } diff --git a/website/src/repl/Repl.css b/website/src/repl/Repl.css index 2d97d8a2..3e13ff5a 100644 --- a/website/src/repl/Repl.css +++ b/website/src/repl/Repl.css @@ -64,3 +64,8 @@ #code .cm-focused { outline: none; } + +#code .cm-matchingBracket { + text-decoration: underline 0.18rem; + text-underline-offset: 0.22rem; +} diff --git a/website/src/repl/panel/SettingsTab.jsx b/website/src/repl/panel/SettingsTab.jsx index dc221300..7b968ad5 100644 --- a/website/src/repl/panel/SettingsTab.jsx +++ b/website/src/repl/panel/SettingsTab.jsx @@ -77,6 +77,7 @@ export function SettingsTab({ started }) { const { theme, keybindings, + isBracketMatchingEnabled, isLineNumbersDisplayed, isPatternHighlightingEnabled, isActiveLineHighlighted, @@ -137,6 +138,11 @@ export function SettingsTab({ started }) { > + settingsMap.setKey('isBracketMatchingEnabled', cbEvent.target.checked)} + value={isBracketMatchingEnabled} + /> settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)} diff --git a/website/src/settings.mjs b/website/src/settings.mjs index 27888800..34aca701 100644 --- a/website/src/settings.mjs +++ b/website/src/settings.mjs @@ -7,6 +7,7 @@ export const defaultAudioDeviceName = 'System Standard'; export const defaultSettings = { activeFooter: 'intro', keybindings: 'codemirror', + isBracketMatchingEnabled: true, isLineNumbersDisplayed: true, isActiveLineHighlighted: true, isAutoCompletionEnabled: false, @@ -40,6 +41,7 @@ export function useSettings() { return { ...state, isZen: [true, 'true'].includes(state.isZen) ? true : false, + isBracketMatchingEnabled: [true, 'true'].includes(state.isBracketMatchingEnabled) ? true : false, isLineNumbersDisplayed: [true, 'true'].includes(state.isLineNumbersDisplayed) ? true : false, isActiveLineHighlighted: [true, 'true'].includes(state.isActiveLineHighlighted) ? true : false, isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,