From ceb3aa0627b78b6a7ac33eff8d6440a1e006eaff Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 19 Feb 2023 13:49:55 +0100 Subject: [PATCH] add emacs mode + fontSize slider --- packages/react/package.json | 1 + packages/react/src/components/CodeMirror6.jsx | 19 ++- packages/react/src/components/style.css | 1 - pnpm-lock.yaml | 16 +++ website/public/store.mjs | 10 +- website/src/repl/Footer.jsx | 125 ++++++++++++++---- website/src/repl/Repl.jsx | 5 +- 7 files changed, 143 insertions(+), 34 deletions(-) diff --git a/packages/react/package.json b/packages/react/package.json index dfc72b46..445910f8 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -37,6 +37,7 @@ "@codemirror/state": "^6.2.0", "@codemirror/view": "^6.7.3", "@lezer/highlight": "^1.1.3", + "@replit/codemirror-emacs": "^6.0.0", "@replit/codemirror-vim": "^6.0.6", "@strudel.cycles/core": "workspace:*", "@strudel.cycles/transpiler": "workspace:*", diff --git a/packages/react/src/components/CodeMirror6.jsx b/packages/react/src/components/CodeMirror6.jsx index c04f422a..5bc8cef5 100644 --- a/packages/react/src/components/CodeMirror6.jsx +++ b/packages/react/src/components/CodeMirror6.jsx @@ -9,6 +9,7 @@ import { useCallback } from 'react'; import { autocompletion } from '@codemirror/autocomplete'; import { strudelAutocomplete } from './Autocomplete'; import { vim } from '@replit/codemirror-vim'; +import { emacs } from '@replit/codemirror-emacs'; export const setFlash = StateEffect.define(); const flashField = StateField.define({ @@ -98,7 +99,8 @@ export default function CodeMirror({ onViewChanged, onSelectionChange, theme, - vimMode, + keybindings, + fontSize = 18, options, editorDidMount, }) { @@ -122,9 +124,18 @@ export default function CodeMirror({ }, [onSelectionChange], ); - const extensions = useMemo(() => [...staticExtensions, ...(vimMode ? [vim()] : [])], [vimMode]); + const extensions = useMemo(() => { + let bindings = { + vim, + emacs, + }; + if (bindings[keybindings]) { + return [...staticExtensions, bindings[keybindings]()]; + } + return staticExtensions; + }, [keybindings]); return ( - <> +
<_CodeMirror value={value} theme={theme || strudelTheme} @@ -133,7 +144,7 @@ export default function CodeMirror({ onUpdate={handleOnUpdate} extensions={extensions} /> - +
); } diff --git a/packages/react/src/components/style.css b/packages/react/src/components/style.css index f2db01cc..8983884e 100644 --- a/packages/react/src/components/style.css +++ b/packages/react/src/components/style.css @@ -2,7 +2,6 @@ background-color: transparent !important; height: 100%; z-index: 11; - font-size: 18px; } .cm-theme { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b8e36d4..d413286a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -164,6 +164,7 @@ importers: '@codemirror/state': ^6.2.0 '@codemirror/view': ^6.7.3 '@lezer/highlight': ^1.1.3 + '@replit/codemirror-emacs': ^6.0.0 '@replit/codemirror-vim': ^6.0.6 '@strudel.cycles/core': workspace:* '@strudel.cycles/transpiler': workspace:* @@ -186,6 +187,7 @@ importers: '@codemirror/state': 6.2.0 '@codemirror/view': 6.7.3 '@lezer/highlight': 1.1.3 + '@replit/codemirror-emacs': 6.0.0_cgfc5aojxuwjajwhkrgidrzxoa '@replit/codemirror-vim': 6.0.6_a4vbhepr4qhxm5cldqd4jpyase '@strudel.cycles/core': link:../core '@strudel.cycles/transpiler': link:../transpiler @@ -3404,6 +3406,20 @@ packages: tsm: 2.3.0 dev: false + /@replit/codemirror-emacs/6.0.0_cgfc5aojxuwjajwhkrgidrzxoa: + resolution: {integrity: sha512-zxSDg3UKm7811hjqNtgvK9G0IBtCWf82Idb9nZQo0ldmGl4d9SV7oCSuXQ58NmOG4AV7coD7kgFSZhEqHhyQhA==} + peerDependencies: + '@codemirror/autocomplete': ^6.0.2 + '@codemirror/commands': ^6.0.0 + '@codemirror/search': ^6.0.0 + '@codemirror/state': ^6.0.1 + '@codemirror/view': ^6.0.2 + dependencies: + '@codemirror/autocomplete': 6.4.0_a4vbhepr4qhxm5cldqd4jpyase + '@codemirror/state': 6.2.0 + '@codemirror/view': 6.7.3 + dev: false + /@replit/codemirror-vim/6.0.6_a4vbhepr4qhxm5cldqd4jpyase: resolution: {integrity: sha512-/Lc+5AmV+T5pTm5P+rWpL+gseNHNye7xaUWpULczHai5ZLVg/ZE3+MBwK3Ai+/SmZKR/mK2YuXgNKnTGToEGYg==} peerDependencies: diff --git a/website/public/store.mjs b/website/public/store.mjs index 1efcd91b..19166810 100644 --- a/website/public/store.mjs +++ b/website/public/store.mjs @@ -1,7 +1,15 @@ export const storeKey = 'strudel-settings'; +const defaults = { + keybindings: 'codemirror', + theme: 'strudelTheme', + fontSize: 18, +}; export function get(prop) { - const state = JSON.parse(localStorage.getItem(storeKey)); + let state = { + ...defaults, + ...JSON.parse(localStorage.getItem(storeKey) || '{}'), + }; if (!prop) { return state; } diff --git a/website/src/repl/Footer.jsx b/website/src/repl/Footer.jsx index 9b11b715..bab35400 100644 --- a/website/src/repl/Footer.jsx +++ b/website/src/repl/Footer.jsx @@ -206,34 +206,107 @@ function SamplesTab() { ); } -function SettingsTab() { - const { state, update } = useStore(); - const { theme, vim } = state; + +function ButtonGroup({ value, onChange, items }) { return ( -
- - + {label} + + ))} +
+ ); +} + +function SelectInput({ value, options, onChange }) { + return ( + + ); +} + +function NumberSlider({ value, onChange, step = 1, ...rest }) { + return ( +
+ onChange(Number(e.target.value))} + {...rest} + /> + onChange(Number(e.target.value))} + /> +
+ ); +} + +function FormItem({ label, children }) { + return ( +
+ + {children} +
+ ); +} + +const themeOptions = Object.fromEntries(Object.keys(themes).map((k) => [k, k])); + +function SettingsTab() { + const { state, update } = useStore(); + const { theme, keybindings, fontSize } = state; + return ( +
+
+ + update((current) => ({ ...current, theme }))} + /> + + + update((current) => ({ ...current, fontSize }))} + min={10} + max={40} + step={2} + /> + +
+ + update((current) => ({ ...current, keybindings }))} + items={{ codemirror: 'Codemirror', vim: 'Vim', emacs: 'Emacs' }} + > +
); } diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx index 3b2f306c..f91310d6 100644 --- a/website/src/repl/Repl.jsx +++ b/website/src/repl/Repl.jsx @@ -121,7 +121,7 @@ export function Repl({ embedded = false }) { const { theme, themeSettings } = useTheme(); const { - state: { vim }, + state: { keybindings, fontSize }, } = useStore(); const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } = @@ -282,7 +282,8 @@ export function Repl({ embedded = false }) {