mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-23 21:47:16 -04:00
Merge branch 'main' into claviature-take2
This commit is contained in:
@@ -127,3 +127,6 @@ fabric.properties
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
# END JetBrains -> BEGIN JetBrains
|
||||
|
||||
samples/*
|
||||
!samples/README.md
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"format-check": "prettier --check .",
|
||||
"report-undocumented": "npm run jsdoc-json && node jsdoc/undocumented.mjs > undocumented.json",
|
||||
"check": "npm run format-check && npm run lint && npm run test",
|
||||
"sampler": "cd samples && node ../packages/sampler/sample-server.mjs",
|
||||
"iclc": "cd paper && pandoc --template=pandoc/iclc.html --citeproc --number-sections iclc2023.md -o iclc2023.html && pandoc --template=pandoc/iclc.latex --citeproc --number-sections iclc2023.md -o iclc2023.pdf"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@@ -27,6 +27,7 @@ import { persistentAtom } from '@nanostores/persistent';
|
||||
const extensions = {
|
||||
isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []),
|
||||
isBracketMatchingEnabled: (on) => (on ? bracketMatching({ brackets: '()[]{}<>' }) : []),
|
||||
isBracketClosingEnabled: (on) => (on ? closeBrackets() : []),
|
||||
isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []),
|
||||
theme,
|
||||
isAutoCompletionEnabled,
|
||||
@@ -41,6 +42,7 @@ const compartments = Object.fromEntries(Object.keys(extensions).map((key) => [ke
|
||||
export const defaultSettings = {
|
||||
keybindings: 'codemirror',
|
||||
isBracketMatchingEnabled: false,
|
||||
isBracketClosingEnabled: true,
|
||||
isLineNumbersDisplayed: true,
|
||||
isActiveLineHighlighted: false,
|
||||
isAutoCompletionEnabled: false,
|
||||
@@ -76,7 +78,6 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, roo
|
||||
widgetPlugin,
|
||||
// indentOnInput(), // works without. already brought with javascript extension?
|
||||
// bracketMatching(), // does not do anything
|
||||
closeBrackets(),
|
||||
syntaxHighlighting(defaultHighlightStyle),
|
||||
history(),
|
||||
EditorView.updateListener.of((v) => onChange(v)),
|
||||
@@ -309,6 +310,9 @@ export class StrudelMirror {
|
||||
setLineNumbersDisplayed(enabled) {
|
||||
this.reconfigureExtension('isLineNumbersDisplayed', enabled);
|
||||
}
|
||||
setBracketClosingEnabled(enabled) {
|
||||
this.reconfigureExtension('isBracketClosingEnabled', enabled);
|
||||
}
|
||||
setTheme(theme) {
|
||||
this.reconfigureExtension('theme', theme);
|
||||
}
|
||||
|
||||
+22
-18
@@ -542,7 +542,7 @@ export class Pattern {
|
||||
* @noAutocomplete
|
||||
*/
|
||||
filterValues(value_test) {
|
||||
return new Pattern((state) => this.query(state).filter((hap) => value_test(hap.value)));
|
||||
return new Pattern((state) => this.query(state).filter((hap) => value_test(hap.value))).setTactus(this.tactus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1147,7 +1147,7 @@ Pattern.prototype.factories = {
|
||||
slowcat,
|
||||
fastcat,
|
||||
cat,
|
||||
timeCat,
|
||||
timecat,
|
||||
sequence,
|
||||
seq,
|
||||
polymeter,
|
||||
@@ -1254,14 +1254,14 @@ function _stackWith(func, pats) {
|
||||
|
||||
export function stackLeft(...pats) {
|
||||
return _stackWith(
|
||||
(tactus, pats) => pats.map((pat) => (pat.tactus.eq(tactus) ? pat : timeCat(pat, gap(tactus.sub(pat.tactus))))),
|
||||
(tactus, pats) => pats.map((pat) => (pat.tactus.eq(tactus) ? pat : timecat(pat, gap(tactus.sub(pat.tactus))))),
|
||||
pats,
|
||||
);
|
||||
}
|
||||
|
||||
export function stackRight(...pats) {
|
||||
return _stackWith(
|
||||
(tactus, pats) => pats.map((pat) => (pat.tactus.eq(tactus) ? pat : timeCat(gap(tactus.sub(pat.tactus)), pat))),
|
||||
(tactus, pats) => pats.map((pat) => (pat.tactus.eq(tactus) ? pat : timecat(gap(tactus.sub(pat.tactus)), pat))),
|
||||
pats,
|
||||
);
|
||||
}
|
||||
@@ -1274,7 +1274,7 @@ export function stackCentre(...pats) {
|
||||
return pat;
|
||||
}
|
||||
const g = gap(tactus.sub(pat.tactus).div(2));
|
||||
return timeCat(g, pat, g);
|
||||
return timecat(g, pat, g);
|
||||
}),
|
||||
pats,
|
||||
);
|
||||
@@ -1364,13 +1364,13 @@ export function cat(...pats) {
|
||||
* the pattern's 'tactus', generally inferred by the mininotation.
|
||||
* @return {Pattern}
|
||||
* @example
|
||||
* timeCat([3,"e3"],[1, "g3"]).note()
|
||||
* timecat([3,"e3"],[1, "g3"]).note()
|
||||
* // the same as "e3@3 g3".note()
|
||||
* @example
|
||||
* timeCat("bd sd cp","hh hh").sound()
|
||||
* timecat("bd sd cp","hh hh").sound()
|
||||
* // the same as "bd sd cp hh hh".sound()
|
||||
*/
|
||||
export function timeCat(...timepats) {
|
||||
export function timecat(...timepats) {
|
||||
const findtactus = (x) => (Array.isArray(x) ? x : [x.tactus, x]);
|
||||
timepats = timepats.map(findtactus);
|
||||
if (timepats.length == 1) {
|
||||
@@ -1392,6 +1392,9 @@ export function timeCat(...timepats) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Deprecated alias for `timecat` */
|
||||
export const timeCat = timecat;
|
||||
|
||||
/**
|
||||
* Allows to arrange multiple patterns together over multiple cycles.
|
||||
* Takes a variable number of arrays with two elements specifying the number of cycles and the pattern to use.
|
||||
@@ -1406,7 +1409,7 @@ export function timeCat(...timepats) {
|
||||
export function arrange(...sections) {
|
||||
const total = sections.reduce((sum, [cycles]) => sum + cycles, 0);
|
||||
sections = sections.map(([cycles, section]) => [cycles, section.fast(cycles)]);
|
||||
return timeCat(...sections).slow(total);
|
||||
return timecat(...sections).slow(total);
|
||||
}
|
||||
|
||||
export function fastcat(...pats) {
|
||||
@@ -1418,14 +1421,20 @@ export function fastcat(...pats) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** See `fastcat` */
|
||||
export function sequence(...pats) {
|
||||
return fastcat(...pats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates patterns beatwise, similar to `timeCat`, but if an argument is a list, the whole pattern will be repeated for each element in the list.
|
||||
* Concatenates patterns stepwise, according to their 'tactus'.
|
||||
* Similar to `timecat`, but if an argument is a list, the whole pattern will be repeated for each element in the list.
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @example
|
||||
* beatCat(["bd cp", "mt"], "bd").sound()
|
||||
* stepcat(["bd cp", "mt"], "bd").sound()
|
||||
*/
|
||||
export function beatCat(...groups) {
|
||||
export function stepcat(...groups) {
|
||||
groups = groups.map((a) => (Array.isArray(a) ? a.map(reify) : [reify(a)]));
|
||||
|
||||
const cycles = lcm(...groups.map((x) => Fraction(x.length)));
|
||||
@@ -1436,16 +1445,11 @@ export function beatCat(...groups) {
|
||||
}
|
||||
result = result.filter((x) => x.tactus > 0);
|
||||
const tactus = result.reduce((a, b) => a.add(b.tactus), Fraction(0));
|
||||
result = timeCat(...result);
|
||||
result = timecat(...result);
|
||||
result.tactus = tactus;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** See `fastcat` */
|
||||
export function sequence(...pats) {
|
||||
return fastcat(...pats);
|
||||
}
|
||||
|
||||
/** Like **cat**, but the items are crammed into one cycle.
|
||||
* @synonyms fastcat, sequence
|
||||
* @example
|
||||
|
||||
@@ -22,8 +22,4 @@ describe('Value', () => {
|
||||
expect(valued(mul).ap(3).ap(3).value).toEqual(9);
|
||||
expect(valued(3).mul(3).value).toEqual(9);
|
||||
});
|
||||
it('union bare numbers for numeral props', () => {
|
||||
expect(n(3).cutoff(500).add(10).firstCycleValues).toEqual([{ n: 13, cutoff: 510 }]);
|
||||
expect(n(3).cutoff(500).mul(2).firstCycleValues).toEqual([{ n: 6, cutoff: 1000 }]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,14 +5,13 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
*/
|
||||
|
||||
import { curry } from './util.mjs';
|
||||
import { logger } from './logger.mjs';
|
||||
|
||||
export function unionWithObj(a, b, func) {
|
||||
if (typeof b?.value === 'number') {
|
||||
// https://github.com/tidalcycles/strudel/issues/262
|
||||
const numKeys = Object.keys(a).filter((k) => typeof a[k] === 'number');
|
||||
const numerals = Object.fromEntries(numKeys.map((k) => [k, b.value]));
|
||||
b = Object.assign(b, numerals);
|
||||
delete b.value;
|
||||
if (b?.value !== undefined && Object.keys(b).length === 1) {
|
||||
// https://github.com/tidalcycles/strudel/issues/1026
|
||||
logger(`[warn]: Can't do arithmetic on control pattern.`);
|
||||
return a;
|
||||
}
|
||||
const common = Object.keys(a).filter((k) => Object.keys(b).includes(k));
|
||||
return Object.assign({}, a, b, Object.fromEntries(common.map((k) => [k, func(a[k], b[k])])));
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# @strudel/sampler
|
||||
|
||||
This package allows you to serve your samples on disk to the strudel REPL.
|
||||
|
||||
```sh
|
||||
cd ~/your/samples/
|
||||
npx @strudel/sampler
|
||||
```
|
||||
|
||||
This will run a server on `http://localhost:5432`.
|
||||
You can now load the samples via:
|
||||
|
||||
```js
|
||||
samples('http://localhost:5432')
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
```sh
|
||||
LOG=1 npx @strudel/sampler # adds logging
|
||||
PORT=5555 npx @strudel/sampler # changes port
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "@strudel/sampler",
|
||||
"version": "0.0.8",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"tidalcycles",
|
||||
"strudel",
|
||||
"pattern",
|
||||
"livecoding",
|
||||
"algorave"
|
||||
],
|
||||
"author": "Felix Roos <flix91@gmail.com>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"bin": "./sample-server.mjs",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.6.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import cowsay from 'cowsay';
|
||||
import { createReadStream } from 'fs';
|
||||
import { readdir } from 'fs/promises';
|
||||
import http from 'http';
|
||||
import { join } from 'path';
|
||||
import os from 'os';
|
||||
|
||||
// eslint-disable-next-line
|
||||
const LOG = !!process.env.LOG || false;
|
||||
|
||||
console.log(
|
||||
cowsay.say({
|
||||
text: 'welcome to @strudel/sampler',
|
||||
e: 'oO',
|
||||
T: 'U ',
|
||||
}),
|
||||
);
|
||||
|
||||
async function getFilesInDirectory(directory) {
|
||||
let files = [];
|
||||
const dirents = await readdir(directory, { withFileTypes: true });
|
||||
for (const dirent of dirents) {
|
||||
const fullPath = join(directory, dirent.name);
|
||||
if (dirent.isDirectory()) {
|
||||
if (dirent.name.startsWith('.')) {
|
||||
LOG && console.warn(`ignore hidden folder: ${fullPath}`);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const subFiles = (await getFilesInDirectory(fullPath)).filter((f) =>
|
||||
['wav', 'mp3', 'ogg'].includes(f.split('.').slice(-1)[0].toLowerCase()),
|
||||
);
|
||||
files = files.concat(subFiles);
|
||||
LOG && console.log(`${dirent.name} (${subFiles.length})`);
|
||||
} catch (err) {
|
||||
LOG && console.warn(`skipped due to error: ${fullPath}`);
|
||||
}
|
||||
} else {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
async function getBanks(directory) {
|
||||
// const directory = resolve(__dirname, '.');
|
||||
let files = await getFilesInDirectory(directory);
|
||||
let banks = {};
|
||||
files = files.map((url) => {
|
||||
const [bank] = url.split('/').slice(-2);
|
||||
banks[bank] = banks[bank] || [];
|
||||
url = url.replace(directory, '');
|
||||
banks[bank].push(url);
|
||||
return url;
|
||||
});
|
||||
banks._base = `http://localhost:5432`;
|
||||
return { banks, files };
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
const directory = process.cwd();
|
||||
const server = http.createServer(async (req, res) => {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
const { banks, files } = await getBanks(directory);
|
||||
if (req.url === '/') {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
return res.end(JSON.stringify(banks));
|
||||
}
|
||||
let subpath = decodeURIComponent(req.url);
|
||||
if (!files.includes(subpath)) {
|
||||
res.statusCode = 404;
|
||||
res.end('File not found');
|
||||
return;
|
||||
}
|
||||
const filePath = join(directory, subpath);
|
||||
const readStream = createReadStream(filePath);
|
||||
readStream.on('error', (err) => {
|
||||
res.statusCode = 500;
|
||||
res.end('Internal server error');
|
||||
console.error(err);
|
||||
});
|
||||
readStream.pipe(res);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
const PORT = process.env.PORT || 5432;
|
||||
const IP_ADDRESS = '0.0.0.0';
|
||||
let IP;
|
||||
const networkInterfaces = os.networkInterfaces();
|
||||
|
||||
Object.keys(networkInterfaces).forEach((key) => {
|
||||
networkInterfaces[key].forEach((networkInterface) => {
|
||||
if (networkInterface.family === 'IPv4' && !networkInterface.internal) {
|
||||
IP = networkInterface.address;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!IP) {
|
||||
console.error("Unable to determine server's IP address.");
|
||||
// eslint-disable-next-line
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
server.listen(PORT, IP_ADDRESS, () => {
|
||||
console.log(`@strudel/sampler is now serving audio files from:
|
||||
${directory}
|
||||
|
||||
To use them in the Strudel REPL, run:
|
||||
samples('http://localhost:${PORT}')
|
||||
|
||||
Or on a machine in the same network:
|
||||
samples('http://${IP}:${PORT}')
|
||||
`);
|
||||
});
|
||||
@@ -194,6 +194,9 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
|
||||
if (sampleMap.startsWith('github:')) {
|
||||
sampleMap = githubPath(sampleMap, 'strudel.json');
|
||||
}
|
||||
if (sampleMap.startsWith('local:')) {
|
||||
sampleMap = `http://localhost:5432`;
|
||||
}
|
||||
if (sampleMap.startsWith('shabda:')) {
|
||||
let [_, path] = sampleMap.split('shabda:');
|
||||
sampleMap = `https://shabda.ndre.gr/${path}.json?strudel=1`;
|
||||
|
||||
Generated
+96
-39
@@ -361,6 +361,12 @@ importers:
|
||||
specifier: ^5.0.10
|
||||
version: 5.0.10
|
||||
|
||||
packages/sampler:
|
||||
dependencies:
|
||||
cowsay:
|
||||
specifier: ^1.6.0
|
||||
version: 1.6.0
|
||||
|
||||
packages/serial:
|
||||
dependencies:
|
||||
'@strudel/core':
|
||||
@@ -5417,10 +5423,10 @@ packages:
|
||||
type-fest: 0.21.3
|
||||
dev: true
|
||||
|
||||
/ansi-regex@2.1.1:
|
||||
resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
/ansi-regex@3.0.1:
|
||||
resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==}
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
@@ -6032,7 +6038,6 @@ packages:
|
||||
/camelcase@5.3.1:
|
||||
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/camelcase@7.0.1:
|
||||
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
|
||||
@@ -6199,6 +6204,14 @@ packages:
|
||||
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
|
||||
dev: false
|
||||
|
||||
/cliui@6.0.0:
|
||||
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 6.2.0
|
||||
dev: false
|
||||
|
||||
/cliui@7.0.4:
|
||||
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
|
||||
dependencies:
|
||||
@@ -6261,11 +6274,6 @@ packages:
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
dev: true
|
||||
|
||||
/code-point-at@1.1.0:
|
||||
resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/collapse-white-space@2.1.0:
|
||||
resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
|
||||
dev: false
|
||||
@@ -6533,6 +6541,17 @@ packages:
|
||||
typescript: 5.3.3
|
||||
dev: true
|
||||
|
||||
/cowsay@1.6.0:
|
||||
resolution: {integrity: sha512-8C4H1jdrgNusTQr3Yu4SCm+ZKsAlDFbpa0KS0Z3im8ueag+9pGOf3CrioruvmeaW/A5oqg9L0ar6qeftAh03jw==}
|
||||
engines: {node: '>= 4'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
get-stdin: 8.0.0
|
||||
string-width: 2.1.1
|
||||
strip-final-newline: 2.0.0
|
||||
yargs: 15.4.1
|
||||
dev: false
|
||||
|
||||
/crelt@1.0.5:
|
||||
resolution: {integrity: sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==}
|
||||
dev: false
|
||||
@@ -6651,7 +6670,6 @@ packages:
|
||||
/decamelize@1.2.0:
|
||||
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/decode-named-character-reference@1.0.2:
|
||||
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
|
||||
@@ -7877,7 +7895,6 @@ packages:
|
||||
/get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
dev: true
|
||||
|
||||
/get-east-asian-width@1.2.0:
|
||||
resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==}
|
||||
@@ -7916,6 +7933,11 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/get-stdin@8.0.0:
|
||||
resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/get-stream@6.0.0:
|
||||
resolution: {integrity: sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -8779,12 +8801,10 @@ packages:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/is-fullwidth-code-point@1.0.0:
|
||||
resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
number-is-nan: 1.0.1
|
||||
dev: true
|
||||
/is-fullwidth-code-point@2.0.0:
|
||||
resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==}
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/is-fullwidth-code-point@3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
@@ -10893,11 +10913,6 @@ packages:
|
||||
set-blocking: 2.0.0
|
||||
dev: true
|
||||
|
||||
/number-is-nan@1.0.1:
|
||||
resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/nx@17.2.8:
|
||||
resolution: {integrity: sha512-rM5zXbuXLEuqQqcjVjClyvHwRJwt+NVImR2A6KFNG40Z60HP6X12wAxxeLHF5kXXTDRU0PFhf/yACibrpbPrAw==}
|
||||
hasBin: true
|
||||
@@ -12187,13 +12202,16 @@ packages:
|
||||
/require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/require-from-string@2.0.2:
|
||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/require-main-filename@2.0.0:
|
||||
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
|
||||
dev: false
|
||||
|
||||
/requirejs-config-file@4.0.0:
|
||||
resolution: {integrity: sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
@@ -12517,7 +12535,6 @@ packages:
|
||||
|
||||
/set-blocking@2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
dev: true
|
||||
|
||||
/set-function-length@1.1.1:
|
||||
resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==}
|
||||
@@ -12890,14 +12907,13 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/string-width@1.0.2:
|
||||
resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
/string-width@2.1.1:
|
||||
resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
code-point-at: 1.1.0
|
||||
is-fullwidth-code-point: 1.0.0
|
||||
strip-ansi: 3.0.1
|
||||
dev: true
|
||||
is-fullwidth-code-point: 2.0.0
|
||||
strip-ansi: 4.0.0
|
||||
dev: false
|
||||
|
||||
/string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
@@ -12999,12 +13015,12 @@ packages:
|
||||
is-regexp: 1.0.0
|
||||
dev: true
|
||||
|
||||
/strip-ansi@3.0.1:
|
||||
resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
/strip-ansi@4.0.0:
|
||||
resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
ansi-regex: 2.1.1
|
||||
dev: true
|
||||
ansi-regex: 3.0.1
|
||||
dev: false
|
||||
|
||||
/strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
@@ -13039,7 +13055,6 @@ packages:
|
||||
/strip-final-newline@2.0.0:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/strip-final-newline@3.0.0:
|
||||
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
|
||||
@@ -14211,6 +14226,10 @@ packages:
|
||||
is-symbol: 1.0.4
|
||||
dev: true
|
||||
|
||||
/which-module@2.0.1:
|
||||
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
|
||||
dev: false
|
||||
|
||||
/which-pm-runs@1.1.0:
|
||||
resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -14267,7 +14286,7 @@ packages:
|
||||
/wide-align@1.1.5:
|
||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||
dependencies:
|
||||
string-width: 1.0.2
|
||||
string-width: 4.2.3
|
||||
dev: true
|
||||
|
||||
/widest-line@4.0.1:
|
||||
@@ -14459,6 +14478,15 @@ packages:
|
||||
worker-timers-worker: 7.0.67
|
||||
dev: false
|
||||
|
||||
/wrap-ansi@6.2.0:
|
||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
dev: false
|
||||
|
||||
/wrap-ansi@7.0.0:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -14551,6 +14579,10 @@ packages:
|
||||
engines: {node: '>=0.4'}
|
||||
dev: true
|
||||
|
||||
/y18n@4.0.3:
|
||||
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
||||
dev: false
|
||||
|
||||
/y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -14567,6 +14599,14 @@ packages:
|
||||
engines: {node: '>= 14'}
|
||||
dev: false
|
||||
|
||||
/yargs-parser@18.1.3:
|
||||
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
camelcase: 5.3.1
|
||||
decamelize: 1.2.0
|
||||
dev: false
|
||||
|
||||
/yargs-parser@20.2.9:
|
||||
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -14576,6 +14616,23 @@ packages:
|
||||
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
/yargs@15.4.1:
|
||||
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
cliui: 6.0.0
|
||||
decamelize: 1.2.0
|
||||
find-up: 4.1.0
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
require-main-filename: 2.0.0
|
||||
set-blocking: 2.0.0
|
||||
string-width: 4.2.3
|
||||
which-module: 2.0.1
|
||||
y18n: 4.0.3
|
||||
yargs-parser: 18.1.3
|
||||
dev: false
|
||||
|
||||
/yargs@16.2.0:
|
||||
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# samples folder
|
||||
|
||||
1. copy any samples to this folder
|
||||
2. run `npx @strudel/sampler` from this folder
|
||||
3. add `samples('local:')` to your code
|
||||
@@ -954,31 +954,6 @@ exports[`runs examples > example "bank" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "beatCat" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/5 | s:bd ]",
|
||||
"[ 1/5 → 2/5 | s:cp ]",
|
||||
"[ 2/5 → 3/5 | s:bd ]",
|
||||
"[ 3/5 → 4/5 | s:mt ]",
|
||||
"[ 4/5 → 1/1 | s:bd ]",
|
||||
"[ 1/1 → 6/5 | s:bd ]",
|
||||
"[ 6/5 → 7/5 | s:cp ]",
|
||||
"[ 7/5 → 8/5 | s:bd ]",
|
||||
"[ 8/5 → 9/5 | s:mt ]",
|
||||
"[ 9/5 → 2/1 | s:bd ]",
|
||||
"[ 2/1 → 11/5 | s:bd ]",
|
||||
"[ 11/5 → 12/5 | s:cp ]",
|
||||
"[ 12/5 → 13/5 | s:bd ]",
|
||||
"[ 13/5 → 14/5 | s:mt ]",
|
||||
"[ 14/5 → 3/1 | s:bd ]",
|
||||
"[ 3/1 → 16/5 | s:bd ]",
|
||||
"[ 16/5 → 17/5 | s:cp ]",
|
||||
"[ 17/5 → 18/5 | s:bd ]",
|
||||
"[ 18/5 → 19/5 | s:mt ]",
|
||||
"[ 19/5 → 4/1 | s:bd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "begin" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/2 | s:rave begin:0 ]",
|
||||
@@ -5672,27 +5647,6 @@ exports[`runs examples > example "rev" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "reweight" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd ]",
|
||||
"[ 1/4 → 1/2 | s:sd ]",
|
||||
"[ 1/2 → 3/4 | s:cp ]",
|
||||
"[ 3/4 → 1/1 | s:bd ]",
|
||||
"[ 1/1 → 5/4 | s:sd ]",
|
||||
"[ 5/4 → 3/2 | s:cp ]",
|
||||
"[ 3/2 → 7/4 | s:bd ]",
|
||||
"[ 7/4 → 2/1 | s:sd ]",
|
||||
"[ 2/1 → 9/4 | s:cp ]",
|
||||
"[ 9/4 → 5/2 | s:bd ]",
|
||||
"[ 5/2 → 11/4 | s:sd ]",
|
||||
"[ 11/4 → 3/1 | s:cp ]",
|
||||
"[ 3/1 → 13/4 | s:bd ]",
|
||||
"[ 13/4 → 7/2 | s:sd ]",
|
||||
"[ 7/2 → 15/4 | s:cp ]",
|
||||
"[ 15/4 → 4/1 | s:bd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "ribbon" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/2 | note:d ]",
|
||||
@@ -7133,6 +7087,31 @@ exports[`runs examples > example "stack" example index 0 2`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "stepcat" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/5 | s:bd ]",
|
||||
"[ 1/5 → 2/5 | s:cp ]",
|
||||
"[ 2/5 → 3/5 | s:bd ]",
|
||||
"[ 3/5 → 4/5 | s:mt ]",
|
||||
"[ 4/5 → 1/1 | s:bd ]",
|
||||
"[ 1/1 → 6/5 | s:bd ]",
|
||||
"[ 6/5 → 7/5 | s:cp ]",
|
||||
"[ 7/5 → 8/5 | s:bd ]",
|
||||
"[ 8/5 → 9/5 | s:mt ]",
|
||||
"[ 9/5 → 2/1 | s:bd ]",
|
||||
"[ 2/1 → 11/5 | s:bd ]",
|
||||
"[ 11/5 → 12/5 | s:cp ]",
|
||||
"[ 12/5 → 13/5 | s:bd ]",
|
||||
"[ 13/5 → 14/5 | s:mt ]",
|
||||
"[ 14/5 → 3/1 | s:bd ]",
|
||||
"[ 3/1 → 16/5 | s:bd ]",
|
||||
"[ 16/5 → 17/5 | s:cp ]",
|
||||
"[ 17/5 → 18/5 | s:bd ]",
|
||||
"[ 18/5 → 19/5 | s:mt ]",
|
||||
"[ 19/5 → 4/1 | s:bd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "striate" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/6 | s:numbers n:0 begin:0 end:0.16666666666666666 ]",
|
||||
@@ -7319,7 +7298,7 @@ exports[`runs examples > example "sustain" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "timeCat" example index 0 1`] = `
|
||||
exports[`runs examples > example "timecat" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 3/4 | note:e3 ]",
|
||||
"[ 3/4 → 1/1 | note:g3 ]",
|
||||
@@ -7332,7 +7311,7 @@ exports[`runs examples > example "timeCat" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "timeCat" example index 1 1`] = `
|
||||
exports[`runs examples > example "timecat" example index 1 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/5 | s:bd ]",
|
||||
"[ 1/5 → 2/5 | s:sd ]",
|
||||
|
||||
@@ -69,7 +69,7 @@ export default defineConfig({
|
||||
registerType: 'autoUpdate',
|
||||
injectRegister: 'auto',
|
||||
workbox: {
|
||||
globPatterns: ['**/*.{js,css,html,ico,png,svg,json,wav,mp3,ogg}'],
|
||||
globPatterns: ['**/*.{js,css,html,ico,png,svg,json,wav,mp3,ogg,ttf,woff2,TTF,otf}'],
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern: ({ url }) =>
|
||||
|
||||
@@ -61,12 +61,12 @@ async function getModule(name) {
|
||||
|
||||
export function Repl({ embedded = false }) {
|
||||
const isEmbedded = embedded || isIframe;
|
||||
const { panelPosition, isZen } = useSettings();
|
||||
const { panelPosition, isZen, isSyncEnabled } = useSettings();
|
||||
const init = useCallback(() => {
|
||||
const drawTime = [-2, 2];
|
||||
const drawContext = getDrawContext();
|
||||
const editor = new StrudelMirror({
|
||||
sync: false,
|
||||
sync: isSyncEnabled,
|
||||
defaultOutput: webaudioOutput,
|
||||
getTime: () => getAudioContext().currentTime,
|
||||
setInterval,
|
||||
|
||||
@@ -81,6 +81,7 @@ export function SettingsTab({ started }) {
|
||||
const {
|
||||
theme,
|
||||
keybindings,
|
||||
isBracketClosingEnabled,
|
||||
isBracketMatchingEnabled,
|
||||
isLineNumbersDisplayed,
|
||||
isPatternHighlightingEnabled,
|
||||
@@ -88,6 +89,7 @@ export function SettingsTab({ started }) {
|
||||
isAutoCompletionEnabled,
|
||||
isTooltipEnabled,
|
||||
isFlashEnabled,
|
||||
isSyncEnabled,
|
||||
isLineWrappingEnabled,
|
||||
fontSize,
|
||||
fontFamily,
|
||||
@@ -147,6 +149,11 @@ export function SettingsTab({ started }) {
|
||||
onChange={(cbEvent) => settingsMap.setKey('isBracketMatchingEnabled', cbEvent.target.checked)}
|
||||
value={isBracketMatchingEnabled}
|
||||
/>
|
||||
<Checkbox
|
||||
label="Auto close brackets"
|
||||
onChange={(cbEvent) => settingsMap.setKey('isBracketClosingEnabled', cbEvent.target.checked)}
|
||||
value={isBracketClosingEnabled}
|
||||
/>
|
||||
<Checkbox
|
||||
label="Display line numbers"
|
||||
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
|
||||
@@ -182,6 +189,16 @@ export function SettingsTab({ started }) {
|
||||
onChange={(cbEvent) => settingsMap.setKey('isFlashEnabled', cbEvent.target.checked)}
|
||||
value={isFlashEnabled}
|
||||
/>
|
||||
<Checkbox
|
||||
label="Sync across Browser Tabs / Windows"
|
||||
onChange={(cbEvent) => {
|
||||
if (confirm('Changing this setting requires the window to reload itself. OK?')) {
|
||||
settingsMap.setKey('isSyncEnabled', cbEvent.target.checked);
|
||||
window.location.reload();
|
||||
}
|
||||
}}
|
||||
value={isSyncEnabled}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="Zen Mode">Try clicking the logo in the top left!</FormItem>
|
||||
<FormItem label="Reset Settings">
|
||||
|
||||
@@ -361,8 +361,8 @@ export const echoPiano = `// "Echo piano"
|
||||
// @by Felix Roos
|
||||
|
||||
n("<0 2 [4 6](3,4,2) 3*2>").color('salmon')
|
||||
.off(1/4, x=>x.add(2).color('green'))
|
||||
.off(1/2, x=>x.add(6).color('steelblue'))
|
||||
.off(1/4, x=>x.add(n(2)).color('green'))
|
||||
.off(1/2, x=>x.add(n(6)).color('steelblue'))
|
||||
.scale('D minor')
|
||||
.echo(4, 1/8, .5)
|
||||
.clip(.5)
|
||||
|
||||
@@ -8,11 +8,13 @@ export const defaultSettings = {
|
||||
activeFooter: 'intro',
|
||||
keybindings: 'codemirror',
|
||||
isBracketMatchingEnabled: true,
|
||||
isBracketClosingEnabled: true,
|
||||
isLineNumbersDisplayed: true,
|
||||
isActiveLineHighlighted: true,
|
||||
isAutoCompletionEnabled: false,
|
||||
isTooltipEnabled: false,
|
||||
isFlashEnabled: true,
|
||||
isSyncEnabled: false,
|
||||
isLineWrappingEnabled: false,
|
||||
isPatternHighlightingEnabled: true,
|
||||
theme: 'strudelTheme',
|
||||
@@ -29,6 +31,8 @@ export const defaultSettings = {
|
||||
|
||||
export const settingsMap = persistentMap('strudel-settings', defaultSettings);
|
||||
|
||||
const parseBoolean = (booleanlike) => ([true, 'true'].includes(booleanlike) ? true : false);
|
||||
|
||||
export function useSettings() {
|
||||
const state = useStore(settingsMap);
|
||||
|
||||
@@ -40,15 +44,17 @@ 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,
|
||||
isPatternHighlightingEnabled: [true, 'true'].includes(state.isPatternHighlightingEnabled) ? true : false,
|
||||
isTooltipEnabled: [true, 'true'].includes(state.isTooltipEnabled) ? true : false,
|
||||
isLineWrappingEnabled: [true, 'true'].includes(state.isLineWrappingEnabled) ? true : false,
|
||||
isFlashEnabled: [true, 'true'].includes(state.isFlashEnabled) ? true : false,
|
||||
isZen: parseBoolean(state.isZen),
|
||||
isBracketMatchingEnabled: parseBoolean(state.isBracketMatchingEnabled),
|
||||
isBracketClosingEnabled: parseBoolean(state.isBracketClosingEnabled),
|
||||
isLineNumbersDisplayed: parseBoolean(state.isLineNumbersDisplayed),
|
||||
isActiveLineHighlighted: parseBoolean(state.isActiveLineHighlighted),
|
||||
isAutoCompletionEnabled: parseBoolean(state.isAutoCompletionEnabled),
|
||||
isPatternHighlightingEnabled: parseBoolean(state.isPatternHighlightingEnabled),
|
||||
isTooltipEnabled: parseBoolean(state.isTooltipEnabled),
|
||||
isLineWrappingEnabled: parseBoolean(state.isLineWrappingEnabled),
|
||||
isFlashEnabled: parseBoolean(state.isFlashEnabled),
|
||||
isSyncEnabled: parseBoolean(state.isSyncEnabled),
|
||||
fontSize: Number(state.fontSize),
|
||||
panelPosition: state.activeFooter !== '' ? state.panelPosition : 'bottom', // <-- keep this 'bottom' where it is!
|
||||
userPatterns: userPatterns,
|
||||
|
||||
Reference in New Issue
Block a user