Skip to content

Commit

Permalink
inline errors sometimes
Browse files Browse the repository at this point in the history
mostly works for glsl and often strudel
  • Loading branch information
garrisonhh committed Jan 16, 2025
1 parent 9da46ac commit 867fd4e
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 19 deletions.
3 changes: 2 additions & 1 deletion kabelsalat.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<body>
<script type="module">
import { SalatRepl } from '@kabelsalat/web';
import { ErrorMessage } from './src/error';
const kabelsalat = new SalatRepl();
function send(type, msg) {
window.parent.postMessage({ type, msg });
Expand Down Expand Up @@ -94,7 +95,7 @@
window.parent.strudel.setDocPattern(docId, docPattern);
}
} catch (err) {
send('onError', [`kabelsalat error: ${err.message}`, docId]);
send('onError', new ErrorMessage(0, `${err}`), docId);
}
}
});
Expand Down
23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 113 additions & 0 deletions src/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { StateEffect, StateField, RangeSet } from '@codemirror/state';
import { EditorView, Decoration, WidgetType } from '@codemirror/view';

const lineFromStackRegex = /:(\d+):\d+$/m;

export class ErrorMessage {
/** if lineno is 0, will display at end of file */
constructor(lineno, text) {
this.lineno = lineno;
this.text = text;
}

static fromError(err, lineOffset) {
console.log(err.stack);
let lineno = 1;
try {
lineno = lineFromStackRegex.exec(err.stack)[1] - lineOffset;
console.log(`parsed lineno ${lineno}`);
} catch (e) {
console.log('parse failure', e);
}
return new ErrorMessage(lineno, err.message);
}

eq(other) {
const eqPos = other.lineno == this.lineno;
const eqText = other.text == this.text;
return eqPos && eqText;
}

toString() {
return `(line ${this.lineno}) ${this.text}`;
}
}

class ErrorWidget extends WidgetType {
constructor(docId, msg) {
super();
this.docId = docId;
this.msg = msg;

const view = window.editorViews.get(docId);
this.from = view.state.doc.length;
if (msg.lineno > 0) {
// display this after the line
const afterLineIndex = view.state.doc.line(msg.lineno).to + 1;
const lastIndex = view.state.doc.length;
this.from = Math.min(afterLineIndex, lastIndex);
}
}

eq(other) {
return this.msg.eq(other.msg);
}

toDOM() {
const msg = document.createElement('div');
msg.classList.add('error');
msg.classList.add(this.msg.lineno > 0 ? 'error-inline' : 'error-file');
msg.classList.add(`error-${this.docId}`);
msg.innerText = this.msg.text;
return msg;
}

ignoreEvent() {
return false;
}
}

const addError = StateEffect.define();
const clearErrors = StateEffect.define();

const errorField = StateField.define({
create() {
return Decoration.none;
},
update(errors, tr) {
errors = errors.map(tr.changes);
for (let e of tr.effects) {
if (e.is(addError)) {
const deco = Decoration.widget({
widget: e.value,
block: true,
}).range(e.value.from);

errors = errors.update({
add: [deco],
});
} else if (e.is(clearErrors)) {
errors = RangeSet.empty;
}
}
return errors;
},
provide: (f) => EditorView.decorations.from(f),
});

export function displayEditorError(docId, msg) {
const view = window.editorViews.get(docId);
const effects = [];
effects.push(addError.of(new ErrorWidget(docId, msg)));

if (!view.state.field(errorField, false)) {
effects.push(StateEffect.appendConfig.of(errorField));
}

view.dispatch({ effects });
}

export function clearEditorErrors(docId) {
const view = window.editorViews.get(docId);
view.dispatch({ effects: [clearErrors.of()] });
}
3 changes: 2 additions & 1 deletion src/hydra.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Hydra from 'hydra-synth';
import { ErrorMessage } from './error';

export class HydraSession {
constructor({ onError, canvas, onHighlight }) {
Expand Down Expand Up @@ -120,7 +121,7 @@ export class HydraSession {
})()`);
} catch (error) {
console.error(error);
this.onError(`${error}`, docId);
this.onError(new ErrorMessage(0, error.message), docId);
}
}
}
14 changes: 3 additions & 11 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { nudelConfirm } from './confirm.js';
import { applySettingsToNudel } from './settings.js';
import { PastaMirror } from './editor.js';
import './style.css';
import { displayEditorError, clearEditorErrors, ErrorMessage } from './error.js';

export const pastamirror = new PastaMirror();
window.editorViews = pastamirror.editorViews;
Expand Down Expand Up @@ -74,20 +75,11 @@ const setError = (message, docId) => {
// todo: where to show global errors?
return;
}
const slot = document.querySelector(`#slot-${docId}`);
let errorEl = document.querySelector(`#slot-${docId} #error-${docId}`);

if (errorEl) {
errorEl.innerText = message;
} else {
slot.insertAdjacentHTML('beforeend', `<div class="error" id="error-${docId}">${message}</div>`);
}
};
const clearError = (docId) => {
document.querySelector(`#slot-${docId} #error-${docId}`)?.remove();
displayEditorError(docId, message);
};
// clear local error when new eval comes in
session.on('eval', (msg) => clearError(msg.docId));
session.on('eval', (msg) => clearEditorErrors(msg.docId));

window.addEventListener('message', (event) => {
if (event.origin !== window.location.origin) {
Expand Down
13 changes: 12 additions & 1 deletion src/shader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
Copyright (C) 2025 nudel contributors
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { ErrorMessage } from './error';

// The standard fullscreen vertex shader.
const vertexShader = `#version 300 es
precision highp float;
Expand Down Expand Up @@ -268,6 +271,14 @@ function reloadShaderInstanceCode(instance, code) {
instance.update();
}

const errorRegex = /ERROR:\s+\d+:(\d+):\s+(.+)/g;
function parseError(text) {
console.log(text);
const m = errorRegex.exec(text);
const linesInTemplateBeforeUserText = 8;
return new ErrorMessage(parseInt(m[1]) - linesInTemplateBeforeUserText, m[2]);
}

export class ShaderSession {
constructor({ onError, canvas }) {
this.onError = onError;
Expand Down Expand Up @@ -295,7 +306,7 @@ export class ShaderSession {
}
console.log('Shader updated!');
} catch (err) {
this.onError(`${err}`, msg.docId);
this.onError(parseError(err), msg.docId);
}
}
}
14 changes: 13 additions & 1 deletion src/strudel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ import { Framer } from '@strudel/draw';
import { registerSoundfonts } from '@strudel/soundfonts';
import { transpiler } from '@strudel/transpiler';
import { getAudioContext, initAudio, registerSynthSounds, samples, webaudioOutput } from '@strudel/webaudio';
import { ErrorMessage } from './error';

const errorRegex = /^\s*(.+)\s*\((\d+):\d+\)\s*/g;

function parseError(text) {
try {
const matches = errorRegex.exec(text);
return new ErrorMessage(parseInt(matches[2]), matches[1]);
} catch {
return new ErrorMessage(0, text);
}
}

controls.createParam('docId');

Expand Down Expand Up @@ -211,7 +223,7 @@ export class StrudelSession {
//console.log("afterEval", meta);
} catch (err) {
console.error(err);
this.onError(`${err}`, docId);
this.onError(parseError(err), docId);
}
}
}
14 changes: 10 additions & 4 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,18 @@ body {
.error {
background-color: black;
font-family: monospace;
padding: 8px;
margin: 0;
border: 2px solid white;
color: tomato;
position: sticky;
bottom: 0;
padding: 0px 2px;
border-radius: 3px;
}

.error-inline {
border-top: 2px dotted tomato;
}

.error-file {
border: 2px solid white;
}
}

Expand Down

0 comments on commit 867fd4e

Please sign in to comment.