mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 13:48:34 +00:00
Merge branch 'main' of https://github.com/tidalcycles/strudel
This commit is contained in:
commit
1c0da7cd49
@ -1,3 +1,4 @@
|
||||
export * from './codemirror.mjs';
|
||||
export * from './highlight.mjs';
|
||||
export * from './flash.mjs';
|
||||
export * from './slider.mjs';
|
||||
|
||||
132
packages/codemirror/slider.mjs
Normal file
132
packages/codemirror/slider.mjs
Normal file
@ -0,0 +1,132 @@
|
||||
import { ref, pure } from '@strudel.cycles/core';
|
||||
import { WidgetType, ViewPlugin, Decoration } from '@codemirror/view';
|
||||
import { StateEffect, StateField } from '@codemirror/state';
|
||||
|
||||
export let sliderValues = {};
|
||||
const getSliderID = (from) => `slider_${from}`;
|
||||
|
||||
export class SliderWidget extends WidgetType {
|
||||
constructor(value, min, max, from, to, view) {
|
||||
super();
|
||||
this.value = value;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.from = from;
|
||||
this.originalFrom = from;
|
||||
this.to = to;
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
eq() {
|
||||
return false;
|
||||
}
|
||||
|
||||
toDOM() {
|
||||
let wrap = document.createElement('span');
|
||||
wrap.setAttribute('aria-hidden', 'true');
|
||||
wrap.className = 'cm-slider'; // inline-flex items-center
|
||||
let slider = wrap.appendChild(document.createElement('input'));
|
||||
slider.type = 'range';
|
||||
slider.min = this.min;
|
||||
slider.max = this.max;
|
||||
slider.step = (this.max - this.min) / 1000;
|
||||
slider.originalValue = this.value;
|
||||
// to make sure the code stays in sync, let's save the original value
|
||||
// becuase .value automatically clamps values so it'll desync with the code
|
||||
slider.value = slider.originalValue;
|
||||
slider.from = this.from;
|
||||
slider.originalFrom = this.originalFrom;
|
||||
slider.to = this.to;
|
||||
slider.style = 'width:64px;margin-right:4px;transform:translateY(4px)';
|
||||
this.slider = slider;
|
||||
slider.addEventListener('input', (e) => {
|
||||
const next = e.target.value;
|
||||
let insert = next;
|
||||
//let insert = next.toFixed(2);
|
||||
const to = slider.from + slider.originalValue.length;
|
||||
let change = { from: slider.from, to, insert };
|
||||
slider.originalValue = insert;
|
||||
slider.value = insert;
|
||||
this.view.dispatch({ changes: change });
|
||||
const id = getSliderID(slider.originalFrom); // matches id generated in transpiler
|
||||
window.postMessage({ type: 'cm-slider', value: Number(next), id });
|
||||
});
|
||||
return wrap;
|
||||
}
|
||||
|
||||
ignoreEvent(e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export const setWidgets = StateEffect.define();
|
||||
|
||||
export const updateWidgets = (view, widgets) => {
|
||||
view.dispatch({ effects: setWidgets.of(widgets) });
|
||||
};
|
||||
|
||||
function getWidgets(widgetConfigs, view) {
|
||||
return widgetConfigs.map(({ from, to, value, min, max }) => {
|
||||
return Decoration.widget({
|
||||
widget: new SliderWidget(value, min, max, from, to, view),
|
||||
side: 0,
|
||||
}).range(from /* , to */);
|
||||
});
|
||||
}
|
||||
|
||||
export const sliderPlugin = ViewPlugin.fromClass(
|
||||
class {
|
||||
decorations; //: DecorationSet
|
||||
|
||||
constructor(view /* : EditorView */) {
|
||||
this.decorations = Decoration.set([]);
|
||||
}
|
||||
|
||||
update(update /* : ViewUpdate */) {
|
||||
update.transactions.forEach((tr) => {
|
||||
if (tr.docChanged) {
|
||||
this.decorations = this.decorations.map(tr.changes);
|
||||
const iterator = this.decorations.iter();
|
||||
while (iterator.value) {
|
||||
// when the widgets are moved, we need to tell the dom node the current position
|
||||
// this is important because the updateSliderValue function has to work with the dom node
|
||||
iterator.value.widget.slider.from = iterator.from;
|
||||
iterator.value.widget.slider.to = iterator.to;
|
||||
iterator.next();
|
||||
}
|
||||
}
|
||||
for (let e of tr.effects) {
|
||||
if (e.is(setWidgets)) {
|
||||
this.decorations = Decoration.set(getWidgets(e.value, update.view));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
decorations: (v) => v.decorations,
|
||||
},
|
||||
);
|
||||
|
||||
export let slider = (value) => {
|
||||
console.warn('slider will only work when the transpiler is used... passing value as is');
|
||||
return pure(value);
|
||||
};
|
||||
// function transpiled from slider = (value, min, max)
|
||||
export let sliderWithID = (id, value, min, max) => {
|
||||
sliderValues[id] = value; // sync state at eval time (code -> state)
|
||||
return ref(() => sliderValues[id]); // use state at query time
|
||||
};
|
||||
// update state when sliders are moved
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('message', (e) => {
|
||||
if (e.data.type === 'cm-slider') {
|
||||
if (sliderValues[e.data.id] !== undefined) {
|
||||
// update state when slider is moved
|
||||
sliderValues[e.data.id] = e.data.value;
|
||||
} else {
|
||||
console.warn(`slider with id "${e.data.id}" is not registered. Only ${Object.keys(sliderValues)}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -200,20 +200,21 @@ function peg$parse(input, options) {
|
||||
var peg$c23 = "*";
|
||||
var peg$c24 = "?";
|
||||
var peg$c25 = ":";
|
||||
var peg$c26 = "struct";
|
||||
var peg$c27 = "target";
|
||||
var peg$c28 = "euclid";
|
||||
var peg$c29 = "slow";
|
||||
var peg$c30 = "rotL";
|
||||
var peg$c31 = "rotR";
|
||||
var peg$c32 = "fast";
|
||||
var peg$c33 = "scale";
|
||||
var peg$c34 = "//";
|
||||
var peg$c35 = "cat";
|
||||
var peg$c36 = "$";
|
||||
var peg$c37 = "setcps";
|
||||
var peg$c38 = "setbpm";
|
||||
var peg$c39 = "hush";
|
||||
var peg$c26 = "..";
|
||||
var peg$c27 = "struct";
|
||||
var peg$c28 = "target";
|
||||
var peg$c29 = "euclid";
|
||||
var peg$c30 = "slow";
|
||||
var peg$c31 = "rotL";
|
||||
var peg$c32 = "rotR";
|
||||
var peg$c33 = "fast";
|
||||
var peg$c34 = "scale";
|
||||
var peg$c35 = "//";
|
||||
var peg$c36 = "cat";
|
||||
var peg$c37 = "$";
|
||||
var peg$c38 = "setcps";
|
||||
var peg$c39 = "setbpm";
|
||||
var peg$c40 = "hush";
|
||||
|
||||
var peg$r0 = /^[1-9]/;
|
||||
var peg$r1 = /^[eE]/;
|
||||
@ -255,64 +256,67 @@ function peg$parse(input, options) {
|
||||
var peg$e30 = peg$literalExpectation("*", false);
|
||||
var peg$e31 = peg$literalExpectation("?", false);
|
||||
var peg$e32 = peg$literalExpectation(":", false);
|
||||
var peg$e33 = peg$literalExpectation("struct", false);
|
||||
var peg$e34 = peg$literalExpectation("target", false);
|
||||
var peg$e35 = peg$literalExpectation("euclid", false);
|
||||
var peg$e36 = peg$literalExpectation("slow", false);
|
||||
var peg$e37 = peg$literalExpectation("rotL", false);
|
||||
var peg$e38 = peg$literalExpectation("rotR", false);
|
||||
var peg$e39 = peg$literalExpectation("fast", false);
|
||||
var peg$e40 = peg$literalExpectation("scale", false);
|
||||
var peg$e41 = peg$literalExpectation("//", false);
|
||||
var peg$e42 = peg$classExpectation(["\n"], true, false);
|
||||
var peg$e43 = peg$literalExpectation("cat", false);
|
||||
var peg$e44 = peg$literalExpectation("$", false);
|
||||
var peg$e45 = peg$literalExpectation("setcps", false);
|
||||
var peg$e46 = peg$literalExpectation("setbpm", false);
|
||||
var peg$e47 = peg$literalExpectation("hush", false);
|
||||
var peg$e33 = peg$literalExpectation("..", false);
|
||||
var peg$e34 = peg$literalExpectation("struct", false);
|
||||
var peg$e35 = peg$literalExpectation("target", false);
|
||||
var peg$e36 = peg$literalExpectation("euclid", false);
|
||||
var peg$e37 = peg$literalExpectation("slow", false);
|
||||
var peg$e38 = peg$literalExpectation("rotL", false);
|
||||
var peg$e39 = peg$literalExpectation("rotR", false);
|
||||
var peg$e40 = peg$literalExpectation("fast", false);
|
||||
var peg$e41 = peg$literalExpectation("scale", false);
|
||||
var peg$e42 = peg$literalExpectation("//", false);
|
||||
var peg$e43 = peg$classExpectation(["\n"], true, false);
|
||||
var peg$e44 = peg$literalExpectation("cat", false);
|
||||
var peg$e45 = peg$literalExpectation("$", false);
|
||||
var peg$e46 = peg$literalExpectation("setcps", false);
|
||||
var peg$e47 = peg$literalExpectation("setbpm", false);
|
||||
var peg$e48 = peg$literalExpectation("hush", false);
|
||||
|
||||
var peg$f0 = function() { return parseFloat(text()); };
|
||||
var peg$f1 = function(chars) { return new AtomStub(chars.join("")) };
|
||||
var peg$f2 = function(s) { return s };
|
||||
var peg$f3 = function(s, stepsPerCycle) { s.arguments_.stepsPerCycle = stepsPerCycle ; return s; };
|
||||
var peg$f4 = function(a) { return a };
|
||||
var peg$f5 = function(s) { s.arguments_.alignment = 'slowcat'; return s; };
|
||||
var peg$f6 = function(a) { return x => x.options_['weight'] = a };
|
||||
var peg$f7 = function(a) { return x => x.options_['reps'] = a };
|
||||
var peg$f8 = function(p, s, r) { return x => x.options_['ops'].push({ type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r }}) };
|
||||
var peg$f9 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'slow' }}) };
|
||||
var peg$f10 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'fast' }}) };
|
||||
var peg$f11 = function(a) { return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a, seed: seed++ } }) };
|
||||
var peg$f12 = function(s) { return x => x.options_['ops'].push({ type_: "tail", arguments_ :{ element:s } }) };
|
||||
var peg$f13 = function(s, ops) { const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
||||
var peg$f1 = function() { return parseInt(text()); };
|
||||
var peg$f2 = function(chars) { return new AtomStub(chars.join("")) };
|
||||
var peg$f3 = function(s) { return s };
|
||||
var peg$f4 = function(s, stepsPerCycle) { s.arguments_.stepsPerCycle = stepsPerCycle ; return s; };
|
||||
var peg$f5 = function(a) { return a };
|
||||
var peg$f6 = function(s) { s.arguments_.alignment = 'slowcat'; return s; };
|
||||
var peg$f7 = function(a) { return x => x.options_['weight'] = a };
|
||||
var peg$f8 = function(a) { return x => x.options_['reps'] = a };
|
||||
var peg$f9 = function(p, s, r) { return x => x.options_['ops'].push({ type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r }}) };
|
||||
var peg$f10 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'slow' }}) };
|
||||
var peg$f11 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'fast' }}) };
|
||||
var peg$f12 = function(a) { return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a, seed: seed++ } }) };
|
||||
var peg$f13 = function(s) { return x => x.options_['ops'].push({ type_: "tail", arguments_ :{ element:s } }) };
|
||||
var peg$f14 = function(s) { return x => x.options_['ops'].push({ type_: "range", arguments_ :{ element:s } }) };
|
||||
var peg$f15 = function(s, ops) { const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
||||
for (const op of ops) {
|
||||
op(result);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
var peg$f14 = function(s) { return new PatternStub(s, 'fastcat'); };
|
||||
var peg$f15 = function(tail) { return { alignment: 'stack', list: tail }; };
|
||||
var peg$f16 = function(tail) { return { alignment: 'rand', list: tail, seed: seed++ }; };
|
||||
var peg$f17 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment, tail.seed); } else { return head; } };
|
||||
var peg$f18 = function(head, tail) { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); };
|
||||
var peg$f19 = function(sc) { return sc; };
|
||||
var peg$f20 = function(s) { return { name: "struct", args: { mini:s }}};
|
||||
var peg$f21 = function(s) { return { name: "target", args : { name:s}}};
|
||||
var peg$f22 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: p, step:parseInt(s) }}};
|
||||
var peg$f23 = function(a) { return { name: "stretch", args :{ amount: a}}};
|
||||
var peg$f24 = function(a) { return { name: "shift", args :{ amount: "-"+a}}};
|
||||
var peg$f25 = function(a) { return { name: "shift", args :{ amount: a}}};
|
||||
var peg$f26 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}};
|
||||
var peg$f27 = function(s) { return { name: "scale", args :{ scale: s.join("")}}};
|
||||
var peg$f28 = function(s, v) { return v};
|
||||
var peg$f29 = function(s, ss) { ss.unshift(s); return new PatternStub(ss, 'slowcat'); };
|
||||
var peg$f30 = function(sg) {return sg};
|
||||
var peg$f31 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)};
|
||||
var peg$f32 = function(sc) { return sc };
|
||||
var peg$f33 = function(c) { return c };
|
||||
var peg$f34 = function(v) { return new CommandStub("setcps", { value: v})};
|
||||
var peg$f35 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
|
||||
var peg$f36 = function() { return new CommandStub("hush")};
|
||||
var peg$f16 = function(s) { return new PatternStub(s, 'fastcat'); };
|
||||
var peg$f17 = function(tail) { return { alignment: 'stack', list: tail }; };
|
||||
var peg$f18 = function(tail) { return { alignment: 'rand', list: tail, seed: seed++ }; };
|
||||
var peg$f19 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment, tail.seed); } else { return head; } };
|
||||
var peg$f20 = function(head, tail) { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); };
|
||||
var peg$f21 = function(sc) { return sc; };
|
||||
var peg$f22 = function(s) { return { name: "struct", args: { mini:s }}};
|
||||
var peg$f23 = function(s) { return { name: "target", args : { name:s}}};
|
||||
var peg$f24 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: p, step:parseInt(s) }}};
|
||||
var peg$f25 = function(a) { return { name: "stretch", args :{ amount: a}}};
|
||||
var peg$f26 = function(a) { return { name: "shift", args :{ amount: "-"+a}}};
|
||||
var peg$f27 = function(a) { return { name: "shift", args :{ amount: a}}};
|
||||
var peg$f28 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}};
|
||||
var peg$f29 = function(s) { return { name: "scale", args :{ scale: s.join("")}}};
|
||||
var peg$f30 = function(s, v) { return v};
|
||||
var peg$f31 = function(s, ss) { ss.unshift(s); return new PatternStub(ss, 'slowcat'); };
|
||||
var peg$f32 = function(sg) {return sg};
|
||||
var peg$f33 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)};
|
||||
var peg$f34 = function(sc) { return sc };
|
||||
var peg$f35 = function(c) { return c };
|
||||
var peg$f36 = function(v) { return new CommandStub("setcps", { value: v})};
|
||||
var peg$f37 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
|
||||
var peg$f38 = function() { return new CommandStub("hush")};
|
||||
var peg$currPos = 0;
|
||||
var peg$savedPos = 0;
|
||||
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
||||
@ -651,6 +655,26 @@ function peg$parse(input, options) {
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parseintneg() {
|
||||
var s0, s1, s2;
|
||||
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parseminus();
|
||||
if (s1 === peg$FAILED) {
|
||||
s1 = null;
|
||||
}
|
||||
s2 = peg$parseint();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f1();
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parseminus() {
|
||||
var s0;
|
||||
|
||||
@ -884,7 +908,7 @@ function peg$parse(input, options) {
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parsews();
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f1(s2);
|
||||
s0 = peg$f2(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -920,7 +944,7 @@ function peg$parse(input, options) {
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parsews();
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f2(s4);
|
||||
s0 = peg$f3(s4);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -968,7 +992,7 @@ function peg$parse(input, options) {
|
||||
}
|
||||
s8 = peg$parsews();
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f3(s4, s7);
|
||||
s0 = peg$f4(s4, s7);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1000,7 +1024,7 @@ function peg$parse(input, options) {
|
||||
s2 = peg$parseslice();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f4(s2);
|
||||
s0 = peg$f5(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1040,7 +1064,7 @@ function peg$parse(input, options) {
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parsews();
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f5(s4);
|
||||
s0 = peg$f6(s4);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1090,6 +1114,9 @@ function peg$parse(input, options) {
|
||||
s0 = peg$parseop_degrade();
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parseop_tail();
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parseop_range();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1115,7 +1142,7 @@ function peg$parse(input, options) {
|
||||
s2 = peg$parsenumber();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f6(s2);
|
||||
s0 = peg$f7(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1143,7 +1170,7 @@ function peg$parse(input, options) {
|
||||
s2 = peg$parsenumber();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f7(s2);
|
||||
s0 = peg$f8(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1197,7 +1224,7 @@ function peg$parse(input, options) {
|
||||
}
|
||||
if (s13 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f8(s3, s7, s11);
|
||||
s0 = peg$f9(s3, s7, s11);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1237,7 +1264,7 @@ function peg$parse(input, options) {
|
||||
s2 = peg$parseslice();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f9(s2);
|
||||
s0 = peg$f10(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1265,7 +1292,7 @@ function peg$parse(input, options) {
|
||||
s2 = peg$parseslice();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f10(s2);
|
||||
s0 = peg$f11(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1295,7 +1322,7 @@ function peg$parse(input, options) {
|
||||
s2 = null;
|
||||
}
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f11(s2);
|
||||
s0 = peg$f12(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1319,7 +1346,35 @@ function peg$parse(input, options) {
|
||||
s2 = peg$parseslice();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f12(s2);
|
||||
s0 = peg$f13(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parseop_range() {
|
||||
var s0, s1, s2;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 2) === peg$c26) {
|
||||
s1 = peg$c26;
|
||||
peg$currPos += 2;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parseslice();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f14(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1345,7 +1400,7 @@ function peg$parse(input, options) {
|
||||
s3 = peg$parseslice_op();
|
||||
}
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f13(s1, s2);
|
||||
s0 = peg$f15(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1370,7 +1425,7 @@ function peg$parse(input, options) {
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$f14(s1);
|
||||
s1 = peg$f16(s1);
|
||||
}
|
||||
s0 = s1;
|
||||
|
||||
@ -1419,7 +1474,7 @@ function peg$parse(input, options) {
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$f15(s1);
|
||||
s1 = peg$f17(s1);
|
||||
}
|
||||
s0 = s1;
|
||||
|
||||
@ -1468,7 +1523,7 @@ function peg$parse(input, options) {
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$f16(s1);
|
||||
s1 = peg$f18(s1);
|
||||
}
|
||||
s0 = s1;
|
||||
|
||||
@ -1489,7 +1544,7 @@ function peg$parse(input, options) {
|
||||
s2 = null;
|
||||
}
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f17(s1, s2);
|
||||
s0 = peg$f19(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1509,7 +1564,7 @@ function peg$parse(input, options) {
|
||||
s2 = null;
|
||||
}
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f18(s1, s2);
|
||||
s0 = peg$f20(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1532,7 +1587,7 @@ function peg$parse(input, options) {
|
||||
s6 = peg$parsequote();
|
||||
if (s6 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f19(s4);
|
||||
s0 = peg$f21(s4);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1582,19 +1637,19 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c26) {
|
||||
s1 = peg$c26;
|
||||
if (input.substr(peg$currPos, 6) === peg$c27) {
|
||||
s1 = peg$c27;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e34); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsemini_or_operator();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f20(s3);
|
||||
s0 = peg$f22(s3);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1611,12 +1666,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c27) {
|
||||
s1 = peg$c27;
|
||||
if (input.substr(peg$currPos, 6) === peg$c28) {
|
||||
s1 = peg$c28;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e34); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1627,7 +1682,7 @@ function peg$parse(input, options) {
|
||||
s5 = peg$parsequote();
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f21(s4);
|
||||
s0 = peg$f23(s4);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1652,12 +1707,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3, s4, s5, s6, s7;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c28) {
|
||||
s1 = peg$c28;
|
||||
if (input.substr(peg$currPos, 6) === peg$c29) {
|
||||
s1 = peg$c29;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e36); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1672,7 +1727,7 @@ function peg$parse(input, options) {
|
||||
s7 = null;
|
||||
}
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f22(s3, s5, s7);
|
||||
s0 = peg$f24(s3, s5, s7);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1692,35 +1747,6 @@ function peg$parse(input, options) {
|
||||
function peg$parseslow() {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c29) {
|
||||
s1 = peg$c29;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e36); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsenumber();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f23(s3);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parserotL() {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c30) {
|
||||
s1 = peg$c30;
|
||||
@ -1729,35 +1755,6 @@ function peg$parse(input, options) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e37); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsenumber();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f24(s3);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parserotR() {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c31) {
|
||||
s1 = peg$c31;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e38); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsenumber();
|
||||
@ -1776,16 +1773,16 @@ function peg$parse(input, options) {
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parsefast() {
|
||||
function peg$parserotL() {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c32) {
|
||||
s1 = peg$c32;
|
||||
if (input.substr(peg$currPos, 4) === peg$c31) {
|
||||
s1 = peg$c31;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e38); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1805,16 +1802,74 @@ function peg$parse(input, options) {
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parserotR() {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c32) {
|
||||
s1 = peg$c32;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsenumber();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f27(s3);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parsefast() {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c33) {
|
||||
s1 = peg$c33;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsenumber();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f28(s3);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parsescale() {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 5) === peg$c33) {
|
||||
s1 = peg$c33;
|
||||
if (input.substr(peg$currPos, 5) === peg$c34) {
|
||||
s1 = peg$c34;
|
||||
peg$currPos += 5;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1834,7 +1889,7 @@ function peg$parse(input, options) {
|
||||
s5 = peg$parsequote();
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f27(s4);
|
||||
s0 = peg$f29(s4);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1859,12 +1914,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 2) === peg$c34) {
|
||||
s1 = peg$c34;
|
||||
if (input.substr(peg$currPos, 2) === peg$c35) {
|
||||
s1 = peg$c35;
|
||||
peg$currPos += 2;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = [];
|
||||
@ -1873,7 +1928,7 @@ function peg$parse(input, options) {
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e43); }
|
||||
}
|
||||
while (s3 !== peg$FAILED) {
|
||||
s2.push(s3);
|
||||
@ -1882,7 +1937,7 @@ function peg$parse(input, options) {
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e43); }
|
||||
}
|
||||
}
|
||||
s1 = [s1, s2];
|
||||
@ -1899,12 +1954,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 3) === peg$c35) {
|
||||
s1 = peg$c35;
|
||||
if (input.substr(peg$currPos, 3) === peg$c36) {
|
||||
s1 = peg$c36;
|
||||
peg$currPos += 3;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e43); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e44); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1926,7 +1981,7 @@ function peg$parse(input, options) {
|
||||
s9 = peg$parsemini_or_operator();
|
||||
if (s9 !== peg$FAILED) {
|
||||
peg$savedPos = s7;
|
||||
s7 = peg$f28(s5, s9);
|
||||
s7 = peg$f30(s5, s9);
|
||||
} else {
|
||||
peg$currPos = s7;
|
||||
s7 = peg$FAILED;
|
||||
@ -1943,7 +1998,7 @@ function peg$parse(input, options) {
|
||||
s9 = peg$parsemini_or_operator();
|
||||
if (s9 !== peg$FAILED) {
|
||||
peg$savedPos = s7;
|
||||
s7 = peg$f28(s5, s9);
|
||||
s7 = peg$f30(s5, s9);
|
||||
} else {
|
||||
peg$currPos = s7;
|
||||
s7 = peg$FAILED;
|
||||
@ -1963,7 +2018,7 @@ function peg$parse(input, options) {
|
||||
}
|
||||
if (s8 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f29(s5, s6);
|
||||
s0 = peg$f31(s5, s6);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -2009,7 +2064,7 @@ function peg$parse(input, options) {
|
||||
s4 = peg$parsecomment();
|
||||
}
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f30(s1);
|
||||
s0 = peg$f32(s1);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -2020,18 +2075,18 @@ function peg$parse(input, options) {
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 36) {
|
||||
s3 = peg$c36;
|
||||
s3 = peg$c37;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e44); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e45); }
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parsews();
|
||||
s5 = peg$parsemini_or_operator();
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f31(s1, s5);
|
||||
s0 = peg$f33(s1, s5);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -2056,7 +2111,7 @@ function peg$parse(input, options) {
|
||||
s1 = peg$parsemini_or_operator();
|
||||
if (s1 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$f32(s1);
|
||||
s1 = peg$f34(s1);
|
||||
}
|
||||
s0 = s1;
|
||||
if (s0 === peg$FAILED) {
|
||||
@ -2089,7 +2144,7 @@ function peg$parse(input, options) {
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parsews();
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f33(s2);
|
||||
s0 = peg$f35(s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -2102,19 +2157,19 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c37) {
|
||||
s1 = peg$c37;
|
||||
if (input.substr(peg$currPos, 6) === peg$c38) {
|
||||
s1 = peg$c38;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e45); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsenumber();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f34(s3);
|
||||
s0 = peg$f36(s3);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -2131,19 +2186,19 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c38) {
|
||||
s1 = peg$c38;
|
||||
if (input.substr(peg$currPos, 6) === peg$c39) {
|
||||
s1 = peg$c39;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e47); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
s3 = peg$parsenumber();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f35(s3);
|
||||
s0 = peg$f37(s3);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -2160,16 +2215,16 @@ function peg$parse(input, options) {
|
||||
var s0, s1;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c39) {
|
||||
s1 = peg$c39;
|
||||
if (input.substr(peg$currPos, 4) === peg$c40) {
|
||||
s1 = peg$c40;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e47); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e48); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$f36();
|
||||
s1 = peg$f38();
|
||||
}
|
||||
s0 = s1;
|
||||
|
||||
|
||||
@ -79,6 +79,9 @@ frac
|
||||
int
|
||||
= zero / (digit1_9 DIGIT*)
|
||||
|
||||
intneg
|
||||
= minus? int { return parseInt(text()); }
|
||||
|
||||
minus
|
||||
= "-"
|
||||
|
||||
@ -123,7 +126,7 @@ slice = step / sub_cycle / polymeter / slow_sequence
|
||||
|
||||
// slice modifier affects the timing/size of a slice (e.g. [a b c]@3)
|
||||
// at this point, we assume we can represent them as regular sequence operators
|
||||
slice_op = op_weight / op_bjorklund / op_slow / op_fast / op_replicate / op_degrade / op_tail
|
||||
slice_op = op_weight / op_bjorklund / op_slow / op_fast / op_replicate / op_degrade / op_tail / op_range
|
||||
|
||||
op_weight = "@" a:number
|
||||
{ return x => x.options_['weight'] = a }
|
||||
@ -146,6 +149,9 @@ op_degrade = "?"a:number?
|
||||
op_tail = ":" s:slice
|
||||
{ return x => x.options_['ops'].push({ type_: "tail", arguments_ :{ element:s } }) }
|
||||
|
||||
op_range = ".." s:slice
|
||||
{ return x => x.options_['ops'].push({ type_: "range", arguments_ :{ element:s } }) }
|
||||
|
||||
// a slice with an modifier applied i.e [bd@4 sd@3]@2 hh]
|
||||
slice_with_ops = s:slice ops:slice_op*
|
||||
{ const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
||||
|
||||
@ -45,6 +45,17 @@ const applyOptions = (parent, enter) => (pat, i) => {
|
||||
pat = pat.fmap((a) => (b) => Array.isArray(a) ? [...a, b] : [a, b]).appLeft(friend);
|
||||
break;
|
||||
}
|
||||
case 'range': {
|
||||
const friend = enter(op.arguments_.element);
|
||||
pat = strudel.reify(pat);
|
||||
const arrayRange = (start, stop, step = 1) =>
|
||||
Array.from({ length: Math.abs(stop - start) / step + 1 }, (value, index) =>
|
||||
start < stop ? start + index * step : start - index * step,
|
||||
);
|
||||
let range = (apat, bpat) => apat.squeezeBind((a) => bpat.bind((b) => strudel.fastcat(...arrayRange(a, b))));
|
||||
pat = range(pat, friend);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console.warn(`operator "${op.type_}" not implemented`);
|
||||
}
|
||||
|
||||
@ -184,6 +184,12 @@ describe('mini', () => {
|
||||
it('supports lists', () => {
|
||||
expect(minV('a:b c:d:[e:f] g')).toEqual([['a', 'b'], ['c', 'd', ['e', 'f']], 'g']);
|
||||
});
|
||||
it('supports ranges', () => {
|
||||
expect(minV('0 .. 4')).toEqual([0, 1, 2, 3, 4]);
|
||||
});
|
||||
it('supports patterned ranges', () => {
|
||||
expect(minS('[<0 1> .. <2 4>]*2')).toEqual(minS('[0 1 2] [1 2 3 4]'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLeafLocation', () => {
|
||||
|
||||
@ -15,10 +15,11 @@ import {
|
||||
updateMiniLocations,
|
||||
} from '@strudel/codemirror';
|
||||
import './style.css';
|
||||
import { sliderPlugin } from '@strudel/codemirror/slider.mjs';
|
||||
|
||||
export { flash, highlightMiniLocations, updateMiniLocations };
|
||||
|
||||
const staticExtensions = [javascript(), flashField, highlightExtension];
|
||||
const staticExtensions = [javascript(), flashField, highlightExtension, sliderPlugin];
|
||||
|
||||
export default function CodeMirror({
|
||||
value,
|
||||
|
||||
13
packages/react/src/hooks/useWidgets.mjs
Normal file
13
packages/react/src/hooks/useWidgets.mjs
Normal file
@ -0,0 +1,13 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { updateWidgets } from '@strudel/codemirror';
|
||||
|
||||
// i know this is ugly.. in the future, repl needs to run without react
|
||||
export function useWidgets(view) {
|
||||
const [widgets, setWidgets] = useState([]);
|
||||
useEffect(() => {
|
||||
if (view) {
|
||||
updateWidgets(view, widgets);
|
||||
}
|
||||
}, [view, widgets]);
|
||||
return { widgets, setWidgets };
|
||||
}
|
||||
@ -5,7 +5,7 @@ import { isNoteWithOctave } from '@strudel.cycles/core';
|
||||
import { getLeafLocations } from '@strudel.cycles/mini';
|
||||
|
||||
export function transpiler(input, options = {}) {
|
||||
const { wrapAsync = false, addReturn = true, emitMiniLocations = true } = options;
|
||||
const { wrapAsync = false, addReturn = true, emitMiniLocations = true, emitWidgets = true } = options;
|
||||
|
||||
let ast = parse(input, {
|
||||
ecmaVersion: 2022,
|
||||
@ -16,9 +16,9 @@ export function transpiler(input, options = {}) {
|
||||
let miniLocations = [];
|
||||
const collectMiniLocations = (value, node) => {
|
||||
const leafLocs = getLeafLocations(`"${value}"`, node.start); // stimmt!
|
||||
//const withOffset = leafLocs.map((offsets) => offsets.map((o) => o + node.start));
|
||||
miniLocations = miniLocations.concat(leafLocs);
|
||||
};
|
||||
let widgets = [];
|
||||
|
||||
walk(ast, {
|
||||
enter(node, parent /* , prop, index */) {
|
||||
@ -35,6 +35,17 @@ export function transpiler(input, options = {}) {
|
||||
emitMiniLocations && collectMiniLocations(value, node);
|
||||
return this.replace(miniWithLocation(value, node));
|
||||
}
|
||||
if (isWidgetFunction(node)) {
|
||||
emitWidgets &&
|
||||
widgets.push({
|
||||
from: node.arguments[0].start,
|
||||
to: node.arguments[0].end,
|
||||
value: node.arguments[0].raw, // don't use value!
|
||||
min: node.arguments[1]?.value ?? 0,
|
||||
max: node.arguments[2]?.value ?? 1,
|
||||
});
|
||||
return this.replace(widgetWithLocation(node));
|
||||
}
|
||||
// TODO: remove pseudo note variables?
|
||||
if (node.type === 'Identifier' && isNoteWithOctave(node.name)) {
|
||||
this.skip();
|
||||
@ -64,15 +75,14 @@ export function transpiler(input, options = {}) {
|
||||
if (!emitMiniLocations) {
|
||||
return { output };
|
||||
}
|
||||
return { output, miniLocations };
|
||||
return { output, miniLocations, widgets };
|
||||
}
|
||||
|
||||
function isStringWithDoubleQuotes(node, locations, code) {
|
||||
const { raw, type } = node;
|
||||
if (type !== 'Literal') {
|
||||
if (node.type !== 'Literal') {
|
||||
return false;
|
||||
}
|
||||
return raw[0] === '"';
|
||||
return node.raw[0] === '"';
|
||||
}
|
||||
|
||||
function isBackTickString(node, parent) {
|
||||
@ -94,3 +104,22 @@ function miniWithLocation(value, node) {
|
||||
optional: false,
|
||||
};
|
||||
}
|
||||
|
||||
// these functions are connected to @strudel/codemirror -> slider.mjs
|
||||
// maybe someday there will be pluggable transpiler functions, then move this there
|
||||
function isWidgetFunction(node) {
|
||||
return node.type === 'CallExpression' && node.callee.name === 'slider';
|
||||
}
|
||||
|
||||
function widgetWithLocation(node) {
|
||||
const id = 'slider_' + node.arguments[0].start; // use loc of first arg for id
|
||||
// add loc as identifier to first argument
|
||||
// the sliderWithID function is assumed to be sliderWithID(id, value, min?, max?)
|
||||
node.arguments.unshift({
|
||||
type: 'Literal',
|
||||
value: id,
|
||||
raw: id,
|
||||
});
|
||||
node.callee.name = 'sliderWithID';
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import Loader from './Loader';
|
||||
import { settingPatterns } from '../settings.mjs';
|
||||
import { code2hash, hash2code } from './helpers.mjs';
|
||||
import { isTauri } from '../tauri.mjs';
|
||||
import { useWidgets } from '@strudel.cycles/react/src/hooks/useWidgets.mjs';
|
||||
|
||||
const { latestCode } = settingsMap.get();
|
||||
|
||||
@ -39,6 +40,7 @@ let modules = [
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/xen'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
import('@strudel/codemirror'),
|
||||
|
||||
import('@strudel.cycles/serial'),
|
||||
import('@strudel.cycles/soundfonts'),
|
||||
@ -128,7 +130,7 @@ export function Repl({ embedded = false }) {
|
||||
} = useSettings();
|
||||
|
||||
const paintOptions = useMemo(() => ({ fontFamily }), [fontFamily]);
|
||||
|
||||
const { setWidgets } = useWidgets(view);
|
||||
const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } =
|
||||
useStrudel({
|
||||
initialCode: '// LOADING...',
|
||||
@ -142,6 +144,7 @@ export function Repl({ embedded = false }) {
|
||||
},
|
||||
afterEval: ({ code, meta }) => {
|
||||
setMiniLocations(meta.miniLocations);
|
||||
setWidgets(meta.widgets);
|
||||
setPending(false);
|
||||
setLatestCode(code);
|
||||
window.location.hash = '#' + code2hash(code);
|
||||
@ -219,7 +222,7 @@ export function Repl({ embedded = false }) {
|
||||
const handleChangeCode = useCallback(
|
||||
(c) => {
|
||||
setCode(c);
|
||||
started && logger('[edit] code changed. hit ctrl+enter to update');
|
||||
//started && logger('[edit] code changed. hit ctrl+enter to update');
|
||||
},
|
||||
[started],
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user