% \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{ffcode.dtx}
% \DoNotIndex{\endgroup,\begingroup,\let,\else,\fi,\newcommand,\newenvironment}

% \iffalse
%<*driver>
\ProvidesFile{ffcode.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{ffcode}
%<*package>
[2026-05-05 0.12.0 Fixed Font Code]
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\AddToHook{env/verbatim/begin}{\microtypesetup{protrusion=false}}
\usepackage{href-ul}
\usepackage{ffcode}
\usepackage{amsmath}
\usepackage{multicol}
\usepackage{xcolor}
\usepackage[dtx,runs=2]{docshots}
\PageIndex
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
	\DocInput{ffcode.dtx}
	\PrintChanges
	\PrintIndex
\end{document}
%</driver>
% \fi

% \title{|ffcode|: \LaTeX{} Package \\ for Fixed-Font Code Blocks\thanks{The sources are in GitHub at \href{https://github.com/yegor256/ffcode}{yegor256/ffcode}}}
% \author{Yegor Bugayenko \\ \texttt{yegor256@gmail.com}}
% \date{\filedate, \fileversion}
%
% \maketitle
%
% \section{Introduction}
%
% This package formats source code in articles
% and ensures it looks nice. After installation from CTAN, the
% typical usage looks like this (note the |\ff| command
% and the |ffcode| environment):
% \begin{docshot}
% \documentclass{article}
% \usepackage{ffcode}
% \pagestyle{empty}
% \begin{document}
% The function |fibo()| is recursive:
% \begin{ffcode}
% int fibo(int n) {
%   if (n < 2) {
%     return n; (*@ \label{ln:ret} @*)
%   }
%   return fibo(n-1)+fibo(n-2);
% }
% \end{ffcode}
% Line no.~\ref{ln:ret} returns \ff{n}
% and terminates it.
% \end{document}
% \end{docshot}

% \DescribeMacro{\ffinput}
% There is also an |\ffinput| command that reads the content from a file
% and places it into the document, formatted exactly as it would be
% if the |ffcode| environment were used. The |ffsave|
% environment may be used first; it acts like the |ffcode|
% environment but, instead of printing the content, saves it to a file
% that can later be read by the |\ffinput| command.

% \section{Package Options}

% \DescribeMacro{samepage}
% The |samepage| package option prevents page breaks inside |ffcode| blocks.

% \DescribeMacro{noframes}
% The |noframes| package option omits the light gray frames around |\ff|
% texts.

% \DescribeMacro{nobars}
% The |nobars| package option omits the vertical gray bar at the left side
% of each snippet.

% \DescribeMacro{nonumbers}
% The |nonumbers| package option omits the line numbers.

% \DescribeMacro{nocn}
% By default, the numbering is continuous: line numbers start at the
% first snippet and increment until the end of the document. The |nocn|
% package option (which stands for ``no continuous numbering'') restarts
% the numbering from one in each snippet.

% \DescribeMacro{bold}
% The |\ff| pieces may be rendered bolder than usual, which may be convenient for some document classes
% (note the use of the \href{https://ctan.org/pkg/lmodern}{lmodern} package; without it, the bold will not work, as explained \href{https://tex.stackexchange.com/a/215489/1449}{here}):
% \docshotOptions{firstline=4,lastline=10}
% \begin{docshot}
% \documentclass{article}
% \usepackage[paperwidth=3in]{geometry}
% \pagestyle{empty}
% \usepackage{lmodern}
% \usepackage[bold,noframes]{ffcode}
% \begin{document}
% Sometimes it's necessary to make
% code pieces look bolder, like
% the |fibo()| function in this text.
% \end{document}
% \end{docshot}

% \DescribeMacro{sf}
% The font family of |\ff| pieces can be changed to |\sffamily|:
% \docshotOptions{firstline=4,lastline=10}
% \begin{docshot}
% \documentclass{article}
% \usepackage[paperwidth=3in]{geometry}
% \pagestyle{empty}
% \usepackage[sf,bold,noframes]{ffcode}
% \begin{document}
% Sometimes a less strictly fixed-width,
% more elegant look may be preferred,
% like the \emph{|fibo()|} here.
% \end{document}
% \end{docshot}

% \section{Typesetting}

% The package correctly formats low-height text, for example, just
% a dot: \ff{.}

% A pair of vertical lines decorates a TeX command inside the snippet.
% A single vertical line can be printed with:
% ``\verb+|\char`\\vert|+''.

% The command |\ff| behaves differently in math mode --- it doesn't
% add gray frames:
% \docshotOptions{firstline=6,lastline=8}
% \begin{docshot}
% \documentclass{article}
% \usepackage{ffcode}
% \usepackage{mathtools}
% \pagestyle{empty}
% \begin{document}
% \begin{equation*}
% x = \int_{|home|}^{\ff{N}} f(x).
% \end{equation*}
% \end{document}
% \end{docshot}

% Lines in the |ffcode| environment can be highlighted,
% and any additional configuration parameters from
% the |listings| package can be applied:
% \docshotOptions{firstline=6,lastline=13}
% \begin{docshot}
% \documentclass{article}
% \usepackage[paperwidth=3in]{geometry}
% \usepackage{ffcode}
% \pagestyle{empty}
% \begin{document}
% \begin{ffcode}[backgroundcolor=\color{gray!20}]
% while (true) {
%   (*@\textcolor{red}{print("Hi!")}@*)
%   print("Enter your name:")
%   scan(x)
%   print("Your name | " + x)
% }
% \end{ffcode}
% \end{document}
% \end{docshot}

% Using the optional argument of |ffcode|,
% any other options from the |listings| package can be passed to the
% snippet.

% The |\lstset| command from the |listings| package can also be used
% to configure defaults for the |ffcode| environment.
% Unlike the optional argument, which applies only to a single snippet,
% |\lstset| has a global effect: every subsequent code listing in the
% document picks up the new settings, including all other |ffcode|
% blocks that follow it.
% To keep the change local to a single |ffcode| block, wrap the call in
% a |\begingroup|\ldots|\endgroup| pair:
% \docshotOptions{firstline=6,lastline=12}
% \begin{docshot}
% \documentclass{article}
% \usepackage[paperwidth=3in]{geometry}
% \usepackage{ffcode}
% \pagestyle{empty}
% \begin{document}
% \begingroup
% \lstset{backgroundcolor=\color{yellow!30}}
% \begin{ffcode}
% print("Hi!")
% \end{ffcode}
% \endgroup
% \end{document}
% \end{docshot}

% A snippet can be rendered in ``condensed'' mode, with smaller spacing
% between letters, by passing |columns=fixed| together with a narrower
% |basewidth| from the |listings| package:
% \docshotOptions{firstline=6,lastline=12}
% \begin{docshot}
% \documentclass{article}
% \usepackage[paperwidth=3in]{geometry}
% \usepackage{ffcode}
% \pagestyle{empty}
% \begin{document}
% \begin{ffcode}[columns=fixed,basewidth=0.4em]
% while (true) {
%   print("Enter your name:")
%   scan(x)
%   print("Hello, " + x)
% }
% \end{ffcode}
% \end{document}
% \end{docshot}

% \StopEventually{}

% \section{Implementation}
% \changes{v0.1.0}{2021/06/10}{Initial version}

% First, we parse package options with the help of
% \href{https://ctan.org/pkg/pgfopts}{pgfopts} package:
% \changes{v0.2.0}{2021/06/13}{Package options \texttt{nonumbers} and \texttt{noframes} added.}
% \changes{v0.3.0}{2021/09/07}{Package option \texttt{nocn} added.}
% \changes{v0.4.0}{2022/01/09}{Package option \texttt{nobars} added.}
% \changes{v0.6.0}{2022/11/16}{We use \texttt{pgfopts} instead of \texttt{xkeyval}.}
% \changes{v0.6.0}{2022/11/16}{Package option \texttt{novert} added, to disable the redefinition of the vertical bar.}
% \changes{v0.7.0}{2022/11/28}{Package option \texttt{bold} added, to make all \texttt{\char`\\ff} pieces look bolder than usual.}
% \changes{v0.7.0}{2022/11/28}{Package option \texttt{sf} added, to print all \texttt{\char`\\ff} pieces with \texttt{\char`\\sffamily}.}
% \changes{v0.9.2}{2024/02/04}{All lengths and sizes are in "em" instead of "pt".}
% \changes{v0.10.0}{2025/01/02}{Package option \texttt{samepage} added, to prevent each \texttt{ffcode} block from breaking across pages.}
% \changes{v0.11.1}{2026/05/01}{Reserve \texttt{xleftmargin} for line numbers so they sit inside the column instead of protruding into the page margin.}
%    \begin{macrocode}
\RequirePackage{pgfopts}
\pgfkeys{
  /ff/.cd,
  bold/.store in=\ff@bold,
  sf/.store in=\ff@sf,
  samepage/.store in=\ff@samepage,
  noframes/.store in=\ff@noframes,
  nonumbers/.store in=\ff@nonumbers,
  nobars/.store in=\ff@nobars,
  novert/.store in=\ff@novert,
  nocn/.store in=\ff@nocn,
}
\ProcessPgfPackageOptions{/ff}
%    \end{macrocode}

% Then, we include the \href{https://ctan.org/pkg/xcolor}{xcolor} package:
%    \begin{macrocode}
\RequirePackage{xcolor}
%    \end{macrocode}

% Then, we configure the \href{https://ctan.org/pkg/listings}{listings} package.
% The defaults are applied here, at package load, so that a user may override
% them globally with \texttt{\char`\\lstset} after \texttt{\char`\\usepackage\{ffcode\}}:
% \changes{v0.9.0}{2024/01/09}{The \texttt{minted} package is replaced by the \texttt{listings} package.}
% \changes{v0.10.2}{2025/07/06}{We started to use \texttt{keepspaces} in order to guarantee correct visual rendering of multi-spaced content.}
% \changes{v0.12.0}{2026/05/05}{Static \texttt{\char`\\lstset} defaults moved from the per-environment hook to the preamble, so that user-supplied \texttt{\char`\\lstset} calls are no longer overwritten on every \texttt{ffcode} usage.}
%    \begin{macrocode}
\RequirePackage{listings}
\makeatletter
% See \href{https://tex.stackexchange.com/questions/706858}{the explanation}:
\lst@AddToHook{Init}{\setlength{\lineskip}{0pt}}
\lstset{breaklines}
\lstset{escapeinside={(*@}{@*)}}
\lstset{basicstyle={\ttfamily}}
\lstset{columns=fullflexible}
\lstset{keepspaces=true}
\ifdefined\ff@nonumbers\else
  \lstset{numbers=left,numbersep=.8em,
    numberstyle={\tiny\sffamily\color{gray}},
    xleftmargin=2.5em}
\fi
\ifdefined\ff@nobars\else
  \lstset{frame=leftline,framerule=.05em,rulecolor={\color{gray}}}
\fi
\ifdefined\ff@nocn\else
  \lstset{firstnumber=last}
\fi
\makeatother
%    \end{macrocode}

% Then, we define a supplementary command \texttt{\char`\\ff@set} that
% applies per-environment options on top of the global defaults:
%    \begin{macrocode}
\makeatletter
\newcommand\ff@set[1]{\lstset{#1}}
\makeatother
%    \end{macrocode}

% \begin{macro}{ffcode}
% Then, we define the |ffcode| environment and its supplementary |ffcode*| counterpart:
%    \begin{macrocode}
\makeatletter
\lstnewenvironment{ffcode}[1][]
  {\ff@set{#1}\ifdefined\ff@samepage\noindent\minipage{\linewidth}\fi}
  {\ifdefined\ff@samepage\endminipage\fi}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{ffinput}
% Then, we define the \texttt{\char`\\ffinput} command:
% \changes{v0.10.0}{2024/12/29}{The \texttt{\char`\\ffinput} command added.}
%    \begin{macrocode}
\makeatletter
\newcommand\ffinput[2][]{%
  \ff@set{#1}%
  \ifdefined\ff@samepage\noindent\minipage{\linewidth}\fi%
  \lstinputlisting[#1]{#2}%
  \ifdefined\ff@samepage\endminipage\fi%
}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{ffsave}
% Then, we define the \texttt{ffsave} environment:
% \changes{v0.11.0}{2025/07/06}{The \texttt{ffsave} environment added.}
%    \begin{macrocode}
\RequirePackage{fancyvrb}
\newenvironment{ffsave}[1][ffsave.txt]
  {\VerbatimEnvironment\begin{VerbatimOut}{#1}}
  {\end{VerbatimOut}}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\ff@print}
% Then, we define a supplementary macro |\ff@print|:
% \changes{v0.5.1}{2022/10/30}{Now, the command \texttt{ff} ignores italic and bold and always prints \texttt{\char`\\texttt} as it should be.}
%    \begin{macrocode}
\makeatletter
\newcommand\ff@print[1]{%
  \textnormal{%
    \ifdefined\ff@sf\sffamily\else\ttfamily\fi%
    \ifdefined\ff@bold\fontseries{b}\selectfont\fi%
    #1%
  }%
}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\ff@rule}
% Then, we define a supplementary command |\ff@rule|:
%    \begin{macrocode}
\makeatletter\newcommand\ff@rule
  {\vrule height 0.6em depth 0.1em width 0em}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\ff@box}
% Then, we use \href{https://ctan.org/pkg/tcolorbox}{tcolorbox} to define the |\ff@box|
% command for a gray box around a verbatim text block:
%    \begin{macrocode}
\makeatletter
\ifdefined\ff@noframes\else
  \RequirePackage{tcolorbox}
  \newtcbox\ff@box{nobeforeafter,colframe=gray!80!white,
    colback=gray!5!white,boxrule=0.01em,arc=0.1em,
    boxsep=0.12em,left=0.05em,right=0.05em,top=0.02em,bottom=0.02em,
    tcbox raise base}
\fi
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\ff@x}
% Then, we define the internal |\ff@x| command for printing a piece of fixed-width-font text:
%    \begin{macrocode}
\makeatletter
\NewDocumentCommand\ff@x{v}{\ff{#1}}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\ff}
% \changes{v0.8.0}{2022/12/01}{The \texttt{\char`\\ff} command is now a normal command, not verbatim.}
% Then, we define |\ff| macro:
%    \begin{macrocode}
\makeatletter
\newcommand\ff[1]{%
  \ifdefined\ff@noframes%
    \ff@rule\ff@print{#1}%
  \else%
    \relax\ifmmode%
      \ff@rule\ff@print{#1}%
    \else%
      \ff@box{\ff@rule\ff@print{#1}}%
    \fi%
  \fi%
}
\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{novert}
% Finally, we let vertical bars work similarly to |\ff|, as suggested
% \href{https://tex.stackexchange.com/a/665105/1449}{here}
% and \href{https://tex.stackexchange.com/a/665303/1449}{here}
% (unless the |novert| package option is used):
%    \begin{macrocode}
\makeatletter\ifdefined\ff@novert\else
  \catcode`\|\active
  \AtBeginDocument{\catcode`\|\active\protected\def|{\ff@x|}}
  \catcode`\| 12 %
\fi\makeatother
%    \end{macrocode}
% \end{macro}

%    \begin{macrocode}
\endinput
%    \end{macrocode}

% \Finale

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