mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-22 13:13:10 -04:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8465517c76 | |||
| 215ab87809 | |||
| e5fe998327 | |||
| 6f75a0a62b | |||
| 0464845262 | |||
| d6ee10e05c | |||
| 36441e7b73 | |||
| 189daa3942 | |||
| d009b9592e | |||
| f7f1bd63e8 | |||
| 7d24e45692 | |||
| 612efad3eb | |||
| e7839a09a1 | |||
| 3292f88810 | |||
| 2eda047108 | |||
| c8cf1dc712 |
@@ -1,68 +1,91 @@
|
|||||||
import jsdoc from '../../doc.json';
|
import jsdoc from '../../doc.json';
|
||||||
// import { javascriptLanguage } from '@codemirror/lang-javascript';
|
|
||||||
import { autocompletion } from '@codemirror/autocomplete';
|
import { autocompletion } from '@codemirror/autocomplete';
|
||||||
import { h } from './html';
|
import { h } from './html';
|
||||||
|
|
||||||
function plaintext(str) {
|
const escapeHtml = (str) => {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.innerText = str;
|
div.innerText = str;
|
||||||
return div.innerHTML;
|
return div.innerHTML;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getDocLabel = (doc) => doc.name || doc.longname;
|
const stripHtml = (html) => {
|
||||||
const getInnerText = (html) => {
|
const div = document.createElement('div');
|
||||||
var div = document.createElement('div');
|
|
||||||
div.innerHTML = html;
|
div.innerHTML = html;
|
||||||
return div.textContent || div.innerText || '';
|
return div.textContent || div.innerText || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Autocomplete({ doc, label }) {
|
const getDocLabel = (doc) => doc.name || doc.longname;
|
||||||
return h`<div class="prose dark:prose-invert max-h-[400px] overflow-auto p-2">
|
|
||||||
<h1 class="pt-0 mt-0">${label || getDocLabel(doc)}</h1>
|
const buildParamsList = (params) =>
|
||||||
${doc.description}
|
params?.length
|
||||||
<ul>
|
? `
|
||||||
${doc.params?.map(
|
<div class="autocomplete-info-params-section">
|
||||||
({ name, type, description }) =>
|
<h4 class="autocomplete-info-section-title">Parameters</h4>
|
||||||
`<li>${name} : ${type.names?.join(' | ')} ${description ? ` - ${getInnerText(description)}` : ''}</li>`,
|
<ul class="autocomplete-info-params-list">
|
||||||
)}
|
${params
|
||||||
|
.map(
|
||||||
|
({ name, type, description }) => `
|
||||||
|
<li class="autocomplete-info-param-item">
|
||||||
|
<span class="autocomplete-info-param-name">${name}</span>
|
||||||
|
<span class="autocomplete-info-param-type">${type.names?.join(' | ')}</span>
|
||||||
|
${description ? `<div class="autocomplete-info-param-desc">${stripHtml(description)}</div>` : ''}
|
||||||
|
</li>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
.join('')}
|
||||||
</ul>
|
</ul>
|
||||||
<div>
|
|
||||||
${doc.examples?.map((example) => `<div><pre>${plaintext(example)}</pre></div>`)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>`[0];
|
`
|
||||||
/*
|
: '';
|
||||||
<pre
|
|
||||||
className="cursor-pointer"
|
const buildExamples = (examples) =>
|
||||||
onMouseDown={(e) => {
|
examples?.length
|
||||||
console.log('ola!');
|
? `
|
||||||
navigator.clipboard.writeText(example);
|
<div class="autocomplete-info-examples-section">
|
||||||
e.stopPropagation();
|
<h4 class="autocomplete-info-section-title">Examples</h4>
|
||||||
}}
|
${examples
|
||||||
>
|
.map(
|
||||||
{example}
|
(example) => `
|
||||||
</pre>
|
<pre class="autocomplete-info-example-code">${escapeHtml(example)}</pre>
|
||||||
*/
|
`,
|
||||||
}
|
)
|
||||||
|
.join('')}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
export const Autocomplete = ({ doc, label }) =>
|
||||||
|
h`
|
||||||
|
<div class="autocomplete-info-tooltip">
|
||||||
|
<h3 class="autocomplete-info-function-name">${label || getDocLabel(doc)}</h3>
|
||||||
|
${doc.description ? `<p class="autocomplete-info-function-description">${doc.description}</p>` : ''}
|
||||||
|
${buildParamsList(doc.params)}
|
||||||
|
${buildExamples(doc.examples)}
|
||||||
|
</div>
|
||||||
|
`[0];
|
||||||
|
|
||||||
|
const isValidDoc = (doc) => {
|
||||||
|
const label = getDocLabel(doc);
|
||||||
|
return label && !label.startsWith('_') && !['package'].includes(doc.kind);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasExcludedTags = (doc) =>
|
||||||
|
['superdirtOnly', 'noAutocomplete'].some((tag) => doc.tags?.find((t) => t.originalTitle === tag));
|
||||||
|
|
||||||
const jsdocCompletions = jsdoc.docs
|
const jsdocCompletions = jsdoc.docs
|
||||||
.filter(
|
.filter((doc) => isValidDoc(doc) && !hasExcludedTags(doc))
|
||||||
(doc) =>
|
|
||||||
getDocLabel(doc) &&
|
|
||||||
!getDocLabel(doc).startsWith('_') &&
|
|
||||||
!['package'].includes(doc.kind) &&
|
|
||||||
!['superdirtOnly', 'noAutocomplete'].some((tag) => doc.tags?.find((t) => t.originalTitle === tag)),
|
|
||||||
)
|
|
||||||
// https://codemirror.net/docs/ref/#autocomplete.Completion
|
// https://codemirror.net/docs/ref/#autocomplete.Completion
|
||||||
.map((doc) /*: Completion */ => ({
|
.map((doc) => ({
|
||||||
label: getDocLabel(doc),
|
label: getDocLabel(doc),
|
||||||
// detail: 'xxx', // An optional short piece of information to show (with a different style) after the label.
|
// detail: 'xxx', // An optional short piece of information to show (with a different style) after the label.
|
||||||
info: () => Autocomplete({ doc }),
|
info: () => Autocomplete({ doc }),
|
||||||
type: 'function', // https://codemirror.net/docs/ref/#autocomplete.Completion.type
|
type: 'function', // https://codemirror.net/docs/ref/#autocomplete.Completion.type
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const strudelAutocomplete = (context /* : CompletionContext */) => {
|
export const strudelAutocomplete = (context) => {
|
||||||
let word = context.matchBefore(/\w*/);
|
const word = context.matchBefore(/\w*/);
|
||||||
if (word.from == word.to && !context.explicit) return null;
|
if (word.from === word.to && !context.explicit) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
from: word.from,
|
from: word.from,
|
||||||
options: jsdocCompletions,
|
options: jsdocCompletions,
|
||||||
@@ -74,11 +97,5 @@ export const strudelAutocomplete = (context /* : CompletionContext */) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function isAutoCompletionEnabled(on) {
|
export const isAutoCompletionEnabled = (enabled) =>
|
||||||
return on
|
enabled ? [autocompletion({ override: [strudelAutocomplete] })] : [];
|
||||||
? [
|
|
||||||
autocompletion({ override: [strudelAutocomplete] }),
|
|
||||||
//javascriptLanguage.data.of({ autocomplete: strudelAutocomplete }),
|
|
||||||
]
|
|
||||||
: []; // autocompletion({ override: [] })
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -493,6 +493,9 @@ export async function midin(input) {
|
|||||||
otherInputs?.length ? `Also available: ${getMidiDeviceNamesString(otherInputs)}` : ''
|
otherInputs?.length ? `Also available: ${getMidiDeviceNamesString(otherInputs)}` : ''
|
||||||
}`,
|
}`,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
// ensure refs for this input are initialized
|
||||||
|
if (!refs[input]) {
|
||||||
refs[input] = {};
|
refs[input] = {};
|
||||||
}
|
}
|
||||||
const cc = (cc) => ref(() => refs[input][cc] || 0);
|
const cc = (cc) => ref(() => refs[input][cc] || 0);
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
"start": "astro dev",
|
"start": "astro dev",
|
||||||
"build": "astro build",
|
"build": "astro build",
|
||||||
"preview": "astro preview --port 3009 --host 0.0.0.0",
|
"preview": "astro preview --port 3009 --host 0.0.0.0",
|
||||||
"astro": "astro",
|
"astro": "astro"
|
||||||
"postinstall": "cp node_modules/hs2js/dist/tree-sitter.wasm public && cp node_modules/hs2js/dist/tree-sitter-haskell.wasm public"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-search": "^5.20.0",
|
"@algolia/client-search": "^5.20.0",
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ import { JsDoc } from '../../docs/JsDoc';
|
|||||||
|
|
||||||
## arp
|
## arp
|
||||||
|
|
||||||
<JsDoc client:idle name="Pattern#arp" h={0} />
|
<JsDoc client:idle name="arp" h={0} />
|
||||||
|
|
||||||
## arpWith 🧪
|
## arpWith 🧪
|
||||||
|
|
||||||
<JsDoc client:idle name="Pattern#arpWith" h={0} />
|
<JsDoc client:idle name="arpWith" h={0} />
|
||||||
|
|
||||||
## struct
|
## struct
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ import { JsDoc } from '../../docs/JsDoc';
|
|||||||
|
|
||||||
## hush
|
## hush
|
||||||
|
|
||||||
<JsDoc client:idle name="hush" h={0} />
|
<JsDoc client:idle name="Pattern#hush" h={0} />
|
||||||
|
|
||||||
## invert
|
## invert
|
||||||
|
|
||||||
|
|||||||
@@ -339,4 +339,18 @@ global effects use the same chain for all events of the same orbit:
|
|||||||
|
|
||||||
<JsDoc client:idle name="phasersweep" h={0} />
|
<JsDoc client:idle name="phasersweep" h={0} />
|
||||||
|
|
||||||
|
## Duck
|
||||||
|
|
||||||
|
### duckorbit
|
||||||
|
|
||||||
|
<JsDoc client:idle name="duckorbit" h={0} />
|
||||||
|
|
||||||
|
### duckattack
|
||||||
|
|
||||||
|
<JsDoc client:idle name="duckattack" h={0} />
|
||||||
|
|
||||||
|
### duckdepth
|
||||||
|
|
||||||
|
<JsDoc client:idle name="duckdepth" h={0} />
|
||||||
|
|
||||||
Next, we'll look at input / output via [MIDI, OSC and other methods](/learn/input-output).
|
Next, we'll look at input / output via [MIDI, OSC and other methods](/learn/input-output).
|
||||||
|
|||||||
@@ -361,6 +361,10 @@ Sampler effects are functions that can be used to change the behaviour of sample
|
|||||||
|
|
||||||
<JsDoc client:idle name="splice" h={0} />
|
<JsDoc client:idle name="splice" h={0} />
|
||||||
|
|
||||||
|
### scrub
|
||||||
|
|
||||||
|
<JsDoc client:idle name="Pattern.scrub" h={0} />{' '}
|
||||||
|
|
||||||
### speed
|
### speed
|
||||||
|
|
||||||
<JsDoc client:idle name="speed" h={0} />
|
<JsDoc client:idle name="speed" h={0} />
|
||||||
|
|||||||
@@ -69,3 +69,133 @@
|
|||||||
text-decoration: underline 0.18rem;
|
text-decoration: underline 0.18rem;
|
||||||
text-underline-offset: 0.22rem;
|
text-underline-offset: 0.22rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Override default styles from the codemirror inline css for autocomplete info tooltip*/
|
||||||
|
.cm-tooltip.cm-completionInfo {
|
||||||
|
padding: 12px !important;
|
||||||
|
padding-bottom: 12px !important;
|
||||||
|
border: 1px solid var(--foreground) !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
|
||||||
|
max-width: 500px !important;
|
||||||
|
min-width: 300px !important;
|
||||||
|
max-height: 400px !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
overflow: auto !important;
|
||||||
|
background-color: var(--lineHighlight) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main tooltip container */
|
||||||
|
.autocomplete-info-tooltip {
|
||||||
|
border-radius: 4px !important;
|
||||||
|
color: var(--foreground);
|
||||||
|
font-family: var(--font-family, 'SF Mono', 'Monaco', monospace);
|
||||||
|
font-size: var(--font-size, 13px);
|
||||||
|
line-height: 1.4;
|
||||||
|
max-width: 600px;
|
||||||
|
max-height: 400px;
|
||||||
|
min-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-function-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--foreground);
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-function-description {
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
color: var(--foreground);
|
||||||
|
line-height: 1.5;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-section-title {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--foreground);
|
||||||
|
margin: 16px 0 6px 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-section-title:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-params-section {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-params-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-param-item {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: var(--lineBackground);
|
||||||
|
border-radius: 3px;
|
||||||
|
border-left: 2px solid var(--foreground, #555);
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-param-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-param-name {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--variable, var(--foreground));
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-param-type {
|
||||||
|
color: var(--comment);
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: var(--gutterForeground);
|
||||||
|
padding: 1px 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-param-desc {
|
||||||
|
color: var(--foreground);
|
||||||
|
font-size: 10px;
|
||||||
|
margin-top: 4px;
|
||||||
|
line-height: 1.4;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-examples-section {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-example-code {
|
||||||
|
background: var(--lineBackground);
|
||||||
|
color: var(--foreground);
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-family: var(--font-family, 'SF Mono', 'Monaco', monospace);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: 4px 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre;
|
||||||
|
border: 1px solid var(--foreground, #3a3a3a);
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-tooltip::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-tooltip::-webkit-scrollbar-track {
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-tooltip::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-info-tooltip::-webkit-scrollbar-thumb:hover {
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user