Docs for the latest release, v0.2.0.
Tiza GitHub

Reference

Document format

This page describes the .tiza document: the JSON file that holds the code reference, the annotations, the moves and the named steps. Use it to read or write a document by hand.

The document and its code

A .tiza file is a JSON document. With autosave on, Tiza saves it next to the source file. For example, tiza src/main.rs saves to src/main.rs.tiza. See Saving.

The document holds its code in one of two forms:

  • A code reference names the source file by path: "code": {"file": "main.rs", "lines": "12-48"}. The path is absolute or relative to the .tiza file. Thus the document always shows the current code of the file.
  • Embedded code is a copy of the code inside the document, as an array of lines. :embed makes this copy. It also copies every file that a code.link move shows.
CommandWhat it does
:embedCopies the code and every linked file into the document.
:ref PATH[:A-B]References a file again, at any step.
:linkReferences the source file again.
:link PATH[:A-B] at step 0Does the same as :ref PATH[:A-B].
:link PATH[:A-B] at step 1 or laterAdds a code.link move at the current step (see Several files).

:ref, and :link when it references a file, refuse two cases:

  • The file has other code, and a move is applied. Go back to step 0 first.
  • A code.link move shows the file already, because its annotations belong to that view.

Examples

Two examples show moves and views:

  • tiza examples/ownership-moves.rs.tiza types a helper function. Later it replaces the function with a method call.
  • tiza examples/stack-and-queue.tiza --no-save shows a stack and a queue in two views. It changes from one view to the other and back. Each view has its own annotations.

Top-level fields

FieldTypeDefaultMeaning
schemaintegerRequiredThe version of the format, 1.
sourceobjectRequiredThe language and the first line of the code (see source).
codearray or objectRequiredThe embedded code as an array of lines, or a file reference.
followsobjectNo defaultA file reference to the file that follow mode reloads when the document has embedded code.
annotationsarray[]The list of annotations.
stepinteger1The step that the document opens at, from 0 to the last step.
movesarray[]The list of moves.
viewsobject{}The code of each linked file that :embed stores, as an array of lines, with the file of its code.link as the key.
stepsarray[]The list of named steps.
looptrue or falsefalseWhen true, the step after the last step is step 0.
stylesobject{}The styles of the document, a mark style for each name.
titlestringNo defaultThe title of the document.
theme"dark", "light" or "terminal"No defaultThe theme of the document.
theme_overridesobjectNo defaultColors that apply over the [theme] table of the config file (see Theme overrides).
paddingarray of two integerspad of the config file, else [0, 1]The blank rows and columns around the code on the screen, as [vertical, horizontal].
marginintegerNo defaultThe maximum width of the right margin in columns. In the right margin, a note, a label or a legend that is longer than the margin continues on the free rows under its line. When no row is free, Tiza cuts it and ends it with ….
numberstrue or falsenumbers of the config file, else trueWhen false, Tiza does not show line numbers.
  • views holds the full code of a linked file. The window stays in the move.
  • When a linked file is not in views, Tiza reads it from disk.
  • A saved step after the last step opens at the last step.
  • terminal uses the colors of the terminal. It works only in the TUI. An export uses dark or light.
  • Tiza ignores a top-level key that it does not know, and does not save it.

source

FieldTypeDefaultMeaning
languagestring""The language of the code, as an extension or a name, for example rs, ts or py.
first_lineinteger1The number of the first line shown, at most 1,000,000,000.
pathstringNo defaultThe path of the original file.

With a code reference, Tiza sets first_line from lines. It also sets a missing path and an empty language from the file.

File reference

code and follows use this object.

FieldTypeDefaultMeaning
filestringRequiredThe file that holds the code, as a path that is absolute or relative to the .tiza file.
lines"12-48", "12..48" or "7"The whole fileThe lines of the file that the document shows.

Annotations

A new annotation from the TUI appears at the current step. A socket or MCP request can name its own step. At step 0, a new annotation goes to step 1. This rule also applies to a socket or MCP request that names step 0.

FieldTypeDefaultMeaning
idstringRequiredThe short public id, unique in the document, for example a1.
stepinteger1The step at which the annotation appears, at most 999.
typestringRequiredThe annotation type, one of the seven values under this table.
colorstringNo defaultA color name or #rrggbb.
effect"draw" or "fade"No defaultExperimental. The enter effect of the annotation. See Enter effects.
filestringThe document's own fileThe main file or a linked file that the annotation belongs to (see Several files).
markersobject {start, end}No defaultThe two texts that Tiza uses to find a range again after the code changes.

The values of type are:

  • highlight
  • mark
  • box
  • arrow
  • note
  • callout
  • spotlight

from_line and to_line give the range of a box, a callout or a spotlight. markers only finds that range again. start is the first match in the code, and end is the first match at or after it.

Tiza ignores a key of an annotation that it does not know, and does not save it.

Annotation types

Each type adds its own fields.

highlight

FieldTypeDefaultMeaning
spanobjectRequiredThe part of the line to highlight, a span.
labelstringNo defaultThe text next to the code.
emphasisstring"fill"How Tiza draws the span, one of the emphasis values.

A highlight from :hl, as its frame shows it:

The span &t on line 7 has a tint. The label shared borrow is under line 7.

mark

FieldTypeDefaultMeaning
kindstringRequiredThe meaning of the mark, one of the kinds.
spanobjectRequiredThe part of the line to mark, a span.
labelstringNo defaultThe text after the legend.
styleobjectNo defaultA mark style for this mark only.
emphasisstring"fill"How Tiza draws the span, one of the emphasis values.

A mark from :mark, as its frame shows it:

Under line 3, the label row shows the move glyph, the legend move and the label the value moves.

box

FieldTypeDefaultMeaning
from_lineintegerRequiredThe first line of the box.
to_lineintegerRequiredThe last line of the box, not before from_line.
labelstringNo defaultThe text on the box.
borderstring"solid"The line of the border, one of the stroke values.
corners"rounded" or "sharp""rounded"The shape of the corners.
filltrue or falsetrueWhen true, Tiza tints the inside of the box.

A box from :box, as its frame shows it:

Lines 6 to 8 are in a box with rounded corners and a tint. The label shared is on the top border.

arrow

FieldTypeDefaultMeaning
fromobjectRequiredThe start of the arrow, an arrow end.
toobjectRequiredThe end of the arrow, an arrow end.
labelstringNo defaultThe text on the arrow.
strokestring"solid"The line of the arrow, one of the stroke values.
route"rounded" or "sharp""rounded"The shape of the corners.
headsobject {start, end}{"start": "none", "end": "arrow"}The heads at the two ends, each one of the head values.

An arrow from :arrow, as its frame shows it:

An arrow goes from s on line 2 to s on line 3, with the label the value moves.

note

FieldTypeDefaultMeaning
lineintegerRequiredThe line of the note.
textstringRequiredThe text of the note, which is not blank.

A note from :note, as its frame shows it:

Line 3 has the note s moves into takes.

callout

FieldTypeDefaultMeaning
from_lineintegerRequiredThe first line that the callout explains.
to_lineintegerfrom_lineThe last line that the callout explains, not before from_line.
textstringRequiredThe text of the callout, which is not blank.
titlestringNo defaultThe title of the callout.
placement"margin", "below" or "auto""margin"Where Tiza draws the callout.
widthintegerDepends on placementThe width at which Tiza wraps the text, in columns.
borderstring"solid"The line of the border, one of the stroke values.
corners"rounded" or "sharp""rounded"The shape of the corners.
filltrue or falsefalseWhen true, Tiza tints the inside of the callout.

A callout from :callout, as its frame shows it:

In the right margin of lines 6 to 8, a callout with a border holds the text t stays with main.

spotlight

FieldTypeDefaultMeaning
from_lineintegerRequired when there are no idsThe first line that the spotlight does not dim.
to_lineintegerfrom_lineThe last line that the spotlight does not dim, not before from_line.
idsarray of idsRequired when there is no from_line, else []The ids of annotations in the document that the spotlight does not dim, also outside its lines.
untilintegerNo defaultThe last step at which the spotlight is active. When until is before step, the spotlight never shows, and tiza check gives the error until.

A spotlight from :spot, as its frame shows it:

Line 6 is dim. Lines 7 and 8 and the label shared borrow are bright.

A spotlight with only ids, from :spot with an id:

All the code is dim, except line 7, with &t and its label shared borrow. The mark on takes and its label the value moves are dim.

Values of annotation fields

  • Stroke values: solid, dashed, dotted, thick, double. The frames of :arrow, :box and :callout show dashed, thick and double.
  • Head values: none, arrow, dot, bar, open. The frames of :arrow and :set show each one.
  • Emphasis values: fill, underline, brackets, strike. The frames of :hl with an emphasis show each one.

Each value has this meaning:

  • emphasis: fill tints the span.
  • emphasis: underline draws a row under the span.
  • emphasis: brackets draws ⌈ ⌉ beside the span. When one side of the span has no space, it draws ⌊ ⌋ on a row under the span, under its first and its last character. At the end of the longest line, the code column has no space after the span. A span that is one column wide keeps its bracket beside it on the side with space, and the other bracket goes under it. When it has no space on either side, it gets ⊔ under it.
  • emphasis: strike draws a line through the span.
  • emphasis: fill is the default. Tiza does not write it to the file.
  • placement: margin puts the callout in the right margin.
  • placement: below puts the callout in its own rows after to_line.
  • placement: auto uses the margin when the terminal has room.
  • width: in the margin, the default is 34. Tiza keeps the width from 8 to 5 columns less than the margin.
  • width: below the code, the default is the room below the code. Tiza keeps the width in that room.
  • width: the block is as wide as its widest line of text, plus 4 columns for the borders and the padding.
  • title: in the margin, a long title makes the block wider. Below the code, Tiza cuts a long title in the border.

Rules for annotations

  • A spotlight is active from its step to until. Without until, it is active only at its step.
  • A spotlight dims the code outside its lines. It does not dim the code of the annotations in its ids.
  • A spotlight also dims each annotation that does not touch its lines and that is not in its ids.
  • A dimmed mark keeps its label, in the dimmed color.
  • An annotation touches the lines of a spotlight when one or more of its lines are in the range. The lines of a box or a callout go from from_line to to_line. The lines of an arrow go from one end to the other. Thus an arrow that goes across the range touches it.
  • A spotlight with only ids shows only the code of those annotations. It dims all the other annotations.
  • When two or more spotlights are active at one step, Tiza uses the lines and the ids of all of them.

Two spotlights at step 1: one on lines 2 and 3, and one on the highlight h1. The image is a real tiza render export of this document at step 1:

Lines 2, 3 and 7 are bright, with &t and its label shared borrow on line 7. The other lines are dim.

spot-two.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "1-8"},
  "annotations": [
    {"id": "h1", "step": 1, "type": "highlight",
     "span": {"line": 7, "start": 16, "end": 18}, "label": "shared borrow"},
    {"id": "s1", "step": 1, "type": "spotlight", "from_line": 2, "to_line": 3},
    {"id": "s2", "step": 1, "type": "spotlight", "ids": ["h1"]}
  ]
}

Save it as spot-two.tiza next to ownership.rs. Then run tiza spot-two.tiza --step 1.

  • Tiza refuses a blank text, and a range that ends before it starts, when you add an annotation.
  • An annotation whose lines are not in the code stays in the file. Tiza does not draw it, and tiza check gives an error for it.

Span and arrow end

A span covers part of one line. An arrow end is one place in the code.

Span

FieldTypeDefaultMeaning
lineintegerRequiredThe line of the span.
startintegerRequiredThe first grapheme (one character as you see it), counted from 0.
endintegerRequiredThe grapheme after the last one, more than start and at most the length of the line.

Arrow end

FieldTypeDefaultMeaning
lineintegerRequiredThe line of the arrow end.
colintegerRequiredThe grapheme of the arrow end, counted from 0, at most the length of the line.

Kinds

The kind of a mark is one of these:

  • A built-in kind: info, note, warn, error, ok, question, important, read, write, move, new, drop, scope, flow, todo.
  • An alias of a built-in kind, from the table under this list.
  • The name of a style in styles. A style with the name of a built-in kind replaces that kind.
  • The name of a personal style in [styles] of the config file. Tiza then copies the style into styles. See Personal styles.
  • Any name, when the mark has a style with a glyph. The name is then the default legend.

When you add a mark, Tiza refuses any other kind. A loaded file keeps such a mark, and tiza check reports it. Case does not matter for a built-in kind or an alias.

AliasKind
borrow, ref, &read
borrow_mut, borrowmut, mut, &mutwrite
lifetime, life, 'ascope
free, deletedrop
alloc, createnew
bugerror
warningwarn
tipinfo

Each built-in kind has its own glyph, legend and color. A mark with no label shows only the glyph and the legend. These images are real tiza render exports at step 1 of docs/frames/kinds-1.tiza and docs/frames/kinds-2.tiza:

Seven marks on lines 1 to 8, each with the glyph and the legend of its kind: info, note, warning for warn, error, ok, why? for question, and important.

kinds-1.tiza

{
  "schema": 1,
  "source": {},
  "code": {
    "file": "ownership.rs",
    "lines": "1-8"
  },
  "annotations": [
    {"id": "m1", "step": 1, "type": "mark", "kind": "info", "span": {"line": 1, "start": 3, "end": 7}},
    {"id": "m2", "step": 1, "type": "mark", "kind": "note", "span": {"line": 2, "start": 8, "end": 9}},
    {"id": "m3", "step": 1, "type": "mark", "kind": "warn", "span": {"line": 3, "start": 4, "end": 9}},
    {"id": "m4", "step": 1, "type": "mark", "kind": "error", "span": {"line": 4, "start": 7, "end": 15}},
    {"id": "m5", "step": 1, "type": "mark", "kind": "ok", "span": {"line": 6, "start": 8, "end": 9}},
    {"id": "m6", "step": 1, "type": "mark", "kind": "question", "span": {"line": 7, "start": 12, "end": 15}},
    {"id": "m7", "step": 1, "type": "mark", "kind": "important", "span": {"line": 8, "start": 4, "end": 12}}
  ]
}

Save it as kinds-1.tiza next to ownership.rs. Then run tiza kinds-1.tiza --step 1.

Eight marks on lines 2 to 13, each with the glyph and the legend of its kind: new, move, scope, read, flow, write, todo and drop.

kinds-2.tiza

{
  "schema": 1,
  "source": {},
  "code": {
    "file": "ownership.rs",
    "lines": "2-13"
  },
  "annotations": [
    {"id": "m1", "step": 1, "type": "mark", "kind": "new", "span": {"line": 2, "start": 12, "end": 18}},
    {"id": "m2", "step": 1, "type": "mark", "kind": "move", "span": {"line": 3, "start": 4, "end": 9}},
    {"id": "m3", "step": 1, "type": "mark", "kind": "scope", "span": {"line": 6, "start": 8, "end": 9}},
    {"id": "m4", "step": 1, "type": "mark", "kind": "read", "span": {"line": 7, "start": 16, "end": 18}},
    {"id": "m5", "step": 1, "type": "mark", "kind": "flow", "span": {"line": 8, "start": 4, "end": 12}},
    {"id": "m6", "step": 1, "type": "mark", "kind": "write", "span": {"line": 10, "start": 12, "end": 13}},
    {"id": "m7", "step": 1, "type": "mark", "kind": "todo", "span": {"line": 11, "start": 4, "end": 8}},
    {"id": "m8", "step": 1, "type": "mark", "kind": "drop", "span": {"line": 13, "start": 0, "end": 1}}
  ]
}

Save it as kinds-2.tiza next to ownership.rs. Then run tiza kinds-2.tiza --step 1.

Mark style

Each entry of styles, and the style of a mark, has these fields. The style of a mark replaces each field that it gives.

FieldTypeDefaultMeaning
glyphstringThe glyph of the kindThe sign before the legend, which should be one or two columns wide.
legendstringThe legend of the kindThe text after the glyph, followed by : and the label of the mark.
colorstringThe color of the kindA color name or #rrggbb.

Color names

NameAliases
orangerust, naranja, accent
blueazul
greenverde
purplemorado, violeta
pinkmagenta, rosa
cyanteal, cian
yellowamarillo
redrojo
graygrey, gris

The nine color names, on highlights. The image is a real tiza render export at step 1 of docs/frames/colors.tiza:

Nine highlights on lines 1 to 11, each with its color name as the label: orange, blue, green, purple, pink, cyan, yellow, red and gray.

colors.tiza

{
  "schema": 1,
  "source": {},
  "code": {
    "file": "ownership.rs",
    "lines": "1-13"
  },
  "annotations": [
    {"id": "h1", "step": 1, "type": "highlight", "span": {"line": 1, "start": 3, "end": 7}, "label": "orange", "color": "orange"},
    {"id": "h2", "step": 1, "type": "highlight", "span": {"line": 2, "start": 12, "end": 18}, "label": "blue", "color": "blue"},
    {"id": "h3", "step": 1, "type": "highlight", "span": {"line": 3, "start": 4, "end": 9}, "label": "green", "color": "green"},
    {"id": "h4", "step": 1, "type": "highlight", "span": {"line": 4, "start": 7, "end": 15}, "label": "purple", "color": "purple"},
    {"id": "h5", "step": 1, "type": "highlight", "span": {"line": 6, "start": 12, "end": 18}, "label": "pink", "color": "pink"},
    {"id": "h6", "step": 1, "type": "highlight", "span": {"line": 7, "start": 12, "end": 15}, "label": "cyan", "color": "cyan"},
    {"id": "h7", "step": 1, "type": "highlight", "span": {"line": 8, "start": 4, "end": 12}, "label": "yellow", "color": "yellow"},
    {"id": "h8", "step": 1, "type": "highlight", "span": {"line": 10, "start": 16, "end": 22}, "label": "red", "color": "red"},
    {"id": "h9", "step": 1, "type": "highlight", "span": {"line": 11, "start": 4, "end": 8}, "label": "gray", "color": "gray"}
  ]
}

Save it as colors.tiza next to ownership.rs. Then run tiza colors.tiza --step 1.

  • Case does not matter. A hex color has exactly six digits, so #rgb is not a color of an annotation.
  • Tiza refuses an unknown color when you add an annotation. In a file, Tiza draws an annotation with an unknown color in its default color.
  • accent gives the accent color of the theme. An override of orange does not change accent.
  • An arrow without a color takes the next color of a palette of seven colors: orange, blue, green, purple, cyan, pink, yellow. The eighth arrow starts the palette again.
  • A mark without a color uses the color of its kind or its style. For example, move is pink and read is cyan.
  • A box without a color uses the box color of the theme. A note or a callout uses the note color, and a highlight or a spotlight uses the accent color.

Arrow styles

The stroke and heads fields change the look of an arrow. For example, examples/ownership.rs.tiza shows a shared borrow with a dashed arrow and a mutable borrow with a thick arrow. In :arrow, heads=none,none gives an arrow with no heads.

Theme overrides

theme_overrides is an object. Each key is a role, a color name or a theme name.

KeyValue
A role, from the list under this tableA color value
A color name, from the list under this tableA color value
dark, light or terminalAn object with the same keys, which applies only with that theme
  • Roles: bg, fg, muted, dimmed, accent, rail, box_line, box_bg, arrow, note, highlight_bg, status_bg, status_fg, cmd_bg, error.
  • Color names: orange, blue, green, purple, pink, cyan, yellow, red, gray.

A color value is one of these:

  • #rrggbb or #rgb.
  • rgb(r, g, b).
  • An ANSI name, for example red or bright-blue. It gives a color of the terminal palette.
  • ansiN, a color of the terminal palette from 0 to 255.
  • reset, default or none, the default color of the terminal.

A color name of an annotation, such as orange, is not a color value. red, blue and the other names that are also ANSI names give the colors of the terminal. In an export, a token with a color of the terminal palette uses the color of the dark or light theme, and Tiza prints a note. The keys are the same as in the [theme] table of the config file.

For example, a document that changes the accent role, the color of a highlight, and the note role. :theme file writes this field from a theme file: see Change a color. The image is a real tiza render export of this document at step 1, with the dark theme:

Lines 6 to 8 on the dark theme. The label shared borrow of &t on line 7 is purple, and the note t is still here under line 8 is cyan.

theme-overrides.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "theme_overrides": {"accent": "#c678dd", "note": "#56b6c2"},
  "annotations": [
    {"id": "h1", "step": 1, "type": "highlight",
     "span": {"line": 7, "start": 16, "end": 18}, "label": "shared borrow"},
    {"id": "n1", "step": 1, "type": "note", "line": 8, "text": "t is still here"}
  ]
}

Save it as theme-overrides.tiza next to ownership.rs. Then run tiza theme-overrides.tiza --step 1.

Moves

A move changes the code or the view at a step. The moves list of a document holds them.

  • n applies the moves of the next step. p reverts them.
  • Tiza always computes the document again from the code of step 0. Thus the document returns to the same state after any number of steps forward and back.

Every move has at_step and action. A code.patch move can also have rebind:

FieldTypeDefaultMeaning
at_stepintegerRequiredThe step of the move, from 1 to 999.
actionstringRequiredThe action of the move, one of the actions in the table under this one.
rebindobject{}The new place of each annotation that the move replaces or deletes (see Annotations after a code.patch move).
ActionWhat it does
code.patchInserts, replaces or deletes whole lines of the file shown at its step.
code.linkShows another file from its step on (see Several files).
cursorPuts the cursor on a line.
selectSelects a span.
waitPauses before the annotations of the step appear.
scrollMoves the view of the TUI to a line, a text or an annotation (see Scroll).

Several moves at one step run in the order of the list.

Moves from a newer version

A newer version of Tiza can write a move that this version does not know. The document opens:

  • Tiza skips a move with an action that this version does not know. The other moves of its step run in the order of the list.
  • align and typing have a list of values. When a move has a value that this version does not know, the move uses the default of the field. op has no default, so Tiza skips the move.
  • A key that this version does not know has no effect, for example alig instead of align.
  • When the TUI opens the file, it writes each skipped move and each value on stderr, where you see the line after the TUI ends. The status bar shows how many entries are not known, with the effects that this version does not know, for example 6 entries are not known: see tiza check. In presentation mode, the last row shows it for 2 seconds. tiza render also writes the line on stderr.
  • tiza check gives the warning move for each skipped move, for each value, and for each move with a key that this version does not know. The warning names a move by its number in the file.
  • A save does not keep the skipped moves, the values or the keys.
  • The step of a skipped move is still a step. A step that has only skipped moves changes nothing. When that step is the last step, the take ends one step before it.
  • A later move can need the code that a skipped move changes. Then Tiza does not open the document. The error names the later move and the skipped move.
  • move.add, scene.put, tiza scene put and add_move refuse a move with an action or a value that this version does not know. move.add, scene.put and tiza scene put also refuse a key of a move that this version does not know, or a key inside a position. add_move refuses an argument that the action does not use.

Fields of a code.patch move

FieldTypeDefaultMeaning
op"insert", "replace" or "delete"RequiredThe change to make.
position (insert)stringRequired when it is the targetFor insert, the one line before which Tiza puts the content, up to one more than the last line.
position (replace, delete)stringRequired when it is the targetFor replace and delete, the line range, "7" or "7-9".
after, beforestringRequired when it is the targetFor insert only, a text in the line next to the new content.
findstringRequired when it is the targetFor replace and delete only, a text in the one line to change.
find_start, find_endstringRequired together when they are the targetFor replace and delete only, texts in the first line and the last line of the range.
occurrenceintegerNo defaultThe match of find, after, before or find_start to use, from 1.
end_occurrenceintegerNo defaultThe match of find_end to use, from 1.
contentstringRequired for insert and replaceThe new lines, with \n between them.
typing"instant", "line" or "char""instant"How Tiza shows the new lines.
speed_msinteger120 for line, 25 for charThe milliseconds for each line or each character, at most 3,600,000.
  • Give exactly one target: position, after, before, find, or find_start with find_end.
  • An insert position is one line. Tiza refuses a range.
  • A delete has no content. Tiza ignores a \n at the end of content.
  • find_end must not come before find_start.

Each image in this section is a real tiza render export of the document above it, from step 0 to step 1. The code is docs/frames/ownership.rs, a copy of examples/ownership.rs.

An insert puts a line after the line with let n = len(&t);:

Lines 6 to 8 at step 0. At step 1, the new line let m = n * 2; comes after line 7, and println moves down one line.

patch-insert.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "moves": [
    {"at_step": 1, "action": "code.patch", "op": "insert",
     "after": "let n = len(&t);", "content": "    let m = n * 2;"}
  ]
}

Save it as patch-insert.tiza next to ownership.rs. Then run tiza patch-insert.tiza --present --step 0, and press → to go to the next step.

A replace changes the line with println!:

Lines 6 to 8 at step 0. At step 1, the println on line 8 prints {n} letters in {t} in place of {t} has {n} letters.

patch-replace.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "moves": [
    {"at_step": 1, "action": "code.patch", "op": "replace",
     "find": "println!", "content": "    println!(\"{n} letters in {t}\");"}
  ]
}

Save it as patch-replace.tiza next to ownership.rs. Then run tiza patch-replace.tiza --present --step 0, and press → to go to the next step.

A delete removes the line with println!:

Lines 6 to 8 at step 0. At step 1, the line with println is gone, and lines 6 and 7 stay.

patch-delete.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "moves": [
    {"at_step": 1, "action": "code.patch", "op": "delete", "find": "println!"}
  ]
}

Save it as patch-delete.tiza next to ownership.rs. Then run tiza patch-delete.tiza --present --step 0, and press → to go to the next step.

Where a code.patch move goes

Tiza finds a target on the code as it is at the step of the move. The target must match exactly once, or occurrence names the match.

  • A text target matches part of a line. A line that holds the text two times counts as two matches.
  • When the text occurs more than once, add "occurrence": N to name the match. N starts at 1.
  • Tiza counts the matches in reading order over the whole code at that step. end_occurrence does the same for find_end.

Typing

With "typing": "line" or "char", Tiza types the content on the screen.

  • speed_ms is the time for each line or each character.
  • The annotations of the step appear when the typing ends.
  • Any key except Ctrl-C finishes the typing. Tiza uses that key only to finish the typing.
  • In presentation mode, with the live pointer off, a key that only moves the view does not finish the typing: ↑, ↓, j, k, J, K, g, G, Home and End. The view moves, and the typing continues.
  • Thus an n during the typing finishes the typing. It does not go to the next step. Press n again.

Each image in this section is a real tiza render export of the document above it, from step 0 to step 1. An animated export types as the TUI does.

"typing": "line" types the new lines one at a time. Here speed_ms gives each line 600 ms, so the pause between the two lines shows:

Lines 6 to 8 at step 0. At step 1, let u = t.clone(); comes after line 6, then let v = u.len(); after it, one line at a time.

typing-line.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "moves": [
    {"at_step": 1, "action": "code.patch", "op": "insert", "after": "let t",
     "content": "    let u = t.clone();\n    let v = u.len();", "typing": "line",
     "speed_ms": 600}
  ]
}

Save it as typing-line.tiza next to ownership.rs. Then run tiza typing-line.tiza --present --step 0, and press → to go to the next step.

"typing": "char" types the new line one character at a time:

Lines 6 to 8 at step 0. At step 1, line 7 becomes let n = t.chars().count();, one character at a time.

typing-char.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "moves": [
    {"at_step": 1, "action": "code.patch", "op": "replace", "find": "let n = len(&t);",
     "content": "    let n = t.chars().count();", "typing": "char"}
  ]
}

Save it as typing-char.tiza next to ownership.rs. Then run tiza typing-char.tiza --present --step 0, and press → to go to the next step.

Annotations after a code.patch move

You add an annotation on the code at its own step. A later move changes the lines. Tiza moves the annotation with them. It does not search for text.

  • An insert or a delete moves the lines after it.
  • A box that loses an edge line gets smaller.
  • When a replace replaces a line, a note, a box, a callout or a spotlight on that line goes to the new line. This occurs only when the new content has a line at that position.
  • When the new content has fewer lines, the extra old lines are gone. A note on one of them loses its line, and a box gets smaller.
  • On a replaced line, a highlight, a mark or an arrow end has no text under its span. Tiza hides it as unanchored. Tiza never deletes it.
  • Tiza also hides an annotation that loses every line.

rebind gives the new place of each annotation that the move replaces or deletes. Each key is the id of an annotation. Tiza finds the target of each entry on the code after the move. For example:

"rebind": {"a4": {"at": {"find": "t.len()", "occurrence": 1}}}
AnnotationFields of a rebind entry
A highlight or a markat, a point
A noteat, a point, or from_line
An arrowfrom, to or both, each a point
A box, a callout or a spotlightfrom_line, to_line or both
  • Each field of an entry is optional, but an entry needs at least one. Tiza refuses a key that it does not know. It also refuses an empty entry for an annotation of the document.
  • Only a code.patch move can have rebind.
  • Tiza keeps an entry for an annotation that is not in the document, and ignores it. tiza render gives a warning for it, and tiza check names it.

A highlight on len(&t) at step 1, and a replace of its line at step 2 with a rebind entry for it. The image is a real tiza render export of this document, from step 1 to step 2:

At step 1, len(&t) on line 7 has a tint and the label borrow. At step 2, line 7 is let n = t.len(); and the tint and the label are on t.len().

rebind.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "annotations": [
    {"id": "h1", "step": 1, "type": "highlight",
     "span": {"line": 7, "start": 12, "end": 19}, "label": "borrow"}
  ],
  "moves": [
    {"at_step": 2, "action": "code.patch", "op": "replace", "find": "let n = len(&t);",
     "content": "    let n = t.len();", "rebind": {"h1": {"at": {"find": "t.len()"}}}}
  ]
}

Save it as rebind.tiza next to ownership.rs. Then run tiza rebind.tiza --present --step 1, and press → to go to the next step.

:list marks a hidden annotation ! unanchored. The socket method scene.list and the MCP tool list_annotations mark it (unanchored). tiza check gives a warning for it, with its steps.

Point

select and a rebind entry use this object for one point of the code.

FieldTypeDefaultMeaning
findstringRequired when there is no lineThe text to find in the code.
occurrenceintegerNo defaultThe match of find to use, from 1.
lineintegerRequired when there is no findThe line of the point, or the line where find searches (see the list under this table).
colintegerDepends on the use (see the list under this table)The grapheme of the point, counted from 0, at most the length of the line.
endintegerThe end of the lineIn a rebind at with line, the grapheme after the span, at most the length of the line.
  • In a select, find searches only line when the point has one. Otherwise it searches the whole code.
  • In a select, find must match exactly once, or the point must have occurrence.
  • In a rebind entry, find searches line first, and then the whole code.
  • In a rebind entry without line, find must match exactly once, or the point must have occurrence. With line, Tiza does not check the number of matches.
  • In a select, find in from starts at the start of the text, and find in to ends at the end of the text.
  • The edge of find that gives a column must be on the edge of a character (a grapheme). That is the start in the from of a select and the end in its to, the two edges in a rebind entry of a span, and the start in a rebind entry of an arrow end. For example, a joiner alone in ad U+200D min is an error. Put the whole character in find, or use line and col. The at of a note takes only the line, so there it is not an error. A document whose select or rebind entry has such a find does not open, and the error names the move. tiza check gives the same error.
  • In a select without col, from is the start of the line and to is the end of the line. In a rebind entry, the default col is 0.

Several files

A code.link move shows another file from its step on. Each file is a view, with its own annotations. For example:

{"at_step": 2, "action": "code.link", "file": "src/queue.rs", "lines": "10-36"}
FieldTypeDefaultMeaning
filestringRequiredThe file to show, as a path relative to the .tiza file.
lines"7" or "7-30"The whole fileThe window of the file on the screen, starting at line 1.

At step 2, :link src/queue.rs:10-36 adds the same move.

  • An annotation that you add while a file is shown belongs to that file. It gets a "file" field. Without file, it belongs to the document's own file.
  • The lines of an annotation are the real line numbers of its file.
  • lines is only a window that crops the screen. Tiza keeps a note outside the window. Tiza does not draw it.
  • The same file with another window is the same view.
  • When you link the document's own file again, its annotations return exactly as they were.
  • At the step of a code.link, the cursor goes to the first line that the link shows. That is the first line of the file, or of its window. The view goes with the cursor. This also occurs when the link goes back to the document's own file.
  • In normal mode, this also occurs at each later step, until another cursor, code.link or scroll move. A cursor move does the same with its line. In presentation mode, it occurs only at the step of the move.
  • A code.patch move changes the file shown at its step.
  • :embed stores every linked file under views. Thus the document stays one .tiza file.
  • A document fails to load when a linked file cannot be read. The error names the move and the path.

This image is a real tiza render export of the document under this paragraph, from step 0 to step 1. At step 1, the screen shows lines 17 to 23 of queue.rs, with a box of that file. A note on each file names it: the export does not show the name of a file.

When a document has a code.link move or an annotation of another file, :list groups the annotations of each step by file. scene.list ends the line of an annotation of another file with that file. For example:

a4 [step 3] box L15-17 (src/queue.rs)

Cursor, select and wait

cursor

FieldTypeDefaultMeaning
lineintegerRequiredA line of the shown file.
colinteger0The grapheme of the cursor, at most the length of the line.

select

FieldTypeDefaultMeaning
fromobjectRequiredThe start of the selection, a point.
toobjectRequiredThe end of the selection, a point.

wait

FieldTypeDefaultMeaning
msintegerRequiredThe pause in milliseconds, from 1 to 3,600,000.
  • n applies these moves. p reverts them.
  • A code.link move removes the cursor and the selection.
  • tiza render --step N and the image exports draw the cursor and the selection immediately.
  • The TUI, the GIF, MP4 and WebM exports and the .tape show the pause of a wait. A .cast adds the pause to the time of the step, except at the last step.
  • A still export ignores a wait.

A cursor move at step 1 and a select move at step 2. The image is a real tiza render export of this document, from step 1 to step 2:

At step 1, the cursor is on t in line 6. At step 2, len(&t) on line 7 is selected, and the cursor stays on t.

cursor-select.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "6-8"},
  "moves": [
    {"at_step": 1, "action": "cursor", "line": 6, "col": 8},
    {"at_step": 2, "action": "select",
     "from": {"line": 7, "find": "len(&t)"}, "to": {"line": 7, "find": "len(&t)"}}
  ]
}

Save it as cursor-select.tiza next to ownership.rs. Then run tiza cursor-select.tiza --present --step 1, and press → to go to the next step.

Scroll

A scroll move moves the view of the TUI to a line, a text or an annotation when the presenter reaches its step. Thus an effect never plays out of the view. A step that has only a scroll move is a camera step: the view moves, and nothing else changes.

FieldTypeDefaultMeaning
lineintegerRequired when it is the targetA line of the code where the move runs.
findstringRequired when it is the targetA text of the code where the move runs. The view goes to its first match.
occurrenceintegerNo defaultWith find only: the match to use, from 1.
annotationstringRequired when it is the targetThe id of an annotation. The view shows its lines, with its borders and its labels.
align"top", "center", "bottom" or "show""center"Where the target goes in the view. "show" moves the view as little as possible to show the target.

A scroll move has exactly one target: line, find or annotation.

{"at_step": 3, "action": "scroll", "line": 50}
{"at_step": 4, "action": "scroll", "find": "fn drop", "align": "top"}
{"at_step": 5, "action": "scroll", "annotation": "b2", "align": "bottom"}
At step 1, the view shows the top of the code. At step 2, line 15 goes to the top of the view. At step 3, Tiza draws a box around lines 15 to 17.

The view goes to fn takes at step 2, a camera step. The document has a note at step 1, a scroll move with "find": "fn takes" and "align": "top" at step 2, and a box with the draw effect at step 3. The code is examples/ownership.rs. This is a screen recording of the TUI in presentation mode, in a real terminal of 100 columns and 10 rows, with the Menlo font.

  • When the presenter reaches the step, the view moves to the target. Then the annotations of the step come in, with their effects.
  • The view stays on the target while its rows move: when the annotations of the step come in after a typed move or a wait, when presentation mode starts or stops, and when the terminal changes size. When the presenter moves the view, the cursor or the pointer, the view stays where the presenter puts it.
  • In normal mode, a step with no scroll move of its own does not move the view. In presentation mode, when you go to a step or Tiza opens at it, the new annotations of the step and the lines that its moves write come into the view, and the view moves as little as possible. See Present for when this occurs. :goto and the other goto commands move the view to the target of the scroll of their step, and in presentation mode they then show what comes in at the step. A goto to the step on screen does the same as a goto to it from a step of the same file. Thus a cursor or a code.link of the step puts the cursor on its line again, and the view goes with it.
  • At a step that no scroll move reaches (no scroll at that step or before it), after a step with one, the view goes to the top. A cursor or a code.link move then moves the view only when its line is not in view.
  • A cursor, a code.link and a scroll move all put the view somewhere. The last of them in the order that the moves run wins: the order of the steps, then the order of the list. When a cursor or a code.link wins, the view does what it did before scroll. In presentation mode, a cursor or a code.link moves the view only at its own step.
  • In a step that types, a scroll move moves the view at its place in the list, before or after a typed move or a wait. It takes no time.
  • The annotation can be of a later step. The view then goes to the lines where the annotation will come in.
  • The view keeps rows for the parts of the target that come in later: the borders, the labels and the callouts of an annotation of a later step, or of the step after a typed move or a wait. When they come in, the lines of the target keep their rows. The new rows above the target push the code above it up, and the new rows under the target push the code under it down. Rows that come in inside the target make it taller, so its lines move apart.
  • Near the start or the end of the code, the view stops at the first or the last line. The target then stays as near to its place as it can.
  • When the live pointer is on and the view moves, the pointer stays if the new view shows its lines. If not, the pointer goes off.
  • A scroll move puts the cursor on the first line of its target. When the live pointer stays, the cursor stays with the pointer: j and k continue from the pointer. To go to an annotation, press Tab.
  • The view moves in normal mode and in presentation mode.
  • A target that does not resolve does not stop the step: the scroll move does not place the view, and tiza check gives a warning. In presentation mode, the new annotations of the step then come into the view. Examples are a line that is not in the code, a text that is not in the code, and an annotation that does not exist.
  • A find that matches more than once goes to the first match. tiza check gives a warning, unless occurrence names the match or all the matches are on one line.
  • When a later move of the same step removes the line of the target, the scroll move does not place the view, and tiza check gives a warning.
  • The exports show the whole take, so they ignore scroll moves. A step that has only a scroll move is a pause in a GIF, WebP, MP4 or WebM, as any step is. Its auto_advance_ms makes the pause shorter.
  • Tiza 0.1.2 and older do not open a document that has a scroll move.

Exports and moves

  • tiza render --step N and .cast apply the moves immediately.
  • A .tape runs the TUI, so the TUI types each typed move. A GIF, MP4 or WebM export shows the typing as frames.
  • tiza render --step N after the last step writes a warning on stderr. It shows the last step.
  • An export that records the steps (GIF, MP4, WebM, .cast, .tape) gives no such warning.
  • A .tape holds a step for its typing and its wait moves, plus half a second. When --interval is longer, it holds the step for --interval.

Named steps

Named steps, auto-advance and loop are automation. Use them for an unattended export, a screen that loops or an editor task that goes to the next step. They do not add speaker notes, a timer or a remote control.

For example:

"steps": [{"step": 3, "id": "borrow", "title": "Shared borrow", "auto_advance_ms": 3000}]
FieldTypeDefaultMeaning
stepintegerRequiredThe number of the step that the entry names, from 0 to 999.
idstringNo defaultThe name that the goto commands use, under the id rules of this section.
titlestringNo defaultThe text that the status bar and status show.
auto_advance_msintegerNo defaultThe time in milliseconds before Tiza goes to the next step by itself, from 1 to 3,600,000.
  • An entry names its step by number, never by its place in the list. Thus + and - move an annotation to another step and change no entry.
  • Entries can skip steps. Tiza saves them sorted by step.
  • One step has one entry or none.

An id must obey these rules. The error for each rule is in Messages.

  • It is not empty. To give no id, leave the field out.
  • It is unique.
  • It is one word. A control character counts as a blank.
  • It is not all digits, because a number always means a step number.
  • It does not start with -, because tiza goto -1 reads it as an option.

Go to a named step

The goto commands go to a step exactly as n does from step 0. Tiza applies the moves and the linked files again. A typed step shows all its text. An unknown id is a not_found error.

CommandWhat it does
:goto IDGoes to the named step, or to a step number.
step.goto {"id": "ID"}The socket method that does the same as :goto ID.
goto_stepThe MCP tool that does the same as :goto ID.
tiza goto IDMakes the live instance do the same as :goto ID.
tiza nextMakes the live instance go to the next step.
tiza prevMakes the live instance go to the previous step.
  • tiza next, tiza prev and tiza goto need no JSON. They use the socket of the session, or --socket and --session as tiza api does.
  • They print the step that the instance reached, for example step 3/7 · Shared borrow.
  • When no instance runs, they exit with a non-zero code and an error. See Messages.

The status reply has these fields about the step:

FieldTypeMeaning
stepintegerThe step on screen.
max_stepintegerThe last step of the document.
step_idstringThe id of the step on screen. The reply leaves it out when the step has no id.
step_titlestringThe title of the step on screen. The reply leaves it out when the step has no title.
step_labelstringThe step and its title, for example step 3/7 · Shared borrow.
auto_advance_msintegerThe auto_advance_ms of the step on screen. The reply leaves it out when the step has none.
looptrueThe document loops. The reply leaves it out when the document does not loop.

Presentation mode has no status bar. Thus n, p and an auto-advance do not show the title in a take. A : command, such as :goto ID, shows its result on the last row for 2 seconds. That result can be step N/M · TITLE.

Auto-advance

With auto_advance_ms, the TUI goes to the next step by itself. The time starts when the step is ready: the typing has finished, and each wait move has elapsed.

  • A key during the typing only finishes the typing. In presentation mode, with the live pointer off, a key that only moves the view moves the view and does not finish the typing.
  • An open : line, a v or V selection, the help, the list or the review holds the countdown until it closes.

Exports use auto_advance_ms in different ways:

  • A GIF, animated WebP, MP4 or WebM export holds such a step for auto_advance_ms instead of --interval.
  • A .tape holds such a step for its typing plus auto_advance_ms, and sends no n for the next step.
  • A .cast ignores auto_advance_ms. It holds each step for --interval plus its wait moves. The last step holds for --interval only.

Loop

With "loop": true, n after the last step goes back to step 0. An auto-advance on the last step does the same. Without loop, Tiza stays on the last step.

Entries that Tiza does not use

Tiza never drops these entries:

  • An entry for a step after the last step.
  • A key of an entry that Tiza does not know, for example a typo or the old timer_min.

Tiza keeps them in the file. It gives one warning for each entry, and the warning names all the unknown keys of that entry. The warning appears when you open the document. It also appears in status.warnings and in the output of tiza render and tiza check.

Only the entries of steps keep unknown keys. Tiza does not keep an unknown key at the top level, in an annotation or in a move. For a move, tiza check gives a warning (see Moves from a newer version).

A position can also have a key that Tiza does not know. These are the positions:

  • a span;
  • an arrow end;
  • the from and to of a select move;
  • the at, from and to of a rebind entry.

The document opens, and Tiza ignores the key. tiza check gives a warning with a known key that is near. A save does not keep the key, and tiza scene put refuses the document. A span calls its first grapheme start. An arrow end and a select point call it col.

The key can be a key that the position needs, under another name, for example col in a span. Then the position does not have the key that it needs, and the document does not open. The error names the key that Tiza took out, and the name to use.

Enter effects (experimental)

This function is an experiment. It can change or go away.

An enter effect shows how an annotation comes in when the step goes forward. Set it with the effect field of the annotation. An annotation without effect comes in at once, as before. The layout does not change. The effect only changes which cells of the final drawing show, and their colors.

{"id": "b1", "step": 2, "type": "box", "from_line": 10, "to_line": 14, "effect": "draw"},
{"id": "n1", "step": 2, "type": "note", "line": 11, "text": "drop runs here"}

At step 2, Tiza draws the stroke of the box. The note comes in at once.

ValueMeaning
"draw"Tiza draws the stroke of the annotation along its path. The code that the annotation colors fades in with the stroke. Then the text of the annotation fades in.
"fade"The annotation fades in, with its text. On a spotlight, the dim fades in and fades out.

Each image under this paragraph is a real tiza render export of the document above it, from step 0 to step 3. An animated export shows the enter effects as the TUI does.

draw on a box at step 1, an arrow at step 2 and an underline at step 3:

Lines 1 to 8. At step 1, the border of a box on lines 6 to 8 is drawn, then the label shared comes in. At step 2, an arrow from s on line 2 to s on line 3 is drawn. At step 3, a line is drawn under &t on line 7.

effect-draw.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "1-8"},
  "annotations": [
    {"id": "b1", "step": 1, "type": "box", "from_line": 6, "to_line": 8,
     "label": "shared", "effect": "draw"},
    {"id": "a1", "step": 2, "type": "arrow", "from": {"line": 2, "col": 8},
     "to": {"line": 3, "col": 10}, "label": "moves", "effect": "draw"},
    {"id": "h1", "step": 3, "type": "highlight", "span": {"line": 7, "start": 16, "end": 18},
     "emphasis": "underline", "label": "borrow", "effect": "draw"}
  ]
}

Save it as effect-draw.tiza next to ownership.rs. Then run tiza effect-draw.tiza --present --step 0, and press → to go to the next step.

fade on a note at step 1 and on a spotlight at step 2. The spotlight has no until, so its dim fades out at step 3:

Lines 1 to 8. At step 1, the note s moves into takes fades in. At step 2, lines 1 to 5 and the note fade to dim. At step 3, the dim fades out, and the note t is still here comes in at once.

effect-fade.tiza

{
  "schema": 1,
  "source": {},
  "code": {"file": "ownership.rs", "lines": "1-8"},
  "annotations": [
    {"id": "n1", "step": 1, "type": "note", "line": 3, "text": "s moves into takes",
     "effect": "fade"},
    {"id": "s1", "step": 2, "type": "spotlight", "from_line": 6, "to_line": 8,
     "effect": "fade"},
    {"id": "n2", "step": 3, "type": "note", "line": 8, "text": "t is still here"}
  ]
}

Save it as effect-fade.tiza next to ownership.rs. Then run tiza effect-fade.tiza --present --step 0, and press → to go to the next step.

  • draw needs a stroke. A box, a callout, an arrow, and a highlight or a mark with the emphasis underline, brackets or strike have a stroke. A note, a spotlight, and a highlight or a mark with fill do not have a stroke.
  • An annotation from a file can have draw without a stroke. It comes in with no effect, and tiza check gives the warning effect.
  • Tiza 0.1.2 and older versions do not know effect. They open the document and show the annotation with no effect. When they save the document, they drop effect and give no warning.
  • A file can have an effect value that this version of Tiza does not know, for example from a newer version. The document opens, and the annotation comes in with no effect. When the TUI opens the file, it writes each annotation and its value on stderr, where you see the line after the TUI ends, and the status bar shows how many entries are not known, with the moves and the values that this version does not know. In presentation mode, the last row shows it for 2 seconds. tiza check gives the warning effect, and a save does not keep the value.
  • Tiza draws a box or a callout clockwise from its top-left corner. When a box has a label or a callout has a title, Tiza starts after the label or the title. Thus the border before it comes in last. Tiza draws an underline, brackets and a strike from left to right, and an arrow from its source. On a strike, the text fades in along the whole stroke, as with an underline, and each letter gets its mark when the line comes to it.
  • The annotations of one step come in at the same time. The text of a draw annotation comes in after the longest stroke of the step. To show annotations one after the other, put them on consecutive steps.
  • The dim of a step comes from all the active spotlights together. When a spotlight with fade starts or stops at a step, all the dim of that step fades. A spotlight stops at the step after its until, or at the step after its step when it has no until. A spotlight that is active until the last step does not stop.
  • When only spotlights without fade start or stop at a step, the dim changes at once.
  • The effect plays when you go forward one step: n, an auto-advance, or a goto to the next step. It plays after the typing of the step. While the step types, the dim of the step before stays when the dim fades at the step: a spotlight with fade starts or stops there. If not, the dim of the step shows while it types.
  • A goto that goes forward more than one step, a step back, p and the loop back to step 0 show the final drawing. When the document opens, Tiza also shows the final drawing. Thus an annotation at step 0 never plays its effect.
  • A key ends the effect, and Tiza ignores that key. A key that ends the typing of a step also ends its effect.
  • With the mouse on, in normal mode, a click or a drag of any button ends the effect as a key does. The wheel lets the effect play. With the live pointer on, a notch of the wheel ends the effect and does nothing else, as a key does.
  • In presentation mode, a key that only moves the view does not end the effect: ↑, ↓, j, k, J, K, g, G, Home and End. The view moves and the effect continues. Thus a trackpad or a mouse wheel does not end the effect. With mouse capture, the wheel moves the view. Without mouse capture, the terminal sends the wheel as ↑ and ↓. When the live pointer is on, these keys end the effect, as any other key does. With mouse capture and the live pointer on, a notch of the wheel also ends the effect, and does nothing else.
  • A change of the live pointer ends the effect, for example when an agent points at a line or the pointer goes off.
  • The auto-advance countdown starts when the effect ends.
  • On the screen, an effect plays at 60 frames each second, or at 30 with effect_fps = 30 in the config file. A GIF, a WebP or a video plays it at 25 frames each second.
  • A GIF, an animated WebP, an MP4 and a WebM show the effect of each step as frames. The first step of the take shows the final drawing, as when the document opens. A .tape records the TUI with its effects. A still, a text export, a .md, a .cast and render --step N show the final drawing.
  • With the terminal theme, a fade changes the color in one step at its middle.

Rules the schema does not check

The document schema accepts some documents that Tiza refuses. Tiza does not load a document that breaks one of these rules:

  • schema is at most 1.
  • Every at_step is 1 or more, because step 0 is the code with no change.
  • No annotation, move or entry of steps names a step after 999.
  • wait.ms is 1 or more.
  • wait.ms, speed_ms and auto_advance_ms are at most 3,600,000 ms, one hour.
  • With embedded code, source.first_line is at most 1,000,000,000.
  • Each code.patch move has exactly one target, of a type that its op accepts.
  • Each scroll move has exactly one target: line, find or annotation. Only a scroll with find has occurrence, and occurrence is 1 or more.
  • insert and replace have content, and delete has no content.
  • Each annotation id is unique.
  • Each step id obeys the rules of Named steps.
  • Only a code.patch move has rebind.
  • A rebind entry for an annotation of the document is not empty.

A spotlight with no from_line and no ids also passes the schema. Tiza loads it, and tiza check gives an error for it.

The schema also refuses some documents that Tiza opens: a file from a newer version with a move action, an op, a value of align or typing, an effect or a key of a position that this version does not know. See Moves from a newer version.

Status bar

Status barMeaning
↪ FILE:A-BA code.link move shows FILE with the window A-B.
↪ FILEA code.link move shows FILE with no window.
step N/M · TITLEThe step on screen has a title.
step N/M · IDThe step on screen has an id and no title.

The status bar cuts a long title to 32 columns. For example:

↪ src/queue.rs:10-36
step 3/7 · Shared borrow
The status bar shows step 2/5 · args.rs: one flag, by hand and ↪ tally/src/args.rs:14-30.

Step 2 of examples/tally-tour.tiza in normal mode, with its title and its code.link: an image of the TUI in a real terminal of 100 columns and 30 rows, with the Menlo font.

Messages

MessageWhen
cannot paste while moves are applied (step N): go back to step 0 firstYou paste at a step where a move is applied.
cannot show another file's code while moves are applied (step N): go back to step 0 first:ref or :link names a file with other code while a move is applied.
FILE is shown by a code.link at step N, with annotations of its own: delete that link first to reference it:ref or :link names a file that a code.link move shows.
tiza: step N does not exist (the document has steps 0 to M); showing step Mtiza render --step N names a step after the last step, for an export that does not record the steps.
tiza: no Tiza instance is listening on PATH (open `tiza <file>` or pass --socket/--session)tiza next, tiza prev or tiza goto finds no instance.
no step is named "ID" (named steps: IDS)A goto command names an unknown id.
no step is named "ID": the document has no named stepsA goto command names an id, and the document has no named steps.
step N is beyond the last step (M)A goto command names a step number after the last step.
step "ID" names step N, beyond the last step (M)A goto command names an id whose entry is after the last step.
steps: entry «ID» names step N, beyond the last step (M); kept, not usedAn entry names a step after the last step.
steps: entry «ID» (step N) has unknown key `KEY`; kept in the file, not used (known: step, id, title, auto_advance_ms)An entry has a key that Tiza does not know.
steps: two entries name step N (one entry per step)Two entries name the same step.
steps: the entry of step N has an empty `id` (leave it out instead)An id is empty.
steps: id "ID" is used twice (ids must be unique)Two entries have the same id.
steps: id "ID" (step N) has blanks; use one word (`shared-borrow`)An id has more than one word.
steps: id "ID" (step N) is all digits; a number means a step number, so ids need a letterAn id is all digits.
steps: id "ID" (step N) starts with `-`, which `tiza goto` would read as an option; start it with a letter or a digitAn id starts with -.
steps: `auto_advance_ms` of step N is 0; give at least 1 ms or leave it outAn auto_advance_ms is 0.
WHAT: step N is past the last step a document can have (999)An annotation, a move or an entry names a step after 999.

The message no Tiza instance is listening on … ends with the error of the system. tiza goto writes tiza: before each goto message. It ends a message about an unknown id with (not_found). It ends a message about a step after the last step with (invalid_argument). For example:

tiza: no step is named "x" (named steps: a) (not_found)

The other messages of tiza are in Messages.

Special cases

A paste while a move is applied

Tiza refuses a paste while a move is applied. Go back to step 0 first. The message is cannot paste while moves are applied (step N): go back to step 0 first.

At step 0, a paste applies the moves again on the pasted code. Tiza anchors each annotation again on the code at its own step. Thus an arrow at step 3 stays on a line that a move typed.

Follow mode with moves

A save in the editor waits while a code.patch is applied. A patch is applied when its at_step is the current step or before it. The change loads at the step before the first patch, or at an earlier step. Thus a document without patches never waits. See Moves in Follow the editor.

How it works

A document depends only on its step. Tiza applies each move up to the current step, in step order, on the code of step 0. Going back applies fewer moves. The document and :embed always keep the code of step 0.

A code.patch move gives the new place of each line. Tiza moves the annotations with the lines. Tiza does not search for text.