% Copyright 2026 Adi Edelhaus % % terminaltrees is licensed under the LaTeX Project Public % License, version 1.3c or any later version. % % Maintenance status: maintained % Current maintainer: Adi Edelhaus % Issue reports: https://github.com/edel67/terminaltrees/issues % % The files comprising this work are listed in manifest.txt. % See LICENSE for the full license terms. \documentclass[10pt]{article} \usepackage[a4paper,margin=25mm]{geometry} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage{terminaltrees} \usepackage{graphicx} \usepackage{listings} \usepackage[colorlinks=true,linkcolor=teal,urlcolor=teal]{hyperref} \hypersetup{pdftitle={terminaltrees: User guide},pdfauthor={Adi Edelhaus}} \lstset{language=[LaTeX]TeX,basicstyle=\small\ttfamily, columns=fullflexible,keepspaces=true,breaklines=true, frame=single,rulecolor=\color{black!20},showstringspaces=false} \setlength{\parindent}{0pt} \setlength{\parskip}{0.6em} \setcounter{tocdepth}{1} \title{\texttt{terminaltrees}\\\large Evenly spaced leaves, rounded branches} \author{Adi Edelhaus} \makeatletter \date{\csname ver@terminaltrees.sty\endcsname} \makeatother \begin{document} \maketitle \begin{center} \begin{forest} terminal tree [EXPR [EXPR [ID [x]]] [+] [EXPR [EXPR [ID [y]]] [*] [EXPR [NUM [2]]]]] \end{forest} \end{center} \texttt{terminaltrees} adds a reusable layout to Forest. Terminal leaves sit at equal intervals on one baseline. Each parent is centered between its first and last immediate children. Side branches curve. Children directly below their parent connect straight down. Label measurements determine spacing. An optional fitting environment shrinks the whole tree to the available page dimensions, subject to a minimum label size. Neither form chooses paper sizes or splits a tree across pages. \tableofcontents \newpage \section{Install and draw a tree} With a current TeX Live installation, install the package using its package manager: \begin{lstlisting}[language={}] tlmgr install terminaltrees \end{lstlisting} If your operating system manages TeX Live, use its package manager instead. With MiKTeX, refresh the package catalogue and install \href{https://miktex.org/packages/terminaltrees}{\texttt{terminaltrees}}: \begin{lstlisting}[language={}] miktex packages update-package-database miktex packages install terminaltrees \end{lstlisting} For manual installation, download the \href{https://mirrors.ctan.org/graphics/pgf/contrib/terminaltrees.zip}{CTAN archive} and place \texttt{terminaltrees.sty} beside your document, or upload it to your Overleaf project. For a personal TeX installation, place the file in \path{tex/latex/terminaltrees/} under your user TEXMF tree. Use your TeX distribution's instructions to refresh its filename database if required. The package loads Forest's edges library and needspace. Forest loads PGF/TikZ. Do not copy these dependencies into your document folder. Compile this complete example with pdfLaTeX: \begin{lstlisting} \documentclass{article} \usepackage{terminaltrees} \begin{document} \begin{forest} terminal tree [EXPR [EXPR [ID [x]]] [+] [EXPR [EXPR [ID [y]]] [*] [EXPR [NUM [2]]]]] \end{forest} \end{document} \end{lstlisting} It produces the tree on the cover. Labels use ordinary LaTeX and Forest bracket syntax. \section{Keep the type size, or fit the page} Both forms use Forest and the same layout: \begin{description} \item[\texttt{forest} with \texttt{terminal tree}] Keeps the tree at its natural size. You manage placement and choose paper large enough for it. This form can be used inside figures and minipages. \item[\texttt{fittedterminaltree}] Shrinks a tree when necessary and reserves space in normal single-column document flow. If it will not fit in the remaining space, it moves to the next page. It does not enlarge small trees or change the paper or margins. \end{description} \begin{lstlisting} \begin{fittedterminaltree} [EXPR [EXPR [x]] [+] [EXPR [1]]] \end{fittedterminaltree} \end{lstlisting} The fitting environment applies \texttt{terminal tree} automatically. Forest options go before the root bracket. Fitting options use \emph{parentheses} after the environment name: \begin{lstlisting} \begin{fittedterminaltree}(minimum label size=7pt) roundness=0.5, for tree={font=\small} [EXPR [EXPR [x]] [+] [EXPR [1]]] \end{fittedterminaltree} \end{lstlisting} \newpage \section{See what fitting changes} \begin{center} \resizebox{\linewidth}{!}{% \setlength{\fboxsep}{0pt}% \fbox{\includegraphics[page=1]{fitting-comparison.pdf}}\hspace{10mm}% \fbox{\includegraphics[page=2]{fitting-comparison.pdf}}% } \end{center} This comparison is generated from the included examples. Both paper previews share one reduction, so their paper and label sizes remain comparable. The example deliberately uses \texttt{leaf pitch=16mm}, not the package default. The author chooses the larger or smaller paper in LaTeX. The unfitted tree keeps its original label size. The fitted tree scales labels and branches together within the smaller text area. The separate \texttt{fitting-comparison.pdf} also includes a third page showing deliberate unfitted overflow. Use the same zoom for its pages rather than fitting each page separately to the window. \subsection{Fitting and the font-size floor} The environment typesets the tree once, then chooses the largest uniform scale no greater than 1 that fits \verb|\linewidth| and \verb|\textheight - \baselineskip|. It rounds the scale down to TeX's supported precision and reserves space with \verb|\Needspace*|. Moving to another page does not change the chosen scale. \texttt{minimum label size} defaults to the document's current \verb|\footnotesize| size. It must be positive. The test uses the smallest base font selected for a node, multiplied by the scale. Select node fonts through Forest's \texttt{font} option. Inline font changes, mathematical subscripts and externally scaled content are not measured. Do not replace the fitting environment's \texttt{execute at begin node} hook. The floor is an author-selected limit, not a guarantee of readability for every reader. If the floor cannot be met, compilation stops. Wrap wide labels, increase a node font that is already below the floor, or split the tree manually. A PDF partially written by a failed compilation is not a valid result. Fitting supports ordinary single-column flow, including lists. It rejects boxed contexts such as floats and minipages. Custom output routines, multicolumn layouts and automatic captions are outside the supported fitting interface. Use \texttt{forest} with \texttt{terminal tree} when managing placement yourself. \newpage \section{Spacing, labels and curves} \subsection{Spacing} \texttt{leaf pitch} is the minimum center-to-center distance between consecutive leaves. Its default, \texttt{0pt}, imposes no additional minimum. Measurements of the labels and Forest's padding determine one uniform pitch for the tree. Wider labels or larger fonts therefore increase spacing automatically. \begin{lstlisting} \begin{forest} terminal tree, leaf pitch=3em, for tree={font=\small} [ROOT [First\\label [a]] [Second [b]]] \end{forest} \end{lstlisting} Use \verb|\\| for deliberate line breaks. Forest controls vertical separation and multiline label height. Its label, font and arrow options remain available. \subsection{Roundness} \texttt{roundness} is a unitless number from 0 to 1. The default is 1, the maximum curvature permitted by each fork's geometry. Zero gives square corners. Intermediate values tighten the bends without moving nodes or changing fitting. Every tree starts at the default, independently of earlier trees. \begin{center} \begin{tabular}{ccc} \texttt{roundness=0} & \texttt{roundness=0.5} & \texttt{roundness=1}\\[1em] \begin{forest}terminal tree,roundness=0 [R [a][b][c]]\end{forest}& \begin{forest}terminal tree,roundness=0.5 [R [a][b][c]]\end{forest}& \begin{forest}terminal tree,roundness=1 [R [a][b][c]]\end{forest} \end{tabular} \end{center} The available space caps the radius. Sibling branches on the same side share a departure curve. Aligned branches stay straight. Values outside the range, physical units and non-finite values are fatal errors. PGF's math parser rejects malformed input. \section{How the layout is calculated} Leaves receive positions $i p$ for indices $i=0,\ldots,N-1$, where $p$ is the effective pitch. Parent positions are computed from the leaves upward, each as the midpoint of its first and last immediate children. Equal leaf spacing does not imply equally spaced internal siblings. A parent need not be centered over all its descendant leaves. A middle branch is vertical only when its child and parent share the same horizontal position. Each subtree reserves one column per descendant leaf, with boundaries half a leaf interval beyond its outer leaves. The pitch grows until each measured label box and half its Forest \texttt{s sep} on each side fit inside its subtree's boundaries. This conservative rule keeps unrelated labels and branches clear but does not minimize total width. \newpage \subsection{How branches are drawn} For each parent, the fork sits halfway through the clear space above its nearest child label. The shared bend radius is the smallest of: \begin{itemize} \item \texttt{roundness} times the fork distance \item half the shortest nonzero horizontal run to a child \item the fork distance minus the arrow clearance. \end{itemize} The result is bounded below by zero. Clearance uses PGF's shaft-shortening distance for the default thin stealth arrow, plus the outer padding at both anchors. This prevents the bend from reversing the arrow shaft. Forest's native forked-edge style draws the paths. \subsection{Custom styles and measurement limits} The style controls horizontal coordinates, terminal alignment, fork placement, corner radii and routing. Manual \texttt{fork sep} and \texttt{rounded corners} do not override the calculated geometry. Alternate growth directions, manual horizontal positioning and replacement paths are outside its intended use. Automatic spacing assumes centered labels, nonnegative separation and positive vertical clearance. It does not measure shifted labels, custom anchors, overlays, edge labels, custom stroke extents or full custom arrowhead shapes. Inspect these additions visually. Shared path segments can be drawn more than once, so transparency and differing sibling styles also need inspection. \section{Examples, checks and compatibility} The archive includes example sources and the test suite. Run: \begin{lstlisting}[language={}] python3 terminaltrees-tests/check.py --preview \end{lstlisting} This writes renderings to a temporary directory and reports its location. It needs Python 3, pdfLaTeX, \texttt{pdfinfo}, \texttt{pdftotext}, \texttt{pdftocairo}, and the standalone class. The default checker also compares the README SVG byte-for-byte. Different TeX, fonts or Poppler versions can change that output without changing layout. The package has been tested with pdfLaTeX on TeX Live 2023 (Ubuntu) and TeX Live 2026 (macOS). Other engines and Overleaf execution have not been verified. The package does not provide tagged-PDF tree semantics or screen-reader support. \section{License, credits and support} Copyright 2026 Adi Edelhaus. Licensed under the LaTeX Project Public License, version 1.3c or later. Maintenance status: maintained. Current maintainer: Adi Edelhaus. See \texttt{LICENSE} and \texttt{manifest.txt} in the archive. Built on Forest by Sa\v{s}o \v{Z}ivanovi\'{c}, PGF/TikZ, the LaTeX kernel and needspace. Dependencies retain their own licenses and are not bundled. Report issues at \url{https://github.com/edel67/terminaltrees/issues}. \end{document} .