add /vanilla route to website
+ disable autocomplete for now
This commit is contained in:
parent
f6f5ee0375
commit
60e559a910
4 changed files with 337 additions and 2 deletions
|
|
@ -6,7 +6,7 @@ import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language'
|
||||||
import { Compartment, EditorState } from '@codemirror/state';
|
import { Compartment, EditorState } from '@codemirror/state';
|
||||||
import { EditorView, highlightActiveLineGutter, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view';
|
import { EditorView, highlightActiveLineGutter, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view';
|
||||||
import { Pattern, Drawer, repl, cleanupDraw } from '@strudel.cycles/core';
|
import { Pattern, Drawer, repl, cleanupDraw } from '@strudel.cycles/core';
|
||||||
import { isAutoCompletionEnabled } from './Autocomplete';
|
// import { isAutoCompletionEnabled } from './Autocomplete';
|
||||||
import { flash, isFlashEnabled } from './flash.mjs';
|
import { flash, isFlashEnabled } from './flash.mjs';
|
||||||
import { highlightMiniLocations, isPatternHighlightingEnabled, updateMiniLocations } from './highlight.mjs';
|
import { highlightMiniLocations, isPatternHighlightingEnabled, updateMiniLocations } from './highlight.mjs';
|
||||||
import { keybindings } from './keybindings.mjs';
|
import { keybindings } from './keybindings.mjs';
|
||||||
|
|
@ -17,7 +17,7 @@ const extensions = {
|
||||||
isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []),
|
isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []),
|
||||||
isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []),
|
isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []),
|
||||||
theme,
|
theme,
|
||||||
isAutoCompletionEnabled,
|
// isAutoCompletionEnabled,
|
||||||
isPatternHighlightingEnabled,
|
isPatternHighlightingEnabled,
|
||||||
isActiveLineHighlighted: (on) => (on ? [highlightActiveLine(), highlightActiveLineGutter()] : []),
|
isActiveLineHighlighted: (on) => (on ? [highlightActiveLine(), highlightActiveLineGutter()] : []),
|
||||||
isFlashEnabled,
|
isFlashEnabled,
|
||||||
|
|
|
||||||
98
website/src/pages/vanilla/index.astro
Normal file
98
website/src/pages/vanilla/index.astro
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
---
|
||||||
|
import HeadCommon from '../../components/HeadCommon.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
<head>
|
||||||
|
<HeadCommon />
|
||||||
|
<title>Strudel Vanilla REPL</title>
|
||||||
|
</head>
|
||||||
|
<body class="h-app-height bg-background">
|
||||||
|
<div class="settings">
|
||||||
|
<form name="settings" class="flex flex-col space-y-1 bg-[#00000080]">
|
||||||
|
<label
|
||||||
|
>theme
|
||||||
|
<select name="theme">
|
||||||
|
<option>strudelTheme</option>
|
||||||
|
<option>bluescreen</option>
|
||||||
|
<option>blackscreen</option>
|
||||||
|
<option>whitescreen</option>
|
||||||
|
<option>teletext</option>
|
||||||
|
<option>algoboy</option>
|
||||||
|
<option>terminal</option>
|
||||||
|
<option>abcdef</option>
|
||||||
|
<option>androidstudio</option>
|
||||||
|
<option>atomone</option>
|
||||||
|
<option>aura</option>
|
||||||
|
<option>bespin</option>
|
||||||
|
<option>darcula</option>
|
||||||
|
<option>dracula</option>
|
||||||
|
<option>duotoneDark</option>
|
||||||
|
<option>eclipse</option>
|
||||||
|
<option>githubDark</option>
|
||||||
|
<option>gruvboxDark</option>
|
||||||
|
<option>materialDark</option>
|
||||||
|
<option>nord</option>
|
||||||
|
<option>okaidia</option>
|
||||||
|
<option>solarizedDark</option>
|
||||||
|
<option>sublime</option>
|
||||||
|
<option>tokyoNight</option>
|
||||||
|
<option>tokyoNightStorm</option>
|
||||||
|
<option>vscodeDark</option>
|
||||||
|
<option>xcodeDark</option>
|
||||||
|
<option>bbedit</option>
|
||||||
|
<option>duotoneLight</option>
|
||||||
|
<option>githubLight</option>
|
||||||
|
<option>gruvboxLight</option>
|
||||||
|
<option>materialLight</option>
|
||||||
|
<option>noctisLilac</option>
|
||||||
|
<option>solarizedLight</option>
|
||||||
|
<option>tokyoNightDay</option>
|
||||||
|
<option>xcodeLight</option>
|
||||||
|
</select> </label
|
||||||
|
><br />
|
||||||
|
<label
|
||||||
|
>keybindings
|
||||||
|
<select name="keybindings">
|
||||||
|
<option>codemirror</option>
|
||||||
|
<option>vim</option>
|
||||||
|
<option>emacs</option>
|
||||||
|
<option>vscode</option>
|
||||||
|
</select> </label
|
||||||
|
><br />
|
||||||
|
<!-- <label>fontFamily
|
||||||
|
<select name="fontFamily">
|
||||||
|
<option>monospace</option>
|
||||||
|
<option>helvetica</option>
|
||||||
|
<option value="monospace">monospace</option>
|
||||||
|
<option value="BigBlueTerminal">BigBlueTerminal</option>
|
||||||
|
<option value="x3270">x3270</option>
|
||||||
|
<option value="PressStart">PressStart2P</option>
|
||||||
|
<option value="galactico">galactico</option>
|
||||||
|
<option value="we-come-in-peace">we-come-in-peace</option>
|
||||||
|
<option value="FiraCode">FiraCode</option>
|
||||||
|
<option value="FiraCode-SemiBold">FiraCode-SemiBold</option>
|
||||||
|
<option value="teletext">teletext</option>
|
||||||
|
<option value="mode7">mode7</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<br /> -->
|
||||||
|
<label>fontSize <input type="number" name="fontSize" /></label>
|
||||||
|
<br />
|
||||||
|
<label><input type="checkbox" name="isLineNumbersDisplayed" />isLineNumbersDisplayed</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="checkbox" name="isActiveLineHighlighted" />isActiveLineHighlighted</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="checkbox" name="isPatternHighlightingEnabled" />isPatternHighlightingEnabled</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="checkbox" name="isFlashEnabled" />isFlashEnabled</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="checkbox" name="isLineWrappingEnabled" />isLineWrappingEnabled</label>
|
||||||
|
<!-- <label><input type="checkbox" name="isAutoCompletionEnabled" />isAutoCompletionEnabled</label> -->
|
||||||
|
<!-- <label><input type="checkbox" name="isTooltipEnabled" />isTooltipEnabled</label> -->
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="code"></div>
|
||||||
|
<script src="../../repl/vanilla/vanilla.mjs"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
38
website/src/repl/vanilla/vanilla.css
Normal file
38
website/src/repl/vanilla/vanilla.css
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
:root {
|
||||||
|
--foreground: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
input {
|
||||||
|
font-family: monospace;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
select {
|
||||||
|
background-color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#code,
|
||||||
|
.cm-editor,
|
||||||
|
.cm-scroller {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex-col;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings > form > * + * {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
199
website/src/repl/vanilla/vanilla.mjs
Normal file
199
website/src/repl/vanilla/vanilla.mjs
Normal file
|
|
@ -0,0 +1,199 @@
|
||||||
|
import { logger, getDrawContext, silence, controls, evalScope, hash2code, code2hash } from '@strudel.cycles/core';
|
||||||
|
import { StrudelMirror } from '@strudel/codemirror';
|
||||||
|
import { transpiler } from '@strudel.cycles/transpiler';
|
||||||
|
import {
|
||||||
|
getAudioContext,
|
||||||
|
webaudioOutput,
|
||||||
|
registerSynthSounds,
|
||||||
|
registerZZFXSounds,
|
||||||
|
samples,
|
||||||
|
} from '@strudel.cycles/webaudio';
|
||||||
|
import './vanilla.css';
|
||||||
|
|
||||||
|
let editor;
|
||||||
|
const initialSettings = {
|
||||||
|
keybindings: 'codemirror',
|
||||||
|
isLineNumbersDisplayed: true,
|
||||||
|
isActiveLineHighlighted: true,
|
||||||
|
isAutoCompletionEnabled: false,
|
||||||
|
isPatternHighlightingEnabled: true,
|
||||||
|
isFlashEnabled: true,
|
||||||
|
isTooltipEnabled: false,
|
||||||
|
isLineWrappingEnabled: false,
|
||||||
|
theme: 'teletext',
|
||||||
|
fontFamily: 'monospace',
|
||||||
|
fontSize: 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const container = document.getElementById('code');
|
||||||
|
if (!container) {
|
||||||
|
console.warn('could not init: no container found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawContext = getDrawContext();
|
||||||
|
const drawTime = [-2, 2];
|
||||||
|
editor = new StrudelMirror({
|
||||||
|
defaultOutput: webaudioOutput,
|
||||||
|
getTime: () => getAudioContext().currentTime,
|
||||||
|
transpiler,
|
||||||
|
root: container,
|
||||||
|
initialCode: '// LOADING',
|
||||||
|
pattern: silence,
|
||||||
|
settings: initialSettings,
|
||||||
|
drawTime,
|
||||||
|
onDraw: (haps, time, frame, painters) => {
|
||||||
|
painters.length && drawContext.clearRect(0, 0, drawContext.canvas.width * 2, drawContext.canvas.height * 2);
|
||||||
|
painters?.forEach((painter) => {
|
||||||
|
// ctx time haps drawTime paintOptions
|
||||||
|
painter(drawContext, time, haps, drawTime, { clear: false });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
prebake: async () => {
|
||||||
|
// populate scope / lazy load modules
|
||||||
|
const modulesLoading = evalScope(
|
||||||
|
import('@strudel.cycles/core'),
|
||||||
|
import('@strudel.cycles/tonal'),
|
||||||
|
import('@strudel.cycles/mini'),
|
||||||
|
// import('@strudel.cycles/xen'),
|
||||||
|
import('@strudel.cycles/webaudio'),
|
||||||
|
import('@strudel/codemirror'),
|
||||||
|
/* import('@strudel/hydra'), */
|
||||||
|
// import('@strudel.cycles/serial'),
|
||||||
|
/* import('@strudel.cycles/soundfonts'), */
|
||||||
|
// import('@strudel.cycles/csound'),
|
||||||
|
/* import('@strudel.cycles/midi'), */
|
||||||
|
// import('@strudel.cycles/osc'),
|
||||||
|
controls, // sadly, this cannot be exported from core directly (yet)
|
||||||
|
);
|
||||||
|
// load samples
|
||||||
|
const ds = 'https://raw.githubusercontent.com/felixroos/dough-samples/main/';
|
||||||
|
await Promise.all([
|
||||||
|
modulesLoading,
|
||||||
|
registerSynthSounds(),
|
||||||
|
registerZZFXSounds(),
|
||||||
|
samples(`${ds}/tidal-drum-machines.json`),
|
||||||
|
samples(`${ds}/piano.json`),
|
||||||
|
samples(`${ds}/Dirt-Samples.json`),
|
||||||
|
samples(`${ds}/EmuSP12.json`),
|
||||||
|
samples(`${ds}/vcsl.json`),
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
afterEval: ({ code }) => {
|
||||||
|
window.location.hash = '#' + code2hash(code);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// init settings
|
||||||
|
editor.updateSettings(initialSettings);
|
||||||
|
|
||||||
|
logger(`Welcome to Strudel! Click into the editor and then hit ctrl+enter to run the code!`, 'highlight');
|
||||||
|
const codeParam = window.location.href.split('#')[1] || '';
|
||||||
|
|
||||||
|
const initialCode = codeParam
|
||||||
|
? hash2code(codeParam)
|
||||||
|
: `// @date 23-11-30
|
||||||
|
// "teigrührgerät" @by froos
|
||||||
|
|
||||||
|
stack(
|
||||||
|
stack(
|
||||||
|
s("bd(<3!3 5>,6)/2").bank('RolandTR707')
|
||||||
|
,
|
||||||
|
s("~ sd:<0 1>").bank('RolandTR707').room("<0 .5>")
|
||||||
|
.lastOf(8, x=>x.segment("12").end(.2).gain(isaw))
|
||||||
|
,
|
||||||
|
s("[tb ~ tb]").bank('RolandTR707')
|
||||||
|
.clip(0).release(.08).room(.2)
|
||||||
|
).off(-1/6, x=>x.speed(.7).gain(.2).degrade())
|
||||||
|
,
|
||||||
|
stack(
|
||||||
|
note("<g1(<3 4>,6) ~!2 [f1?]*2>")
|
||||||
|
.s("sawtooth").lpf(perlin.range(400,1000))
|
||||||
|
.lpa(.1).lpenv(-3).room(.2)
|
||||||
|
.lpq(8).noise(.2)
|
||||||
|
.add(note("0,.1"))
|
||||||
|
,
|
||||||
|
chord("<~ Gm9 ~!2>")
|
||||||
|
.dict('ireal').voicing()
|
||||||
|
.s("sawtooth").vib("2:.1")
|
||||||
|
.lpf(1000).lpa(.1).lpenv(-4)
|
||||||
|
.room(.5)
|
||||||
|
,
|
||||||
|
n(run(3)).chord("<Gm9 Gm11>/8")
|
||||||
|
.dict('ireal-ext')
|
||||||
|
.off(1/2, add(n(4)))
|
||||||
|
.voicing()
|
||||||
|
.clip(.1).release(.05)
|
||||||
|
.s("sine").jux(rev)
|
||||||
|
.sometimesBy(sine.slow(16), add(note(12)))
|
||||||
|
.room(.75)
|
||||||
|
.lpf(sine.range(200,2000).slow(16))
|
||||||
|
.gain(saw.slow(4).div(2))
|
||||||
|
).add(note(perlin.range(0,.5)))
|
||||||
|
)`;
|
||||||
|
|
||||||
|
editor.setCode(initialCode); // simpler alternative to above init
|
||||||
|
|
||||||
|
// settingsMap.listen((settings, key) => editor.changeSetting(key, settings[key]));
|
||||||
|
onEvent('strudel-toggle-play', () => editor.toggle());
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
|
|
||||||
|
function onEvent(key, callback) {
|
||||||
|
const listener = (e) => {
|
||||||
|
if (e.data === key) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('message', listener);
|
||||||
|
return () => window.removeEventListener('message', listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// settings form
|
||||||
|
function getInput(form, name) {
|
||||||
|
return form.querySelector(`input[name=${name}]`) || form.querySelector(`select[name=${name}]`);
|
||||||
|
}
|
||||||
|
function getFormValues(form, initial) {
|
||||||
|
const entries = Object.entries(initial).map(([key, initialValue]) => {
|
||||||
|
const input = getInput(form, key);
|
||||||
|
if (!input) {
|
||||||
|
return [key, initialValue]; // fallback
|
||||||
|
}
|
||||||
|
if (input.type === 'checkbox') {
|
||||||
|
return [key, input.checked];
|
||||||
|
}
|
||||||
|
if (input.type === 'number') {
|
||||||
|
return [key, Number(input.value)];
|
||||||
|
}
|
||||||
|
if (input.tagName === 'SELECT') {
|
||||||
|
return [key, input.value];
|
||||||
|
}
|
||||||
|
return [key, input.value];
|
||||||
|
});
|
||||||
|
return Object.fromEntries(entries);
|
||||||
|
}
|
||||||
|
function setFormValues(form, values) {
|
||||||
|
Object.entries(values).forEach(([key, value]) => {
|
||||||
|
const input = getInput(form, key);
|
||||||
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (input.type === 'checkbox') {
|
||||||
|
input.checked = !!value;
|
||||||
|
} else if (input.type === 'number') {
|
||||||
|
input.value = value;
|
||||||
|
} else if (input.tagName) {
|
||||||
|
input.value = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const form = document.querySelector('form[name=settings]');
|
||||||
|
setFormValues(form, initialSettings);
|
||||||
|
form.addEventListener('change', () => {
|
||||||
|
const values = getFormValues(form, initialSettings);
|
||||||
|
// console.log('values', values);
|
||||||
|
editor.updateSettings(values);
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue