The Kalem Book GitHub

This Book describes Kalem's main branch, which may be ahead of the latest release.

LaTeX

Kalem opens a .tex file rendered, as the document reads, and edits it in place. The file stays standard LaTeX: Kalem defines no dialect, adds no syntax and never regenerates the file from a tree. This chapter is the reference for what Kalem reads in a LaTeX document, what it draws, what it leaves as source, how it edits, checks and builds, and against what each of these is tested. It describes the code at main: the crates latex-syntax and latex-model and the latex_* modules of kalem-core. The manual's chapter LaTeX files says the same things for the writer; this one says them exactly.

1. The standard and the oracles

LaTeX has no reference grammar. TeX is a macro language whose category codes, commands and environments can all be redefined, and the structure of a document depends on the class and packages it loads. Kalem therefore cannot claim, as its Org mode does, to agree with a reference parser on every input. What the project established about the language itself, independent of Kalem, is written down as a specification in the appendix LaTeX as written. The standard it follows is standard LaTeX as the TeX engines accept it: TeX's standard category codes, the LaTeX 2ε kernel, the standard classes (article, report, book), amsmath, and the conventions of the common packages. Its claims are narrower and each has an oracle.

Claim Oracle State
The tree's text is the input, byte for byte, whatever the input Byte-exact round trip: property tests on random input and on random edit sequences (crates/latex-syntax/tests/parse.rs), fuzz targets fuzz/fuzz_targets/latex_parse.rs and latex_reparse.rs, and kalem check, which fails when the parse does not reproduce the file Holds on generated input; the arXiv corpus (T2.7h.30) is not yet in the repository
An incremental reparse gives the tree a full parse gives Property tests: incremental reparse equal to a full parse on random edits Holds
Numbers (sections, equations, floats, theorems, footnotes, items) are the ones LaTeX prints on the documents tested The .aux files pdflatex writes for the documents of tests/latex/model (the standard classes, amsbook, memoir, counters, lists, sub-figures, theorems, math environments; tools/latex-labels.sh) and tests/latex/project/main.tex: every \label gets the number in the matching *.labels file; references and citations against what pdflatex and bibtex typeset (tests/latex/references, tests/latex/citations) Holds on those documents; a document using a package or a class the tests do not cover may be numbered otherwise
On the structure it reads, Kalem agrees with pandoc's LaTeX reader kalem diff-pandoc, which counts ten categories on both sides (below) All categories agree on the fixtures of tests/latex but two deliberate differences, listed in Known differences
What an editing command generates compiles Compiling with a TeX engine; every template is compiled with pdflatex in the tests, the Turkish thesis only where babel's Turkish is installed (it is skipped, with a note, where it is not) Templates compiled; compile-and-compare on a corpus (T2.7h.33) is open
Formulas are laid out as KaTeX lays them out org-math renders with RaTeX and the KaTeX fonts; image snapshots in crates/org-math/tests/render.rs 25 image snapshots; a thousand formulas KaTeX renders read by the renderer (T2.7h.34)
A stated share of a document's body is rendered rather than shown as source The coverage metric of kalem check --unrendered Measured per document; the target and the corpus (T2.7h.1, T2.7h.36) are open

1.1. pandoc's reader: kalem diff-pandoc

kalem diff-pandoc FILE... [--summary] [--format json] runs pandoc -f latex -t json on each file (in the file's folder) and counts the same things on Kalem's side, over every file the project includes:

Category Kalem counts pandoc counts
headings sectioning commands of the project model Header
heading-levels the levels of those commands, ranked from 1 (LaTeX and pandoc number levels differently) the levels of Header, ranked
inline-math $…$ and \(…\) in each file's body InlineMath
display-math $$…$$, \[…\], and equation, align, gather, multline, eqnarray, alignat, flalign, displaymath (starred too) not inside another math environment DisplayMath
citations the keys of every citation command the citations of each Cite
footnotes \footnote commands Note
figures floats of kind figure (figure, figure*, wrapfigure) Figure
tables tabular, tabularx, longtable environments Table
code-blocks verbatim environments other than comment CodeBlock
list-items \item commands the items of BulletList, OrderedList, DefinitionList

A file's body is its document environment, or the whole file for an included file without one. Without --summary it prints each disagreement as FILE: CATEGORY: kalem A, pandoc B; with --summary, how many files agree in each category; --format json gives every category of every file with an agree flag.

2. The rules

The three rules of every standard mode (Part II overview) take this form in LaTeX:

  1. Ranges, never text. The parser returns a tree whose leaves are ranges of the file. The view, the model, the diagnostics and every command work on those ranges. An edit replaces only the characters it changes; spacing, comments, line endings and the order of arguments stay as the author wrote them. There is no pretty printer behind any command; kalem fmt changes only blanks and says so.
  2. No extension. Everything an editing command writes is conventional LaTeX that the engines compile: \textbf{…}, \item, \begin{…} … \end{…}, \cite{…}. Nothing Kalem needs is stored in the file; there are no magic comments of Kalem's own. The toolbar and menus of a LaTeX document carry only LaTeX commands.
  3. Unknown constructs stay visible. A command or environment outside the rendered subset is drawn as its source: its name dimmed, its arguments as text with their braces. Nothing is hidden and nothing is guessed. A long environment the view does not render folds to its first line away from the cursor, as a drawer does in Org, and unfolds when the cursor enters it.

3. Files and detection

A file is a LaTeX document when its extension is .tex, .latex or .ltx, or when its first line carries an Emacs mode line naming latex, tex or ltx (% -*- mode: latex -*-). .sty, .cls and .bst files are not documents: they open as plain text. .bib files open in the BibTeX grid, described in BibTeX. kalem check and kalem fmt decide the same way.

4. Parsing

The parser is the latex-syntax crate. It produces a lossless rowan tree: concatenating the tree's tokens gives back the input, byte for byte, for any input, balanced or not. It never fails and never panics.

4.1. Tokens

The lexer uses TeX's standard category codes, fixed:

Characters Token Meaning
\ and letters CONTROL_WORD a command name: \ and a run of ASCII letters (and @ after \makeatletter)
\ and one other character CONTROL_SYMBOL \\, \%, \(, \,, \é; a line ending after \ counts as the character
{ } L_BRACE R_BRACE groups and mandatory arguments
[ ] L_BRACKET R_BRACKET optional arguments where a signature asks for one; text elsewhere
$, $$ DOLLAR, DOUBLE_DOLLAR math shifts
& # ^ _ ~ one token each alignment tab, parameter, superscript, subscript, tie
% to the end of the line COMMENT a comment (the line ending is not part of it)
spaces and tabs WHITESPACE  
one line ending NEWLINE LF, CRLF or a lone CR
a line ending and blank lines PAR_BREAK a line ending followed by lines of only spaces and tabs: the end of a paragraph
anything else TEXT a run of characters with no special meaning

Two token kinds come from the parser rather than the lexer: STAR (the star of \section* and of a starred environment's argument list) and VERBATIM (text taken as it is), and ENV_NAME is the name inside \begin{…} and \end{…}. An environment name is a run of ASCII letters, digits and *, @, :, _, - between braces, with spaces or tabs allowed between \begin and the brace.

4.2. Paragraphs, groups and arguments

The document is a sequence of paragraphs separated by paragraph breaks; so is the body of every environment that is not verbatim. A paragraph is a sequence of elements: tokens, groups, commands, environments and formulas. A group {…} closed before the end of its container may contain paragraph breaks.

A command takes the arguments its signature lists, read left to right:

Letter Argument How it is read
* an optional star a * immediately after what precedes it, with no blank between
o an optional argument after spaces, tabs and at most one line ending: [ with a matching ] before the end of the paragraph and before an unmatched } (groups and verbatim arguments inside are skipped); otherwise there is no optional argument and the [ is text
m a mandatory argument after spaces, tabs and at most one line ending: a group; or a single control word (not \begin, \end, \verb, \lstinline, \url, \href, \makeatletter, \makeatother); or a control symbol; or the first character of a text run. Anything else ends the argument list

A command not in the signature table takes no arguments. What follows it is parsed as ordinary text and groups, which keeps it visible: an unknown \foo{a}{b} is the command \foo followed by two groups.

The commands whose arguments are text even inside math (\text, \textrm, \textbf, \textit, \textsf, \texttt, \textnormal, \mbox, \hbox, \intertext, \emph, \textup) parse their arguments in text mode, so $ inside them starts a formula.

4.3. The signature table of commands

The complete table (crates/latex-syntax/src/signatures.rs):

Signature Commands
*om \part \chapter \section \subsection \subsubsection \paragraph \subparagraph \includegraphics
m \textbf \textit \texttt \textsc \textsf \textrm \textup \textmd \textsl \textnormal \emph \underline \textsuperscript \textsubscript \mbox \fbox \text \mathrm \mathbf \mathit \mathcal \mathbb \mathsf \mathtt \mathfrak \mathscr \boldsymbol \overline \hat \bar \tilde \vec \dot \ddot \check \breve \acute \grave \widehat \widetilde \overbrace \underbrace \overrightarrow \overleftarrow \label \ref \eqref \pageref \autoref \cref \Cref \nameref \input \include \includeonly \bibliography \bibliographystyle \date \thanks \phantom \hphantom \vphantom \intertext \sout \uline \appendixname \keywords \email \affiliation \address \subtitle \vref \Vref \cpageref \refstepcounter \stepcounter \subfile \graphicspath \IEEEauthorblockN \IEEEauthorblockA \IEEEmembership \institution \department \city \state \country \streetaddress \postcode \orcid \institute \inst \pacs \glossary \ensuremath \indexsee
mm \IEEEPARstart \frac \dfrac \tfrac \cfrac \binom \dbinom \tbinom \stackrel \overset \underset \setlength \setcounter \addtocounter \texorpdfstring \import \subimport \href
om \index \ccsdesc \ead \affil \bibitem \hyperref \includepdf \author \title \caption \footnote \footnotetext \color \usepackage \RequirePackage \documentclass \addbibresource \xrightarrow \xleftarrow \shortauthor \sqrt
omm \nomenclature \numberwithin \textcolor \colorbox
*m \tag \enquote \hspace \vspace \operatorname
*mm \counterwithin \counterwithout \DeclareMathOperator
*mom \captionof
oom \subfloat \makebox \framebox
mo \newcounter
o \footnotemark \item
moom \raisebox
ooomm \parbox
*oom \cite \citep \citet \parencite \textcite \autocite \footcite \citeauthor \citeyear \citealt \citealp \nocite \smartcite \Cite \Citep \Citet \Parencite \Textcite \Autocite
*moom \newcommand \renewcommand \providecommand
*moomm \newenvironment \renewenvironment
*momo \newtheorem
*o \\ (the star and the optional argument must follow at once, with no blank)

The *oom signature is what makes a command a citation command everywhere in Kalem: the model, the view, completion and the insert command all ask for it.

4.4. The signature table of environments

The arguments after \begin{name}:

Signature Environments
om tabular array longtable subfigure subtable minipage minted
mom tabularx tabulary tabular*
omom wrapfigure wraptable
o figure figure* table table* itemize enumerate description theorem lemma proof definition corollary proposition example remark lstlisting Verbatim BVerbatim
m thebibliography multicols multicols* alignat alignat*

Other environments take no arguments at \begin; a [note] after the \begin of a theorem-like environment the table does not know is read by the model all the same (see Theorems).

4.5. Commands the parser treats specially

Command How it is parsed
\verb, \verb* a VERB node: the command, then the delimiter (any character but a space, a tab or *), the code and the same delimiter, all on one line, taken as one VERBATIM token. Without the closing delimiter on the line: a diagnostic, and the command is an ordinary one
\lstinline as \verb, with an optional [options] first and a braced form \lstinline{…} (braces balanced on the line)
\url the braces of the address, on the same line, taken whole: the address is one VERBATIM token, so %, # and _ in it are not special. Without braces on the line: a diagnostic
\href the address as for \url, then one ordinary mandatory argument, the text
\begin, \end an environment (below). \begin without a name is a diagnostic; \end{x} with no open x is a diagnostic and an END node on its own
\left, \right, \middle the next delimiter as their argument: one character, a control symbol or word, [ or ]
\def, \gdef, \edef, \xdef every token up to and including the first group (the body); the parameter text (\def\name#1#2{…}) is kept as tokens. A paragraph break or a stray } ends it
\makeatletter, \makeatother from here on, @ is (is not) a letter in control words
\( \[ open inline and display math, in text mode only
\\ a command with signature *o read immediately after it

4.6. Environments

\begin{name} opens an environment that ends at the matching \end{name}. Pairing is done in one pass before parsing, as TeX pairs them: each \end{x} closes the nearest open x, and environments opened inside it and not closed stay unclosed. The environment is an ENVIRONMENT node holding a BEGIN node (the command, the name and the arguments of its signature), a BODY and an END.

Verbatim environments keep their body as one VERBATIM token: the body ends at the first literal \end{name} in the text, so nothing inside it is a command, a comment or a group. Their arguments are read on the \begin line only, as they are written. The verbatim environments are verbatim, verbatim*, Verbatim, Verbatim*, BVerbatim, lstlisting, minted, comment, filecontents and filecontents*.

The body of a math environment is parsed in math mode. The math environments are, each with its starred form: equation, align, gather, multline, eqnarray, alignat, flalign, math, displaymath, split, aligned, gathered, alignedat, cases, dcases, matrix, pmatrix, bmatrix, Bmatrix, vmatrix, Vmatrix, smallmatrix, array. Every other environment's body is parsed in text mode.

4.7. Math

Delimiters Node Mode in which it opens
$…$ INLINE_MATH text
\(…\) INLINE_MATH text
$$…$$ DISPLAY_MATH text
\[…\] DISPLAY_MATH text

Inside math, $ closes inline math and $$ closes display math; \( and \[ are not special. A formula not closed before the end of its paragraph ends there, with a diagnostic.

4.8. What the parser does not follow

The parser reads LaTeX's conventions, not TeX's macro expansion. It does not follow:

  • \catcode changes, \ExplSyntaxOn (where _ and : are letters), active characters and babel's shorthands. Only \makeatletter and \makeatother change the lexing.
  • Macros: a \newcommand does not give its command a signature, so the arguments of the document's own macros parse as the groups after an unknown command. Bodies of definitions are ordinary tokens (#1 is a HASH token and the text 1).
  • Verbatim environments defined by the document or a package beyond the list above (\lstnewenvironment, fancyvrb's \DefineVerbatimEnvironment): their bodies parse as LaTeX.
  • The primitive form \input file without braces: the parser's m argument is the first character; the model reads the file's name up to a blank, as TeX does, so the project follows it.
  • Conditionals: \iffalse … \fi parses normally; only the view dims it.

4.9. Error tolerance

Unbalanced input is closed where a reader would close it, and each closing is reported with its range:

Situation What the parser does Message
{ with no matching } the group ends at the end of the paragraph { is not closed
} with no { kept as a token } without {
\begin{x} with no \end{x} the body ends at the next sectioning command (\part to \subparagraph) after it, or at the end of its container \begin{x} is not closed
\end{x} with no open x an END node on its own \end{x} without \begin{x}
\begin without a name an ordinary command \begin without an environment name
a formula not closed it ends at the end of the paragraph math is not closed
\) or \] outside math kept as a token \) without its opening, \] without its opening
\verb or \lstinline without delimiter on the line an ordinary command \verb without its closing delimiter
\url or \href without braces on the line an ordinary command \url without its address
nesting deeper than 1,000 levels deeper groups, commands and formulas stay flat tokens nested too deeply to be structured

Parsing stays linear on unbalanced input because the pairing of braces and environments is computed once, before the tree is built. These messages are the diagnostics with code latex-syntax (see Diagnostics).

4.10. Incremental reparsing

After an edit, Parse::reparse parses again only the paragraph around the edit, and only when that is certain to give the tree a full parse gives; otherwise it parses the whole text. The region is found by going down into the innermost closed, non-verbatim environment whose body holds the edit strictly inside (after the body's first non-blank token, which must not be [, so the arguments of \begin cannot change, and before its \end), then taking the children of that body from the paragraph break before the edit to the one after it. The full parse is taken when any of these holds:

  • the edit reaches the start or the end of an environment's body, where no paragraph break separates it from \begin or \end;
  • a diagnostic of the old parse overlaps the region, or a \makeatletter or \makeatother lies in it;
  • the document has an environment left open and the region holds a sectioning command, before or after the edit;
  • the region holds the \begin or \end of a verbatim environment, before or after the edit;
  • inside an environment, without a paragraph break at its end, the region's last line holds %, \verb, \url, \href or \lstinline;
  • the new region, parsed alone, has a diagnostic, an unclosed environment or a \makeatletter toggle, or does not begin and end with the paragraph breaks the old one had.

The property tests check that the result is always the full parse's tree. Measured (book/part-4/performance.org): a 1 MB paper parses in 32 ms and a keystroke reparses in 0.64 ms (median).

5. Projects

A document of several files is one project. The latex-model crate finds its root document and reads the included files where they are included, so that numbers continue across files and labels resolve between them.

5.1. The root document

find_root decides the root of a file in this order; the first that applies wins:

  1. A % !TEX root = FILE line among the first 20 lines (! optional, TEX root in any case), resolved from the file's folder, FILE.tex tried before FILE when the name has no .tex extension; it must be readable.
  2. \documentclass[MAIN]{subfiles}: the subfile's main document, resolved the same way.
  3. A file named NAME.latexmain in the file's folder or a folder above it: NAME in that folder.
  4. The setting latex.root, a path relative to the project's folder (the folder with .git, .kalem or another project marker; the file's folder without one), usually in the workspace's settings; it must exist.
  5. The file itself, when a line of it starts with \documentclass (not the subfiles class).
  6. The first .tex file with a \documentclass, in the file's folder or a folder above (up to the project's folder), whose project includes the file.
  7. The first .tex file of the project, by path, with a \documentclass whose project includes the file (a main document in a sibling folder: src/main.tex for chapters/one.tex).
  8. The file itself.
% !TEX root = ../thesis.tex
\chapter{Methods}
\label{ch:methods}

The editors look for the root on a thread when a .tex file opens, and again when an edit within the first 4,096 bytes changes the % !TEX root line.

5.2. Included files

Command Where the file is looked for Folder for the \input and \include inside it
\input{name} the current base folder: name.tex, then name (only name when it ends in .tex) the same base
\include{name} the current base folder: name.tex only the same base
\subfile{name} the including file's folder: name, then name.tex the subfile's folder
\import{dir}{name} dir relative to the root's folder (or absolute): name.tex, then name the imported file's folder
\subimport{dir}{name} dir relative to the including file's folder: name.tex, then name the imported file's folder

The base folder starts as the root's folder, as LaTeX runs there. Each included file is read in place: its events are numbered where the include stands. A file included by \subfile counts only inside its document environment, as the subfiles package arranges; an included file's \documentclass is ignored. \includeonly{a,b} marks the \include files it leaves out as excluded, but they are still read and numbered, because LaTeX keeps their numbers from their .aux files. A file already being read (a cycle) is not read again, and reading stops 32 files deep. \graphicspath{{a/}{b/}} adds folders in which pictures are looked for.

\documentclass{report}
\usepackage{import}
\includeonly{chapters/intro}
\begin{document}
\include{chapters/intro}
\include{chapters/results}
\import{appendices/}{data}
\end{document}

5.3. A file seen as part of its project

In the editors the model of a file of a project is the project's model seen from that file (Model::seen_from): the file becomes file 0 and the root takes its index, so everything in it is numbered as the whole document numbers it (a chapter file's first chapter is numbered after the chapters before it) and its references to labels in other files resolve. The file being edited comes from the editor, with its incremental parse; the other files come from the disk and are read again when their modification time changes. A root document that includes nothing needs no project and uses its own model.

6. The document model and numbering

The model (latex_model::Model) holds: the document class and its options; the packages loaded, with their options, one entry per name of \usepackage{a,b} or \RequirePackage; the preamble (everything before \begin{document}, or the whole file without one) and the body; the sectioning commands with their numbers and parents; labels with their numbers and targets; references; citations with their notes; floats with their captions; equations; the theorem-like environments declared and used; footnotes; the macros defined; the environments defined; the bibliography sources and style; the includes; \includeonly; \graphicspath; and the project's files. It is kept per paragraph between edits: after an edit only the changed paragraphs are read again and numbering runs over what they say.

6.1. Classes

Class kind Classes Chapters secnumdepth default Counters within chapter
book book scrbook extbook yes 2 equation figure table footnote
amsbook amsbook yes 3 figure table footnote, printed without the chapter; section printed without it too
memoir memoir yes 1 equation figure table footnote
report report scrreprt extreport yes 2 equation figure table footnote
article every other class, and a document without \documentclass no 3 none

In every class subsection is within section, subsubsection within subsection, paragraph within subsubsection and subparagraph within paragraph; in chaptered classes section is within chapter. \part resets nothing. Resets cascade, as LaTeX's \@stpelt steps each reset counter from -1: a new chapter resets section and, through it, subsection and a theorem numbered within section. In book and report, \theequation, \thefigure and \thetable leave the chapter out while it is 0 (Figure 1 before the first chapter, not 0.1).

6.2. Sections

Level Command Numbered when Printed as (\the…)
-1 \part secnumdepth > -2 upper-case Roman: I, II
0 \chapter secnumdepth > -1 and in the main matter 1; in the appendix A
1 \section secnumdepth ≥ 1 1 (article), 1.1 (chaptered); A in an article's appendix
2 \subsection secnumdepth ≥ 2 1.1, 1.1.1
3 \subsubsection secnumdepth ≥ 3 parent's number, ., its own
4 \paragraph secnumdepth ≥ 4 the same
5 \subparagraph secnumdepth ≥ 5 the same

A starred command is not numbered. \setcounter{secnumdepth}{n} and \addtocounter{secnumdepth}{n} change the depth. \frontmatter and \backmatter stop the numbering of chapters (a section there is still numbered, as 0.1 in a book's front matter); \mainmatter resumes it. \appendix resets section and subsection in an article, chapter and section otherwise, and switches the letters on. Each section's parent is the nearest section before it with a smaller level.

6.3. Counters

\setcounter{c}{n} and \addtocounter{c}{n} set any counter to an integer. \numberwithin{c}{w} (amsmath) and \counterwithin{c}{w} make c reset with w and print as w's number, a dot and its own; \counterwithout{c}{w} undoes it. \newcounter{c}[w] makes c reset with w but print alone. \stepcounter{c} steps it, and \refstepcounter{c} also makes it what a \label points at. \renewcommand{\thec}{…} changes how c prints: \arabic, \roman, \Roman, \alph and \Alph of a counter, other \the… and text are read, other commands print nothing (\renewcommand{\thesection}{\Roman{section}} gives II, and \thesubsection built on it II.a). A definition's body is not read where it is defined: \newcommand{\step}{\refstepcounter{s}} steps nothing until it is used, and the model does not expand macros.

6.4. Equations

Environment Numbers
equation, multline, dmath (breqn) one
align, gather, flalign, alignat, eqnarray, xalignat, IEEEeqnarray one per line: each \\ ends a line, and so does the end of the environment (so an empty line after a final \\ is numbered, as amsmath numbers it)
the starred forms none, but a \tag still gives its line a number
subequations steps equation once; the lines inside number as that number and a letter: 3a, 3b

\[…\] and displaymath are unnumbered equations: a \tag there numbers them, as amsmath does; in $$…$$ it does not (amsmath's \tag fails there). empheq numbers as the environment its argument names (\begin{empheq}{align} as align). xxalignat numbers nothing, and CD, multlined, rcases and the other inner environments number nothing of their own.

On a line, \nonumber or \notag takes the number away and \tag{x} replaces it with x. A \label in a line gets that line's number.

\begin{align}
  a &= b \label{eq:first} \\
  c &= d \nonumber \\
  e &= f \tag{$\star$}
\end{align}

Here eq:first is 1, the second line has no number and the third shows (⋆).

6.5. Floats and captions

A \caption inside figure or wrapfigure steps the figure counter; inside table, wraptable or longtable the table counter (starred forms too). Inside subfigure and subtable (subcaption), and for subfig's \subfloat[caption]{…}, a caption is lettered instead, a, b, … within its float, and \ref prints the float's number and the letter, 1a: the number the float's caption has, or the one it is about to get when it comes after. \captionof{figure}{…} steps figure outside a float. Any other caption outside a float is not numbered. The model keeps each float's captions with their short captions.

6.6. Theorems

\newtheorem{env}{Title} declares a theorem-like environment with its own counter; \newtheorem{env}[other]{Title} shares other's counter; \newtheorem{env}{Title}[within] numbers it within within (1.1); \newtheorem* declares an unnumbered one (a \label in it prints nothing). thmtools' \declaretheorem[options]{env} declares one too: name (or title) is its title, the name with a capital first letter when missing; numberwithin (or within, parent) numbers it within a counter; sibling (or sharenumber, numberlike) shares one; numbered=no leaves it unnumbered; style and the other options are not read. ntheorem's \newtheorem is LaTeX's. Each environment of a declared name in the text steps its counter; its note is its optional argument, or a [note] at the very start of its body when the signature table does not give the environment an optional argument.

\newtheorem{theorem}{Theorem}[section]
\newtheorem{lemma}[theorem]{Lemma}

6.7. Labels

A \label takes the number and the kind of the last numbered thing in scope, as \refstepcounter leaves them: a section, an equation (line), a float's caption, a theorem, a footnote, an item of enumerate or a counter stepped by \refstepcounter. An item prints as the standard classes print it: 2, 2a, 2(b)i, 2(b)iA at the four levels; \item[label] and items of itemize and description number nothing. An environment is a group: at its end, what a \label would point at is restored to what it was before it. The same holds for a footnote's text. A label with nothing numbered before it has no number and the target None.

6.8. Definitions

The model collects \newcommand, \renewcommand, \providecommand (name, number of arguments, default of the optional first one, body), \def, \gdef, \edef, \xdef (the number of # parameters), \DeclareMathOperator (no arguments), \newenvironment and \renewenvironment (arguments, default, begin and end code). The bodies of definitions are templates: no label, citation or section inside them counts. \bibliography{a,b} and \addbibresource{a.bib} give the bibliography files, .bib added where missing, found as BibTeX finds them: beside the root document, else in the folders of BIBINPUTS, else where kpsewhich says (a library in ~/texmf/bibtex/bib); \bibliographystyle gives the style. A command without arguments in a numbered display that the document defines with \tag (the common \numberthis) numbers its line, and one defined with \nonumber or \notag (\nn) leaves it unnumbered, as LaTeX does.

7. The rendered subset

The view (kalem_core::latex_view::line_view) draws each source line of the file as the document reads. The same lines are drawn by the graphical and the terminal editor. The rule that governs every construct: away from the cursor a construct is drawn; when the cursor is inside its source range (or at either end), it shows its source, so what is edited is always the text itself. The source view (Ctrl+/) shows the file as text, highlighted as LaTeX.

7.1. Commands

Every command the view renders, and how:

Command(s) Drawn as
\part … \subparagraph a heading line, its level counted from the document's highest level; the number LaTeX gives it and an em space before the title; command, star, short title and braces hidden. \paragraph and \subparagraph are run-in: bold text, not a heading line
the formatting commands (next table) their argument styled; command and braces hidden
\maketitle the title (title style) and a byline "author · date" from \title, \author and \date written before \begin{document}; several \author commands are listed; with none of them in the preamble, \maketitle stays source
\item its bullet, number or label (see Lists)
\caption in a float, "Figure 3: " or "Table 1: " in bold in place of the command, its short caption and its brace; "(a) " in subfigure and subtable; the closing brace hidden. Şekil and Tablo with babel's turkish
\includegraphics the picture, when its file is found (see Pictures); otherwise source
\centering hidden; the float's lines centered
\footnote its number raised (a link) in place of the command and its brace, then its text dimmed; the closing brace hidden
\ref \eqref \pageref \autoref \cref \Cref \nameref \vref \Vref a chip with what the reference resolves to (see References)
the *oom citation commands a chip with authors and years (see Citations)
\url{a}, \href{a}{t} a link showing a, and t for \href
\verb, \lstinline the code in monospace with a background; command, options and delimiters hidden. \lstinline is colored in its language (its language= option, or \lstset's)
\\ ↵, dimmed, in place of the command with its star and optional argument
the word commands (see Characters) the character or word they typeset; the blanks after them, or an empty {}, eaten as TeX eats them
the front matter commands (see Front matter) styled as the class prints them
the \begin and \end of theorems and proof see Theorems and proofs
\tableofcontents (a line of its own) the live table of contents (see Outline)
\iffalse … \fi everything between them dimmed (other \if… inside nest)

7.2. Formatting commands

Command Style of the argument
\emph \textit \textsl italic
\textbf bold
\texttt monospace
\underline \uline underlined
\sout struck through
\textsuperscript raised
\textsubscript lowered
\textsc \textsf \textrm \textup \textmd \textnormal plain

Styles nest: \textbf{a \emph{b}} shows b bold italic.

Font declarations style the rest of their group (latex_view::declaration): \bf and \bfseries bold; \it, \itshape, \sl, \slshape and \em italic; \tt and \ttfamily monospace; \upshape ends italic, \mdseries bold, \rmfamily and \sffamily monospace, and \normalfont and \rm all three; \sc, \scshape and \sf are known and change nothing shown. The sizes \tiny, \scriptsize, \footnotesize, \small, \large, \Large, \LARGE, \huge and \Huge show the text at the ratio the standard classes give them at 10pt (5, 7, 8, 9, 12, 14.4, 17.28, 20.74 and 24.88 points) to a 12-point text; \normalsize ends them. A declaration is followed from where it is to the end of its group {…} (Plain {\bf bold}), of its environment's body (an environment is a group), or, at the top level, of its paragraph; a declaration in the document's body does not reach into the paragraphs after it. The declarations themselves stay as source, dimmed.

Command Shown
\index \indexsee \glossary \nomenclature Dimmed with their arguments: they typeset nothing where they are
\texorpdfstring{TeX}{PDF} The first argument, the command, braces and second hidden
\ensuremath{…} The formula, outside math

7.3. Characters

Typographic replacements apply in running text and in the arguments of the commands a reader reads (the formatting, front matter and sectioning commands, \footnote, \caption, \item, \title, \author, \date, \text, \mbox, \textcolor, \thanks, \enquote), never in math, verbatim text, \begin and \end lines, or the arguments of other commands. With the cursor on one of them, it shows as typed.

Source Shown
`` “
'' ”
` ‘
' ’
-- –
--- —
~ a no-break space

Control symbols in text:

Source Shown
\& \% \$ \# \_ \{ \} the character
\, a thin space
\ and a space a space
\@ \/ \- nothing

Commands without arguments (the word table):

Command(s) Shown
\ldots \dots \textellipsis …
\LaTeX \TeX \LaTeXe \METAFONT LaTeX, TeX, LaTeX2ε, METAFONT
\textendash \textemdash – —
\S \textsection / \P \textpilcrow § / ¶
\copyright \textcopyright ©
\textregistered \texttrademark ® ™
\texteuro \euro €
\pounds \textsterling \textyen \textcent £ ¥ ¢
\textdegree \textmu \textpm \texttimes \textdiv ° µ ± × ÷
\textonehalf \textonequarter \textthreequarters ½ ¼ ¾
\textasciitilde \textasciicircum \textbackslash ~ ^ \
\textbar \textless \textgreater the vertical bar, < and >
\textbullet \textperiodcentered • ·
\textdagger \dag / \textdaggerdbl \ddag † / ‡
\textquoteleft \textquoteright \textquotedblleft \textquotedblright ‘ ’ “ ”
\quad / \qquad one / two em spaces
\hfill \hfil \enspace \enskip an en space
\thinspace a thin space
\newline \linebreak ↵
\medskip \smallskip \bigskip \vfill \par \noindent \indent nothing
\vspace{…} \addvspace{…} / \hspace{…} (with their argument) nothing / a space
\newpage \clearpage \cleardoublepage \pagebreak ↡
\slash \textquotesingle \textvisiblespace / ' ␣
\guillemotleft \guillemotright \guilsinglleft \guilsinglright « » ‹ ›
\today today's date as LaTeX prints it in English: September 30, 2026
\listoffigures \listoftables \printbibliography the heading LaTeX prints: List of Figures, List of Tables, References
\ss \ae \AE \oe \OE \o \O \aa \AA \l \L \i \j ß æ Æ œ Œ ø Ø å Å ł Ł ı ȷ
\th \TH \dh \DH \ng \NG \dj \DJ þ Þ ð Ð ŋ Ŋ đ Đ

A text accent and its letter show as one character, composed where Unicode has one: \"o (and \"{o}) ö, \'e é, \`e è, \^o ô, \~n ñ, \=a ā, \.z ż, and, with the letter after a blank or in braces, \u{g} ğ, \v{s} š, \H{o} ő, \c{c} ç, \k{a} ą, \r{a} å, \d{a} ạ, \b{a} a̱; \'{\i} is í. The BibTeX grid shows them the same way.

7.4. Front matter

The journal classes put their front matter in commands of their own. Written in the body (as acmart and RevTeX require), these commands show their text styled, with the words the class prints before it:

Command(s) Style Words before it
\title title  
\author \affiliation \affil \institute \address \email \ead \IEEEauthorblockN \IEEEauthorblockA \institution \department \city \state \country \streetaddress \postcode \orcid \subtitle byline  
\keywords byline "Keywords: "
\ccsdesc byline "CCS: "
\pacs byline "PACS: "
\thanks dimmed  
\inst raised  
\IEEEPARstart plain (its two arguments run together)  

The parts of an address run together in one argument (acmart's \affiliation{\institution{…}\city{…}\country{…}}) are separated by ", ". The front matter environments show a heading on their \begin line: IEEEkeywords "Index Terms—", keyword and keywords "Keywords: "; elsarticle's frontmatter is a container whose \begin and \end lines are delimiter lines. For \maketitle in the preamble case, the byline leaves out \thanks, \inst, \footnote, \footnotemark, \IEEEauthorblockA, \IEEEmembership, \affiliation, \institute, \address, \email, \orcid and \textsuperscript with their arguments, and \and and \\ separate the names.

7.5. Environments

Environment(s) Drawn as
document its body; \begin{document} ends the folded preamble; the \end{document} line lists the footnotes
itemize enumerate description lists (below); \begin and \end lines are delimiter lines
center flushleft flushright their lines centered, left or right aligned; delimiter lines
quote quotation verse indented as a list level; delimiter lines
abstract indented; its \begin line a centered bold "Abstract" ("Özet" with babel's or the class's turkish option)
figure figure* table table* wrapfigure wraptable subfigure subtable delimiter lines; centered when \centering stands directly in the body; captions and pictures as above
the display math environments and \[…\], $$…$$ a typeset formula (see Mathematics)
the other math environments (split, aligned, cases, matrices …) inside a formula; typeset with it
the verbatim environments the body monospace, its \begin and \end lines delimiters; comment dimmed
proof and the environments \newtheorem declares see Theorems and proofs
IEEEkeywords keyword keywords frontmatter see Front matter
simple tables (tabular, tabular*, tabularx, tabulary, array, longtable) the grid (see Tables)

A delimiter line is a \begin or \end line of its own; the frontends draw it discreetly.

7.6. Lists

Each \item of a list away from the cursor shows its label, indented by two em spaces per enclosing list (and per enclosing quote, quotation, verse or abstract) below the first; continuation lines are indented to the item's depth, the source's own indentation hidden.

List Label
itemize by its itemize depth: •, –, ∗, · (deeper stays ·)
enumerate by its enumerate depth: 1., (a), i., A. (deeper stays A.)
description nothing
any \item[label] shows label (bold in description) and is not counted by enumerate

enumitem's options are read from the list's optional argument: label= (\arabic*, \alph*, \Alph*, \roman*, \Roman* replaced by the item's number; in itemize the label as written) and start=. Other options are ignored. \setcounter{enumi}{4} (or \addtocounter, with the counter of the list's level) in the list sets the number the next item counts on from, as in LaTeX. LaTeX stops at an \item outside a list and at lists nested more than four of a kind or six in all; Kalem draws them as the table says and kalem check warns (latex-item-outside-list, latex-too-deep).

7.7. Theorems and proofs

The \begin of an environment declared with \newtheorem or \declaretheorem shows "Title N (note)": the title and number bold, the note from the optional argument or from […] at the start of the body, followed by a period when amsthm is loaded (\usepackage{amsthm} or an AMS class), as amsthm's heads end, and by nothing otherwise, as LaTeX's own \newtheorem prints it. Its \end line is a delimiter line. \begin{proof} shows "Proof. " bold italic, or "X. " for \begin{proof}[X] (amsthm prints the note in place of "Proof"), and \end{proof} shows ∎. \theoremstyle is not read: every body is shown upright, where amsthm's plain style sets it in italics.

\begin{theorem}[Pythagoras]\label{thm:p}
  $a^2 + b^2 = c^2$.
\end{theorem}
\begin{proof}
  Trivial.
\end{proof}

In a report with \newtheorem{theorem}{Theorem}[chapter] in the second chapter and amsthm loaded, the first line shows "Theorem 2.1 (Pythagoras). ".

7.8. Pictures

\includegraphics[options]{name} is drawn as the picture when its file is found: name in the document's folder, then in each \graphicspath folder; a name without an extension is tried with .png, .jpg, .jpeg, .pdf, .svg and .eps, in that order. The size comes from the first of these options present:

Option Size
width a share of the line when it ends in \textwidth, \linewidth, \columnwidth or \hsize (0.5\linewidth is 50%, clamped to 1–1000%); otherwise a length in cm, mm, in, pt or px, at 96 pixels an inch
height a length as above; the width follows the picture's proportions
scale a share of the picture's own size

The graphical editor draws PNG, JPEG, SVG and PDF (its first page, as vectors, through hayro); an EPS or PostScript picture is converted to PDF once by Ghostscript, found where TeX's programs are, and drawn the same way, or shows as its name where Ghostscript is not installed. The terminal editor draws pictures through the kitty, iTerm2 or sixel protocols where the terminal has one, and [image: …] otherwise.

7.9. Code, verbatim and comments

The bodies of the verbatim environments are monospace. lstlisting and minted are code blocks colored by kalem-highlight in the language their options name: lstlisting's language= option (a [dialect]Name form keeps Name), else the last \lstset{language=…} in the document; minted's argument. verbatim has no language and stays monospace. Comments (% to the end of the line) are dimmed; so are comment environments and the text between \iffalse and its \fi.

7.10. What stays source, and how

Everything outside the tables above is drawn as its source:

  • A control word outside the signature table and the formatting table is dimmed, away from the cursor. A command the signature table knows but the view does not render (\label, \hspace, \usepackage) is drawn in the surrounding style, not dimmed. Arguments are drawn as text, with their braces.
  • The \begin and \end of an environment the view does not render show as source, the command dimmed.
  • A formula the renderer cannot lay out shows as its source in a red frame, as in Org.

Some commands have no drawing of their own but count as rendered in the coverage report, because they need none or have their effect elsewhere: \label, \begin, \end, \appendix, \frontmatter, \mainmatter, \backmatter, \bibliography, \bibliographystyle, \noindent, \par, \iffalse and \fi. Their names show as source.

7.11. The coverage report

kalem check FILE.tex --unrendered lists the commands and environments of the document's body the view does not render, most frequent first (\foo and \begin{bar} with their counts), and the share of the body rendered. Commands whose names are not all letters and @ are not listed, and nothing inside a formula counts, since formulas are the math renderer's. The share is computed over the body's non-blank characters: every command or environment not rendered counts as source whole, with its arguments and body. An environment counts as rendered when it is in the table above, or when the model declares it as a theorem.

7.12. Folding

The view gives the editors blocks (latex_view::blocks), which fold as Org's elements do. Each folds to its first line while the cursor is elsewhere.

Block When Kind
the preamble the lines before the line of \begin{document}, when there are at least two drawer
\iffalse … \fi alone on its lines, spanning at least three lines drawer
a comment environment spanning at least three lines drawer
an environment the view does not render eight line breaks or more (nine lines, counting its \begin and \end lines), alone on its lines drawer
a simple table its rows table
a displayed formula a display math environment, \[…\] or $$…$$ alone on lines of its own and spanning more than one: one formula on its first line math
a verbatim environment (not comment) alone on lines of its own code
a section each sectioning command at the start of its line is a heading block; the blocks after it, down to the next section of its level or higher, are under it heading

Tab on a section's line cycles its folding as Tab does on an Org heading: its text and subsections hidden, its subsections shown, everything shown.

7.13. Outline, table of contents and footnote list

The outline panel lists the sections of the project in reading order with their numbers, levels counted from the highest level among them: those of the file shown, and those of the files it includes (\input, \include, \subfile=…) or that include it; choosing a section of another file opens that file at the section. A =\tableofcontents line, away from the cursor, shows the table of contents LaTeX prints there: the unstarred sections down to \subsubsection (\subsection in the classes with chapters: book, report, amsbook, memoir, scrbook, scrreprt, extbook, extreport), or down to the level \setcounter{tocdepth}{n} names, with their short titles, and the entries \addcontentsline{toc}{level}{title} adds where it stands, including those of the project's other files; each entry leads to its section. The \end{document} line, away from the cursor, lists the file's footnotes, each with its number and text, leading to it.

8. References, citations and footnotes

8.1. References

A reference shows what it resolves to, as a link; with any key unknown, that key shows as ?? and the chip is red. Every form is checked against what pdflatex typesets with hyperref and cleveref (tests/latex/references, regenerated by tools/latex-typeset.py).

Command Shows
\ref \vref \Vref the label's number
\eqref the number in parentheses: (3)
\pageref the key itself (Kalem does not paginate)
\nameref a float's caption, a theorem's note (nothing without one), else the title of the section the label is in
\autoref hyperref's name, a no-break space and the number: "chapter 1", "section 1.1", "subsection 1.1.1", "Equation 1.1", "Figure 1", "Table 1", "footnote 2", "item 1", "Part I", "Appendix A" for a chapter of the appendix; a theorem by its counter's name ("Theorem 2" for a lemma sharing theorem's counter), and the number alone for a counter hyperref has no name for; the document's \<counter>autorefname wins
\cref cleveref's names: "chapter 1", "section 1.1" for every level, "appendix A.1" in the appendix, "eq. (3)", "fig. 1", "table 1", "footnote 2", "item 1", "part I", the theorem's title in lower case
\Cref the same with a capital, "Equation (3)" and "Figure 1" written out

\ref, \eqref, \pageref, \autoref and \nameref take one key: \ref{a,b} looks up the label a,b and shows ??, as LaTeX does. \cref and \Cref take a list, printed as cleveref prints it: keys of one kind grouped under the plural ("eqs. (1) and (2)", "sections 1 and 2"), sorted, three or more consecutive numbers as a range ("eqs. (1) to (3)"), kinds joined with "and", and three or more kinds with commas and ", and" ("fig. 1, table 1, and eq. (1)"). \cpageref is read by the model but not drawn.

8.2. Citations

With a \bibliographystyle Kalem knows, a citation shows what bibtex and LaTeX print for it (tests/latex/citations, one document per style, regenerated by tools/latex-typeset.py). Only the entries cited, \nocite included (\nocite{*} adds the rest of the bibliography), are numbered, and \nocite itself shows nothing.

Style Citations
plain, abbrv, siam, amsplain, acm numbers in the order of the sorted bibliography (plain.bst's presort: the authors' names, von part first, then the year, then the title without a leading "A", "An" or "The"): [5], [5, 8], [7, p. 3]
unsrt, ieeetr, IEEEtran numbers in the order of first citation
alpha, amsalpha alpha.bst's labels: three letters of one author's name (Knu84), the initials of two to four (LL90), three initials and + for more (ABG+10), von parts in lower case (vdB01), the key's first three letters without an author; a, b for labels that meet
plainnat, abbrvnat, unsrtnat natbib's author-year labels, a, b after years that meet: \cite and \citet "Knuth [1984a]", \citep "[Knuth, 1984a]", \citealt "Knuth 1984a", \citealp "Knuth, 1984a", \citeauthor, \citeyear, \citeyearpar; one author's keys named once, "[Knuth, 1984a,b]"

With natbib and a numeric style, \citet shows "Knuth [5]" and \citep "[5]"; \citenum shows the number alone. For other styles (biblatex, or no \bibliographystyle), a citation shows author and year from the bibliography files the document names (\bibliography, \addbibresource), resolved from the document's folder. For each key: the family names of the authors (or editors) from the entry, "A", "A and B" or "A et al.", and the year (year, or the first four digits of date). Keys are joined with "; "; a key the bibliography lacks shows as itself and the chip is red.

Command(s) Shows
\citet \Citet \textcite \Textcite Knuth (1984)
\citeauthor Knuth
\citeyear 1984
\citep \Citep \parencite \Parencite \autocite \Autocite \footcite \citealp (Knuth 1984)
\cite \Cite \citealt \nocite \smartcite [Knuth 1984]

With one optional argument it is the postnote, appended after ", "; with two, the first is the prenote, put before, and the second the postnote. A ~ in a note shows as a no-break space.

\citep[see][p.~12]{knuth84,lamport94}

shows "(see Knuth 1984; Lamport 1994, p. 12)".

8.3. What the cursor and the mouse show

With the cursor on a citation, a reference or a footnote, the status bar says what it is, and so does a tooltip under the mouse in the graphical editor:

  • a citation: for each key, @key: and the entry as the bibliography of a CSL style renders it, or "No bibliography has the key @key";
  • a reference: for each key, what the label numbers, "Section 2: Title" or "Figure 1: Caption", or "No label key";
  • a footnote: its number and text.

The CSL style is chosen from biblatex's style= option, else \bibliographystyle:

Style named CSL style
ieeetr ieee ieeetran unsrt numeric numeric-comp plain abbrv alpha ieee
apalike apa apacite plainnat abbrvnat unsrtnat apa
mla modern-language-association
anything else, or none chicago-author-date

8.4. Open Link

Open Link (latex.link.open; Ctrl-click, Cmd-click on macOS) follows the command at the cursor: a reference to its \label (in another file of the project, that file); \url and \href to their address; \input, \include, \subfile and \import to their file (.tex added when the name has no extension and does not exist); \includegraphics to its picture; a citation to the first bibliography file. A reference to an unknown label says so.

9. Mathematics

Formulas are typeset by org-math, Kalem's formula engine (RaTeX with the KaTeX fonts), the same that typesets Org's LaTeX fragments. A formula away from the cursor is drawn: inline math as a formula in the line, \[…\], $$…$$ and the display environments (equation, align, gather, multline, eqnarray, alignat, flalign, displaymath, math, starred too) as displayed formulas. A display formula over several lines, alone on its lines, is one math block, shown as one formula on its first line with the other lines hidden until the cursor enters it. The outermost math node is what is drawn; environments such as split or pmatrix are drawn with the formula around them. While the cursor is inside a formula, the formula is previewed under the cursor, rendered in the graphical editor and as its Unicode approximation in the terminal.

What the renderer receives (math_source) is the formula's source with these changes:

  1. \label{…}, \nonumber and \notag are taken out (the renderer has no \label).
  2. In a display environment, each numbered line gets \tag{N} with the number the model gives it (a line with its own \tag keeps it), and the environment is renamed to its starred form, so that only these tags number it.
  3. The definitions: first those of the packages the document loads that the renderer lacks (below), then the document's own \newcommand, \renewcommand, \providecommand, \def and \DeclareMathOperator definitions, as written, which win. This is what #+LATEX_HEADER lines do for Org.

For

\begin{equation}
  E = mc^2 \label{eq:e}
\end{equation}

as the second equation of a document, the renderer receives (the blank left by the label kept, the tag at the end of the body):

\begin{equation*}
  E = mc^2 
\tag{2}\end{equation*}

The package definitions (PACKAGE_MACROS), given only when the document loads the package:

Package Definitions
bm \bm{x} as \boldsymbol{x}
physics \abs{x}, \norm{x}, \qty{x} (\left(x\right)), \dv{f}{x}, \pdv{f}{x}, \vb{x} (\mathbf), \va{x} (\vec), \vu{x} (\hat{\mathbf{x}}), \bra{x}, \ket{x}, \braket{a}{b}, \expval{x}, \order{x} (\mathcal{O}\left(x\right)), \tr, \Tr (operators)
siunitx \SI{n}{u} and \qty{n}{u} (n\,\mathrm{u}), \si{u}, \unit{u}, \num{n}, \ang{n}; units \metre \meter \second \kilogram \gram \kelvin \ampere \mole \newton \joule \watt \volt \hertz \pascal \coulomb \tesla \ohm \litre \hour \electronvolt \percent \degree; prefixes \kilo \milli \micro \centi \mega \giga \nano; \per (/), \squared, \cubed; with physics also loaded, \qty is siunitx's

Only the one-argument forms of these are defined; optional arguments and starred variants of physics are not.

In running text, siunitx's commands show what version 3 typesets with its default options (crate::siunitx): \num{12345.678} "12 345.678" (digits in groups of three, thin spaces, from five digits on), \num{-1.5e3} "−1.5 × 10³", \unit{\kilo\gram\per\second\squared} "kg s⁻²" (prefixes and units by their macros, \per as a negative power, \square, \cubic, \squared, \cubed, \tothe{n}; a unit written out, m/s, as it is), \qty{3}{\metre} and \SI "3 m" (a thin space; none before \degree, \arcminute, \arcsecond), \ang{1;2;3} "1°2′3″", \numrange and \qtyrange (\SIrange) with "to" and the unit repeated, \numlist with ", " and " and ". siunitx is not in the test machine's TeX installation, so these follow its manual, not a comparison with its output.

9.1. Formulas against KaTeX

The renderer is held to KaTeX on real formulas: tools/math-corpus.py reads every formula of two openly licensed books (the Open Logic Project and the HoTT book, 57,460 formulas) as Kalem's view reads them, and asks KaTeX 0.16 and the renderer about each, without the books' own macros. KaTeX renders 31,873 of them, and the renderer reads every one of those (the last one it did not, a control space ending a formula, L\ =, is handled since); it also reads 649 that KaTeX refuses, mostly =bussproofs trees, xymatrix diagrams and eqnarray that Kalem maps for it. A thousand of KaTeX's formulas, chosen by their hash, are kept in tests/corpus/math/katex-corpus.txt (CC BY-SA), and crates/org-math/tests/katex.rs checks that the renderer reads them all and renders a sample.

9.2. Macros the renderer leaves as source

The formulas are drawn by RaTeX, which reads KaTeX's LaTeX. Of the math macros in the test list crates/org-math/tests/macros.txt (some three hundred, by package, each with an example), these are the ones it does not know; a formula using one shows as its source in a red frame, as in Org, unless Kalem handles the macro itself first. The test unsupported_macros checks that this table names exactly the macros the renderer refuses, so it changes when the renderer does.

Package Macro In Kalem
amsmath \idotsint source
amsmath \sideset source
amsmath \intertext source
amsmath \eqref source (a reference inside a formula)
latex \ref source (a reference inside a formula)
latex \label taken out of the formula, the equation numbered by the model
mathtools \prescript source
mathtools \shortintertext source
upgreek \upmu source
cancel \cancelto source (\cancel, \bcancel and \xcancel are drawn)
nicefrac \nicefrac source
xfrac \sfrac source
bbm \mathbbm source
dsfont \mathds source
tensor \tensor source
physics \dv given to the renderer as a definition when the document loads physics

10. Tables

A table environment is drawn as the shared grid (the one Org tables use) when it is simple. The definition (latex_table::simple):

  1. The environment is tabular, tabular*, tabularx, tabulary, array or longtable, and has its \end.
  2. Its column specification is the last mandatory argument of \begin, and contains only:

    Letter Column
    l c r aligned left, centered, right
    p{…} m{…} b{…} left (the width's braces balanced)
    X L C R J left
    the vertical bar, spaces, tabs, line endings nothing (ignored)

    Anything else (@{}, >{…}, *{3}{c}, S) makes the table not simple.

  3. Nothing but blanks follows the \begin… on its line, and the \end stands on a line of its own (blanks before it allowed).
  4. Every line between them is a rule line or a row line. There is no blank line.
    • A rule line holds only rule commands: \hline, \toprule, \midrule, \bottomrule, \cline, \cmidrule, \addlinespace, each with its optional (…), […] and {…}.
    • A row line holds one row: cells separated by the & outside braces, ended by \\ (with an optional […]), after which only rule commands may follow (they are drawn under the row). It has no %, no \verb or \lstinline, and its braces balance. At most as many cells as columns. Only the last row may lack its \\.
  5. A cell that is all \multicolumn{n}{spec}{text} spans n columns, aligned as the first letter of its spec; a cell that is all \multirow{n}[…]{width}{text} (width may be *) shows its text in the middle of the n rows it covers, as LaTeX sets it, when the cell of the middle row is empty, else in its own cell. Any other cell containing \multicolumn or \multirow makes the table not simple.
\begin{tabular}{l|cr}
  \toprule
  Name & Count & Share \\
  \midrule
  \multicolumn{2}{c}{Total} & 100\% \\
  \bottomrule
\end{tabular}

The grid is drawn away from the cursor, columns aligned as the specification says, the rows before the first rule under a row as the header; a rule written after a row's \\ is drawn under that row. Each cell's text is drawn as the view draws the line (formulas, emphasis, chips). When the cursor enters the table it is its source, so edits and the file's own alignment of & stay as written; Tab and Shift+Tab move to the next and previous cell. A table that is not simple stays source.

11. Diagnostics

kalem check FILE.tex and the editors report the same diagnostics (latex_check). Each has a stable code and a severity: warning (probably wrong, a red wavy line) or info (style, a blue one). A language server's warnings, in code, are orange instead (the chapter Language plugins): the checks' warnings keep the red of errors.

Code Severity When Fix
latex-syntax warning what the parser closed or skipped (the messages of Error tolerance)  
latex-duplicate-label warning a \label of this file whose key is defined more than once in the project  
latex-label-clash warning a second \label on one line of an amsmath environment, where amsmath stops with "Multiple \label's"  
latex-label-unwritten warning a \label on a line without a number (\nonumber, \notag) with no numbered line after it: LaTeX never writes it, and \ref prints ??  
latex-label-before-caption warning a \label in a float before its \caption: it refers to the section, or with the caption package to nothing  
latex-undefined-reference warning a key of a reference command of this file that no \label of the project defines  
cite-unknown-key warning a citation key of this file that no bibliography file has (checked when at least one file could be read)  
bibliography-unreadable warning a bibliography file that cannot be read, reported on this file's \bibliography or \addbibresource  
bibliography-entry-skipped warning an entry of a bibliography file left out for a syntax error (the others are read, as BibTeX goes on), reported on this file's bibliography command with the reason  
cite-unused-entry info an entry nothing in the project cites; reported on the root document's bibliography command, only when every file was read and no \nocite{*}  
latex-missing-file warning an \input, \include, \subfile, \import or \subimport of this file that resolves to no readable file (a cycle too)  
latex-missing-picture warning an \includegraphics whose file is not found from the root document's folder, where LaTeX runs (with \graphicspath and LaTeX's extensions)  
latex-item-outside-list warning an \item in the body outside any list (LaTeX's "Lonely \item")  
latex-too-deep warning the fifth enumerate or itemize inside lists of its kind, or the seventh list in all ("Too deeply nested")  
latex-empty-list warning a list (itemize, enumerate, description, their enumitem and paralist kinds) with no \item ("Something's wrong–perhaps a missing \item")  
latex-blank-line-in-math warning a blank line in a math environment (equation, align, …), where TeX ends the paragraphgraph ended before …", "Missing $ inserted")  
latex-deprecated info \bf \it \rm \sc \sf \tt \sl \cal \bfseries \itshape \rmfamily \scshape \sffamily \ttfamily \slshape; none for \cal, nor in math, where the message names \mathbf and its kin
latex-deprecated info $$…$$ \[…\]
latex-tie info \ref, \eqref, \cite, \cref, \autoref or \pageref after a space that follows text, outside math ~ for the space
latex-ellipsis info ... in text outside math (the first in each run of text) \ldots{}
latex-quotes info " in text outside math  
latex-build warning; info for bad boxes a problem the last build's log reported on a line of this file  

Outside math means outside formulas, math environments and verbatim environments. The project is found as Projects says; the labels and citations of the whole project count, and each file reports what is in it.

In the editors the diagnostics are worked out on a thread 400 ms after typing stops (at once when the file opens, and again when a build ends), the file as edited and the rest of the project from the disk. While typing, the diagnostics shown move with the text and those an edit touches are dropped, until the next pass. The text under each is flagged in the rendered and the source view; the message shows in the status bar at the cursor and in a tooltip under the mouse, with "(Quick Fix fixes it)" when there is a fix. Quick Fix (latex.fix, Ctrl+., Alt+. in terminals) applies the fix of the diagnostic at the cursor, or of the first on its line that has one. Next Problem and Previous Problem (Alt+F8, Alt+Shift+F8) go through them, wrapping around; Show Problems lists them all with their lines.

kalem check prints FILE:LINE:COLUMN: SEVERITY[CODE]: MESSAGE, or JSON with --format json (code, severity, message, byte range, line and column, and whether the file round-trips). It fails when the parse does not reproduce the file, and with --deny-warnings when there is a warning. It does not include the build's problems.

12. Editing

Every editing command writes conventional LaTeX with the line's own indentation and changes only what it must.

Command Keys What it does
New Line or Item (latex.enter) Enter on an \item line of a list: a new \item at the same indentation, the rest of the line going to it; on an empty item (\item or \item[…] alone), the item goes and the cursor moves to a new line after the list's \end. Elsewhere a new line
Nest Item (latex.list.indent) Tab on a section's line: cycle its folding. On an \item line that is not the first of its list: into a list of the same kind under the item before it (joining one that ends on the line before), the whole item going: its further lines and the lists inside it; when it ends inside a line (a group closing on the line of the next item or of the list's \end), what follows goes on a line of its own. In math: the next empty {} on the line, else the next cell of a matrix or cases. In a simple table: the next cell. Otherwise indent
Unnest Item (latex.list.outdent) Shift+Tab on an \item of a nested list: out, after that list, as an item of the list around, the whole item going as with Nest Item (the nested list goes when it empties, what shares its first and last lines staying). In a simple table: the previous cell. Otherwise outdent
Bold, Emphasis, Typewriter, Underline (latex.format.bold, .italic, .code, .underline) Ctrl+B, Ctrl+I, Ctrl+Shift+K, Ctrl+U \textbf, \emph, \texttt, \underline: taken off when the selection or cursor is in its argument; else put around the selection or the word at the cursor
Heading Level (latex.section.setLevel) Ctrl+1 … Ctrl+6, Ctrl+0 the line's sectioning command set to level N of the class (\chapter first in book, report, memoir, scrbook, scrreprt, amsbook; \section first otherwise; beyond the last, \subparagraph); a plain line becomes \name{line}; level 0 turns a section back into its title
Promote Section, Demote Section (latex.section.promote, .demote) Alt+Shift+Left, Alt+Shift+Right every sectioning command of the section's subtree one level up or down; not above the document's top (\section in a document without chapters, \part above chapters), not below \subparagraph
Move Section Up, Move Section Down (latex.section.moveUp, .moveDown) Alt+Shift+Up, Alt+Shift+Down the section with its subtree swapped with the previous or next section of the same level; \end{document} stays last
Display Math (latex.math.toggleDisplay)   $x$ (or \(x\)) at the cursor to \[ x \], and a displayed formula to $x$
Number Equation (latex.math.toggleNumbering)   the star added to or taken from both ends of the equation, align, gather, multline, flalign, alignat or eqnarray at the cursor
Insert Figure (latex.insert.figure)   asks for the picture, the width (0.8 of the line offered; a number is a share of \linewidth, anything else a length) and the caption, and writes the figure below
Insert Table (latex.insert.table)   columns (3) and rows (2): a table with a simple tabular, booktabs' rules when the document loads booktabs, \hline otherwise; the cursor in the caption
Insert Equation (latex.insert.equation)   an equation with a \label{eq:}, the cursor in it
Insert Citation (latex.insert.citation)   without a key, a picker over the bibliography's entries; \cite{key} at the cursor, or ,key added inside the citation the cursor is in
Quick Fix, Next/Previous Problem, Show Problems   see Diagnostics

An insert goes on the cursor's line when it is empty, otherwise on a new line after it. Insert Figure writes:

\begin{figure}[htbp]
  \centering
  \includegraphics[width=0.8\linewidth]{figures/plot.pdf}
  \caption{Measured values.}
  \label{fig:plot}
\end{figure}

That is the default; the inserts follow the document's own style (latex_edit::Style), read from what it already has: the indentation of an environment's body (the most common step after a \begin line: two spaces, four, a tab or none), where a float's \label goes (inside the caption's braces, on its own line before the caption, or after it, by the document's majority), whether an equation's \label sits on its \begin{equation} line, and the prefix of each kind of label (fig:, f-, =figure:=…, the most common among the document's figures, tables and equations).

The formatting toggles keep the braces balanced: a selection that starts or ends inside a command, a group or a formula takes all of it (a \emph{b| c} d| with Bold gives a \textbf{\emph{b c} d}), and \emph and \textit toggle as one: Emphasis inside \textit{…} takes the \textit off.

Behaviours while typing:

Typed Result
} closing \begin{name} when the parser reports the environment not closed: a line for the body (\item in a list) and \end{name} below, at the \begin line's indentation, the cursor on the body line
a character in an environment's name the same edit in the name at the other end, when both ends have the same name
$ in text $$ with the cursor between; not after an unescaped \
$ before the closing $ of a formula steps over it
( or [ after \ \(\), \[\], the cursor inside
(, [, ., the vertical bar after \left the delimiter, a space and the matching \right (\right), \right], \right., the bar)
{ after \left\ \left\{ \right\}
" in text `` after a blank, an opening bracket, ~ or at the start, else ''; typed again right after either, a plain ". Not in math, code, comments, or documents whose preamble loads babel with german, dutch, danish, finnish, swedish, russian or czech (where " is a shorthand)

BibTeX pasted into a LaTeX document is appended to its first bibliography file (entries whose keys it has are left out) and a \cite{…} of the pasted keys is inserted instead.

12.1. Formatting

kalem fmt FILE.tex [--check] [--align] changes only blanks: each line indented by the environments around it (not document), with the document's own step, the most common indentation the first line of an environment adds to its \begin line (a document that does not indent its environments keeps its indentation); runs of blank lines made one; blanks at line ends removed; one line ending at the end. Verbatim text is not touched, nor the \end line where it ends: verbatim environment bodies and verbatim arguments, the bodies of alltt, of fancyvrb's, PythonTeX's, LuaLaTeX's, SageTeX's and tcolorbox's listing environments, and of the environments \lstnewenvironment, \DefineVerbatimEnvironment (and its kin), \newtcblisting and minted's \newminted declare; none of them votes for the step. --align lines up the top-level & of the rows of tabular, tabularx, longtable, array, align, alignat, flalign, eqnarray, the matrices and cases written one row a line (\multicolumn rows and nested environments left). --check changes nothing and lists the files that would change.

13. Completion

The LaTeX completer offers, as you type or on request (Ctrl+Space or Alt+/):

After Offered
\ and letters (a bare \ only on request) 134 built-in command names, the commands of the packages the document loads, and the document's own macros; inserted with one {} per mandatory argument (from the signature table, else the package's or macro's count), the cursor in the first. \sum, \prod, \coprod, \int, \iint, \oint, \bigcup, \bigcap come with _{}^{}, \lim with _{}
\begin{ the built-in environments, those of the loaded packages, the document's \newenvironment=s and theorems; inserted with =}, a body line (\item in lists) and \end{name}; matrices and cases as two rows of two cells
\end{ the innermost environment open at the cursor
the argument of a citation command the keys of the bibliography files, matched fuzzily on key, authors and title, with the entry as detail
the argument of \ref, \eqref, \pageref, \autoref, \cref, \Cref, \nameref, \vref, \Vref the project's labels, with their kind and number ("equation 3")
\input{, \include{, \subfile{ .tex files (without the extension) and folders, from the document's folder
\includegraphics{ pictures (png, jpg, jpeg, pdf, eps, svg) and folders
\usepackage{, \RequirePackage{ 56 common packages
\usepackage[ / \documentclass[ the options of the package named after the cursor (babel, inputenc, fontenc, geometry, hyperref, biblatex, natbib, xcolor, graphicx, caption, cleveref, siunitx), all of them before it is named; the standard class options

The package commands and environments known cover amsmath, amssymb, mathtools, bm, hyperref, url, cleveref, varioref, xcolor, color, graphicx, siunitx, physics, booktabs, multirow, natbib, biblatex, csquotes, ulem, soul, todonotes, listings, minted, subcaption, caption, geometry, fancyhdr, tikz, algpseudocode, enumitem, footmisc, acro, glossaries, babel and fontspec, and the environments of amsmath, tikz, algorithm, algpseudocode, algorithm2e, listings, minted, subcaption, wrapfig, longtable, tabularx, multicol, comment, framed, tcolorbox, mdframed, enumitem, pgfplots and forest (latex_complete.rs has the lists).

14. Building

Build PDF (latex.build, F5) compiles the project's root document in the background; latex.build_on_save builds on each save. One build runs at a time: a build asked for while another runs (F5, or a save) is made when it ends, the last asked for only; Cancel Build (latex.cancelBuild) kills the program that runs and forgets the one asked for. kalem latex build FILE does the same on the command line.

14.1. SyncTeX

Builds ask for SyncTeX (-synctex=1 to latexmk and the engines, --synctex to tectonic), so a NAME.synctex.gz lies beside the PDF. kalem_core::synctex reads it: its input files, then each page's boxes and points with the file and line they come from, in scaled points from the page's top left corner, given in PDF points.

  • Show in PDF (latex.showInPdf) opens the root document's PDF (in latex.output_directory when set) at the first page holding a line of text from the cursor's line, or from the next line that typesets anything (a blank line or a comment typesets nothing).
  • Ctrl-click (Cmd-click on macOS) on a page of a PDF that has a SyncTeX file opens the source at the line of the material nearest the point, in the line of text nearest it. A paragraph's lines of text carry the line where the paragraph ends and boundaries (x records) often do too; the material in them (kerns, glue, boxes) carries the line it was written on, so it is preferred, as synctex edit does.

Both are checked against TeX Live's synctex program on a compiled document of six sections and an included file (kalem-core/tests/synctex.rs, in the pdflatex job of CI): every line's page and box, and every line found again from a point in it.

14.2. The engine

The first of these that applies:

  1. % !TEX program = NAME or % !TEX TS-program = NAME among the first 20 lines of the root document (! optional, any case).
  2. The latex.engine setting (or --engine on the command line) unless it is auto or empty.
  3. XeLaTeX when the project loads fontspec, unicode-math or polyglossia.
  4. pdfLaTeX.

A name of step 1 or 2 means XeLaTeX when it is xelatex, LuaLaTeX when it is lualatex, Tectonic when it is tectonic (which then runs alone, below), and pdfLaTeX for anything else.

14.3. The tool

Looked for in PATH, in this order:

Tool When Command line (in the root's folder)
latexmk latexmk and the engine are installed latexmk -pdf -interaction=nonstopmode -file-line-error -halt-on-error -pdflatex (or -xelatex, -lualatex) [-outdir=DIR] FILE
the engine alone the engine is installed ENGINE -interaction=nonstopmode -file-line-error [-output-directory=DIR] FILE; then biber STEM when the run left STEM.bcf, or bibtex STEM when STEM.aux has \bibdata{ (looked for beside the engine, then in PATH; run in the output folder); then the engine twice more after a bibliography run, once more without
tectonic named as the engine, or neither of those is installed tectonic --keep-logs --synctex [--outdir=DIR] FILE (tectonic's own engine)

Without any of them, the build fails and says what to install: the command that installs TeX Live here (Homebrew's MacTeX, winget's MiKTeX, or the Linux distribution's packages), and Tectonic's site; with TeX but not the engine the document needs, it names both. latex.output_directory (or --outdir) names a folder relative to the root's, created if needed; the PDF and the log are looked for there as STEM.pdf and STEM.log.

14.4. The log

The log is read after the build:

  • Lines of exactly 79 characters are joined with the next, as TeX wraps them.
  • FILE:LINE: MESSAGE (-file-line-error; the file has no blank and an extension of one to four letters or digits) is an error at that file and line, whether the file is the document's or a package's.
  • ! MESSAGE is an error; its line is the l.N within the next 12 lines; its file is the one the log was reading.
  • A line containing Warning: is a warning, continued on the following lines that start with three spaces until the text ends with a period; its line comes from input line N, at lines N or at line N.
  • A line starting with Overfull or Underfull is a bad box.
  • The file being read is followed through the log's parentheses: ( and a name opens a file, ) closes it.
  • A message naming a missing file (File `x.sty' not found) gets the command that installs it: tlmgr install x when tlmgr is in PATH (TeX Live), mpm --install=x when mpm or miktex is (MiKTeX).

The status bar gives the first error at its file and line with the count of the others, or the PDF and the number of warnings. The problems are kept with their files and show in each file of the project as latex-build diagnostics. kalem latex build prints them as FILE:LINE: error|warning|info: MESSAGE followed by the PDF's path, or with --format json as an object with root, pdf and problems (file, line, severity, message); it exits with 1 when there is an error or no PDF.

15. Export and conversion

With pandoc installed:

Command pandoc command line (in the root's folder) Output
Export as HTML (pandoc) (latex.export.html) pandoc --from latex --to html5 --standalone --output OUT --mathml [--citeproc] --resource-path DIR ROOT ROOT.html
Export as Markdown (pandoc) (latex.export.markdown) the same with --to markdown, without --mathml ROOT.md
Export as Word (pandoc) (latex.export.docx) the same with --to docx ROOT.docx
Convert to Org (pandoc) (latex.convertToOrg) pandoc --from latex --to org --standalone --wrap=none --extract-media=STEM_assets FILE, then Kalem's Org clean-up FILE.org

The exports write the project's root document beside it, in the background, with --citeproc when the root's text contains \bibliography{ or \addbibresource{, and open the result when export.open_after is on. Convert to Org converts the current file, refuses to overwrite an existing .org file, and says that it is one way: the LaTeX file stays as it is and edits to the Org file do not go back to it. Org's own LaTeX export (kalem export --to latex) writes files that open in this mode.

16. Templates

New from Template… (file.newFromTemplate) writes a copy of a template as NAME.tex beside the current document (NAME-2.tex and so on when taken) and opens it; the templates themselves never change. Each parses without diagnostics and compiles with pdflatex in the tests.

Name Title What it is
article Article article, 11pt A4, inputenc, fontenc, amsmath, amssymb, graphicx, hyperref; title, abstract, a section
report Report report, the same packages; title, contents, a chapter
book Book book, the same packages; front matter with title and contents, main matter, back matter
beamer Presentation (beamer) beamer; a title frame and a frame with a list
letter Letter letter, 11pt A4; signature, address, opening and closing
cv Curriculum vitae article with geometry (2 cm), no page style or indentation; education, experience, skills
thesis Thesis report, 12pt A4 one-sided, 2.5 cm margins, one and a half spacing, amsthm, a theorem within chapters; abstract, contents, two chapters
tez Tez (YÖK biçimi) a Turkish thesis after the Council of Higher Education's guidelines: babel turkish, A4 with 3/2.5/3.5/2.5 cm margins, one and a half spacing, a title page, ÖZET and ABSTRACT in the contents, GİRİŞ and SONUÇ

17. Settings

Setting Default Meaning
latex.engine auto the TeX engine: auto, pdflatex, xelatex, lualatex or tectonic
latex.build_on_save false build the PDF each time a LaTeX document is saved
latex.output_directory empty where builds go, relative to the root document; empty: beside it
latex.root empty the root document, relative to the project's folder (step 4 above)
export.open_after false open the PDF of a build and the files pandoc writes

18. Limits and known gaps

What Kalem does not do today, from the code and the open items of the roadmap (docs/roadmap.md; the old ids of docs/todo.md in brackets):

  • Corpus and differentials. The coverage of the rendered view is measured on 925 arXiv papers (the limitations page), the parse and editing round trip on the same sample and 50 CC BY papers committed under tests/corpus/latex/arxiv, formulas against KaTeX on two open books. kalem diff-pandoc compares counts per category, not titles or text (T2.7h.32); compiling the corpus after editing commands needs their packages and is not done (T2.7h.33).
  • Parsing. No catcode changes but \makeatletter; no signatures for the document's own macros; no verbatim environments beyond the fixed list.
  • Projects. The project's last-resort search reads at most 2,000 .tex files.
  • Mathematics. The macros the renderer does not know are in the table above. The definitions given to the renderer are cut from the edited file by the ranges of the model's macros, so in a file of a multi-file project macros defined in other files (the root's preamble) are not applied reliably. \newenvironment definitions are not given to the renderer.
  • References and citations. \pageref shows the key, as there are no pages; \cpageref stays source.
  • Editing. No typographic dashes while typing, and no style for the blank lines around an insert (T2.7h.15).
  • Completion. No texlab bridge (T2.7h.17, which needs the language server plugin).
  • BibTeX. No entries added from a DOI (T2.7h.19).
  • Building and the PDF. The PDF opens as a document of its own, at the cursor's page through SyncTeX, and Ctrl-click on it goes back to the source; it is not yet a panel beside the text that follows each build (T2.7h.24), and the terminal editor cannot go from the page to the source. Tectonic is used when the document or latex.engine names it, or when no TeX engine is installed, and is not downloaded on demand (D5); no debounce beyond one build at a time (T2.7h.22). A build compiles the files as saved on disk.
  • Performance. A keystroke in a 10 MB document takes about 78 ms: the blocks are found again over the whole text and the screen's model is rebuilt (roadmap R4.3).
  • Not started. Typst (a plugin by D29, T2.7h.25), spell checking in LaTeX (T2.7h.29), the exit criteria of a paper and a thesis edited end to end (T2.7h.39).

The deliberate differences from pandoc's reader are in Known differences.

19. Where the code is

Part Code
lexer, parser, signatures, pairing, reparse crates/latex-syntax/src/ (lexer.rs, parser.rs, signatures.rs, tables.rs, incremental.rs)
model, numbering, projects crates/latex-model/src/ (extract.rs, lib.rs, project.rs)
the view, chips, math, blocks crates/kalem-core/src/latex_view.rs
tables crates/kalem-core/src/latex_table.rs
editing crates/kalem-core/src/latex_edit.rs, the latex.* commands in builtin.rs
formatting crates/kalem-core/src/latex_fmt.rs
completion crates/kalem-core/src/latex_complete.rs
diagnostics, coverage crates/kalem-core/src/latex_check.rs
building, log crates/kalem-core/src/latex_build.rs, pdf.rs
citations, CSL cards crates/kalem-core/src/cite.rs
pandoc crates/kalem-core/src/pandoc.rs
templates crates/kalem-core/src/latex_templates.rs
table of contents, footnote list crates/kalem-core/src/toc.rs
kalem diff-pandoc crates/kalem-cli/src/commands/diff_pandoc.rs