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 (
-
-