Fence syntax bench

A test bench for runnable code fences, replays, and patches.

Every mechanism of the unified grammar, one section each, so a glance says whether it still works. This is a draft, it never hits a public feed.

html · setup
<link rel="stylesheet" href="/demo/reset.css">
<script src="https://cdn.jsdelivr.net/npm/p5@2.3.0/lib/p5.min.js"></script>

1. f=name run, name a file and run it

f=orbits names this content orbits; run also runs it here (code + result).

orbits · js file
const N = 26
let SPEED = 0.6
function setup() { createCanvas(480, 240) }
function draw() {
  background(22, 19, 16)
  colorMode(HSB, 360, 100, 100)
  noStroke()
  for (let i = 0; i < N; i++) {
    const a = millis() * 0.001 * SPEED + i / N * TWO_PI
    const x = width / 2 + cos(a) * (30 + i * 6)
    const y = height / 2 + sin(a * 1.3) * 90
    fill(i / N * 360, 70, 90)
    circle(x, y, 10)
  }
}

2. run=name, replay, result only

Empty body → just the result (the code is already above).

js · run orbits

3. run=name + a one-line update

js · run orbits
- let SPEED = 0.6
+ let SPEED = 2.4

4. run=name + a multi-line update

js · run orbits
-  const x = width / 2 + cos(a) * (30 + i * 6)
-  const y = height / 2 + sin(a * 1.3) * 90
+  const x = width / 2 + cos(a) * (60 + i * 3)
+  const y = height / 2 + sin(a * 2.1) * 70

5. override, persist the update to the file

This replay bumps the count to 80 and writes the result back to orbits:

js · run orbits
- const N = 26
+ const N = 80

6. …and the next replay sees 80

A plain run=orbits now, no update, should already be 80 dots, proof the override persisted (v1 → v2). Stack a SPEED update on top → 80 and fast (compounding v2 → v3):

js · run orbits
- let SPEED = 0.6
+ let SPEED = 3.0

7. f=name as data + fetch()

palette.json is a virtual file, not run, just fetched by the demo below.

palette.json · json file
["#d4a24e", "#83A598", "#FE8019", "#8EC07C"]
js · run
async function setup() {
  createCanvas(480, 160)
  window.PAL = await (await fetch('palette.json')).json()
  noLoop()
}
function draw() {
  noStroke()
  PAL.forEach((c, i) => { fill(c); rect(i * width / PAL.length, 0, width / PAL.length, height) })
}

8. hide + show=

run hide runs but keeps the code hidden; show= windows the shown lines of a plain block.

js
// line 1, hidden by show=
const kept = 'lines 2 and 3 only'
const also = 'still runs + copies in full'
// line 5, hidden

9. Pure insertion, anchor on context, no -

An update needs an anchor, not a removal. Hang a + off an unprefixed context line and it inserts with nothing taken out, here a translate slips in right after background, so the whole swarm drifts side to side. A context-less + block would warn nothing to anchor to instead.

js · run orbits
  background(22, 19, 16)
+ translate(sin(millis() * 0.001) * 40, 0)

10. ... gap, two far-apart edits in one patch

A ... on its own line skips any number of lines, so one fence can change two regions without pasting everything between them. Here: speed up and fatten the dots, anchors far apart in orbits, matched in order, the gap untouched.

js · run orbits
- let SPEED = 0.6
+ let SPEED = 2.5
...
-     circle(x, y, 10)
+     circle(x, y, 22)

11. patch, a slice that knows where it is

No -, no +, nothing changes. patch on the header says the body is a patch anyway, so those lines anchor into orbits and the gutter numbers them where they live in the file, not 1, 2. The header reads patch, not variant.

orbits · js file
    const x = width / 2 + cos(a) * (30 + i * 6)
    const y = height / 2 + sin(a * 1.3) * 90

12. ~, rewrite a whole block

A rewritten function as a - per old line and a + per new one is a wall of red the reader has to climb. ~ names the block, and what follows stands in its place, pasted once, no marker inside it. Bare ~ would find draw from the new text itself; here the prefix is written out, which is what you do when two lines start alike.

js · run orbits
~ function draw(
function draw(){
  background(22, 19, 16)
  colorMode(HSB, 360, 100, 100)
  noStroke()
  for (let i = 0; i < N; i++) {
    const a = millis() * 0.001 * SPEED + i / N * TWO_PI
    fill(i / N * 360, 70, 90)
    circle(width / 2 + cos(a) * (40 + i * 5), height / 2 + sin(a) * (40 + i * 5), 12)
  }
}

Comments & reactions

Sign in with GitHub to join the conversation.

Comments load as you reach this section.