canvas.code

canvas.codeNode

Code as a canvas environment: the full editor experience — syntax highlighting, line numbers, a line/column readout, error markers — with the code choreographed like everything else on a canvas. Content is written as lines{} chunks; cues wrap chunks to bring them in and out on the timeline, and the environment assembles whatever is visible into one document, numbering the lines actually shown. With editable: true, the reader’s first keystroke forks the assembled text into their own copy (kept between visits); choreography freezes until they reset.

#The code environment

canvas.code puts code on the canvas with syntax highlighting, line numbers, a line/column readout and error markers, and lets cues choreograph it like anything else there. Its implicit attribute is language; title names the environment, editable lets the reader edit the text, and continue: #id carries session state forward from an earlier environment.

canvas.code{
    lines{
        import numpy as np

        area = np.array([25.09, 1.24, 903.82])
    }
}(
    language: python
)
A code environment does not execute anything by default. An output shown to the reader is authored — a comment or a later chunk asserting what an interpreter would print. A runnable environment is the opt-in exception: the reader may run it, into the environment's console, and nothing it prints ever reaches the canvas.

#Lines

Code lives in lines chunks: the unit a cue wraps and the unit every other reference addresses. Chunks rather than line numbers, so that inserting a line above a chunk does not renumber what a cue points at. A chunk takes indent (its implicit attribute), highlight, and the error and diff attributes error-lines with error-message, added-lines and removed-lines.

#The typing cue

cue.type types the chunks it wraps in character by character on the timeline. in: anchors when the typing starts and speed: is characters per second, 20 by default.

canvas.code{
    lines{
        z, log_c = np.polyfit(log_area, log_species, 1)
    }
    cue.type{
        lines{
            print(z)   # ≈ 0.34
        }
    }(
        in: 1
    )
}(
    language: python
)

#Splicing values into code

{{ }} substitution reaches literal code bodies exactly as it reaches prose — it is a preprocessor over source text, so an @let constant or a fully-qualified dataset column splices into a chunk before anything is parsed:

@data#survey:galapagos-plants-1973.csv

scene{
    The areas come from the attached survey.
}[
    canvas.code{
        lines{
            area = np.array([{{#survey.area}}])
        }
    }(
        language: python
    )
]

The column arrives as its cells joined with commas, which is the form a Python list literal takes.

#Running code

runnable: true puts a Run button in the environment's toolbar for signed-in readers. A run executes exactly what the editor shows — the reader's fork, once they have edited — in a disposable sandbox with no network access; stdout and stderr stream into a console that folds out of the environment's footer, and a runtime error marks the line it names in the editor. Running needs an explicit language (auto never runs). Python runs with the scientific stack ready — numpy, pandas, statsmodels, matplotlib — plus the standard library; JavaScript runs on Node with its built-in modules; C compiles with gcc, AddressSanitizer on, so memory errors report their line. No other packages can be installed.

A chunk with setup: true is provisioning rather than content: it never displays, and it always executes, prepended in source order outside cue gating — so what a run computes cannot depend on where the reader has scrolled. Imports and fixture values live there.

canvas.code{
    lines{
        import statistics
    }(
        setup: true
    )
    lines{
        area = [25.09, 1.24, 903.82]
        print(statistics.mean(area))
    }
}(
    language: python,
    runnable: true,
    editable: true
)

#Attributes

languageImplicit
autojavascripttypescriptpythonjavacsharprubygocppphpswiftplaintexthtmlcssjsonxmlbashsqlkotlinrustscaladartluahaskellelixirclojureerlangperlrmatlabgroovyobjective cvisual-basicassemblyfortrancobolfsharpocamlpowershellshellyamlmarkdowngraphqlprotobufchalkpostgrespostgresqlsassscssotherjstspycsc#rbc++ktrsshhsexscljcljserlplmvbvbsasmf90f95f03f08f15f18cobcblfsfsifsxmlmlips1psm1ymlmdgqlprotopgpsqltxttextplainobjc
Also written: langDrives the syntax highlighting, the header icon, and the display name.Can be written as shorthand: canvas.code:value
Defaultauto
title
Also written: name, filename, file-name, fileThe filename shown in the header tab, beside the language’s own mark.
editable
The reader may edit the code. Editing forks the assembled text into their own copy and freezes choreography; on a runnable environment, Run executes the fork.
Defaultfalse
runnable
The reader may run the environment: the shown text (their fork, once edited) plus setup chunks executes in a disposable sandbox, streaming stdout and stderr into the environment's console. Needs an explicit language (auto never runs); Python (with the scientific stack), JavaScript and C.
Defaultfalse
show-line-numbers
Also written: line-numbersShow the line-number gutter. Numbering runs over whatever the timeline has made visible, not over the chunks as written.
Defaulttrue
Start with soft wrap on.
Defaultfalse
continue
Inherit an earlier same-type environment's state: continue: #that-environment.

#Allowed content

#Allowed in

#Examples

canvas.code{
    lines{
def greet(name):
    return f"Hello, {name}!"
    }
}(
    language: python
    title: greet.py
)
canvas.code{
    lines{
x = 1
    }
    cue{
        lines{
y = x + 1
        }
    }(
        in: 1
    )
}(
    language: python
)