% !TeX program = lualatex
% =====================================================================
%  scholatex.tex  --  user documentation for the scholatex package
%
%  This is a STANDALONE document: it uses the standard article class and
%  compiles with any LuaLaTeX (or pdfLaTeX) distribution, independently
%  of the scholatex class it documents. It does NOT require any images.
%
%  Compile:  lualatex scholatex.tex   (twice, for the table of contents)
% =====================================================================
\documentclass[11pt,a4paper]{article}

\usepackage[T1]{fontenc}
\usepackage[margin=25mm]{geometry}
\usepackage{xcolor}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{array}
\usepackage{enumitem}
\usepackage{fancyvrb}
\usepackage{titlesec}
\usepackage[colorlinks=true,linkcolor=Navy,urlcolor=Navy]{hyperref}

% \fint (average integral) built as an integral crossed by a short bar,
% without pulling in esint/commath, so the documentation keeps compiling on
% a bare amsmath + graphicx setup.
\usepackage{graphicx}
\providecommand{\fint}{\mathchoice
  {\rlap{\,\,\raisebox{0.32em}{\scalebox{0.7}{$-$}}}\!\int}
  {\rlap{\,\,\raisebox{0.30em}{\scalebox{0.6}{$-$}}}\!\int}
  {\rlap{\,\raisebox{0.28em}{\scalebox{0.5}{$-$}}}\!\int}
  {\rlap{\,\raisebox{0.28em}{\scalebox{0.5}{$-$}}}\!\int}}

% The surface/volume integrals and the integer-interval brackets are shown in
% the maths table below. Under unicode-math the package provides \oiint,
% \iiint, \lBrack and \rBrack natively; here, on a bare amsmath setup, we
% supply lightweight fallbacks so the documentation keeps compiling without
% esint or stmaryrd. They illustrate the syntax, not the production glyph.
\providecommand{\oiint}{\mathop{\vcenter{\hbox{$\oint\!\!\!\!\oint$}}}}
\providecommand{\iiint}{\mathop{\vcenter{\hbox{$\int\!\!\!\int\!\!\!\int$}}}}
\providecommand{\llbracket}{\mathopen{[\![}}
\providecommand{\rrbracket}{\mathclose{]\!]}}

\definecolor{Navy}{HTML}{1F3A5F}
\definecolor{CodeBg}{HTML}{F4F5F7}
\definecolor{CodeFrame}{HTML}{D7DBE0}
\definecolor{Accent}{HTML}{8A1C1C}

% --- code blocks -----------------------------------------------------
\DefineVerbatimEnvironment{slcode}{Verbatim}{%
  frame=single,
  framerule=0.4pt,
  rulecolor=\color{CodeFrame},
  fontsize=\small,
  xleftmargin=4mm,
  xrightmargin=4mm,
  framesep=3mm,
  formatcom=\color{black!88}}

\newcommand{\tg}[1]{\texttt{#1}}
\newcommand{\opt}[1]{\texttt{\textcolor{Accent}{#1}}}

% Three-level hierarchy: \part for the broad categories, \section and
% \subsection beneath. \part is reformatted as a compact coloured banner
% (no dedicated blank page), so the table of contents reads as a plan
% without wasting a page per part. The leading \par in the format forces
% vertical mode, so a \part may follow a paragraph of prose directly
% without titlesec's "Entered in horizontal mode" error.
\titleformat{\part}[block]
  {\bigskip\Huge\bfseries\color{Navy}}
  {\partname~\thepart\quad}{0pt}{}
\titlespacing*{\part}{0pt}{0.4em}{0.8em}
\titleformat{\section}{\Large\bfseries\color{Navy}}{\thesection}{0.6em}{}
\titleformat{\subsection}{\large\bfseries\color{Navy!85!black}}{\thesubsection}{0.6em}{}
\titlespacing*{\section}{0pt}{1.4em}{0.5em}
\setcounter{tocdepth}{2}

% Section numbering restarts at 1 in every part (each part is a fresh
% chapter-like unit), instead of running 1..n across the whole document.
\usepackage{chngcntr}
\counterwithin*{section}{part}

\setlength{\parindent}{0pt}
\setlength{\parskip}{0.55em}

\hypersetup{
  pdftitle={scholatex --- user manual},
  pdfauthor={Gerard Dubard},
}

% =====================================================================
\begin{document}

\begin{titlepage}
\centering
\vspace*{3.5cm}
{\Huge\bfseries\color{Navy} scholatex\par}
\vspace{0.8cm}
{\Large Print-ready teaching worksheets, the easy way\par}
\vspace{2.5cm}
{\large A small tag-based language for handouts and exercises,\\[2pt]
built on LuaLaTeX\par}
\vspace{3cm}
{\large Gérard Dubard\par}
\vspace{0.4cm}
{\large Version 2.5\par}
\vfill
{\small Released under the GNU General Public License v3.0\par}
\end{titlepage}

\tableofcontents
\newpage

% =====================================================================
\part{Getting started}


% =====================================================================
\section{Introduction}
% =====================================================================

\textbf{scholatex} is a small markup language for producing print-ready
teaching materials --- worksheets, exercise sheets, handouts, short
assessments --- without writing LaTeX. It is not a general-purpose
replacement for LaTeX; it is a focused, consistent little language for the
documents a teacher actually makes: a few framed exercises, a table of
results, a couple of simple formulas, an image or two, laid out cleanly on
a page meant to be printed and handed out.

It compiles to LuaLaTeX, so the output has full LaTeX typesetting quality,
but the syntax is meant to be read and edited in minutes by someone who
does not know LaTeX: no \tg{\textbackslash begin\{tabular\}\{|c|c|\}}, no
counting ampersands, no hunting for the package that draws a coloured box. A
single tag syntax covers text, tables, images, simple maths, framed boxes,
lists and full-page named-area layouts --- the building blocks of a
worksheet. scholatex is a \emph{closed language}: the backslash is an
ordinary character, so raw LaTeX commands in the body are typeset literally
rather than executed. Everything a worksheet needs is expressed through tags,
which keeps documents consistent and safe to share.

It is built for the people LaTeX usually loses: teachers preparing
classroom materials, and anyone who wants a clean printable sheet without
climbing the LaTeX learning curve.

You write a \tg{.tex} file with a tiny, readable syntax between
\tg{\textbackslash begin\{document\}} and \tg{\textbackslash end\{document\}}.
At compile time the \tg{scholatex} class reads that body, transpiles it to
LaTeX, and typesets it. Nothing to install beyond a LuaLaTeX distribution.

\begin{slcode}
% !TeX program = lualatex
\documentclass[margins=20, size=12, imgdir=IMG]{scholatex}
\begin{document}

<Navy b 18pt c>My first scholatex document

This is a normal paragraph. <b>{Bold}, <i>{italic}, <Red>{red}.

<box line:Navy fill:AliceBlue radius:3 title:{A framed note}>{
Boxes, tables, images and maths all use the same tag syntax.
}

\end{document}
\end{slcode}

% =====================================================================
\section{The one rule}
% =====================================================================

Everything is a \textbf{tag}: \tg{<attributes>} followed either by
\tg{\{content\}} (inline) or by a line that ends in \tg{\{} (a block).
Attribute words follow a single case convention:

\begin{center}
\begin{tabular}{@{}lll@{}}
\toprule
\textbf{Form} & \textbf{Meaning} & \textbf{Examples} \\
\midrule
\tg{lowercase} & a short keyword (style, alignment, skip) & \tg{b}, \tg{i}, \tg{c}, \tg{2tab} \\
\tg{CamelCase} & a CSS colour (151 of them) & \tg{Navy}, \tg{SteelBlue}, \tg{Crimson} \\
\tg{UPPERCASE} & a font name & \tg{DEJAVU SANS} \\
\bottomrule
\end{tabular}
\end{center}

The order of words inside a tag never matters --- emission is always
normalised (page break, then vertical skips, then alignment, then tabs, then
styles).

% =====================================================================
\section{Class options}
% =====================================================================

Set in \tg{\textbackslash documentclass[...]\{scholatex\}}:

\begin{center}
\small
\begin{longtable}{@{}p{2.4cm}p{2.6cm}p{8.4cm}@{}}
\toprule
\textbf{Option} & \textbf{Default} & \textbf{Meaning} \\
\midrule
\endhead
\opt{margins} & \tg{20} & \tg{N} (all sides) or \tg{\{top,right,bottom,left\}} in mm \\
\opt{font} & \tg{Latin Modern Roman} & main text font \\
\opt{mathfont} & \tg{Latin Modern Math} & math font \\
\opt{size} & \tg{11} & base font size in pt \\
\opt{imgdir} & \tg{img} & folder(s) searched for bare image names; accepts a comma-separated list, e.g. \tg{\{IMG, IMAGES/PNG\}} \\
\opt{tabwidth} & \tg{8} & width of one tab, in mm \\
\opt{lineheight} & \tg{8} & height of one explicit line skip (\tg{<line>}, \tg{<Nlines>}), in mm \\
\opt{linespread} & \tg{1.0} & overall line spacing (\tg{1.5} = one-and-a-half); tall maths never touches even at \tg{1.0} \\
\opt{scriptscale} & \tg{100} & scale (\%) of \tg{up}/\tg{down} scripts \\
\opt{padding} & \tg{2} & inner padding (mm) between a box/grid-area frame and its content \\
\opt{lang} & \tg{fr} & decimal separator: \tg{fr} (comma) or \tg{en} (point); affects both literal decimals in maths and interpolated values \\
\opt{untrusted} & \tg{false} & when \tg{true}, runs the document's Lua in a restricted sandbox (see \S\ref{sec:security}) \\
\bottomrule
\end{longtable}
\end{center}

Headings carry no extra vertical space of their own, and no built-in colour:
to style a heading (colour, weight, size, or a line skip before it), fold a
heading keyword into an alias and use it (see \S\ref{sec:aliases}).

% =====================================================================
\part{Text and structure}


% =====================================================================
\section{Text attributes}
% =====================================================================

\textbf{Inline styles} --- \tg{b} bold, \tg{i} italic, \tg{u} underline,
\tg{emph}, \tg{sf} sans-serif, \tg{sc} small caps.

\textbf{Colours} --- a colour is always one of the 151 CSS / svgnames
colours, written in CamelCase: \tg{Navy}, \tg{Red}, \tg{Tomato},
\tg{SteelBlue}, \tg{ForestGreen}, \dots. There is a single rule --- no
lowercase shortcuts --- so the everyday colours are simply capitalised:
\tg{Red}, \tg{Blue}, \tg{Green}, \tg{Gray}. These are exactly the colours
xcolor provides under \tg{svgnames}: the 147 CSS Color Module names plus the
four X11 extras \tg{LightGoldenrod}, \tg{LightSlateBlue}, \tg{NavyBlue} and
\tg{VioletRed}. Names are case-sensitive --- write \tg{Seashell}, not
\tg{SeaShell}. The \texttt{README} groups all 151 by family for browsing.

\textbf{Fonts and sizes} --- a font name in CAPITALS
(\tg{<DEJAVU SANS>\{\dots\}}); sizes as \tg{Npt} or \tg{Npx}
(\tg{<14pt>\{\dots\}}).

\textbf{Alignment} --- \tg{l} left, \tg{c} centre, \tg{r} right, \tg{j}
justified (the same letters as table columns).

\textbf{Tabs and skips} (the number is always a prefix) --- \tg{Ntab} indents
the first line by N tabs; vertical skips follow singular/plural agreement:
\tg{line} or \tg{1line} skips one line, \tg{2lines}, \tg{3lines}, \dots\ skip
several. Bare \tg{tab} = \tg{1tab}.

\textbf{Scripts} --- \tg{upN} raises text by N mm (superscript-like),
\tg{downN} lowers it (subscript-like): \tg{x<up4>\{2\}}, \tg{H<down2>\{2\}O}.

\textbf{Page break} --- \tg{nextpage}.

\textbf{Section headings} --- \tg{section}, \tg{subsection},
\tg{subsubsection} give the three heading levels, numbered automatically:

\begin{slcode}
<section>First topic
<subsection>A detail
<subsubsection>A finer point
\end{slcode}

renders as `1 First topic', `1.1 A detail',
`1.1.1 A finer point'. By default the numbers are hierarchical; a counter
keyword on a heading sets the style of that level on its own, with no
inherited prefix: \tg{num} (1, 2, 3), \tg{roman} (i, ii), \tg{ROMAN}
(I, II), \tg{alpha} (a, b), \tg{ALPHA} (A, B). Thus
\tg{<section ROMAN>} with \tg{<subsection num>} gives \texttt{I}, \texttt{II}
and, under each, \texttt{1}, \texttt{2} --- not \texttt{I.1}. A heading can
also be written as a
\textbf{block} carrying a \tg{title:} option, with its body in braces:

\begin{slcode}
<subsection title:{A heading}>{
<tab>This body paragraph is indented on its first line.
}
\end{slcode}

A \textbf{table of contents} is printed with \tg{<tableofcontents>}; give it
a title in braces:

\begin{slcode}
<tableofcontents>{Table of contents}
\end{slcode}

Combine anything in one tag:

\begin{slcode}
<nextpage 2lines 2tab j Navy b>{A new page, a two-line skip, a two-tab
indent, justified, Navy, bold --- all before the first letter of the text.}
\end{slcode}

% =====================================================================
\section{Aliases and macros --- the factoring tool}\label{sec:aliases}
% =====================================================================

This is what makes scholatex scale. Define a style \textbf{once}, at the top
of the document, then name it everywhere instead of repeating its attributes.
One edit at the definition restyles the whole document.

\begin{slcode}
let title = <Navy b 18pt c>          % style alias
let h1    = <Navy b section>         % a heading style, reusable
let p     = <tab>                    % a standard indented paragraph
<title>My heading
<h1>First topic
<p>{ A paragraph, indented and justified, named not described. }

let n = 7                            % value, usable in #{...}
Seven squared is #{n*n}.

let greet{name} = Hello #name!       % text macro with parameters
\end{slcode}

Change \tg{let h1 = <Navy b section>} to \tg{<ForestGreen b section>} once
and \textbf{every} first-level heading follows --- the single point of
control that keeps a long document consistent.

% =====================================================================
\section{Lists}
% =====================================================================

\tg{<list:STYLE>\{ \dots \}} makes a list; the style is required and comes
right after the name. One item per non-empty line --- no item tag. A
\tg{<list:\dots>} written under an item becomes its sub-list, nested as deep
as you like.

\begin{slcode}
<list:disc>{
Fruits
<list:circle>{
apples
pears
}
Vegetables
}
\end{slcode}

Styles --- bullets: \tg{none} \tg{disc} \tg{circle} \tg{square}; numbered:
\tg{decimal} \tg{alpha} \tg{ALPHA} \tg{roman} \tg{ROMAN} (the case of the
keyword sets the case of the letters); checkboxes: \tg{check}.

% =====================================================================
\section{Escapes}
% =====================================================================

To print a character that scholatex treats specially, double it:
\tg{<<} \tg{>>} give a literal \tg{<} \tg{>}, \tg{\{\{} \tg{\}\}} a literal
\tg{\{} \tg{\}}, and \tg{\#\#} a literal \tg{\#}. A backslash
\tg{\textbackslash} is an ordinary character --- write it as itself, so a
Windows path like \tg{C:\textbackslash Users} just works. The characters
\tg{\_} \tg{\&} \tg{\%} \tg{\textasciitilde} \tg{\textasciicircum} are escaped automatically.

Braces carry structure (they delimit blocks and groups), so a \emph{literal}
brace must be \textbf{balanced}: write the pair \tg{\{\{\dots\}\}} to print
\tg{\{\dots\}}. A lone, unmatched \tg{\{\{} or \tg{\}\}} is reported as an
unbalanced brace naming its line, rather than silently swallowing the rest of
the document --- so set-builder notation like \tg{\{\{ x : x > 0 \}\}} is
written as a pair and prints as one. Angle brackets and hashes have no such
constraint; only braces need to balance.

A line break is the tag \tg{<nextline>}; it works in running text and inside table
cells. In ordinary text a blank line already starts a new paragraph, so
\tg{<nextline>} is only needed for a break \emph{without} a paragraph change.

A line whose first non-space character is \tg{\%} is a \textbf{comment} and
is dropped. A bare \tg{\#} not followed by a name or \tg{\{\dots\}} is a
literal \tg{\#}: only \tg{\#name} and \tg{\#\{expr\}} interpolate.

% =====================================================================
\part{Containers and layout}


% =====================================================================
\section{Tables}
% =====================================================================

Columns are declared in brackets, \textbf{one two-letter placement code per
column}. The first letter is vertical (\tg{t} top, \tg{m} middle, \tg{b}
bottom), the second horizontal (\tg{l}, \tg{c}, \tg{r}). So \tg{mc} is
middle-centre, \tg{br} bottom-right. Columns share the page equally; \tg{N:}
before the code fixes a width in mm (\tg{[40:tl, 30:mc]}). Cells are
separated by \tg{|}, rows by line breaks, and \tg{<nextline>}
breaks a line inside a cell.

\begin{slcode}
<table [mc, tl, br] borders header>{
Figure | Formula | Value
<img 25>{cat.png} | $1/2 + 1/3$ | $5/6$
}
\end{slcode}

\tg{borders} draws rules; \tg{header} bolds the first row. \tg{gap:N} sets
the horizontal spacing between columns, in mm.

A cell may span several columns with \tg{colspan:N}, or several rows with
\tg{rowspan:N} (\tg{N}~$\geq$~2). For a \tg{rowspan}, each cell it covers on
the lines below is marked with a lone \tg{.}.

\begin{slcode}
<table [mc, ml, mc, mc] borders header gap:3>{
<colspan:4 mc>{Term report}
Day | Subject | Mark | Coef.
<rowspan:2 mc>{Monday} | Maths | 15 | 4
. | French | 12 | 3
}
\end{slcode}

Colour options act \textbf{inside} the table, on its cells and rules ---
\tg{fill:} colours every body cell, \tg{line:} the rules, \tg{text:} the text
colour, and \tg{headerfill:} / \tg{headertext:} the header row. These are not
box options: a table has no \tg{radius:}, \tg{title:} or outer frame. To
frame a table, wrap it in a \tg{<box>}.

% =====================================================================
\section{Images}
% =====================================================================

\begin{slcode}
<img>{chat.png}        % fills the available width (the cell or line)
<img 25>{chat.png}     % 25 mm wide
<img 25x15>{chat.png}  % fits a 25x15 mm box, ratio preserved
\end{slcode}

A bare name is searched in each folder of \tg{imgdir} in turn, then at the
project root. An explicit path always works, with or without \tg{./}.

% =====================================================================
\section{Boxes}
% =====================================================================

\begin{slcode}
<box line:Crimson fill:MistyRose radius:4 title:{A note}>{
Content here.
}
\end{slcode}

Options: \tg{line:} frame colour, \tg{fill:} background, \tg{text:} text
colour, \tg{radius:N} rounded corners (mm), \tg{width:N} or \tg{width:N\%},
\tg{boxrule:N}, \tg{sep:N} (inner padding, mm; \tg{boxsep:N} is a synonym), \tg{break:yes} (allow page breaks),
\tg{title:\{\dots\}}, \tg{titlefill:}, \tg{titletext:}. A line containing
only \tg{-{-}-} splits a box into an upper and a lower region.

\tg{<row gap:N>\{ \dots \}} lays its child boxes side by side, with equal
widths and equalised heights. A \tg{row} accepts only \tg{<box>} children.

A box also takes a \textbf{two-letter placement code} (\tg{tl tc tr ml mc mr
bl bc br}, default \tg{tl}) that positions its content; the vertical part
needs a \tg{height:} to have room to act.

% =====================================================================
\section{Grid (named-area layout)}
% =====================================================================

For full-page layouts, \tg{<grid>} borrows CSS Grid's named-area idea. A
\tg{template:[ \dots ]} of quoted rows draws the layout; each word names the
cell at that position. A name repeated \textbf{horizontally} spans columns;
repeated \textbf{vertically} it spans rows. A dot \tg{.} is an empty cell.
Each name must form a solid rectangle.

\begin{slcode}
<grid template:[
  "title  title  logo"
  "intro  info   logo"
  "body   body   body"
] gap:4>{
  <area title>{ <Red b 16pt>Maths assessment }
  <area logo >{ <img>{blason.png} }
  <area intro>{ Instructions: no calculator. }
  <area info >{ Name: <nextline> First name: }
  <area body line:Navy fill:AliceBlue radius:2 title:{Exercise 1}>{
    Solve the equation...
  }
}
\end{slcode}

An area can be framed like a box by giving it the same options
(\tg{line:}, \tg{fill:}, \tg{radius:}, \tg{title:}). An area with no options
stays invisible (a bare cell). The grid itself takes \tg{width:} (a
percentage of the text width or a millimetre value) and \tg{height:} (a
millimetre value fixing the total height).

% =====================================================================
\section{Drawing figures}
% =====================================================================

\tg{<draw>} draws a plane geometric figure from a description alone: you
name the shape and give its measurements, and the coordinates are computed
trigonometrically and emitted as hard numbers. One drawing unit is one
centimetre, so \tg{side:5} draws a 5\,cm side --- nothing is rescaled, and a
figure wider than the page is simply the cue to adjust the measurements
before printing.

\begin{slcode}
<draw>triangle ABC equilateral side:5 marks:on measures:cm
\end{slcode}

\tg{marks:on} codes the equal sides and right angles; \tg{measures:cm} or
\tg{measures:mm} labels each side with its length, set parallel to the side.
Both are off by default. The block form \tg{<draw>\{ \dots \}} holds several
figures (see \emph{Composite figures} below); the inline form above is a
single figure.

\subsection*{The figures}

\renewcommand{\arraystretch}{1.25}
\begin{longtable}{@{}p{0.46\linewidth}p{0.5\linewidth}@{}}
\toprule
\textbf{You write} & \textbf{You get} \\
\midrule
\tg{triangle ABC equilateral side:s} & equilateral triangle \\
\tg{triangle ABC isosceles side:e base:b} & isosceles, equal sides \tg{e}, base \tg{b} \\
\tg{triangle ABC right sides:(p,q)} & right angle at the first point (or \tg{right:X}), legs \tg{p}, \tg{q} \\
\tg{triangle ABC sides:(a,b,c)} & three sides \\
\tg{triangle ABC AB:3 BC:4 CA:5} & three sides named one by one (same as \tg{sides:(3,4,5)}) \\
\tg{triangle ABC sides:(a,b) angle:t} & two sides and the included angle \\
\tg{triangle ABC angles:(A,B) side:c} & two angles and a side \\
\tg{square ABCD side:s} & square \\
\tg{rectangle ABCD sides:(w,h)} & rectangle \\
\tg{rhombus ABCD side:s angle:t} & rhombus \\
\tg{parallelogram ABCD sides:(a,b) angle:t} & parallelogram \\
\tg{trapezoid ABCD bases:(b1,b2) height:h} & trapezoid \\
\tg{kite ABCD sides:(a,b) angle:t} & kite: upper pair \tg{a}, lower pair \tg{b}, apex angle \tg{t} \\
\tg{pentagon}, \tg{hexagon}, \tg{octagon} & regular polygons by name \\
\tg{polygon ABCDE side:s} & regular polygon, any number of points \\
\tg{circle O radius:r} \quad \tg{circle O diameter:d} & circle by centre and length \\
\tg{circle O radius:AB} & radius given by a placed segment (compass span) \\
\tg{circle ABC} & circle through three placed points (circumscribed) \\
\tg{circle ABC inscribed} & incircle of the triangle \tg{ABC} \\
\bottomrule
\end{longtable}

A \tg{kite} is distinct from a \tg{rhombus}: it has two pairs of adjacent
equal sides of \emph{different} lengths, the rhombus being the special case
where both pairs are equal.

When a figure has two pairs of equal sides of \emph{different} lengths ---
a kite, a rectangle, a parallelogram --- \tg{marks:on} tells the pairs apart
by the number of ticks: a single tick on the one pair, a double tick on the
other. A kite therefore never reads as a rhombus, nor a rectangle as a
square. On a composite figure a shared edge is ticked once, not once per
figure, so the coding stays clean where two pieces meet.

\subsection*{Composite figures: sharing an edge}

Several figures in one \tg{<draw>\{ \dots \}} block share their points. When
a figure repeats a point already placed, it is grafted onto it; when two
figures share an \textbf{edge} (two points), the new figure deduces that
edge's length from the existing one --- so only the first figure states its
side --- and is flipped to the far side of the edge so the pieces abut
instead of overlapping.

\begin{slcode}
<draw>{
  rhombus ABEF side:4 angle:60
  square ABCD
  triangle BCG equilateral
  triangle ADK right:D DK:6 measures:cm
}
\end{slcode}

\subsection*{Point names, loops, rotation}

Point names are single letters written glued together --- \tg{triangle ABC}
names A, B and C. When a figure needs many points, or names with a digit,
they are written as a parenthesised, comma-separated list:
\tg{triangle (O, A0, B0)}. The rule is one of the first character: an opening
parenthesis introduces the list form, anything else is the glued form.

A draw block runs the same loops as the rest of the language,
\tg{for VARIABLE in FROM..TO \{ \dots \}}. Inside a loop, \tg{\#k} inserts the
loop variable and \tg{\#\{expr\}} evaluates an expression, so point names and
measurements can be generated. The attribute \tg{rotate:$\theta$} turns a
figure by $\theta$ degrees about its first point, and \tg{labels:off} hides
the vertex names. On the tag itself, \tg{scale:F} multiplies every
coordinate of the picture by \tg{F} while leaving the text size alone
(default \tg{1}; it applies to every form of \tg{<draw>} --- figures,
axes, trigcircle, solids). Twelve isosceles triangles sharing an apex, stepped
$30^\circ$ apart, fan into a full turn:

\begin{slcode}
<draw>{
  for k in 0..11 {
    triangle (O, A#k, B#k) isosceles side:4 base:2 rotate:#{k*30} labels:off
  }
}
\end{slcode}

\subsection*{Points and segments by coordinate}

Two low-level primitives sit below the named figures. A point is placed at
explicit coordinates, a segment is drawn between two points. Coordinates are
declared once with \tg{let NAME = \{x, y\}}, then referred to by name. A
point's label is placed clear of any segment leaving it.

\begin{slcode}
let P0 = {-1.6, -2.3}
let P1 = {-1, 1.5}
let P2 = {2.7, 3.1}
<draw>{
  point(P0)
  point(P1)
  point(P2)
  line(P1, P2)
}
\end{slcode}

An argument may also be a literal pair, \tg{line(\{0,0\}, \{3,2\})}, and a
segment takes \tg{measures:} like a figure side. Because each coordinate is
an ordinary expression, a loop can compute endpoints --- twelve rays around
a disc make a sun:

\begin{slcode}
<draw>{
  circle O radius:1.2
  for k in 0..11 {
    line({1.2*math.cos(k*math.pi/6), 1.2*math.sin(k*math.pi/6)},
         {2.4*math.cos(k*math.pi/6), 2.4*math.sin(k*math.pi/6)})
  }
}
\end{slcode}

\subsection*{In a coordinate frame: \texttt{axes:}}

The figures above are \emph{constructed} --- you give measurements and the
coordinates are computed. The opposite need, a graduated frame on which
points are placed \emph{at} their coordinates, is the same block in analytic
mode. \tg{<draw axes:\{xmin,xmax,ymin,ymax\}>} draws the axes and switches
every line to the analytic vocabulary; without \tg{axes:} the block stays in
the construction mode above. One unit is still one centimetre, and the
drawing is clipped to the declared window.

\begin{slcode}
<draw axes:{-5,5,-5,5}>{
  point A (2,3)
  point B (-1,1)
  vector u (3,1)
  line y = 2x-1
  line through A B
}
\end{slcode}

Each directive takes coordinates, never measurements. \tg{point NAME (x,y)}
places and labels a point; a placed name is then available to later lines.
\tg{vector u (x,y)} draws a free vector from the origin, \tg{vector AB} the
bound vector between two placed points. \tg{line} accepts an equation
(\tg{y = 2x-1}, \tg{x = -3}, or the general \tg{2x+3y = 6}) or
\tg{line through A B}.

A named vector is remembered and composes. \tg{vector s = u+v} (or
\tg{u-v}) draws the sum or difference, labelled with the expression itself,
written along the arrow. \tg{from:} moves any vector's tail --- to a placed
point, a literal pair, or \tg{\textasciitilde{}u}, the \emph{tip} of a drawn
vector --- and \tg{style:} restyles the copy (\tg{style:dashed-gray},
\tg{style:Blue}). The parallelogram and triangle rules then read on one
frame: each side is copied dashed to the far tip, the sum closes the
parallelogram, and the difference runs from the tip of \tg{v} to the tip of
\tg{u}:

\begin{slcode}
<draw axes:{-5,5,-5,5}>{
  vector u (3,1)
  vector v (1,3)
  vector v from:~u style:dashed-gray
  vector u from:~v style:dashed-gray
  vector s = u+v style:Blue
  vector d = u-v from:~v style:Red
}
\end{slcode}

A circle carries a tangent at a point on it. \tg{circle} takes \tg{center:}
(a placed point or a literal pair) with \tg{radius:}, or an equation
\tg{x\^{}2+y\^{}2 = 4}; a named circle (\tg{circle C \dots}) then accepts a
\tg{tangent to:C at:P}:

\begin{slcode}
<draw axes:{-5,5,-5,5}>{
  point T (0,3)
  circle C center:(0,0) radius:3
  tangent to:C at:T
}
\end{slcode}

\tg{region} shades the half-plane of a linear inequality (\tg{<}, \tg{>}),
the boundary drawn dashed:

\begin{slcode}
<draw axes:{-5,5,-5,5}>{
  region y > x+1
}
\end{slcode}

\textbf{The trigonometric circle.}

One synthetic line draws the circle, its axes, and the sixteen remarkable
angles labelled by their principal measure in $\left(-\pi, \pi\right]$:

\begin{slcode}
<draw>trigcircle radius:4
<draw>trigcircle radius:4 values:on
<draw>trigcircle radius:4 step:{pi/6}
<draw>trigcircle radius:4 range:{0, pi/2} step:{pi/12} values:on
\end{slcode}

\tg{radius:} is in centimetres (default 4). \tg{step:} replaces the
remarkable set by the multiples of a fraction of $\pi$; \tg{range:}
restricts to an arc --- the first-quadrant close-up. \tg{values:on} adds
the dashed cosine and sine projections of the drawn first-quadrant angles,
exact ($\tfrac12$, $\tfrac{\sqrt2}2$, $\tfrac{\sqrt3}2$) at the
remarkable ones, two decimals elsewhere. Labels too crowded to read are a
compilation error suggesting a larger step.

\textbf{Solids in cabinet projection.}

\tg{solid} lines draw the space-geometry repertoire in the French
\emph{perspective cavali\`ere}: receding axis at $45^{\circ}$, ratio $0.5$
(override with \tg{angle:} and \tg{ratio:}). Hidden edges are
\emph{computed}, not declared: a face of a convex solid is visible exactly
when the projection preserves its outward orientation, and an edge is dashed
exactly when both of its faces are hidden. Several solids in one block sit
side by side.

\begin{slcode}
<draw>{
  solid cube ABCDEFGH edge:4
  solid pyramid SABCD base:4 height:5
}
<draw>{
  solid cuboid sides:{5, 3, 2}
  solid cylinder radius:1.5 height:4
  solid cone radius:2 height:4.5
  solid sphere radius:2.5
}
\end{slcode}

Vertex names are optional on \tg{cube}, \tg{cuboid} (eight letters, base
then top) and \tg{pyramid} (apex first). Plane sections are not in this
release.

% =====================================================================
\part{Maths}


% =====================================================================
\section{Basics}
% =====================================================================

Wrap maths in \Verb|$...$|. A small mini-language keeps it light:

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{You write} & \textbf{You get} \\
\midrule
\tg{*} & $\times$ \\
\tg{+-} & $\pm$ \\
\tg{<=} \tg{>=} \tg{!=} & $\leq$ \quad $\geq$ \quad $\neq$ \\
\tg{a/b} & fraction (chained \tg{a/b/c} reads as \tg{(a/b)/c}) \\
\tg{x\^{}2} \quad \tg{x\_i} & power / index (bind tighter than \tg{/}) \\
\tg{sqrt(2)} & $\sqrt{2}$ \\
\tg{sum(i=1, n) i} & $\sum$ with bounds, display style \\
\tg{prod(k=1, n) k} & $\prod$ with bounds, display style \\
\tg{int(x) f(x)} & $\int f(x)\,\mathrm{d}x$ (differential added) \\
\tg{int(x=a, b) f(x)} & $\int_{a}^{b} f(x)\,\mathrm{d}x$ \\
\tg{contourint(C) f(z)} & $\oint$ contour integral \\
\tg{pvint(x=a, b) f(x)} & $\mathrm{p.v.}\!\int$ principal value \\
\tg{meanint(x=a, b) f(x)} & $\fint$ average integral \\
\tg{dy/dx}, \tg{df/dx} & derivative, upright $\mathrm{d}$ (ISO) \\
\tg{sin(x)} \tg{cos(x)} \tg{ln(x)} & upright function names \\
\tg{abs(x)} & $|x|$ \\
\tg{norm(v)} & $\|v\|$ \\
\tg{vec(AB)} & $\overrightarrow{AB}$ \\
\tg{floor(x)} \tg{ceil(x)} & $\lfloor x\rfloor$ \quad $\lceil x\rceil$ \\
\tg{bar(z)}, \tg{conj(z)} & $\overline{z}$ (conjugate, mean, closure) \\
\tg{not(A cup B)} & $\overline{A\cup B}$ (logical negation) \\
\tg{lim(x->0) f(x)} & limit, target under the word \\
\tg{partial}, \tg{nabla} & $\partial$, $\nabla$ \\
\tg{pi}, \tg{alpha}, \dots & Greek letters \\
\tg{inf} & $\infty$ \\
\bottomrule
\end{tabular}
\end{center}

The helpers nest, so the secondary-school staples come for free:
\tg{norm(vec(AB))} is the norm of a vector,
\tg{vec(AB) + vec(BC) = vec(AC)} is Chasles' relation.

% =====================================================================
\subsection*{Sets, logic and relations}

A worksheet from collège to the upper years needs more than arithmetic. The
mini-language carries the standard notation as plain words and ASCII
shortcuts, so a statement reads as one types it.

\textbf{Number sets} --- a doubled capital gives the blackboard-bold set,
the ASCIIMath convention. Doubling avoids any clash with a one-letter
variable: \tg{NN} $\mathbb{N}$, \tg{ZZ} $\mathbb{Z}$, \tg{DD} $\mathbb{D}$,
\tg{QQ} $\mathbb{Q}$, \tg{RR} $\mathbb{R}$, \tg{CC} $\mathbb{C}$, plus
\tg{PP} \tg{KK} \tg{HH} \tg{FF} \tg{EE} \tg{UU} for the advanced ones.

\textbf{Comparisons} --- inside a formula, \tg{<} \tg{>} \tg{<=} \tg{>=}
\tg{!=} give $<\ >\ \leq\ \geq\ \neq$. (In running prose, double the
chevrons --- \tg{<<=>>} prints a literal $\Leftrightarrow$.)

\textbf{Quantifiers and logic} --- \tg{forall} $\forall$, \tg{exists}
$\exists$; the connectives \tg{and} $\land$, \tg{or} $\lor$, \tg{lnot}
$\lnot$, \tg{neg} $\neg$. Implication and equivalence come both as words and
as arrows: \tg{=>} or \tg{implies} $\Rightarrow$, \tg{<<=>>} or \tg{iff}
$\Leftrightarrow$. The longer arrow forms always win over the comparison
they contain, so \tg{abs(x) <= 1 <=> -1 <= x <= 1} reads correctly inside a
formula.

\textbf{Negation} --- a single rule: \tg{!} in front of a relation or
quantifier negates it, choosing the proper struck-through glyph. So
\tg{!in} is $\notin$, \tg{!exists} is $\nexists$, \tg{!subset} is
$\not\subset$, \tg{!subseteq} is $\nsubseteq$, \tg{!equiv} is
$\not\equiv$. (\tg{!=} stays ``not equal'', $\neq$.)

\textbf{Set relations} --- \tg{in} $\in$, \tg{subset} $\subset$,
\tg{supset} $\supset$, \tg{subseteq} $\subseteq$, \tg{supseteq}
$\supseteq$, \tg{cup} $\cup$, \tg{cap} $\cap$, \tg{setminus} $\setminus$,
\tg{emptyset} $\varnothing$ (negate any of them with \tg{!}).

\textbf{Arrows} --- \tg{->} or \tg{to} $\to$, \tg{mapsto} $\mapsto$.

\begin{slcode}
$forall epsilon > 0, exists eta > 0$
$x in RR setminus QQ$
$x !in QQ$
$(P and Q) => P$
\end{slcode}

% =====================================================================
\subsection*{Brackets and accents}

The integer part and a few one-argument wrappers follow the same
\tg{name(...)} shape as \tg{abs} and \tg{vec}: \tg{floor(x)} $\lfloor
x\rfloor$, \tg{ceil(x)} $\lceil x\rceil$, \tg{set(x : x > 0)} a
brace set, \tg{abr(u, v)} $\langle u, v\rangle$ an inner product.

An overline is named by intent, the same rule under two words:
\tg{bar(...)} for the generic bar (complex conjugate, mean, closure of a
set) and \tg{not(...)} for logical negation --- so \tg{bar(z)} is
$\overline{z}$ and \tg{not(A cup B)} is $\overline{A\cup B}$. The usual
accents complete the set: \tg{hat(f)} $\widehat{f}$, \tg{tilde(x)}
$\widetilde{x}$.

% =====================================================================
\subsection*{Arithmetic and sets}

A few arithmetic helpers and the set-builder notations:

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{You write} & \textbf{You get} \\
\midrule
\tg{lcm(a, b)} \tg{sign(x)} \tg{card(A)} & $\operatorname{lcm}$, $\operatorname{sgn}$, $\operatorname{card}$ \\
\tg{powerset(A)} & $\mathcal{P}(A)$ \\
\tg{range(1, n)} & $\llbracket 1, n\rrbracket$ (integer interval) \\
\tg{euler(n)} \tg{mobius(n)} & $\varphi(n)$, \quad $\mu(n)$ \\
\tg{a equiv b mod n} & $a \equiv b \pmod{n}$ \\
\bottomrule
\end{tabular}
\end{center}

% =====================================================================
\section{Algebra}
% =====================================================================

Matrices and systems as blocks, then the named vocabulary of linear maps.


% =====================================================================
\subsection*{Matrix blocks}

Matrices and systems are blocks: \textbf{one line is one row}, and inside a
matrix \tg{;} separates the entries.

\begin{slcode}
<matrix>{
1 ; 2 ; 3
4 ; 5 ; 6
}
\end{slcode}

\tg{<matrix>} draws parentheses, \tg{<det>} the vertical bars of a
determinant, \tg{<bmatrix>} square brackets. A single \tg{|} inside a row
draws the separation bar of an \textbf{augmented matrix}, at the column where
you type it; it is allowed on \tg{matrix} and \tg{bmatrix}, never on \tg{det}:

\begin{slcode}
<bmatrix>{
2 ; 1 | 7
1 ; -1 | 1
}
\end{slcode}

A \tg{<system>} stacks equations under a brace and aligns them on the first
relational operator:

\begin{slcode}
<system>{
2x + 3y = 7
x - y = 1
}
\end{slcode}

% =====================================================================
\subsection*{Linear-algebra vocabulary}

Named operators on top of the matrix blocks:

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{You write} & \textbf{You get} \\
\midrule
\tg{ker(f)} \tg{im(f)} \tg{rank(A)} & $\operatorname{Ker}(f)$, $\operatorname{Im}(f)$, $\operatorname{rg}(A)$ \\
\tg{span(u, v)} \tg{tr(A)} \tg{com(A)} & $\operatorname{Span}(u, v)$, $\operatorname{tr}(A)$, $\operatorname{com}(A)$ \\
\tg{transpose(A)} \tg{inv(A)} & $A^{\top}$ \quad $A^{-1}$ \\
\tg{eigen(A)} \tg{adj(A)} & $\operatorname{Sp}(A)$, \quad $\operatorname{adj}(A)$ \\
\bottomrule
\end{tabular}
\end{center}

% =====================================================================
\subsection*{Counting}

The binomial coefficient and arrangement take \textbf{two} arguments, so a one-argument \tg{C(t)} stays an ordinary function:

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{You write} & \textbf{You get} \\
\midrule
\tg{C(n, k)} \quad \tg{A(n, k)} & $\binom{n}{k}$ \quad $A_{n}^{k}$ \\
\tg{factorial(n)}, \tg{n!} & $n!$ \\
\bottomrule
\end{tabular}
\end{center}

% =====================================================================
\section{Analysis}
% =====================================================================

Limits, operators, functions, derivatives and integrals, the vector operators and transforms, and the full function studies.


% =====================================================================
\subsection*{Limits with an arrow}

\tg{lim(x->0) f(x)} already sets a limit with its target under the word.
For the running phrase ``$u_n$ tends to $\ell$'' written over an arrow, use
\tg{arrow(...)}: \tg{u\_n arrow(n to +inf) l} sets a long right arrow with
the condition underneath. \tg{to} and \tg{->} are interchangeable inside
it.

\begin{slcode}
$lim(n -> +inf) u_n = l$
$u_n arrow(n to +inf) l$
\end{slcode}

Scripts bind tighter than division, as in ordinary reading: \tg{x\^{}2/y} is
the fraction $\frac{x^{2}}{y}$ and \tg{1/i\^{}2} is $\frac{1}{i^{2}}$, not
$\frac{1}{i}^{2}$. To divide by a base before its script, parenthesise.

% =====================================================================
\subsection*{Operators with an index}

\tg{sum}, \tg{prod} and \tg{lim} carry their index in \tg{(...)} and set
their whole expression in display style, so a fraction in the body keeps full
size and a limit's target sits \emph{under} the word, as on a blackboard. A
\tg{sum}/\tg{prod}/\tg{lim} body runs to the end of the formula or to the
first \tg{=}, so the right-hand side of an identity stays outside the
operator:

\begin{slcode}
$sum(i=1, n) i = n(n+1)/2$
$lim(x->0) sin(x)/x = 1$
$lim(x->+inf) 1/x$
\end{slcode}

% =====================================================================
\subsection*{Functions and trigonometry}

Function names are set upright automatically --- no backslashes:
\tg{sin cos tan cot sec csc}, the inverses \tg{arcsin arccos arctan}, the
hyperbolics \tg{sinh cosh tanh coth}, and \tg{ln log exp det dim gcd deg ker
arg max min sup}. A name glued to \tg{(...)} takes its argument as one atom,
so fractions and powers behave:

\begin{slcode}
$sin(x)^2 + cos(x)^2 = 1$
$tan(x) = sin(x)/cos(x)$
\end{slcode}

% =====================================================================
\subsection*{Derivatives}

A Leibniz derivative is written as the fraction it is, and the differential
\tg{d} is set upright (ISO 80000-2), matching the \tg{d} of the integrals.
The romanisation triggers \emph{only} when both sides of the fraction carry
the differential, so a variable named \tg{d} is never disturbed: \tg{d/2}
stays the fraction d over 2.

\begin{slcode}
$dy/dx$                 % upright d
$(d^2 y)/(dx^2)$        % second derivative
$dy/dx + y = 0$         % differential equation
\end{slcode}

Partial derivatives use \tg{partial} ($\partial$); parenthesise each side so
the fraction groups correctly:

\begin{slcode}
$(partial f)/(partial x)$
$(partial u)/(partial t) = (partial^2 u)/(partial x^2)$
\end{slcode}

Inject a computed value with \tg{\#\{expr\}} (or \tg{\#name}), including
inside maths: \Verb|$#k^2$|. Decimal numbers follow the \tg{lang} option.

% =====================================================================
\subsection*{Differential operators and transforms}

The vector operators, the Landau notations (spelt out so \tg{o}/\tg{O} stay free), and the integral transforms:

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{You write} & \textbf{You get} \\
\midrule
\tg{grad(f)} \tg{div(F)} \tg{curl(F)} & $\operatorname{grad} f$, $\operatorname{div} F$, $\operatorname{rot} F$ \\
\tg{lap(f)} & $\Delta f$ (no parentheses) \\
\tg{dirderiv(f, u)} & $\nabla_{u} f$ \\
\tg{bigO(...)} \tg{litO(...)} & $O(\cdot)$, \quad $o(\cdot)$ \\
\tg{laplace(f)} \tg{fourier(f)} & $\mathcal{L}\{f\}$, \quad $\mathcal{F}\{f\}$ \\
\tg{surfint(S)} \tg{volint(V)} & $\oiint_{S}$, \quad $\iiint_{V}$ \\
\bottomrule
\end{tabular}
\end{center}

% =====================================================================
\subsection*{Integrals}

The integral family names its variable and bounds in the head \tg{(...)} and
captures the integrand as its body; the differential is appended for you. No
bounds gives a primitive, a comma-separated pair a definite integral:

\begin{slcode}
$int(x) f(x)$              % primitive
$int(x=a, b) f(x)$         % definite
\end{slcode}

Separate several domains with \tg{;} for multiple integrals: the count of
domains chooses $\int$, $\iint$ or $\iiint$, and the differentials come out in
reverse order (the Fubini convention). A single named domain is a region
integral:

\begin{slcode}
$int(x=a, b ; y=c, d) f(x,y)$
$int(D) f$
\end{slcode}

Three named integrals complete the family: \tg{contourint(C) f(z)} a contour
integral $\oint$, \tg{pvint(x=a, b) f(x)} a Cauchy principal value, and
\tg{meanint(x=a, b) f(x)} the average (normalised) integral.

% =====================================================================
\subsection*{Function studies}

% =====================================================================

Three tags turn a function into a variation table and a curve. They share
one source of truth: a \emph{function object} built once with \tg{<fn>},
then read by \tg{<vartab>} (the table) and \tg{<plot>} (the graph).

\textbf{The function object.}

The equation form registers itself under its left-hand name and reads as
the board does; the variable is declared in situ, table attributes stay
attributes after the expression:

\begin{slcode}
<fn f(x) = (x+2)(x-3)>
<fn g(t) = t^2 - 2t  x:{-inf | 1 | +inf}  deriv:{- | +}
                     var:{+inf \ -1 / +inf}>
\end{slcode}

A tabular-only object takes the head without \tg{=} ---
\tg{<fn v(x) x:\{...\} var:\{...\}>}. Objects rebind sequentially: a
later \tg{<fn f(x) = ...>} shadows the name for what follows, never for
what precedes. The 2.4 \tg{name:}/\tg{expr:} attributes still parse but
are deprecated; the \tg{let} binding remains available:

\begin{slcode}
let k = <fn name:{k(x)}
            expr:{(x^2+1)/(x-1)}
            x:{-inf | 1-sqrt(2) | 1 | 1+sqrt(2) | +inf}
            second:{- | - || + | +}
            deriv:{+ | - || - | +}
            var:{-inf / 2-2sqrt(2) \ -inf || +inf \ 2+2sqrt(2) / +inf}>
\end{slcode}

\tg{let NAME = <fn \dots>} stores the object under \texttt{NAME} (the
assignment may span several lines, up to the closing \tg{>}). The fields are
\tg{name:} (function and variable, fixing the row labels), \tg{expr:} (the
formula, read only by \tg{<plot>}), \tg{x:} (remarkable abscissas separated
by \tg{|}), \tg{deriv:} and \tg{second:} (sign of the first and second
derivative, one per interval), and \tg{var:} (the variation line).

\textbf{The table.}

\tg{<vartab k>} reads the object; or write the data inline with
\tg{<vartab x:\{\dots\} deriv:\{\dots\} var:\{\dots\}>}. Only \tg{x:} and
\tg{var:} are required, so the table comes in four shapes:

\begin{itemize}
\item \tg{second:} + \tg{deriv:} --- full study: $x$, $f''(x)$, $f'(x)$, $f(x)$
\item \tg{deriv:} --- classic variation table: $x$, $f'(x)$, $f(x)$
\item \tg{second:} --- convexity table: $x$, $f''(x)$, $f(x)$
\item neither --- plain value table: $x$, $f(x)$
\end{itemize}

Sign lines take one sign per interval (\tg{+}, \tg{-}, or empty); \tg{||}
marks a forbidden value and crosses every row; zeros at sign changes are
placed automatically. In \tg{var:}, a connector is \tg{/} (rising) or
\tg{\textbackslash} (falling) \emph{surrounded by spaces} --- glued, as in
\tg{2/3}, it is a fraction. A value between two arrows of the same direction
is rejected: the table lists only bounds and extrema.

\textbf{The sign table.}

\tg{<signtab>} is \tg{<vartab>}'s companion for factored expressions. The
automatic form \emph{computes} the rows from a product or quotient of
affine factors --- rational zeros printed exactly, a forbidden value at
each denominator zero, even multiplicities known not to change sign:

\begin{slcode}
<fn f(x) = (x+2)(x-3)>
<signtab f>

<fn g(x) = (x+1)/(x-2)>
<signtab g>
\end{slcode}

The manual block form is the general one, for rows the affine engine
cannot derive (a trigonometric factor, an irreducible quadratic): one row
per factor, usually a conclusion row last.

\begin{slcode}
<signtab x:{-inf | -2 | 3 | +inf}>{
  x+2  : - | 0 | + | +
  x-3  : - | - | 0 | +
  f(x) : + | 0 | - | 0 | +
}
\end{slcode}

A cell is a sign per interval; a \tg{0} marks a zero at the boundary it
follows, \tg{||} a forbidden value. The invariant is checked: a row that
changes sign without a \tg{0} or a \tg{||} at the boundary is a compilation
error, not a wrong table in print --- an expression cannot change sign
without vanishing or ceasing to exist.

\textbf{The graph.}

\begin{slcode}
<plot k samples:200 x:{-4, 6} y:{-10, 12}>
\end{slcode}

\tg{<plot k>} reads \tg{expr:} and \tg{name:} from the object. \tg{x:\{a, b\}}
is the horizontal display window (defaults to the table's finite abscissas),
\tg{y:\{c, d\}} the vertical window (needed when the function runs to
infinity), \tg{samples:N} the number of points. The formula is translated to
the plotter's syntax (variable renamed, trigonometry in degrees, implicit
products made explicit) and poles are handled so no spurious line joins the
branches. Supported in \tg{expr:}: \verb!+ - * / ^!, parentheses,
\texttt{sin cos tan exp ln log sqrt abs}, and \texttt{pi}.

\tg{<vartab>} is declarative, \tg{<plot>} is computed: keeping \tg{var:}
consistent with \tg{expr:} is the author's responsibility.

\textbf{Parametric and polar curves.}

A curve that is not a function graph is the same \tg{<plot>} with \tg{kind:}.
\tg{kind:parametric} reads \tg{expr:\{x(t), y(t)\}} --- two components in the
parameter \texttt{t} --- over the window \tg{t:\{a, b\}}. \tg{kind:polar}
reads \tg{expr:\{r(theta)\}} over \tg{theta:\{a, b\}} and is drawn as the
parametric pair $(r\cos\theta, r\sin\theta)$. Bounds may use \texttt{pi}
(\tg{t:\{0, 2pi\}}), and \tg{x:} / \tg{y:} set the display window as before.

\begin{slcode}
let ell = <fn expr:{3cos(t), 2sin(t)}>
<plot ell kind:parametric t:{0, 2pi} x:{-4, 4} y:{-3, 3}>

let cardio = <fn expr:{1+cos(theta)}>
<plot cardio kind:polar theta:{0, 2pi}>
\end{slcode}

A conic is drawn through its parametrisation: an ellipse as
\tg{\{a cos(t), b sin(t)\}}, a parabola as \tg{\{t, t\^{}2\}}, a branch of a
hyperbola as \tg{\{a cosh(t), b sinh(t)\}} --- no separate conic directive,
the parametric form already names them all.

\textbf{Areas.}

\tg{area:\{a, b\}} shades the region between the curve and the $x$-axis on
$[a, b]$, dashed verticals at the bounds; \tg{between:g} shades between two
curves instead, clipped to \tg{area:} when given:

\begin{slcode}
<plot f x:{-1, 4} area:{1, 3}>
<plot f x:{-1, 4} between:g area:{0, 3}>
\end{slcode}

\textbf{Sequences: the cobweb.}

\tg{cobweb:\{u0\}} (or \tg{cobweb:\{u0, n\}}, default $n = 8$) draws the
bisector $y = x$ and the staircase of $u_{n+1} = f(u_n)$, the iterates
computed at compile time and the first three labelled on the axis:

\begin{slcode}
let h = <fn name:{h(x)} expr:{sqrt(2x+3)}>
<plot h x:{0, 4} y:{0, 4} cobweb:{0.2, 10}>
\end{slcode}

\textbf{Probability laws.}

The two laws of the lyc\'ee need no \tg{<fn>} object; \tg{area:} highlights
$P(a \leq X \leq b)$ on both --- shaded under the Gaussian, stronger bars on
the binomial:

\begin{slcode}
<plot normal:{0, 1} area:{-1, 1.5}>
<plot binomial:{12, 0.4} area:{3, 6}>
\end{slcode}

The normal window defaults to $\mu \pm 4\sigma$; the binomial masses are
computed exactly.

\textbf{The number line.}

\tg{<numberline>} draws the graduated line with interval sets --- the figure
of inequalities and absolute values:

\begin{slcode}
<numberline x:{-5, 5} set:{[-2, 3) union (4, inf)} points:{-4}>
\end{slcode}

The block form \emph{solves}: it takes one inequality (a tag's braces
cannot carry \tg{<} and \tg{>}) and computes the set exactly --- an
affine expression against a constant, a product or quotient of affine
factors against 0, or \tg{abs(affine)} against a constant. Strictness
decides open or closed; a denominator zero is always excluded; an
isolated solution is a point.

\begin{slcode}
<numberline x:{-5, 5}>{
  abs(x - 1/2) >= 5/2
}
\end{slcode}

Brackets follow the international convention (\tg{[ ]} included, \tg{( )}
excluded); a bound may be \tg{inf}, the segment then runs to the arrow.
\tg{points:} pins isolated values. One unit is one centimetre, halved
automatically while the line exceeds the page.

% =====================================================================
\section{Probability}
% =====================================================================

Counting feeds probability; the blackboard operators are the doubled letters \tg{PP} and \tg{EE}, with the conditional bar written \tg{mid}.

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{You write} & \textbf{You get} \\
\midrule
\tg{PP(A)}, \tg{PP(A mid B)} & $\mathbb{P}(A)$, \quad $\mathbb{P}(A \mid B)$ \\
\tg{EE(X)} & $\mathbb{E}(X)$ \\
\tg{var(X)} \tg{std(X)} \tg{cov(X, Y)} & $\operatorname{Var}(X)$, $\sigma(X)$, $\operatorname{Cov}(X, Y)$ \\
\tg{normal(mu, sigma)} & $\mathcal{N}(\mu, \sigma^{2})$ \\
\tg{poisson(lambda)} \tg{binomial(n, p)} & $\mathcal{P}(\lambda)$, \quad $\mathcal{B}(n, p)$ \\
\tg{repart(X, x)} \tg{densite(X, x)} & $F_{X}(x)$, \quad $f_{X}(x)$ \\
\bottomrule
\end{tabular}
\end{center}

\textbf{The weighted tree.}

\tg{<tree>} is the most-drawn object of premi\`ere and terminale. Each line
reads \tg{LABEL PROBABILITY}, an optional brace opening the children; a
leading \tg{!} is the complementary event, rendered with the overline.
Probabilities may be numbers or symbols (\tg{p}, \tg{1-p}), both typeset
through the math mini-language.

A node with exactly one branch receives its complement automatically ---
the only case that is mathematically determined; sibling probabilities
that do not sum to 1 are a compilation error.

\begin{slcode}
<tree products:on>{
  A 0.3 {
    B 0.6
  }
  !A 0.7 {
    B 0.1
  }
}
\end{slcode}

\tg{products:on} writes $P(A \cap B) = 0.18$ at the end of each leaf: the
exact product when every probability on the path is numeric, the symbolic
chain otherwise. The layout is computed --- leaves evenly spaced, each node
at the mean height of its children. No loops inside the block: a tree is
written by hand, that is the point of a tree.

% =====================================================================
\section{Statistics}
% =====================================================================

Descriptive statistics is one tag, \tg{<stats>}, five \tg{kind:}s, every
number computed at compile time:

\begin{slcode}
<stats kind:bars data:{1: 4 | 2: 7 | 3: 2}>
<stats kind:bars data:{Walk: 5 | Bus: 3 | Bike: 2}>
<stats kind:histogram bounds:{0, 5, 10, 20} counts:{3, 7, 2}>
<stats kind:pie data:{Walk: 5 | Bus: 3 | Bike: 2}>
<stats kind:boxplot data:{12, 15, 9, 21, 14, 15, 18}>
<stats kind:scatter data:{(1, 2.1) (2, 2.6) (3, 3.4)} fit:on>
\end{slcode}

Three honesty guarantees, because a statistics figure teaches by its
construction: the histogram draws \emph{density} (count over class width),
so unequal classes stay truthful; the boxplot uses the French
secondary-school quartiles ($Q_1$ the smallest value with at least a quarter
of the data at or below it, $Q_3$ likewise at three quarters); \tg{fit:on}
draws the least-squares line, computed, not eyeballed. The pie starts at
twelve o'clock and runs clockwise, percentages appended to the labels.
The dictionary \tg{key: value | ...} is the form of the mappings (bars
--- numeric keys give a numeric axis, words give categories --- and pie);
pairs \tg{(x, y)} remain the form of the clouds, where an abscissa may
repeat.

A Lua table declared with \tg{let} is passed by name --- the home of
data reused across figures:

\begin{slcode}
let notes = {
    Mathematiques = 15.5,
    Francais = 12.0,
    Anglais = 18.0
}
<stats kind:bars data:notes>
<stats kind:pie data:notes>
\end{slcode}

A Lua table has no writing order: map keys come out \emph{sorted}
(numbers numerically, words alphabetically); when the order matters, a
list of pairs keeps it: \tg{let t = \{\{"T1", 11.5\}, \{"T2", 13\}\}}.
Lists of numbers feed \tg{boxplot}, lists of pairs feed \tg{scatter},
two list variables feed \tg{histogram} through \tg{bounds:} and
\tg{counts:}.

\part{Programming the document}


% =====================================================================
\section{Block aliases}
% =====================================================================

Define a reusable component once; \tg{\#param} placeholders are filled at the
call site, and the call-site body becomes the block content.

\begin{slcode}
let card{title, frame} = <box title:{#title} line:#frame radius:2>

<card First, Crimson>{
Called with two arguments. No box options to repeat.
}
<card Second, Navy>{
Same component, different look.
}
\end{slcode}

% =====================================================================
\section{Control flow}
% =====================================================================

\begin{slcode}
for n in 1..3 {            % numeric range
<c Navy b>Sheet #n
}

for f in [chat.png, chien.png] {   % explicit list
<img 16>{#f}
}

if score >= 10 {
<Green>Passed.
} else {
<Red>Try again.
}
\end{slcode}

Loops and conditions work in the document body, inside boxes, and inside
table bodies. The loop variable interpolates everywhere via \tg{\#}.

% =====================================================================
\part{Reference}


% =====================================================================
\section{Security}\label{sec:security}
% =====================================================================

scholatex evaluates \tg{let name = expr}, \tg{\#\{expr\}} and the conditions
of \tg{for}/\tg{if}/\tg{while} as Lua at compile time, so by default a
document can run arbitrary code --- exactly like \tg{\textbackslash directlua}.

Setting \tg{untrusted=true} runs that Lua in a restricted environment: only
pure, side-effect-free names are visible (the maths the document needs plus
\tg{string}/\tg{table} helpers), while \tg{os}, \tg{io}, \tg{package},
\tg{require}, \tg{load}, \tg{debug}, \tg{setmetatable} and \tg{getmetatable}
are absent. A blocked access stops the compile with a clear message; a runaway
loop is aborted by an instruction-count ceiling. Because the step counter
cannot interrupt work inside a single C call, \tg{string.rep} and
\tg{string.format} are capped --- both through the global \tg{string} table
and through method calls on a string value (\tg{("x"):rep(n)}), which a
restricted string metatable routes to the same capped functions.

\textbf{Scope.} \tg{untrusted} hardens the scholatex expression layer only.
It does \emph{not} sandbox LuaLaTeX as a whole: a hostile \tg{.tex} can still
call \tg{\textbackslash directlua}, \tg{\textbackslash write18} (with
shell-escape), \tg{\textbackslash input}, and so on. To compile a whole
\tg{.tex} you do not trust, run \tg{lualatex} \textbf{without}
\tg{-{-}shell-escape}, ideally inside a container.

% =====================================================================
\section{Examples}
% =====================================================================

The \tg{examples/} folder contains seven self-contained, fully commented
documents that together exercise every feature:

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{File} & \textbf{Covers} \\
\midrule
\tg{text-style.tex} & case rule, styles, colours, fonts, sizes, alignment, escapes, aliases, TOC \\
\tg{containers.tex} & tables, boxes and the named-area grid \\
\tg{basics.tex} & mini-language, sets, logic, negation, integer part, the overline, arithmetic helpers \\
\tg{algebra.tex} & matrix, determinant, augmented matrix, systems, and the linear-algebra vocabulary \\
\tg{analysis.tex} & operators, limits, trigonometry, derivatives, the vector operators, integrals, transforms \\
\tg{statistics-probability.tex} & counting, probability, variance, distributions --- then trees, the two laws and the descriptive-statistics figures \\
\bottomrule
\end{tabular}
\end{center}

Compile any of them with \tg{lualatex <file>.tex} from the \tg{examples/}
folder. The image folders \tg{IMG/} and \tg{IMAGES/PNG/} ship alongside them;
\tg{containers.tex} uses \tg{imgdir=\{IMG, IMAGES/PNG\}} to show that bare
image names are resolved across several directories.

% =====================================================================
\section{Diagnostics}
% =====================================================================

Errors point at the source line, e.g.
\tg{scholatex: line 12: unknown tag attribute: 'xyz'}. Defining an alias
whose name is a built-in (\tg{let section = \dots}, \tg{let tab = \dots})
prints a warning: the built-in always wins, so the alias would be silently
dead --- pick a different name.

\vfill
\begin{center}\small\color{black!55}
scholatex --- Released under the GNU General Public License v3.0.
\end{center}

\end{document}
