aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-15 00:09:23 +0200
committeruser <user@clank>2026-08-15 00:09:23 +0200
commitf4e4e52ff9293b413bd477464ccf492c063e9442 (patch)
treea8714ea0bf1bd1d02fa23e96cae2f0c6f219dc19 /contrib
parentcontrib: presets worth stealing, and a test that they do anything (diff)
downloadslosh-f4e4e52ff9293b413bd477464ccf492c063e9442.tar.gz
slosh-f4e4e52ff9293b413bd477464ccf492c063e9442.tar.xz
slosh-f4e4e52ff9293b413bd477464ccf492c063e9442.zip
contrib: the shadertoy presets, usable in sl0ppty
They only existed in a browser, which is a strange place for a terminal multiplexer's shaders to live. Now each one is a file you can paste. contrib/shaders/ holds all thirty-two, one per file, *generated* from the presets in shadertoy.html by contrib/gen-shaders. The page stays the source: it is where they are written, previewed and conformance-tested against the compiler, and a hand-kept second copy would drift the day after it was written. `gen-shaders --check` says whether the files are current, which is a test, so the drift is a failing build rather than a stale example. contrib/shader-tour cycles a session through them, in the shape theme-tour already established — write the config the session watches and let the watcher do the rest. It takes one shader, one group, or nothing for all of them, and it resolves a short name (`torch`) as well as the whole slug (`guides-torch`), because nobody remembers which group a shader is in. The tour writes the theme alongside the shader: shaders resolve default-coloured text through theme's default_fg/default_bg, so a preset judged without one is being judged against a guess. The new test is the one that matters. Every shipped file is loaded into a real session and has to *change the cells of a pane* -- an example that previews beautifully and does nothing when pasted is worse than no example, and neither the toy's conformance test nor a config parse would notice. Three of them are then checked for the specific thing they claim: scanlines alternate row by row, indent guides land on every fourth column, a flat dim is flat. One session, reloaded per preset, which is both quick and a fair exercise of the path anyone will actually use. Renamed the "the built-ins, as expressions" group to drop the qualifier from its filenames; it was generating built-ins-as-expressions-scanlines.kdl, which is a sentence rather than a name.
Diffstat (limited to 'contrib')
-rw-r--r--contrib/README.md32
-rwxr-xr-xcontrib/gen-shaders92
-rwxr-xr-xcontrib/shader-tour81
-rw-r--r--contrib/shaders/built-ins-checker.kdl14
-rw-r--r--contrib/shaders/built-ins-gradient.kdl14
-rw-r--r--contrib/shaders/built-ins-ruler.kdl14
-rw-r--r--contrib/shaders/built-ins-scanlines.kdl14
-rw-r--r--contrib/shaders/built-ins-spotlight.kdl14
-rw-r--r--contrib/shaders/built-ins-vignette.kdl14
-rw-r--r--contrib/shaders/built-ins-zebra.kdl14
-rw-r--r--contrib/shaders/crt-amber.kdl16
-rw-r--r--contrib/shaders/crt-film.kdl16
-rw-r--r--contrib/shaders/crt-interlace.kdl14
-rw-r--r--contrib/shaders/crt-phosphor.kdl17
-rw-r--r--contrib/shaders/crt-rolling-bar.kdl14
-rw-r--r--contrib/shaders/guides-crosshair.kdl14
-rw-r--r--contrib/shaders/guides-cursor-line.kdl14
-rw-r--r--contrib/shaders/guides-edge-falloff.kdl14
-rw-r--r--contrib/shaders/guides-focus-mode.kdl14
-rw-r--r--contrib/shaders/guides-indent-guides.kdl14
-rw-r--r--contrib/shaders/guides-right-margin.kdl14
-rw-r--r--contrib/shaders/guides-thirds.kdl14
-rw-r--r--contrib/shaders/guides-torch.kdl14
-rw-r--r--contrib/shaders/motion-barber-pole.kdl14
-rw-r--r--contrib/shaders/motion-matrix-rain.kdl15
-rw-r--r--contrib/shaders/motion-plasma.kdl14
-rw-r--r--contrib/shaders/motion-pulse.kdl14
-rw-r--r--contrib/shaders/motion-ripples.kdl14
-rw-r--r--contrib/shaders/motion-sonar.kdl14
-rw-r--r--contrib/shaders/motion-sweep.kdl14
-rw-r--r--contrib/shaders/motion-typewriter.kdl14
-rw-r--r--contrib/shaders/pane-states-dead.kdl15
-rw-r--r--contrib/shaders/pane-states-scrolled.kdl14
-rw-r--r--contrib/shaders/pane-states-suspended.kdl15
-rw-r--r--contrib/shaders/pane-states-unfocused.kdl14
-rw-r--r--contrib/shadertoy.html2
36 files changed, 664 insertions, 1 deletions
diff --git a/contrib/README.md b/contrib/README.md
index 5aba78f..eabd14e 100644
--- a/contrib/README.md
+++ b/contrib/README.md
@@ -34,6 +34,38 @@ It works by writing the theme over the file the session was started with and
letting the config watcher notice, which is also a fair demonstration of the
watcher.
+## shaders/ and shader-tour
+
+Thirty-two ready-made shaders, one file each, generated from the presets in
+`shadertoy.html` by `gen-shaders` — the page is where they are written and
+previewed, and a second copy kept by hand would be a second copy kept badly.
+`tests/test_shader_presets.py` fails if the two ever disagree.
+
+To use one, append it to `~/.config/sl0ppty/config.kdl`; a running session
+picks it up when you save.
+
+```sh
+cat contrib/shaders/guides-torch.kdl >> ~/.config/sl0ppty/config.kdl
+```
+
+To look before choosing:
+
+```sh
+contrib/shader-tour # spawn a session and cycle every one
+contrib/shader-tour crt # cycle one group
+contrib/shader-tour torch # apply one to the session named by $SESSION
+DWELL=8 contrib/shader-tour motion # linger longer on each
+```
+
+The groups are `guides` (a cursor line, a crosshair, indent guides, a torch —
+things that tell you where you are), `crt` (phosphor, amber, film grain, a
+rolling bar), `motion` (sonar, ripples, plasma, matrix rain), `built-ins`
+(every compiled-in shader written as an expression, which is the point:
+`vignette` is `dim` with an argument) and `pane-states`.
+
+Move the mouse while the cursor-following ones are up. `curx`/`cury` is where
+the cursor is, and standing still tells you nothing about a torch.
+
## shader-plugin/
A skeleton for adding your own shaders as a shared library, with a Makefile
diff --git a/contrib/gen-shaders b/contrib/gen-shaders
new file mode 100755
index 0000000..0ec27c3
--- /dev/null
+++ b/contrib/gen-shaders
@@ -0,0 +1,92 @@
+#!/usr/bin/env node
+/*
+ * Write contrib/shaders/*.kdl from the presets in contrib/shadertoy.html.
+ *
+ * The page is the source: it is where the presets are written, previewed and
+ * conformance-tested, and a second copy maintained by hand would be a second
+ * copy maintained badly. tests/test_shader_presets.py regenerates into a temp
+ * directory and fails if the committed files have drifted, so "I edited the
+ * page and forgot" is a failing test rather than a stale example.
+ *
+ * contrib/gen-shaders write the files
+ * contrib/gen-shaders --check say whether they are current, write nothing
+ */
+"use strict";
+const fs = require("fs");
+const path = require("path");
+
+const here = __dirname;
+const html = fs.readFileSync(path.join(here, "shadertoy.html"), "utf8");
+const script = html.split("<script>")[1].split("</script>")[0];
+/* Everything up to the DOM: the presets and nothing that needs a browser. */
+const prelude = script.slice(0, script.indexOf("/* ---- the chain UI"));
+const PRESETS = new Function(prelude + "; return PRESETS;")();
+
+/* "built-ins, as expressions" is a heading, not a filename: the qualifier is
+ * dropped so the file is built-ins-scanlines.kdl and not a sentence. */
+const slug = (s) => s.toLowerCase().replace(/,.*$/, "")
+ .replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
+
+function render(group, name, chain) {
+ const body = chain.map((p) => {
+ const color = p.op === "tint" ? ` color="${p.color}"` : "";
+ return ` ${p.op}${color} amount="${p.amount}"`;
+ }).join("\n");
+ return `// ${name} — ${group}
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+${body}
+}
+`;
+}
+
+const outDir = process.argv.includes("--out")
+ ? process.argv[process.argv.indexOf("--out") + 1]
+ : path.join(here, "shaders");
+const check = process.argv.includes("--check");
+
+if (!check) fs.mkdirSync(outDir, { recursive: true });
+
+let stale = [];
+let count = 0;
+for (const [group, entries] of Object.entries(PRESETS)) {
+ for (const [name, chain] of Object.entries(entries)) {
+ const file = path.join(outDir, `${slug(group)}-${slug(name)}.kdl`);
+ const text = render(group, name, chain);
+ count++;
+ if (check) {
+ let have = null;
+ try { have = fs.readFileSync(file, "utf8"); } catch { /* missing */ }
+ if (have !== text) stale.push(path.basename(file));
+ } else {
+ fs.writeFileSync(file, text);
+ }
+ }
+}
+
+if (check) {
+ /* A file nobody generates any more is as stale as one that has changed. */
+ const want = new Set();
+ for (const [group, entries] of Object.entries(PRESETS))
+ for (const name of Object.keys(entries))
+ want.add(`${slug(group)}-${slug(name)}.kdl`);
+ for (const f of fs.readdirSync(outDir))
+ if (f.endsWith(".kdl") && !want.has(f)) stale.push(`${f} (no longer a preset)`);
+
+ if (stale.length) {
+ console.error("stale, run contrib/gen-shaders:\n " + stale.join("\n "));
+ process.exit(1);
+ }
+ console.log(`${count} preset files are current`);
+} else {
+ console.log(`wrote ${count} files to ${path.relative(process.cwd(), outDir)}`);
+}
diff --git a/contrib/shader-tour b/contrib/shader-tour
new file mode 100755
index 0000000..e0678b9
--- /dev/null
+++ b/contrib/shader-tour
@@ -0,0 +1,81 @@
+#!/bin/sh
+# Show the shaders in contrib/shaders on a running session.
+#
+# contrib/shader-tour spawn a session and cycle every one
+# contrib/shader-tour torch apply one to the session named below
+# contrib/shader-tour guides cycle just that group
+# SESSION=work contrib/shader-tour ...to a different session
+# DWELL=8 contrib/shader-tour linger longer on each
+#
+# Like theme-tour, it works by writing the config the session was started with
+# and letting the watcher notice. The cursor-following ones (torch, sonar,
+# ripples, crosshair) want the mouse moved over the session while they are up:
+# `curx`/`cury` is where the cursor is, and standing still tells you nothing.
+set -e
+here=$(cd "$(dirname "$0")" && pwd)
+bin="$here/../build/sl0ppty"
+SESSION=${SESSION:-shaders}
+CONF=${SL0PPTY_CONFIG:-/tmp/sl0ppty-shader-tour.kdl}
+DWELL=${DWELL:-5}
+
+# A name can be the whole slug (guides-torch), or just the interesting half
+# (torch) when that is unambiguous, because nobody wants to remember which
+# group a shader is in.
+resolve() {
+ [ -f "$here/shaders/$1.kdl" ] && { echo "$1"; return 0; }
+ set -- $(cd "$here/shaders" && ls -- *-"$1".kdl 2>/dev/null | sed 's|\.kdl$||')
+ [ $# -eq 1 ] && { echo "$1"; return 0; }
+ return 1
+}
+
+apply() {
+ name=$(resolve "$1") || { echo "no such shader: $1"; exit 1; }
+ f="$here/shaders/$name.kdl"
+ # The theme goes with it: shaders resolve default-coloured text through
+ # theme's default_fg/default_bg, so a preset judged without one is being
+ # judged against a guess.
+ {
+ cat "$here/themes/sl0p.kdl"
+ echo
+ cat "$f"
+ } > "$CONF"
+ printf ' %-26s %s\n' "$name" "$(sed -n '1s|// ||p' "$f")"
+}
+
+# A tour needs something to tour. Applying a single shader does not: it may
+# well be aimed at a session you already have, or at a config you are editing.
+ensure_session() {
+ "$bin" ls 2>/dev/null | grep -q "^$SESSION " && return 0
+ cp "$here/themes/sl0p.kdl" "$CONF"
+ echo "starting a session called $SESSION..."
+ SL0PPTY_CONFIG="$CONF" "$bin" -s "$SESSION" -- "${SHELL:-/bin/sh}" &
+ sleep 1
+}
+
+if [ -n "$1" ]; then
+ # A whole group (guides, crt, motion, built-ins, pane-states) or one shader.
+ set +e
+ ls "$here/shaders/$1-"*.kdl >/dev/null 2>&1
+ isgroup=$?
+ set -e
+ if [ $isgroup -eq 0 ]; then
+ ensure_session
+ echo "cycling $1, ${DWELL}s each. ^C to stop wherever you like."
+ for f in "$here/shaders/$1-"*.kdl; do
+ apply "$(basename "$f" .kdl)"
+ sleep "$DWELL"
+ done
+ else
+ apply "$1"
+ fi
+ exit 0
+fi
+
+ensure_session
+
+echo "cycling every shader, ${DWELL}s each. ^C to stop wherever you like."
+echo "move the mouse over the session for the ones that follow the cursor."
+for f in "$here"/shaders/*.kdl; do
+ apply "$(basename "$f" .kdl)"
+ sleep "$DWELL"
+done
diff --git a/contrib/shaders/built-ins-checker.kdl b/contrib/shaders/built-ins-checker.kdl
new file mode 100644
index 0000000..e689305
--- /dev/null
+++ b/contrib/shaders/built-ins-checker.kdl
@@ -0,0 +1,14 @@
+// checker — built-ins, as expressions
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="((x / 8 + y / 4) % 2) * 45"
+}
diff --git a/contrib/shaders/built-ins-gradient.kdl b/contrib/shaders/built-ins-gradient.kdl
new file mode 100644
index 0000000..69f977f
--- /dev/null
+++ b/contrib/shaders/built-ins-gradient.kdl
@@ -0,0 +1,14 @@
+// gradient — built-ins, as expressions
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="y * 200 / rows"
+}
diff --git a/contrib/shaders/built-ins-ruler.kdl b/contrib/shaders/built-ins-ruler.kdl
new file mode 100644
index 0000000..e4643aa
--- /dev/null
+++ b/contrib/shaders/built-ins-ruler.kdl
@@ -0,0 +1,14 @@
+// ruler — built-ins, as expressions
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#ff5fd7" amount="(x == 40) * 220"
+}
diff --git a/contrib/shaders/built-ins-scanlines.kdl b/contrib/shaders/built-ins-scanlines.kdl
new file mode 100644
index 0000000..6d25c05
--- /dev/null
+++ b/contrib/shaders/built-ins-scanlines.kdl
@@ -0,0 +1,14 @@
+// scanlines — built-ins, as expressions
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="(y % 2) * 40"
+}
diff --git a/contrib/shaders/built-ins-spotlight.kdl b/contrib/shaders/built-ins-spotlight.kdl
new file mode 100644
index 0000000..2635871
--- /dev/null
+++ b/contrib/shaders/built-ins-spotlight.kdl
@@ -0,0 +1,14 @@
+// spotlight — built-ins, as expressions
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp(dist(x, y, curx, cury) * 9, 0, 200)"
+}
diff --git a/contrib/shaders/built-ins-vignette.kdl b/contrib/shaders/built-ins-vignette.kdl
new file mode 100644
index 0000000..138bd84
--- /dev/null
+++ b/contrib/shaders/built-ins-vignette.kdl
@@ -0,0 +1,14 @@
+// vignette — built-ins, as expressions
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp(dist(x, y, cols / 2, rows / 2) * 4, 0, 190)"
+}
diff --git a/contrib/shaders/built-ins-zebra.kdl b/contrib/shaders/built-ins-zebra.kdl
new file mode 100644
index 0000000..852e66a
--- /dev/null
+++ b/contrib/shaders/built-ins-zebra.kdl
@@ -0,0 +1,14 @@
+// zebra — built-ins, as expressions
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="(y / 3 % 2) * 60"
+}
diff --git a/contrib/shaders/crt-amber.kdl b/contrib/shaders/crt-amber.kdl
new file mode 100644
index 0000000..746aa4e
--- /dev/null
+++ b/contrib/shaders/crt-amber.kdl
@@ -0,0 +1,16 @@
+// amber — crt
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ grayscale amount="255"
+ tint color="#ffb000" amount="95"
+ dim amount="(y % 2) * 40"
+}
diff --git a/contrib/shaders/crt-film.kdl b/contrib/shaders/crt-film.kdl
new file mode 100644
index 0000000..19b295f
--- /dev/null
+++ b/contrib/shaders/crt-film.kdl
@@ -0,0 +1,16 @@
+// film — crt
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ grayscale amount="255"
+ dim amount="((x * 7 + y * 13 + t / 40) % 17 < 2) * 70"
+ dim amount="clamp(dist(x, y, cols / 2, rows / 2) * 5, 0, 165)"
+}
diff --git a/contrib/shaders/crt-interlace.kdl b/contrib/shaders/crt-interlace.kdl
new file mode 100644
index 0000000..18bd1c5
--- /dev/null
+++ b/contrib/shaders/crt-interlace.kdl
@@ -0,0 +1,14 @@
+// interlace — crt
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="((y + t / 80) % 2) * 45"
+}
diff --git a/contrib/shaders/crt-phosphor.kdl b/contrib/shaders/crt-phosphor.kdl
new file mode 100644
index 0000000..7cdb397
--- /dev/null
+++ b/contrib/shaders/crt-phosphor.kdl
@@ -0,0 +1,17 @@
+// phosphor — crt
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ grayscale amount="255"
+ tint color="#33ff66" amount="80"
+ dim amount="(y % 3 == 0) * 55"
+ dim amount="clamp(dist(x, y, cols / 2, rows / 2) * 4, 0, 150)"
+}
diff --git a/contrib/shaders/crt-rolling-bar.kdl b/contrib/shaders/crt-rolling-bar.kdl
new file mode 100644
index 0000000..b9ce7ef
--- /dev/null
+++ b/contrib/shaders/crt-rolling-bar.kdl
@@ -0,0 +1,14 @@
+// rolling bar — crt
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="(abs(y - (t / 90) % rows) < 2) * 70"
+}
diff --git a/contrib/shaders/guides-crosshair.kdl b/contrib/shaders/guides-crosshair.kdl
new file mode 100644
index 0000000..7c8ab09
--- /dev/null
+++ b/contrib/shaders/guides-crosshair.kdl
@@ -0,0 +1,14 @@
+// crosshair — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="((y == cury) || (x == curx)) * 55"
+}
diff --git a/contrib/shaders/guides-cursor-line.kdl b/contrib/shaders/guides-cursor-line.kdl
new file mode 100644
index 0000000..b3cb744
--- /dev/null
+++ b/contrib/shaders/guides-cursor-line.kdl
@@ -0,0 +1,14 @@
+// cursor line — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#ff5fd7" amount="(y == cury) * 45"
+}
diff --git a/contrib/shaders/guides-edge-falloff.kdl b/contrib/shaders/guides-edge-falloff.kdl
new file mode 100644
index 0000000..865a8f5
--- /dev/null
+++ b/contrib/shaders/guides-edge-falloff.kdl
@@ -0,0 +1,14 @@
+// edge falloff — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp((5 - min(x, cols - 1 - x)) * 34, 0, 170)"
+}
diff --git a/contrib/shaders/guides-focus-mode.kdl b/contrib/shaders/guides-focus-mode.kdl
new file mode 100644
index 0000000..2acf5ac
--- /dev/null
+++ b/contrib/shaders/guides-focus-mode.kdl
@@ -0,0 +1,14 @@
+// focus mode — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp(abs(y - cury) * 26, 0, 190)"
+}
diff --git a/contrib/shaders/guides-indent-guides.kdl b/contrib/shaders/guides-indent-guides.kdl
new file mode 100644
index 0000000..210b495
--- /dev/null
+++ b/contrib/shaders/guides-indent-guides.kdl
@@ -0,0 +1,14 @@
+// indent guides — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#7aa2f7" amount="(x % 4 == 0) * 38"
+}
diff --git a/contrib/shaders/guides-right-margin.kdl b/contrib/shaders/guides-right-margin.kdl
new file mode 100644
index 0000000..3d6a96d
--- /dev/null
+++ b/contrib/shaders/guides-right-margin.kdl
@@ -0,0 +1,14 @@
+// right margin — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp((x - cols * 3 / 4) * 30, 0, 170)"
+}
diff --git a/contrib/shaders/guides-thirds.kdl b/contrib/shaders/guides-thirds.kdl
new file mode 100644
index 0000000..4c099cd
--- /dev/null
+++ b/contrib/shaders/guides-thirds.kdl
@@ -0,0 +1,14 @@
+// thirds — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#ff5fd7" amount="(x == cols / 3 || x == cols * 2 / 3) * 140"
+}
diff --git a/contrib/shaders/guides-torch.kdl b/contrib/shaders/guides-torch.kdl
new file mode 100644
index 0000000..41e1f3c
--- /dev/null
+++ b/contrib/shaders/guides-torch.kdl
@@ -0,0 +1,14 @@
+// torch — guides
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp((dist(x, y, curx, cury) - 8) * 22, 0, 215)"
+}
diff --git a/contrib/shaders/motion-barber-pole.kdl b/contrib/shaders/motion-barber-pole.kdl
new file mode 100644
index 0000000..21c01ba
--- /dev/null
+++ b/contrib/shaders/motion-barber-pole.kdl
@@ -0,0 +1,14 @@
+// barber pole — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="((x + y + t / 50) / 3 % 2) * 50"
+}
diff --git a/contrib/shaders/motion-matrix-rain.kdl b/contrib/shaders/motion-matrix-rain.kdl
new file mode 100644
index 0000000..cb46843
--- /dev/null
+++ b/contrib/shaders/motion-matrix-rain.kdl
@@ -0,0 +1,15 @@
+// matrix rain — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ grayscale amount="220"
+ tint color="#33ff66" amount="clamp(240 - (((t / 70 + (x * 11) % 23 * 3) % rows - y + rows) % rows) * 45, 0, 240)"
+}
diff --git a/contrib/shaders/motion-plasma.kdl b/contrib/shaders/motion-plasma.kdl
new file mode 100644
index 0000000..6689753
--- /dev/null
+++ b/contrib/shaders/motion-plasma.kdl
@@ -0,0 +1,14 @@
+// plasma — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp(abs((x * 2 + t / 40) % 34 - 17) * 7 + abs((y * 3 - t / 55) % 26 - 13) * 6 - 40, 0, 170)"
+}
diff --git a/contrib/shaders/motion-pulse.kdl b/contrib/shaders/motion-pulse.kdl
new file mode 100644
index 0000000..1646fe5
--- /dev/null
+++ b/contrib/shaders/motion-pulse.kdl
@@ -0,0 +1,14 @@
+// pulse — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#ff5fd7" amount="clamp((t / 6) % 300 - 45, 0, 160)"
+}
diff --git a/contrib/shaders/motion-ripples.kdl b/contrib/shaders/motion-ripples.kdl
new file mode 100644
index 0000000..551a888
--- /dev/null
+++ b/contrib/shaders/motion-ripples.kdl
@@ -0,0 +1,14 @@
+// ripples — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#7aa2f7" amount="((dist(x, y, curx, cury) + t / 30) % 10 < 5) * 50"
+}
diff --git a/contrib/shaders/motion-sonar.kdl b/contrib/shaders/motion-sonar.kdl
new file mode 100644
index 0000000..d62ef09
--- /dev/null
+++ b/contrib/shaders/motion-sonar.kdl
@@ -0,0 +1,14 @@
+// sonar — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#33ff66" amount="(abs(dist(x, y, curx, cury) - (t / 22) % 80) < 3) * 220"
+}
diff --git a/contrib/shaders/motion-sweep.kdl b/contrib/shaders/motion-sweep.kdl
new file mode 100644
index 0000000..bb6eef3
--- /dev/null
+++ b/contrib/shaders/motion-sweep.kdl
@@ -0,0 +1,14 @@
+// sweep — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="clamp(abs(x - (t / 24) % cols) * 22, 0, 200)"
+}
diff --git a/contrib/shaders/motion-typewriter.kdl b/contrib/shaders/motion-typewriter.kdl
new file mode 100644
index 0000000..e8ce5c0
--- /dev/null
+++ b/contrib/shaders/motion-typewriter.kdl
@@ -0,0 +1,14 @@
+// typewriter — motion
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="(y > (t / 400) % rows) * 200"
+}
diff --git a/contrib/shaders/pane-states-dead.kdl b/contrib/shaders/pane-states-dead.kdl
new file mode 100644
index 0000000..d2ab61c
--- /dev/null
+++ b/contrib/shaders/pane-states-dead.kdl
@@ -0,0 +1,15 @@
+// dead — pane states
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ grayscale amount="200"
+ dim amount="90"
+}
diff --git a/contrib/shaders/pane-states-scrolled.kdl b/contrib/shaders/pane-states-scrolled.kdl
new file mode 100644
index 0000000..6c8699f
--- /dev/null
+++ b/contrib/shaders/pane-states-scrolled.kdl
@@ -0,0 +1,14 @@
+// scrolled — pane states
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ tint color="#ffcc88" amount="30"
+}
diff --git a/contrib/shaders/pane-states-suspended.kdl b/contrib/shaders/pane-states-suspended.kdl
new file mode 100644
index 0000000..9cc6cb3
--- /dev/null
+++ b/contrib/shaders/pane-states-suspended.kdl
@@ -0,0 +1,15 @@
+// suspended — pane states
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ grayscale amount="180"
+ dim amount="90"
+}
diff --git a/contrib/shaders/pane-states-unfocused.kdl b/contrib/shaders/pane-states-unfocused.kdl
new file mode 100644
index 0000000..746ac08
--- /dev/null
+++ b/contrib/shaders/pane-states-unfocused.kdl
@@ -0,0 +1,14 @@
+// unfocused — pane states
+//
+// Generated from contrib/shadertoy.html by contrib/gen-shaders; edit the
+// preset there, where you can see what it does, and run that again.
+//
+// Drop this into ~/.config/sl0ppty/config.kdl (a running session picks it up
+// when you save), or point $SL0PPTY_CONFIG at this file. To hang it off a
+// pane state instead of every pane, put the same passes inside one:
+//
+// states { unfocused { ... } }
+
+shaders {
+ dim amount="90"
+}
diff --git a/contrib/shadertoy.html b/contrib/shadertoy.html
index 809cdd4..d796d12 100644
--- a/contrib/shadertoy.html
+++ b/contrib/shadertoy.html
@@ -392,7 +392,7 @@ const PRESETS = {
"typewriter": [{ op: "dim", amount: "(y > (t / 400) % rows) * 200", color: "#ff5fd7" }],
},
- "the built-ins, as expressions": {
+ "built-ins, as expressions": {
"scanlines": [{ op: "dim", amount: "(y % 2) * 40", color: "#ff5fd7" }],
"vignette": [{ op: "dim", amount: "clamp(dist(x, y, cols / 2, rows / 2) * 4, 0, 190)", color: "#ff5fd7" }],
"spotlight": [{ op: "dim", amount: "clamp(dist(x, y, curx, cury) * 9, 0, 200)", color: "#ff5fd7" }],