-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshadertoy_goto_error.user.js
149 lines (134 loc) · 5.53 KB
/
shadertoy_goto_error.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// ==UserScript==
// @name Shadertoy error navigation
// @namespace http://tampermonkey.net/
// @version 0.4.20201030
// @description Go to first/prev/next error
// @author Andrei Drexler
// @match https://www.shadertoy.com/view/*
// @match https://www.shadertoy.com/new
// @run-at document-end
// @grant none
// ==/UserScript==
/* global ShaderToy:true, gShaderToy */
/* eslint curly: 0, no-multi-spaces: 0 */
(function() {
'use strict';
let toolBar = document.getElementById("toolBar"),
compilationTime = document.getElementById("compilationTime");
if (!toolBar || !compilationTime) {
return;
}
/* helper: search array in ascending/descending order, depending on direction */
function find(arr, dir, pred) {
if (dir >= 0)
return arr.findIndex(pred);
for (let i=arr.length-1; i>=0; --i)
if (pred(arr[i]))
return i;
return -1;
}
/* error nav functions */
function goToError(index) {
if (!gShaderToy.mErrors.length)
return;
let cm = gShaderToy.mCodeEditor;
let lineNo = cm.getLineNumber(gShaderToy.mErrors[index].line);
let pos = cm.charCoords({line: lineNo, ch: 0}, "local").top;
let middleHeight = cm.getScrollerElement().offsetHeight / 2;
cm.setCursor({line: lineNo, ch: 0});
cm.scrollTo(null, pos - middleHeight - 5);
cm.focus();
}
function goToNext(dir) {
let cm = gShaderToy.mCodeEditor,
cursor = cm.getCursor(),
errors = gShaderToy.mErrors,
index = find(errors, dir, err => cm.getLineNumber(err.line) * dir > cursor.line * dir);
if (index == -1)
index = (dir >= 0) ? 0 : errors.length - 1;
goToError(index);
}
/* create UI elements */
let errorContainer = document.createElement("div");
errorContainer.id = "ext-error-info"
errorContainer.style = "position:absolute; width:180px; height:auto; left:64px; top:4px; visibility:hidden; user-select:none;";
toolBar.appendChild(errorContainer);
let errorInfo = document.createElement("a");
errorInfo.id = "ext-error-count";
errorInfo.classList.add("regular");
errorInfo.style.cursor = "pointer";
errorInfo.title = "Go to first error";
errorContainer.appendChild(errorInfo);
let prevError = document.createElement("a");
prevError.id = "ext-prev-error";
prevError.text = "\u25C0";
prevError.classList.add("regular");
prevError.style.cursor = "pointer";
prevError.style.paddingLeft = "8px";
prevError.style.paddingRight = "4px";
prevError.title = "Go to previous error (Shift-F8)";
errorContainer.appendChild(prevError);
let nextError = document.createElement("a");
nextError.id = "ext-next-error";
nextError.text = "\u25B6";
nextError.classList.add("regular");
nextError.style.cursor = "pointer";
nextError.style.paddingLeft = "4px";
nextError.style.paddingRight = "8px";
nextError.title = "Go to next error (F8)";
errorContainer.appendChild(nextError);
prevError.addEventListener("click", function() { goToNext(-1); });
nextError.addEventListener("click", function() { goToNext(1); });
errorInfo.addEventListener("click", function() { goToError(0); });
/* override error update to hide compilation time/show error info when needed */
let oldSetErrors = ShaderToy.prototype.SetErrors;
ShaderToy.prototype.SetErrors = function(...args) {
let result = oldSetErrors.apply(this, args);
let errors = gShaderToy && gShaderToy.mErrors;
if (errors && errors.length) {
this.mEleCompilerTime.style.visibility = "hidden";
if (errors.length == 1) {
errorInfo.text = `1 error`;
prevError.style.display = "none";
nextError.style.display = "none";
} else {
errorInfo.text = `${errors.length} errors`;
prevError.style.display = "unset";
nextError.style.display = "unset";
}
errorContainer.style.visibility = "visible";
} else {
this.mEleCompilerTime.style.visibility = "visible";
errorContainer.style.visibility = "hidden";
}
return result;
};
/* override recompilation to restore status visibility */
let oldSetShaderFromEditor = ShaderToy.prototype.SetShaderFromEditor;
ShaderToy.prototype.SetShaderFromEditor = function(...args) {
this.mEleCompilerTime.style.visibility = "visible";
errorContainer.style.visibility = "hidden";
return oldSetShaderFromEditor.apply(this, args);
};
/* override ShaderToy initialization to add prev error/next error editor keys */
let oldShaderToy = ShaderToy,
oldShaderToyProto = ShaderToy.prototype;
ShaderToy = function(parentElement, editorParent, passParent) {
let result = new oldShaderToy(parentElement, editorParent, passParent);
if (result && result.mCodeEditor) {
result.mCodeEditor.addKeyMap({
"Shift-F8": function() { goToNext(-1); },
"F8": function() { goToNext(1); }
});
}
return result;
};
ShaderToy.prototype = oldShaderToyProto;
/* bonus: focus editor when changing tabs */
let oldChangePass = ShaderToy.prototype.ChangePass;
ShaderToy.prototype.ChangePass = function(id) {
let result = oldChangePass.call(this, id);
gShaderToy.mCodeEditor.focus();
return result;
};
})();