% \iffalse meta-comment
% SPDX-FileCopyrightText: Copyright (c) 2021-2026 Yegor Bugayenko
% SPDX-License-Identifier: MIT
% \fi

% \CheckSum{0}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}

% \GetFileInfo{crumbs.dtx}
% \DoNotIndex{\endgroup,\begingroup,\let,\else,\fi,\newcommand,\newenvironment}

% \iffalse
%<*driver>
\ProvidesFile{crumbs.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{crumbs}
%<*package>
[2026-10-15 0.4.2 Navigation Crumbs for Presentations]
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage{lmodern}
\usepackage{fail-fast}
\usepackage{silence}
\WarningFilter{latex}{Marginpar on page}
\usepackage{crumbs}
\PassOptionsToPackage{hyperindex=false}{hyperref}
\usepackage{href-ul}
\usepackage{bookmark}
\renewcommand{\RerunFileCheck}[3]{\AddToHook{enddocument/info}{#2}}
\PageIndex
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{crumbs.dtx}
  \PrintChanges
  \PrintIndex
\end{document}
%</driver>
% \fi

% \title{|crumbs|: \LaTeX{} Package \\ for Navigation Crumbs\thanks{The sources are in GitHub at \href{https://github.com/yegor256/crumbs}{yegor256/crumbs}}}
% \author{Yegor Bugayenko \\ \texttt{yegor256@gmail.com}}
% \date{\filedate, \fileversion}
%
% \maketitle
%
% \section{Introduction}
%
% \DescribeMacro{\crumbs}
% \DescribeMacro{\subcrumbs}
% This package facilitates the addition of navigation crumbs to a document,
% a feature particularly valuable in presentations and slide decks:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\documentclass{article}
\usepackage{crumbs}
\usepackage{fancyhdr}
  \fancyhf{}
  \pagestyle{fancy}
  \fancyhead[L]{\crumbs / \subcrumbs}
\begin{document}
\section{Introduction}
Some text here.
\section{Related Works}
Some other text here.
\end{document}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{\crumb}
% The |\crumb{}| and |\subcrumb{}| commands may be redefined
% in order to refine the visual presentation of the crumbs, for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\renewcommand\crumb[2]{{
  \ifnum\value{section}=\value{crumbi}
    \color{orange}
  \fi
  #1
}}
\end{verbatim}
%\iffalse
%</verb>
%\fi
% The command is invoked by |\crumbs| with two arguments: the first
% denotes the short name of the crumb, the second its long form.
% The counter |crumbi| holds the position of the crumb currently being
% rendered, indexed from one.

% \DescribeMacro{\subcrumb}
% The same applies to |\subcrumb{}|, except that the comparison is
% performed between the |subsection| and |subcrumbi| counters
% rather than between |section| and |crumbi|.

% \DescribeMacro{\section}
% \DescribeMacro{\subsection}
% The first parameter of both |\crumb{}| and |\subcrumb{}|
% corresponds to the optional argument of |\section{}| and |\subsection{}|,
% respectively. The second is their mandatory argument, namely the full
% text of the section or subsection.
% Within the |crumbs| package, |\section| and |\subsection| accept an
% optional argument that is reused in the crumbs and still reaches
% the table of contents and the running head as usual, for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\section[Details]{More Details About The Method}
\subsection[SLR]{Systematic Literature Review}
\end{verbatim}
%\iffalse
%</verb>
%\fi
% The starred forms |\section*{}| and |\subsection*{}| are passed
% through untouched and produce no crumbs.
% A |\subsection{}| that precedes the first |\section{}| raises an error,
% since its subcrumbs would have no section to belong to.
% \changes{v0.4.2}{2026/10/15}{Starred sections and subsections are passed through untouched instead of becoming a crumb titled with an asterisk.}
% \changes{v0.4.2}{2026/10/15}{The optional argument of \texttt{\char`\\section} and \texttt{\char`\\subsection} is forwarded to the original commands, so the table of contents and the running head receive the short title again.}
% \changes{v0.4.2}{2026/10/15}{A subsection before the first section raises an error instead of silently appending its subcrumb to the top-level trail.}

% \section{Package Options}

% \DescribeMacro{dry}
% \DescribeMacro{\crumbection}
% \DescribeMacro{\subcrumbection}
% A ``dry'' mode may be enabled, which prevents the package from
% redefining the |\section{}| and |\subsection{}| commands.
% The crumbs mechanism nevertheless remains available via the
% |\crumbection{}| and |\subcrumbection{}| commands, for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\documentclass{article}
\usepackage[dry]{crumbs}
\begin{document}
\crumbection[Intro]{Introduction} % Add it to \crumbs
\section{Introduction} % Print it to the page
Hello, world!
\end{document}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{increment}
% The |increment| package option instructs the package to step
% the |section| counter upon each invocation of |\crumbection{}|
% and the |subsection| counter upon each invocation
% of |\subcrumbection{}|.
% This option is intended for the |dry| mode only, since otherwise
% the redefined |\section{}| and |\subsection{}| would advance
% their counters twice.

% \section{How It Works}

% On every compilation, the file |jobname.crumbs| is written afresh,
% with one line for each |\section| and |\subsection| command.

% At the beginning of the next compilation, this file is loaded and
% it populates the |\crumbs| command with a collection of |\crumb{}|
% invocations, together with one command per section that aggregates
% its |\subcrumb{}| invocations and is printed by |\subcrumbs|.
% The trail therefore always reflects the previous run, just like
% a table of contents does.
% \changes{v0.4.2}{2026/10/15}{The crumbs file is rewritten on every run, so sections added or renamed after the first compilation reach the trail without deleting the file by hand.}

% \StopEventually{}

% \section{Implementation}

% \changes{v0.2.0}{2021/07/10}{Initial version}

% First, we load the \href{https://ctan.org/pkg/etoolbox}{etoolbox}
% package and declare the |dry| and |increment| options:
%    \begin{macrocode}
\RequirePackage{etoolbox}
\makeatletter
\newif\ifcrumbs@dry
\DeclareOption{dry}{\crumbs@drytrue}
\newif\ifcrumbs@increment
\DeclareOption{increment}{\crumbs@incrementtrue}
\makeatother
\ProcessOptions\relax
%    \end{macrocode}

% \begin{macro}{\crumbs@back}
% The |\crumbs| command is populated from the |jobname.crumbs| file.
% We define a special command for the backslash character
% inside that file, as suggested \href{https://tex.stackexchange.com/a/12414/1449}{here}:
%    \begin{macrocode}
\makeatletter
\newcommand\crumbs@back{\@backslashchar}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\crumbs@out}
% \begin{macro}{\crumbs@write}
% Then, we allocate the output stream |\crumbs@out| and define
% |\crumbs@write|, which writes one purified line to it; the stream
% stays open for the whole run:
% \changes{v0.4.2}{2026/10/15}{Internal helpers are prefixed with \texttt{crumbs@}, so a document may define \texttt{\char`\\temp} or \texttt{\char`\\appendtofile} without interference.}
%    \begin{macrocode}
\makeatletter
\newwrite\crumbs@out
\ExplSyntaxOn
\cs_new:Npn\crumbs@write#1{\immediate\write\crumbs@out{\text_purify:n{#1}}}
\ExplSyntaxOff
\makeatother
%    \end{macrocode}
% \end{macro}
% \end{macro}

% \begin{macro}{\subcrumbs}
% The command |\subcrumbs| prints all subcrumbs of the current section:
%    \begin{macrocode}
\newcommand\subcrumbs{%
  \ifnum\value{section}=0\else%
    \expandafter\ifcsname crumbs\romannumeral\the\value{section}\endcsname%
      \csname crumbs\romannumeral\the\value{section}\endcsname{}%
    \fi%
  \fi%
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\crumbection}
% The command |\crumbection| registers a new crumb:
%    \begin{macrocode}
\makeatletter
\newcommand\crumbection[2][]{%
  \def\crumbs@temp{#1}%
  \crumbs@write{%
    \crumbs@back ifx\crumbs@back crumbs\crumbs@back empty%
      \crumbs@back gappto\crumbs@back crumbs\{\crumbs@back setcounter\{crumbi\}\{0\}\}%
    \crumbs@back fi%
    \crumbs@back gappto\crumbs@back crumbs\{\crumbs@back stepcounter\{crumbi\}\crumbs@back crumb{\ifx\crumbs@temp\empty \{#2\}\else \{#1\}\fi}{\{#2\}}\}%
  }%
  \ifcrumbs@increment\stepcounter{section}\fi%
}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\subcrumbection}
% The command |\subcrumbection| registers a new subcrumb, refusing
% to do so before the first section:
%    \begin{macrocode}
\makeatletter
\newcommand\subcrumbection[2][]{%
  \ifnum\value{section}=0%
    \PackageError{crumbs}{A subcrumb needs a section, but the section counter is zero}{Put \string\section\space or \string\crumbection\space before \string\subsection\space or \string\subcrumbection}%
  \else%
    \def\crumbs@temp{#1}%
    \crumbs@write{%
      \crumbs@back ifcsname crumbs\romannumeral\the\value{section}\crumbs@back endcsname\crumbs@back else
        \crumbs@back expandafter\crumbs@back newcommand\crumbs@back csname crumbs\romannumeral\the\value{section}\crumbs@back endcsname\{%
          \crumbs@back setcounter\{subcrumbi\}\{0\}%
        \}%
      \crumbs@back fi%
      \crumbs@back expandafter\crumbs@back gappto\crumbs@back csname crumbs\romannumeral\the\value{section}\crumbs@back endcsname\{%
        \crumbs@back stepcounter\{subcrumbi\}%
        \crumbs@back subcrumb{\ifx\crumbs@temp\empty \{#2\}\else \{#1\}\fi}{\{#2\}}\}%
    }%
    \ifcrumbs@increment\stepcounter{subsection}\fi%
  \fi%
}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\section}
% \begin{macro}{\subsection}
% We also redefine the |\section| and |\subsection| commands:
%    \begin{macrocode}
\makeatletter
\ifcrumbs@dry%
  \message{Since "dry" mode is ON we don't renew "section" and "subsection" commands}%
\else%
  \NewCommandCopy\crumbs@oldsection\section
  \RenewDocumentCommand\section{s o m}{%
    \IfBooleanTF{#1}%
      {\crumbs@oldsection*{#3}}%
      {\IfValueTF{#2}%
        {\crumbection[#2]{#3}\crumbs@oldsection[#2]{#3}}%
        {\crumbection{#3}\crumbs@oldsection{#3}}}%
  }
  \NewCommandCopy\crumbs@oldsubsection\subsection
  \RenewDocumentCommand\subsection{s o m}{%
    \IfBooleanTF{#1}%
      {\crumbs@oldsubsection*{#3}}%
      {\IfValueTF{#2}%
        {\subcrumbection[#2]{#3}\crumbs@oldsubsection[#2]{#3}}%
        {\subcrumbection{#3}\crumbs@oldsubsection{#3}}}%
  }
\fi
\makeatother
%    \end{macrocode}
% \end{macro}
% \end{macro}

% \begin{macro}{\crumb}
% We define a default implementation of |\crumb| command:
%    \begin{macrocode}
\ifcsname crumb\endcsname%
  \message{The command "crumb" is already defined}%
\else%
  \newcommand\crumb[2]{#1}%
\fi%
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\subcrumb}
% We define a default implementation of |\subcrumb| command:
%    \begin{macrocode}
\ifcsname subcrumb\endcsname%
  \message{The command "subcrumb" is already defined}%
\else%
  \newcommand\subcrumb[2]{#1}%
\fi%
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\crumbs}
% The command |\crumbs| stays empty until the |jobname.crumbs| file
% populates it:
%    \begin{macrocode}
\newcommand*\crumbs{}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{crumbi}
% \begin{macro}{subcrumbi}
% We also define two counters:
%    \begin{macrocode}
\newcounter{crumbi}
\newcounter{subcrumbi}
%    \end{macrocode}
% \end{macro}
% \end{macro}

% Finally, at the beginning of the document we load the file written
% by the previous run and then open it for writing again, so that
% every run produces a fresh one:
%    \begin{macrocode}
\makeatletter
\AtBeginDocument{%
  \IfFileExists{\jobname.crumbs}{\input{\jobname.crumbs}}{}%
  \immediate\openout\crumbs@out=\jobname.crumbs\relax%
}
\AtEndDocument{\immediate\closeout\crumbs@out}
\makeatother
%    \end{macrocode}

% \Finale

%\clearpage
%
%\PrintChanges
%\clearpage
%\PrintIndex
