mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-24 20:18:34 +00:00
tidal highlighting (single line only for now)
This commit is contained in:
parent
5fb3aadad9
commit
a94ddc7947
@ -28,11 +28,6 @@ function getInfixOperators() {
|
|||||||
ops['~>'] = (l, r) => reify(l).late(reify(r));
|
ops['~>'] = (l, r) => reify(l).late(reify(r));
|
||||||
ops['<~'] = (l, r) => reify(l).early(reify(r));
|
ops['<~'] = (l, r) => reify(l).early(reify(r));
|
||||||
ops['<$>'] = (l, r) => reify(r).fmap(l).outerJoin(); // is this right?
|
ops['<$>'] = (l, r) => reify(r).fmap(l).outerJoin(); // is this right?
|
||||||
ops['string'] = (node) => {
|
|
||||||
const str = node.text.slice(1, -1);
|
|
||||||
console.log('string node', node);
|
|
||||||
return m(str, 1);
|
|
||||||
};
|
|
||||||
return ops;
|
return ops;
|
||||||
}
|
}
|
||||||
const ops = getInfixOperators();
|
const ops = getInfixOperators();
|
||||||
@ -51,9 +46,30 @@ export async function initTidal() {
|
|||||||
return loadParser();
|
return loadParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tidal(code) {
|
// offset is expected to be passed in from transpiler
|
||||||
|
/*
|
||||||
|
1. acorn parses JS to find location of tidal call
|
||||||
|
2. haskell-tree-sitter calls "string" function with node (including location)
|
||||||
|
3. m function sets locations for individual mini notation atom
|
||||||
|
|
||||||
|
so the location for a mini notation atom is:
|
||||||
|
|
||||||
|
js offset + hs offset + atom offset
|
||||||
|
*/
|
||||||
|
export function tidal(code, offset = 0) {
|
||||||
if (Array.isArray(code)) {
|
if (Array.isArray(code)) {
|
||||||
code = code.join('');
|
code = code.join('');
|
||||||
}
|
}
|
||||||
return evaluate(code, window, ops);
|
return evaluate(code, window, {
|
||||||
|
...ops,
|
||||||
|
string: (node) => {
|
||||||
|
// parses strings as mini notation and passes location
|
||||||
|
const str = node.text.slice(1, -1);
|
||||||
|
const col = node.startIndex + offset;
|
||||||
|
// problem: node.startIndex is wrong because hs2js parser removes newlines
|
||||||
|
// for some reason, the parser doesn't like newlines
|
||||||
|
// this means highlighting only works in the first line for now
|
||||||
|
return m(str, col);
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,16 @@ export function transpiler(input, options = {}) {
|
|||||||
|
|
||||||
walk(ast, {
|
walk(ast, {
|
||||||
enter(node, parent /* , prop, index */) {
|
enter(node, parent /* , prop, index */) {
|
||||||
|
if (isTidalTeplateLiteral(node)) {
|
||||||
|
const raw = node.quasi.quasis[0].value.raw;
|
||||||
|
const offset = node.quasi.start + 1;
|
||||||
|
if (emitMiniLocations) {
|
||||||
|
const stringLocs = collectHaskellMiniLocations(raw, offset);
|
||||||
|
miniLocations = miniLocations.concat(stringLocs);
|
||||||
|
}
|
||||||
|
this.skip();
|
||||||
|
return this.replace(tidalWithLocation(raw, offset));
|
||||||
|
}
|
||||||
if (isBackTickString(node, parent)) {
|
if (isBackTickString(node, parent)) {
|
||||||
const { quasis } = node;
|
const { quasis } = node;
|
||||||
const { raw } = quasis[0].value;
|
const { raw } = quasis[0].value;
|
||||||
@ -207,3 +217,46 @@ function labelToP(node) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tidal highlighting
|
||||||
|
// this feels kind of stupid, when we also know the location inside the string op (tidal.mjs)
|
||||||
|
// but maybe it's the only way
|
||||||
|
|
||||||
|
function isTidalTeplateLiteral(node) {
|
||||||
|
return node.type === 'TaggedTemplateExpression' && node.tag.name === 'tidal';
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectHaskellMiniLocations(haskellCode, offset) {
|
||||||
|
const stringLocations = haskellCode.split('').reduce((acc, char, i) => {
|
||||||
|
if (char !== '"') {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
if (!acc.length || acc[acc.length - 1].length > 1) {
|
||||||
|
acc.push([i + 1]);
|
||||||
|
} else {
|
||||||
|
acc[acc.length - 1].push(i);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
return stringLocations
|
||||||
|
.map(([start, end]) => {
|
||||||
|
const miniString = haskellCode.slice(start, end);
|
||||||
|
return getLeafLocations(`"${miniString}"`, offset + start - 1);
|
||||||
|
})
|
||||||
|
.flat();
|
||||||
|
}
|
||||||
|
|
||||||
|
function tidalWithLocation(value, offset) {
|
||||||
|
return {
|
||||||
|
type: 'CallExpression',
|
||||||
|
callee: {
|
||||||
|
type: 'Identifier',
|
||||||
|
name: 'tidal',
|
||||||
|
},
|
||||||
|
arguments: [
|
||||||
|
{ type: 'Literal', value },
|
||||||
|
{ type: 'Literal', value: offset },
|
||||||
|
],
|
||||||
|
optional: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user