From bddefbf234bbe8889456b2e1b09cce68cf590891 Mon Sep 17 00:00:00 2001
From: Norbert Preining <preining@logic.at>
Date: Mon, 27 May 2013 01:20:56 +0000
Subject: skdoc 5/27

git-svn-id: svn://tug.org/texlive/trunk@30697 c570f23f-e606-0410-a88d-b1316a301751
---
 Master/texmf-dist/source/latex/skdoc/skdoc.dtx | 1046 ++++++++++++++++++++----
 1 file changed, 892 insertions(+), 154 deletions(-)

(limited to 'Master/texmf-dist/source/latex/skdoc/skdoc.dtx')

diff --git a/Master/texmf-dist/source/latex/skdoc/skdoc.dtx b/Master/texmf-dist/source/latex/skdoc/skdoc.dtx
index e8fea60711c..afd57482a03 100644
--- a/Master/texmf-dist/source/latex/skdoc/skdoc.dtx
+++ b/Master/texmf-dist/source/latex/skdoc/skdoc.dtx
@@ -1,7 +1,7 @@
 % \iffalse
 %% skdoc documentation class
 %%
-%% Copyright (C) 2012 by Simon Sigurdhsson <sigurdhsson@gmail.com>
+%% Copyright (C) 2012-2013 by Simon Sigurdhsson <sigurdhsson@gmail.com>
 %% 
 %% This work may be distributed and/or modified under the
 %% conditions of the LaTeX Project Public License, either version 1.3
@@ -73,7 +73,7 @@
 %</driver>
 %<class>\ProvidesExplClass{skdoc}
 %<*class>
-    {2012/12/26}{1.0}{skdoc documentation class}
+    {2013/05/24}{1.3a}{skdoc documentation class}
 %</class>
 %
 %<*driver>
@@ -82,15 +82,20 @@
 \IfFileExists{skdoc.cls}{}{
     \msg_fatal:nn{skdoc-dtx}{not-installed}
 }
+\cs_set_protected_nopar:Npn\ExplHack{
+    \char_set_catcode_letter:n{ 58 }
+    \char_set_catcode_letter:n{ 95 }
+}
 \ExplSyntaxOff
 \DeclareDocumentCommand\MakePercentIgnore{}{\catcode`\%9\relax}
 \DeclareDocumentCommand\MakePercentComment{}{\catcode`\%14\relax}
 \DeclareDocumentCommand\DocInput{m}{
     \MakePercentIgnore\input{#1}\MakePercentComment
 }
-\documentclass{skdoc}
+\documentclass[highlight=false]{skdoc}
 \usepackage{hologo}
 \usepackage{booktabs}
+\usepackage{csquotes}
 \usepackage[style=authoryear,backend=biber]{biblatex}
 %%\usepackage{chslacite}
 \begin{filecontents}{skdoc.bib}
@@ -106,6 +111,14 @@
     year = {2013},
     url = {http://tex.stackexchange.com/a/89830/66}
 }
+@manual{Rahtz10,
+    author = {Sebastian Rahtz and Herbert Vo\ss},
+    title = {The \enquote{\textsf{fancyvrb}} package},
+    subtitle = {Fancy Verbatims in \LaTeX},
+    date = {2012-05-15},
+    version = {2.8},
+    url = {http://mirrors.ctan.org/macros/latex/contrib/fancyvrb/fancyvrb.pdf}
+}
 \end{filecontents}
 \addbibresource{skdoc.bib}
 \OnlyDescription
@@ -119,10 +132,15 @@
 % {}{\small\pagemark}
 % \pagestyle{skdoc-class}
 %
-% \version{1.0}
+% \version{1.3a}
 % \changes{1.0}{Initial version}
+% \changes{1.1}{Added support for syntax highlighting using \pkg{minted}}
+% \changes{1.1a}{Deprecate the use of \pkg{bibtex} in favour of \pkg{biblatex}}
+% \changes{1.2}{Use \pkg{l3prg} booleans instead of toggles}
+% \changes{1.2b}{Use \pkg{inconsolata}. Don't use \pkg{ascii}}
+% \changes{1.3}{Allow multiple targets per \env{MacroCode}}
 %
-% \package[ctan=skbundle,vcs=https://github.com/urdh/skdoc]{skdoc}
+% \package[ctan=skdoc,vcs=https://github.com/urdh/skdoc]{skdoc}
 % \repository{https://github.com/urdh/skdoc}
 % \title{The \thepkg{} document class}
 % \author{Simon Sigurdhsson}
@@ -179,13 +197,27 @@
 %
 % \subsection{Options}
 % \Option{load}\WithValues{\meta{package}}\AndDefault{\cs{jobname}}
-% The \thepkg\ document class has only one option. The \opt{load}
+% \label{ssec:options:load} The \opt{load}
 % option declares that if the package specified exists, it should
 % be loaded. This is intended to load any package provided in the
 % implementation, but requires that the documentation provides
 % stub variants of the macros used in the documentation so that
-% \LaTeX\ still completes its first run. \Warning{The \opt{load}
-% option will likely disappear in a future version.}
+% \LaTeX\ still completes its first run.
+%
+% \Option{highlight}\WithValues{true,false}\AndDefault{true}
+% \label{ssec:option:highlight}
+% The \opt{highlight} option enables or disabled syntax highlighting
+% of the implementation code. Highlighting is performed using
+% \pkg{minted}, and falls back to no highlighting if there is no
+% \cs{write18} access, if \pkg{minted} is unavailable or if the
+% \texttt{pygmentize} binary can't be found.
+% \Notice{On non-unix platforms, the test for \texttt{pygmentize}
+% will likely fail. Therefore, syntax highlighting is not supported
+% on such platforms.}
+%
+% Generally, there should be no reason to disable syntax highlighting
+% unless the documentation describes a very large package, and the
+% repeated calls to \texttt{pygmentize} take too long.
 %
 % \subsection{General macros}
 % The document class defines a number of general macros intended for
@@ -383,7 +415,7 @@
 %   \label{tab:args}
 %   \begin{tabular}{ll}
 %      \toprule
-%      Invokation            % Result          \\
+%      Invokation            & Result          \\
 %      \midrule
 %      \Macro\marg{argument} & \marg{argument} \\
 %      \Macro\oarg{argument} & \oarg{argument} \\
@@ -394,6 +426,39 @@
 %   \end{tabular}
 % \end{table}
 %
+% \subsubsection{Examples}
+% \DescribeEnv[<example code>]{example}
+% Perhaps the most powerful way to illustrate features of a package
+% is to show their function by examples. This is made possible by
+% the \env{example} environment. By enclosing example code in this
+% environment, the actual code is typeset next to the result it would
+% produce, as seen below\footnote{Note that the showcased \env{example}
+% environment doesn't contain another \env{example} environment --- the
+% environment is not intended to be nested inside itself.}\footnote{The
+% percent characters in the example are caused by the \pkg{docstrip}
+% requirement of prefixing the documentation with them.}:
+% \begin{example}
+% Simply typesetting a
+% \emph{paragraph} may
+% be simple enough, but
+% it should showcase
+% the utility of the
+% environment well enough.
+% \end{example}
+%
+% Note that for this to work the package obviously needs to be loaded.
+% As such, it is probably a good idea to combine the use of \env{example}
+% with the \opt{load} option, so be sure to read up on the caveats of
+% using that option (see page \pageref{ssec:options:load}).
+%
+% Since the \env{example} environment is based on the same mechanisms
+% as \env{MacroCode}, (mostly) the same typesetting properties apply.
+% In particular, the code will be highlighted if \pkg{minted} is
+% available. \Notice{Since the backend utilizes \cs{verbatim}, the
+% usual caveats apply. In particular, leaving whitespace before
+% \cs{end}\marg{example} will result in an extra newline at the end
+% of the displayed code.}
+%
 % \subsubsection{Options}
 % Package options are of course important to describe, and to this
 % end four macros are provided. They aid in describing options of
@@ -534,16 +599,16 @@
 % improve readability of the implementation code.
 %
 % \DescribeEnv[<description>]{macro}{<\textbackslash macro>}
-%                     <\# of args>{<arg 1 description>}'...'
-%                                 {<arg n description>}
+%                     [<\# of args>]{<arg 1 description>}'...'
+%                                   {<arg n description>}
 % With this environment, the implementation of a macro is described.
 % Note that as with \cs{DescribeMacro}, \LaTeX3-style macros can not
 % be used in \meta{\textbackslash macro} without the catcode hack
 % mentioned earlier.
 %
 % \DescribeEnv[<description>]{environment}{<environment>}
-%                     <\# of args>{<arg 1 description>}'...'
-%                                 {<arg n description>}
+%                     [<\# of args>]{<arg 1 description>}'...'
+%                                   {<arg n description>}
 % This environment describes the implementation of an environment.
 %
 % \DescribeEnv[<description>]{option}{<option>}
@@ -588,12 +653,16 @@
 % the sequence
 % \Macro\PreambleTo{<\textbackslash token>}{\cs*{jobname}.tex}.
 %
-% \DescribeEnv[<implementation>]{MacroCode}{<key>}
+% \DescribeEnv[<implementation>]{MacroCode}{<key>',...'}
 % The \env{MacroCode} environment typesets and exports
 % \meta{implementation} verbatim to the file associated with \meta{key}.
 % As such, it is the analogue of the \env{macrocode} environment from
 % \pkg{ltxdoc}, but does not suffer from some of its drawbacks (the
-% sensitivity to whitespace, for instance).
+% sensitivity to whitespace, for instance). As detailed by the
+% description of the \opt{highlight} option (on page
+% \pageref{ssec:option:highlight}), the environment will highlight
+% the code using \pkg{minted} if possible. Multiple \meta{key}s are
+% allowed, and the code will be written to all corresponding files.
 %
 % \subsubsection{Hiding the implementation}
 % For lagre packages it may be of interest to hide the implementation
@@ -653,17 +722,19 @@
 % the list of changes, this requires that you run 
 % \texttt{makeglossaries} between the two \LaTeX\ runs.
 %
+% \section{Known issues}
+% A list of current issues is available in the Github repository of this
+% package\footnote{\url{https://github.com/urdh/skdoc/issues}}, but as
+% of the release of \theversion, there are no known issues.
 % \iffalse
-% \section{Planned improvements}
-% Planned improvements of this class include
-% \begin{itemize}
-%     \item Do things the \LaTeX3 way, rename the variables properly
-%           and generally conform to \pkg{expl3} guidelines when
-%           applicable. (Way future thing.)
-% \end{itemize}
+% \begin{description}
+%   \item[\#?]  ???
+% \end{description}
 % \fi
+% If you discover any bugs in this package, please report them to the 
+% issue tracker in the \thepackage\ Github repository.
 %
-% \Implementation
+% \Implementation \ExplHack
 % \section{Implementation}
 % \iffalse
 %</driver>
@@ -685,11 +756,11 @@
 % These packages are basic low-level things that we use to declare
 % commands, work with strings and so on.
 %    \begin{macrocode}
-\RequirePackage{etoolbox,xstring,xparse,atbegshi,kvoptions}
+\RequirePackage{etoolbox,xstring,xparse,atbegshi,kvoptions,pdftexcmds}
 %    \end{macrocode}
 % Now, higher-level packages we use in our definitions.
 %    \begin{macrocode}
-\RequirePackage{verbatim,marginnote,calc,hyperref,multicol,hologo}
+\RequirePackage{verbatim,needspace,marginnote,calc,hyperref,multicol,hologo}
 \RequirePackage[nomain,xindy,numberedsection,order=letter,
                 sanitize={description=false,sort=false}]{glossaries}
 %    \end{macrocode}
@@ -702,10 +773,12 @@
 \RequirePackage[british]{babel}
 \RequirePackage[english=british]{csquotes}
 \RequirePackage[font=small,labelfont=bf,textfont=it]{caption}
-\RequirePackage{scrpage2,PTSerif,ascii}
+\RequirePackage{scrpage2,PTSerif}
+\usepackage[scaled=1.03]{inconsolata}
 \RequirePackage[defaultsans,osfigures,scale=0.95]{opensans}
 \RequirePackage[babel]{microtype}
 %    \end{macrocode}
+%
 % \subsection{Error messages}
 % Set up some error message texts for later use.
 %    \begin{macrocode}
@@ -714,18 +787,95 @@
 \msg_new:nnn{skdoc}{wrote-file}{Writing~things~to~file~"#1".}
 \msg_new:nnn{skdoc}{read-preamble}{Reading~preamble~from~file~"#1".}
 \msg_new:nnn{skdoc}{no-lppl}{Could~not~include~LPPL:~lppl.tex~does~not~exist!}
+\msg_new:nnn{skdoc}{no-minted}{Syntax~highlighting~disabled:~couldn't~find~minted.sty!}
+\msg_new:nnn{skdoc}{no-shell-escape}{Syntax~highlighting~disabled:~running~without~unrestricted~\string\write18.}
+\msg_new:nnn{skdoc}{no-pygments}{Syntax~highlighting~disabled:~couldn't~find~"pygmentize".}
+\msg_new:nnnn{skdoc}{bibtex-unsupported}{The `bibtex` package is unsupported: continue at own risk!}{Use a more modern bibliography system (i.e. `biblatex`) instead.}
+%    \end{macrocode}
+%
+% \subsection{Booleans}
+% Set up some booleans used throughout the code.
+% \begin{macro}{\g__skdoc_use_minted_bool}
+% The \texttt{use_minted} boolean keeps track of wether we're using
+% \pkg{minted} or not. The default value is \emph{false}.
+%    \begin{macrocode}
+\bool_new:N\g__skdoc_use_minted_bool
+\bool_gset_false:N\g__skdoc_use_minted_bool
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g__skdoc_no_index_bool}
+% The \texttt{no_index} boolean keeps track of wether the indexing
+% macros should write things to the index or not. The default value is
+% \emph{false} (don't not write things to the index).
+%    \begin{macrocode}
+\bool_new:N\g__skdoc_no_index_bool
+\bool_gset_false:N\g__skdoc_no_index_bool
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g__skdoc_in_example_bool}
+% The \texttt{in_example} boolean keeps track of wether we are currently
+% inside an example or not (used mainly by \cs{skdoc@verbatim}). The
+% default value is of course \emph{false}.
+%    \begin{macrocode}
+\bool_new:N\g__skdoc_in_example_bool
+\bool_gset_false:N\g__skdoc_in_example_bool
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g__skdoc_with_implementation_bool}
+% The \texttt{with_implementation} boolean keeps track of wether we are
+% going to typeset the implementation or not. The default value is
+% \emph{true}, and this is only changed by \cs{OnlyDescription}.
+%    \begin{macrocode}
+\bool_new:N\g__skdoc_with_implementation_bool
+\bool_gset_true:N\g__skdoc_with_implementation_bool
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g__skdoc_in_implementation_bool}
+% The \texttt{in_implementation} boolean keeps track of wether we are
+% in the implementation part of the documentation or not. It defaults
+% to \emph{false}, and is changed by \cs{Implementation} and \cs{Finale}.
+%    \begin{macrocode}
+\bool_new:N\g__skdoc_in_implementation_bool
+\bool_gset_false:N\g__skdoc_in_implementation_bool
+%    \end{macrocode}
+% \end{macro}
+%
+% Finally, we define a helpful conditional based on the last two
+% booleans. It decides wether code in \cs{skdoc@verbatim} is typeset
+% or just output to a file.
+% \begin{macro*}{\__skdoc_if_print_code_p:}
+% \begin{macro*}{\__skdoc_if_print_code:T}
+% \begin{macro*}{\__skdoc_if_print_code:F}
+% \begin{macro}{\__skdoc_if_print_code:TF}
+%    \begin{macrocode}
+\prg_new_conditional:Nnn\__skdoc_if_print_code:{p,T,F,TF}{
+    \bool_if:nTF{
+        \g__skdoc_in_implementation_bool &&
+        !\g__skdoc_with_implementation_bool
+    }{
+        \prg_return_false:
+    }{
+        \prg_return_true:
+    }
+}
 %    \end{macrocode}
+% \end{macro}
+% \end{macro*}
+% \end{macro*}
+% \end{macro*}
+%
 % \subsection{Options}
-% Define the (as of version 1.0) only option, and process it.
+% Define the all options, and process them.
 %    \begin{macrocode}
 \SetupKeyvalOptions{
     family=skdoc,
     prefix=skdoc@
 }
 \DeclareStringOption{load}[\jobname]
+\DeclareBoolOption[true]{highlight}
 \ProcessKeyvalOptions*
 %    \end{macrocode}
-% If the option was used, load the given package if it exists.
+% If the \opt{load} option was used, load the given package if it exists.
 %    \begin{macrocode}
 \IfStrEq{\skdoc@load}{}{}{%
     \IfFileExists{\skdoc@load.sty}{%
@@ -733,6 +883,305 @@
     }{}
 }
 %    \end{macrocode}
+%
+% \subsection{Special case: syntax highlighting}
+% We support syntax highlighting through \pkg{minted}, but only if 
+% we're running with unrestricted \cs{write18} access \emph{and}
+% there exists a suitable executable (\texttt{pygmentize}). Since
+% \pkg{minted} bails out without \cs{write18} access, we have to test
+% that before even loading it.
+%
+% \subsubsection{A simple \cs{write18} test}
+% Using the \cs{pdf@shellescape} macro from \pkg{pdftexcmds}, we
+% can define a new conditional that decides if we have unrestricted
+% \cs{write18} or not.
+% \begin{macro*}{\__skdoc_if_shellescape:T}
+% \begin{macro*}{\__skdoc_if_shellescape:F}
+% \begin{macro}{\__skdoc_if_shellescape:TF}
+%    \begin{macrocode}
+\prg_new_conditional:Nnn\__skdoc_if_shellescape:{T,F,TF}{
+    \if_cs_exist:N\pdf@shellescape
+%    \end{macrocode}
+% If the command sequence exists (it really should), we test to see
+% if it is equal to one. The \cs{pdf@shellescape} macro will be zero
+% if no \cs{write18} access is available, two if we have restricted
+% access and one if access is unrestricted.
+%    \begin{macrocode}
+        \if_int_compare:w\pdf@shellescape=\c_one
+            \prg_return_true:
+        \else:
+            \prg_return_false:
+        \fi:
+%    \end{macrocode}
+% If the command sequence doesn't exist, we assume that we have
+% unrestricted \cs{write18} access (we probably don't), and let
+% \LaTeX\ complain about it later.
+%    \begin{macrocode}
+    \else:
+        \prg_return_true:
+    \fi:
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro*}
+% \end{macro*}
+%
+% \subsubsection{Testing for an application}
+% In order to find out wether \texttt{pygmentize} is installed, we
+% have to test for its binary. This is done by shelling out to
+% \texttt{which} and reading a temporary file, which means we need
+% a way to delete that file.
+% \begin{macro}{\__skdoc_rm:n}[1]
+%   {The file to be removed}
+%    \begin{macrocode}
+\cs_new:Npn\__skdoc_rm:n#1{
+    \immediate\write18{rm~#1}
+}
+%    \end{macrocode}
+% \end{macro}
+% Now, let's define the actual test. Note that this test will fail
+% on non-unixy platforms (\emph{i.e.} Windows). Deal with it for now.
+% \begin{macro*}{\__skdoc_if_pygmentize:nT}
+% \begin{macro*}{\__skdoc_if_pygmentize:nF}
+% \begin{macro}{\__skdoc_if_pygmentize:nTF}[1]
+%   {The name of the binary to check existence of}
+%    \begin{macrocode}
+\prg_new_conditional:Nnn\__skdoc_if_pygmentize:{T,F,TF}{
+%    \end{macrocode}
+% First, run \texttt{which} to create the temporary file.
+%    \begin{macrocode}
+    \immediate\write18{which~pygmentize~&&~touch~\jobname.aex}
+%    \end{macrocode}
+% A temporary boolean is defined to hold the result of the test (this
+% is a bit of carco cult programming, any clues as to why placing the
+% result inside \cs{file_if_exists:nTF} doesn't work are welcome), and
+% if the test is successful we remove the temporary file.
+%    \begin{macrocode}
+    \bool_set:Nn\l_tmpa_bool{\c_false_bool}
+    \file_if_exist:nT{\jobname.aex}{
+        \__skdoc_rm:n{\jobname.aex}
+        \bool_set:Nn\l_tmpa_bool{\c_true_bool}
+    }
+%    \end{macrocode}
+% Finally, the temporary boolean is used to return a result.
+%    \begin{macrocode}
+    \if_bool:N\l_tmpa_bool
+        \prg_return_true:
+    \else:
+        \prg_return_false:
+    \fi:
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro*}
+% \end{macro*}
+%
+% Using the macros defined above, we can test for both \cs{write18}
+% and \texttt{pygmentize}, loading \pkg{minted} and setting a flag
+% if both exist. If the option \opt{highlight} was supplied and set
+% to \texttt{false}, we do nothing.
+%    \begin{macrocode}
+\ifskdoc@highlight
+    \IfFileExists{\skdoc@load.sty}{
+        \__skdoc_if_shellescape:TF{
+            \__skdoc_if_pygmentize:TF{
+                \bool_gset_true:N\g__skdoc_use_minted_bool
+                \RequirePackage{minted}
+%    \end{macrocode}
+% Now that we have \pkg{minted}, we redefine the style of the line
+% numbers to match what we have further down for the non-highlighted
+% mode.
+%    \begin{macrocode}
+                \renewcommand{\theFancyVerbLine}{
+                    \sffamily\tiny\textcolor{lightgray}{
+                    \oldstylenums{\arabic{FancyVerbLine}}}
+                }
+%    \end{macrocode}
+% We also define our own Pygments style, to match the \thepackage%
+% color theme. This is a bunch of code generated by running
+% \texttt{pygmentize -S default -f latex}, with modifications. Note
+% the abundancy of \verb|#| characters; this is somewhat black magic,
+% but apparently \LaTeX\ expands them one more time than I'd expect
+% in this context. Probably a \LaTeX3 artifact. Also, the macro names
+% somehow correspond to Pygments entities (see \emph{e.g.}
+% \texttt{pygmentize -S default -f html}), but it's not entirely
+% apparent which macro corresponds to what entity.
+%    \begin{macrocode}
+                \renewcommand\minted@usedefaultstyle{}
+                \def\PY@reset{\let\PY@it=\relax \let\PY@bf=\relax%
+                    \let\PY@ul=\relax \let\PY@tc=\relax%
+                    \let\PY@bc=\relax \let\PY@ff=\relax}
+                \def\PY@tok##1{\csname PY@tok@##1\endcsname}
+                \def\PY@toks##1+{\ifx\relax##1\empty\else%
+                    \PY@tok{##1}\expandafter\PY@toks\fi}
+                \def\PY@do##1{\PY@bc{\PY@tc{\PY@ul{%
+                    \PY@it{\PY@bf{\PY@ff{##1}}}}}}}
+                \def\PY##1##2{\PY@reset\PY@toks##1+\relax+\PY@do{##2}}
+                \expandafter\def\csname PY@tok@gd\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@gu\endcsname{%
+                    \let\PY@bf=\textbf%
+                    \def\PY@tc####1{\textcolor{optioncolor}{####1}}}
+                \expandafter\def\csname PY@tok@gt\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@gs\endcsname{%
+                    \let\PY@bf=\textbf}
+                \expandafter\def\csname PY@tok@gr\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@cm\endcsname{%
+                    \let\PY@it=\textit%
+                    \def\PY@tc####1{\textcolor{lightgray}{####1}}}
+                \expandafter\def\csname PY@tok@vg\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@m\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta}{####1}}}
+                \expandafter\def\csname PY@tok@mh\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta}{####1}}}
+                \expandafter\def\csname PY@tok@cs\endcsname{%
+                    \let\PY@it=\textit%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@ge\endcsname{%
+                    \let\PY@it=\textit}
+                \expandafter\def\csname PY@tok@vc\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@il\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta}{####1}}}
+                \expandafter\def\csname PY@tok@go\endcsname{%
+                    \def\PY@tc####1{\textcolor{gray}{####1}}}
+                \expandafter\def\csname PY@tok@cp\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp!75}{####1}}}
+                \expandafter\def\csname PY@tok@gi\endcsname{%
+                    \def\PY@tc####1{\textcolor{bright}{####1}}}
+                \expandafter\def\csname PY@tok@gh\endcsname{%
+                    \let\PY@bf=\textbf%
+                    \def\PY@tc####1{\textcolor{section}{####1}}}
+                \expandafter\def\csname PY@tok@ni\endcsname{%
+                    \let\PY@bf=\textbf%
+                    \def\PY@tc####1{\textcolor{keydesc}{####1}}}
+                \expandafter\def\csname PY@tok@nn\endcsname{%
+                    \let\PY@ul=\underline%
+                    \def\PY@tc####1{\textcolor{black}{####1}}}
+                \expandafter\def\csname PY@tok@no\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@na\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta!50}{####1}}}
+                \expandafter\def\csname PY@tok@nb\endcsname{%
+                    \def\PY@tc####1{\textcolor{black}{####1}}}
+                \expandafter\def\csname PY@tok@nc\endcsname{%
+                    \let\PY@ul=\underline%
+                    \def\PY@tc####1{\textcolor{bright}{####1}}}
+                \expandafter\def\csname PY@tok@nd\endcsname{%
+                    \def\PY@tc####1{\textcolor{gray}{####1}}}
+                \expandafter\def\csname PY@tok@si\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@nf\endcsname{%
+                    \def\PY@tc####1{\textcolor{bright}{####1}}}
+                \expandafter\def\csname PY@tok@s2\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@vi\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@nt\endcsname{%
+                    \let\PY@bf=\textbf%
+                    \def\PY@tc####1{\textcolor{meta!50}{####1}}}
+                \expandafter\def\csname PY@tok@nv\endcsname{%
+                    \def\PY@tc####1{\textcolor{scriptcolor}{####1}}}
+                \expandafter\def\csname PY@tok@s1\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@gp\endcsname{%
+                    \def\PY@tc####1{\textcolor{gray}{####1}}}
+                \expandafter\def\csname PY@tok@sh\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@ow\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@sx\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@bp\endcsname{%
+                    \def\PY@tc####1{\textcolor{black}{####1}}}
+                \expandafter\def\csname PY@tok@c1\endcsname{%
+                    \let\PY@it=\textit%
+                    \def\PY@tc####1{\textcolor{lightgray}{####1}}}
+                \expandafter\def\csname PY@tok@kc\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@c\endcsname{%
+                    \let\PY@it=\textit%
+                    \def\PY@tc####1{\textcolor{lightgray}{####1}}}
+                \expandafter\def\csname PY@tok@mf\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta}{####1}}}
+                \expandafter\def\csname PY@tok@err\endcsname{%
+                    \def\PY@tc####1{\textcolor{intlink}{####1}}%
+                    \def\PY@bc####1{\setlength{\fboxsep}{0pt}%
+                    \colorbox{bright}{\strut ####1}}}
+                \expandafter\def\csname PY@tok@kd\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@ss\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@sr\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta}{####1}}}
+                \expandafter\def\csname PY@tok@mo\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta}{####1}}}
+                \expandafter\def\csname PY@tok@mi\endcsname{%
+                    \def\PY@tc####1{\textcolor{meta}{####1}}}
+                \expandafter\def\csname PY@tok@kn\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@kr\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@s\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@kp\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@w\endcsname{%
+                    \def\PY@tc####1{\textcolor{lightgray}{####1}}}
+                \expandafter\def\csname PY@tok@kt\endcsname{%
+                    \def\PY@tc####1{\textcolor{black}{####1}}}
+                \expandafter\def\csname PY@tok@sc\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@sb\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@k\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \expandafter\def\csname PY@tok@se\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@sd\endcsname{%
+                    \def\PY@tc####1{\textcolor{sharp}{####1}}}
+                \expandafter\def\csname PY@tok@nl\endcsname{%
+                    \def\PY@tc####1{\textcolor{bright}{####1}}}
+                \expandafter\def\csname PY@tok@ne\endcsname{%
+                    \def\PY@tc####1{\textcolor{bright}{####1}}}
+                \expandafter\def\csname PY@tok@o\endcsname{%
+                    \def\PY@tc####1{\textcolor{macroimpl}{####1}}}
+                \def\PYZbs{\char`\\}
+                \def\PYZus{\char`\_}
+                \def\PYZob{\char`\{}
+                \def\PYZcb{\char`\}}
+                \def\PYZca{\char`\^}
+                \def\PYZam{\char`\&}
+                \def\PYZlt{\char`\<}
+                \def\PYZgt{\char`\>}
+                \def\PYZsh{\char`\#}
+                \def\PYZpc{\char`\%}
+                \def\PYZdl{\char`\$}
+                \def\PYZhy{\char`\-}
+                \def\PYZsq{\char`\'}
+                \def\PYZdq{\char`\"}
+                \def\PYZti{\char`\~}
+                \def\PYZat{@}
+                \def\PYZlb{[}
+                \def\PYZrb{]}
+%    \end{macrocode}
+% If there's no \texttt{pygmentize}, no \cs{write18} or no \pkg{minted},
+% we display a warning message and proceed without highlighting.
+%    \begin{macrocode}
+            }{
+                \msg_warning:nn{skdoc}{no-pygments}
+            }
+        }{
+            \msg_warning:nn{skdoc}{no-shell-escape}
+        }
+    }{
+        \msg_warning:nn{skdoc}{no-minted}
+    }
+\fi
+%    \end{macrocode}
 % \subsection{The \env{MacroCode} environment}
 % We need a token list and input/output.
 %    \begin{macrocode}
@@ -745,6 +1194,8 @@
 %   {Filename of the file being declared}
 % This declares a file as part of the bundle, which means we will be
 % writing things to it.
+%    \changes{1.1a}{Don't create a new token list until we know the
+%                   key isn't a duplicate}
 %    \begin{macrocode}
 \DeclareDocumentCommand\DeclareFile{om}{
     \group_begin:
@@ -757,13 +1208,15 @@
     \def\skdoc@preamble{}%
     \def\skdoc@key{#2}%
     \IfNoValueTF{#1}{}{\keys_set:nn{skdoc@declarefile}{#1}}
-    \tl_new:c{skdoc@output@\skdoc@key}
     \int_if_exist:cTF{skdoc@output@\skdoc@key @line}{
         \msg_critical:nnx{skdoc}{key-exists}{\skdoc@key}
     }{
         \int_zero_new:c{skdoc@output@\skdoc@key @line}
     }
-    \IfStrEq{\skdoc@preamble}{}{}{
+    \tl_new:c{skdoc@output@\skdoc@key}
+    \IfStrEq{\skdoc@preamble}{}{
+        \def\skdoc@preamble@extra{}
+    }{
         \tl_set:Nx\l_tmpa_tl{\skdoc@preamble}
         \edef\skdoc@temp{\tl_head:N\l_tmpa_tl}
         \def\skdoc@preamble@extra{
@@ -787,67 +1240,212 @@
 % \end{macro}
 % \begin{environment}{skdoc@verbatim}[1]
 %   {The key of the file being described}
+% \changes{1.1}{Introducing syntax highlighting}
+% \changes{1.1a}{Test for key existence before bumping counter,
+%                use \cs{Needspace*} to prevent code label from
+%                staying on the wrong page in some situations}
+% \changes{1.2}{Hide line numbers when inside \env{example}}
+% \changes{1.3}{Allow multiple (comma-separated) targets}
+% \changes{1.3a}{Fix critical bug}
 % This environment does all the actual work for \env{MacroCode}.
 %    \begin{macrocode}
+\clist_new:N\l__skdoc_keys
 \DeclareDocumentEnvironment{skdoc@verbatim}{m}{%
-    \iftoggle{skdoc@impl}{\@bsphack}{}
-    \def\skdoc@key{#1}
-    \int_if_exist:cTF{skdoc@output@\skdoc@key @line}{}{
-        \msg_critical:nnx{skdoc}{key-nexists}{\skdoc@key}
-    }%
-    \marginnote{
-        \leavevmode
-        \llap{
-            \scriptsize\color{gray}
-            $\langle$\skdoc@key$\rangle$
-            \makebox[2ex]{\strut}
+    \clist_set:Nn\l__skdoc_keys{#1}
+%    \end{macrocode}
+% If the file we're supposed to write to hasn't been initialized yet,
+% we error out with a critical error.
+%    \begin{macrocode}
+    \clist_map_inline:Nn\l__skdoc_keys{
+        \int_if_exist:cTF{skdoc@output@##1@line}{}{
+            \msg_critical:nnn{skdoc}{key-nexists}{##1}
+        }%
+%    \end{macrocode}
+% Before doing anything, set create or increment a counter keeping
+% track of the line number of the file we're writing to.
+%    \begin{macrocode}
+        \int_compare:nNnT{\int_use:c{skdoc@output@##1@line}}=\c_zero%
+            {\int_gincr:c{skdoc@output@##1@line}}%
+    }
+%    \end{macrocode}
+% Now, if we're supposed to print code, we set a few things up.
+%    \begin{macrocode}
+    \__skdoc_if_print_code:T{
+        \bool_if:NTF\g__skdoc_use_minted_bool{
+%    \end{macrocode}
+% If we're using \pkg{minted}, we set a few options ans open the
+% output file.
+%    \begin{macrocode}
+            \minted@resetoptions%
+            \exp_args:Nnx\setkeys{minted@opt}{
+                \int_compare:nNnF{\clist_count:N\l__skdoc_keys}>\c_one{
+                    \bool_if:NF\g__skdoc_in_example_bool{linenos,}
+                    firstnumber=\int_use:c{skdoc@output@#1@line}
+                }
+            }%
+            \iow_open:Nn\minted@code{\jobname.pyg}%
+            \Needspace*{2\baselineskip}%
+        }{
+%    \end{macrocode}
+% Otherwise, we hack spaces with \cs{@bsphack} (unless we're in an
+% \env{example} environment).
+%    \begin{macrocode}
+            \bool_if:NF\g__skdoc_in_example_bool{\@bsphack}%
+        }
+        \bool_if:NF\g__skdoc_in_example_bool{
+%    \end{macrocode}
+% In all non-example code, \pkg{minted} or not, we output a small
+% marker showing what file we are writing to.
+%    \begin{macrocode}
+            \marginnote{
+                \leavevmode
+                \llap{
+                    \scriptsize\color{gray}
+                    $\langle$#1$\rangle$
+                    \makebox[2ex]{\strut}
+                }
+            }
         }
     }
+%    \end{macrocode}
+% Otherwise, we set up the \env{verbatim} line processor.
+%    \begin{macrocode}
     \def\verbatim@processline{%
-        \tl_gput_right:cx{skdoc@output@\skdoc@key}{\the\verbatim@line\iow_newline:}%
-        \int_gincr:c{skdoc@output@\skdoc@key @line}%
-        \iftoggle{skdoc@impl}{
-            \noindent\leavevmode%
-            \hspace*{-5ex}
-            \begin{minipage}[c][1ex]{\textwidth}
-                \makebox[4ex]{%
-                    \leavevmode
-                    \tiny\color{lightgray}\hfill%
-                    \int_use:c{skdoc@output@\skdoc@key @line}%
-                }%
-                \hspace*{1ex}%
-                {
-                    \verbatim@font\footnotesize
-                    \the\verbatim@line
-                }
-            \end{minipage}
-            \vskip-.75ex\par
-        }{}
+%    \end{macrocode}
+% We alsays append the line to the appropriate token list, so that it
+% is saved to the output file.
+%    \begin{macrocode}
+        \clist_map_inline:Nn\l__skdoc_keys{
+            \tl_gput_right:cx{skdoc@output@####1}{\the\verbatim@line\iow_newline:}%
+        }
+%    \end{macrocode}
+% If we're supposed to print code, we do a lot more...
+%    \begin{macrocode}
+        \__skdoc_if_print_code:T{
+            \bool_if:NTF\g__skdoc_use_minted_bool{
+%    \end{macrocode}
+% ...but if we're using minted, \enquote{a lot more} consists of also
+% writing the line to the file used by \pkg{minted}.
+%    \begin{macrocode}
+                \iow_now:Nx\minted@code{\the\verbatim@line}%
+            }{
+%    \end{macrocode}
+% Otherwise, we actually do a lot of stuff. We typeset the line number
+% (unless we're in an example):
+%    \begin{macrocode}
+                \noindent\leavevmode%
+                \bool_if:NF\g__skdoc_in_example_bool{\hspace*{-5ex}}
+                \begin{minipage}[c][1ex]{\textwidth}
+                    \bool_if:nF{
+                        \g__skdoc_in_example_bool &&
+                        !\int_compare_p:nNn{\clist_count:N\l__skdoc_keys}>\c_one
+                    }{
+                        \makebox[4ex]{%
+                            \leavevmode
+                            \sffamily\tiny\color{lightgray}\hfill%
+                            \clist_map_inline:Nn\l__skdoc_keys{
+                                \oldstylenums{\int_use:c{skdoc@output@####1@line}}%
+                            }
+                        }%
+                        \hspace*{1ex}%
+                    }
+%    \end{macrocode}
+% We also typeset the actual line:
+%    \begin{macrocode}
+                    {
+                        \verbatim@font
+                        \the\verbatim@line
+                    }
+                \end{minipage}
+%    \end{macrocode}
+% Both of them in the same one-line-high minipage covering the page
+% width. Note the use of \cs{llap} for line numbers in the margin.
+% We end with a \cs{par} for the next line.
+%    \begin{macrocode}
+                \par
+            }
+        }
+%    \end{macrocode}
+% Finally, the line number counter is incremented.
+%    \begin{macrocode}
+        \clist_map_inline:Nn\l__skdoc_keys{
+            \int_gincr:c{skdoc@output@####1@line}%
+        }
     }%
+%    \end{macrocode}
+% Now the \env{verbatim} catcode magic begins.
+%    \begin{macrocode}
+    \group_begin:
     \let\do\@makeother\dospecials\catcode`\^^M\active%
-    \iftoggle{skdoc@impl}{
+    \bool_if:nT{
+        \__skdoc_if_print_code_p: &&
+        !\g__skdoc_use_minted_bool
+    }{
         \frenchspacing\@vobeyspaces
-    }{}
+    }
     \verbatim@start%
 }{%
-    \iftoggle{skdoc@impl}{\@esphack}{}%
+    \group_end:
+%    \end{macrocode}
+% The catcode magic is over! Now, if we're printing code, there are
+% a few things left to do.
+%    \begin{macrocode}
+    \__skdoc_if_print_code:T{
+        \bool_if:NTF\g__skdoc_use_minted_bool{
+%    \end{macrocode}
+% If we're using \pkg{minted}, we still have to actually print the code.
+% We begin with closing the output file.
+%    \begin{macrocode}
+            \iow_close:N\minted@code%
+%    \end{macrocode}
+% A few spacing fixes are applied. Since \pkg{minted} uses
+% \pkg{fancyvrb}, these negative \cs{vspace}s are derived from the
+% \pkg{fancyvrb} documentation \parencite[pp.~46--47]{Rahtz10}. What
+% we want to do is to offset the spacing produced by \pkg{minted}, so
+% that we are in control.
+%    \begin{macrocode}
+            \bool_if:NF\g__skdoc_in_example_bool{
+                \vspace*{-\topsep}
+                \vspace*{-\partopsep}
+                \vspace*{-\parskip}
+            }
+%    \end{macrocode}
+% Now, the internal \pkg{minted} macro \cs{minted@pygmentize} is called
+% to highlight and typeset the code, and the temporary file is removed.
+%    \begin{macrocode}
+            \minted@pygmentize{latex}%
+            \DeleteFile{\jobname.pyg}%
+%    \end{macrocode}
+% This is followed by more space-offsetting.
+%    \begin{macrocode}
+            \vspace*{-\topsep}
+            \vspace*{-\partopsep}
+        }{
+%    \end{macrocode}
+% If we aren't using \pkg{minted}, we hack spaces with \cs{@esphack}
+% instead.
+%    \begin{macrocode}
+            \bool_if:NF\g__skdoc_in_example_bool{\@esphack}%
+        }
+    }%
 }
 %    \end{macrocode}
 % \end{environment}
 % \begin{environment}{MacroCode}[1]
 %   {The key of the file being described}
+% \changes{1.1}{Minor changes due to syntax highlighting}
 %    \begin{macrocode}
 \DeclareDocumentEnvironment{MacroCode}{m}{
-    \iftoggle{skdoc@impl}{
+    \__skdoc_if_print_code:T{
         \vspace{.2\baselineskip}
-        \par\noindent
-    }{}
+        \bool_if:NF\g__skdoc_use_minted_bool{\par\noindent}
+    }
     \skdoc@verbatim{#1}
 }{
     \endskdoc@verbatim
-    \iftoggle{skdoc@impl}{
+    \__skdoc_if_print_code:T{
         \vspace{.5\baselineskip}
-    }{}
+    }
 }
 %    \end{macrocode}
 % \end{environment}
@@ -945,13 +1543,6 @@
 % We introduce a couple of macros for referencing various constructs
 % in running text, \emph{i.e.} \cs{cs}-like macros. The starred
 % variants will not index the use, the non-starred variants will.
-%
-% First, though, we introduce a toggle letting us permanently disable
-% indexing inside \emph{e.g.} the table of contents and index.
-%    \begin{macrocode}
-\newtoggle{skdoc@noindex}
-\togglefalse{skdoc@noindex}
-%    \end{macrocode}
 % \begin{macro}{\cs}[2]
 %   {True if this is the starred variant}
 %   {The macro name to be typeset}
@@ -959,7 +1550,7 @@
 %    \begin{macrocode}
 \DeclareDocumentCommand\cs{sm}{
     \texttt{\char`\\#2}
-    \iftoggle{skdoc@noindex}{}{
+    \bool_if:NF\g__skdoc_no_index_bool{
         \IfBooleanTF{#1}{}{\index@macro{#2}}
     }
 }
@@ -972,7 +1563,7 @@
 %    \begin{macrocode}
 \DeclareDocumentCommand\env{sm}{
     \texttt{#2}
-    \iftoggle{skdoc@noindex}{}{
+    \bool_if:NF\g__skdoc_no_index_bool{
         \IfBooleanTF{#1}{}{\index@environment{#2}}
     }
 }
@@ -985,7 +1576,7 @@
 %    \begin{macrocode}
 \DeclareDocumentCommand\pkg{sm}{
     \textsf{#2}
-    \iftoggle{skdoc@noindex}{}{
+    \bool_if:NF\g__skdoc_no_index_bool{
         \IfBooleanTF{#1}{}{\index@package{#2}}
     }
 }
@@ -998,7 +1589,7 @@
 %    \begin{macrocode}
 \DeclareDocumentCommand\opt{sm}{
     \texttt{#2}
-    \iftoggle{skdoc@noindex}{}{
+    \bool_if:NF\g__skdoc_no_index_bool{
         \IfBooleanTF{#1}{}{\index@option{#2}}
     }
 }
@@ -1011,7 +1602,7 @@
 %    \begin{macrocode}
 \DeclareDocumentCommand\bib{sm}{
     \texttt{@#2}
-    \iftoggle{skdoc@noindex}{}{
+    \bool_if:NF\g__skdoc_no_index_bool{
         \IfBooleanTF{#1}{}{\index@bibentry{#2}}
     }
 }
@@ -1024,7 +1615,7 @@
 %    \begin{macrocode}
 \DeclareDocumentCommand\thm{sm}{
     \textrm{#2}
-    \iftoggle{skdoc@noindex}{}{
+    \bool_if:NF\g__skdoc_no_index_bool{
         \IfBooleanTF{#1}{}{\index@theme{#2}}
     }
 }
@@ -1037,7 +1628,7 @@
 %    \begin{macrocode}
 \DeclareDocumentCommand\file{sm}{
     \texttt{#2}
-    \iftoggle{skdoc@noindex}{}{
+    \bool_if:NF\g__skdoc_no_index_bool{
         \IfBooleanTF{#1}{}{\index@file{#2}}
     }
 }
@@ -1177,9 +1768,10 @@
 %    \end{macrocode}
 % \end{macro}
 % \begin{macro*}{\skdoc@WithValues@peek}
+% \changes{1.2a}{Add \cs{ignorespaces} to fix spacing bug}
 %    \begin{macrocode}
 \def\skdoc@WithValues@peek{
-    \ifx\@let@token\AndDefault\else\par\noindent\nobreak\fi
+    \ifx\@let@token\AndDefault\else\par\noindent\nobreak\ignorespaces\fi
 }
 %    \end{macrocode}
 % \end{macro*}
@@ -1199,9 +1791,10 @@
 %   {The value of a key-value option}
 % Typesets the default value of a key-value option. To the far
 % right of the line.
+% \changes{1.2a}{Add \cs{ignorespaces} to fix spacing bug}
 %    \begin{macrocode}
 \DeclareDocumentCommand\AndDefault{m}{
-    \llap{\textcolor{gray}{\texttt{(#1)}}}\par\noindent\nobreak
+    \llap{\textcolor{gray}{\texttt{(#1)}}}\par\noindent\nobreak\ignorespaces
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1222,6 +1815,7 @@
 % \begin{macro}{\WithFields}[2]
 %   {Optional fields}
 %   {Mandatory fields}
+% \changes{1.2a}{Add \cs{ignorespaces} to fix spacing bug}
 %    \begin{macrocode}
 \DeclareDocumentCommand\WithFields{om}{
     \noindent\makebox[\linewidth]{
@@ -1230,7 +1824,7 @@
             \textcolor{gray}{\texttt{,#2}}
         }
     }
-    \par\noindent\nobreak
+    \par\noindent\nobreak\ignorespaces
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1238,13 +1832,14 @@
 % A macro for describing themes is supplied.
 % \begin{macro}{\Theme}[1]
 %   {The theme name}
+% \changes{1.2a}{Add \cs{ignorespaces} to fix spacing bug}
 %    \begin{macrocode}
 \DeclareDocumentCommand\Theme{m}{
     \marginnote{
         \index@theme*{#1}
         \hfill\llap{\textcolor{macrodesc}{\thm{#1}}}
     }
-    \nobreak\par\noindent\nobreak
+    \nobreak\par\noindent\nobreak\ignorespaces
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1252,28 +1847,147 @@
 % And finally, a macro for describing files is provided.
 % \begin{macro}{\DescribeFile}[1]
 %   {The filename}
+% \changes{1.2a}{Add \cs{ignorespaces} to fix spacing bug}
 %    \begin{macrocode}
 \DeclareDocumentCommand\DescribeFile{m}{
     \marginnote{
         \index@file*{#1}
         \hfill\llap{\textcolor{macrodesc}{\file{#1}}}
     }
-    \nobreak\par\noindent\nobreak
+    \nobreak\par\noindent\nobreak\ignorespaces
 }
 %    \end{macrocode}
 % \end{macro}
 %
-% \paragraph{Missing commands}
-% Descriptional commands for \hologo{BibTeX} entry types and themes
-% are not yet implemented.
+% Lastly, we define an envionment for showing examples. It's quite
+% complex, utilizing (and kind of hacking) \cs{skdoc@verbatim} and
+% typesetting the content using \pkg{l3coffins}.
+%
+% First, three dimensions used in constructing the side-by-side boxes.
+% \begin{macro}{\c__skdoc_example_margin_dim}
+% This dimension, set to half of \cs{baselineskip}, dictates the margin
+% between the content of the coffins and the dividing ruler.
+%    \begin{macrocode}
+\dim_const:Nn\c__skdoc_example_margin_dim{0.5\baselineskip}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\c__skdoc_example_linewidth_dim}
+% This dimension sets the width of the dividing ruler.
+%    \begin{macrocode}
+\dim_const:Nn\c__skdoc_example_linewidth_dim{1pt}
+%    \end{macrocode}
+% \end{macro}
+%
+% Next, three coffins used by the \env{example} environment are defined.
+% One for code, one for the divider and one for the result.
+% \begin{macro}{\l__skdoc_example_code_coffin}
+%    \begin{macrocode}
+\coffin_new:N\l__skdoc_example_code_coffin
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\l__skdoc_example_divider_coffin}
+%    \begin{macrocode}
+\coffin_new:N\l__skdoc_example_divider_coffin
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\l__skdoc_example_result_coffin}
+%    \begin{macrocode}
+\coffin_new:N\l__skdoc_example_result_coffin
+%    \end{macrocode}
+% \end{macro}
 %
-% Lastly, we define an envionment for showing examples. It's
-% rediculously simple, really.
+% Finally, we can define the actual \env{example} environment!
 % \begin{environment}{example}
+% \changes{1.2}{Print example code next to the result}
 %    \begin{macrocode}
 \DeclareDocumentEnvironment{example}{}{
-    \minisec{Example:}
-}{}
+%    \end{macrocode}
+% The environment starts by priting a small header indicating that
+% the content is in fact an example. It also sets a couple of counters
+% and IO variables to trick \cs{skdoc@verbatim} into thinking that it's
+% actually writing to a defined output file.
+%    \begin{macrocode}
+    \bool_gset_true:N\g__skdoc_in_example_bool%
+    \minisec{Example:}%
+    \int_zero_new:c{skdoc@output@skdoc@private@example@line}%
+    \tl_if_exist:cTF{skdoc@output@skdoc@private@example}{
+        \tl_clear:c{skdoc@output@skdoc@private@example}
+    }{
+        \tl_new:c{skdoc@output@skdoc@private@example}
+    }
+%    \end{macrocode}
+% Next, we calculate the coffin width. We do this locally, not in a
+% global constant, since we may be somewhere where \cs{textwidth}
+% might have changed.
+%    \begin{macrocode}
+    \dim_set:Nn\l_tmpa_dim{ \textwidth/2
+                           -\c__skdoc_example_margin_dim
+                           -\c__skdoc_example_linewidth_dim/2}
+%    \end{macrocode}
+% The code coffin is now filled, after clearing it. It'll get filled
+% with the contents of the verbatim environment, typeset like other
+% \env{MacroCode} environments in the document (\emph{i.e.} \pkg{minted}
+% if possible).
+%    \begin{macrocode}
+    \coffin_clear:N\l__skdoc_example_code_coffin
+    \vcoffin_set:Nnw\l__skdoc_example_code_coffin{\l_tmpa_dim}
+    \skdoc@verbatim{skdoc@private@example}
+}{
+    \endskdoc@verbatim
+    \vcoffin_set_end:
+%    \end{macrocode}
+% Next comes the example result coffin. After clearing it, it gets
+% filled by writing the contents of the token list defined previously
+% (the one \cs{skdoc@verbatim} is tricked into writing to) to a
+% temporary file, then reading that temporary file using \cs{input}.
+% We leave the temporary file behind; cleaning up requires \cs{write18}.
+% Also: Meh.
+%    \begin{macrocode}
+    \coffin_clear:N\l__skdoc_example_result_coffin
+    \vcoffin_set:Nnw\l__skdoc_example_result_coffin{\l_tmpa_dim}
+    \iow_open:Nn\skdoc@output{\jobname.skdoc.tmp}
+    \iow_now:Nx\skdoc@output{\tl_to_str:c{skdoc@output@skdoc@private@example}}
+    \iow_close:N\skdoc@output
+    \input{\jobname.skdoc.tmp}
+    \vcoffin_set_end:
+%    \end{macrocode}
+% The divider coffin, being dependent on the height of the two previous
+% coffins, is also reset every time. After clearing, we calculate the
+% maximum height of the two coffins, and add two margins (top and
+% bottom). This value is used to typeset a (gray) rule of the width
+% specified earlier (by \cs{c__skdoc_example_linewidth_dim}). Margins
+% are also added to either side of this rule.
+%    \begin{macrocode}
+    \coffin_clear:N\l__skdoc_example_divider_coffin
+    \dim_set:Nn\l_tmpa_dim{
+        \dim_max:nn{\coffin_ht:N\l__skdoc_example_code_coffin}%
+                   {\coffin_ht:N\l__skdoc_example_result_coffin}
+        + 2\c__skdoc_example_margin_dim}
+    \hcoffin_set:Nn\l__skdoc_example_divider_coffin{
+        \color{lightgray}
+        \hspace*{\c__skdoc_example_margin_dim}
+        \rule{\c__skdoc_example_linewidth_dim}{\l_tmpa_dim}
+        \hspace*{\c__skdoc_example_margin_dim}
+    }
+%    \end{macrocode}
+% It's finally time to join and typeset the coffins. We clear a temporary
+% coffin, copy the divider into it, and proceed to attach the example
+% result coffin to the left and the code to the right (vertical centers
+% touching, so that they are \enquote{centered} vertically). The
+% temporary coffin is then typeset.
+%    \begin{macrocode}
+    \coffin_clear:N\l_tmpa_coffin
+    \coffin_set_eq:NN\l_tmpa_coffin\l__skdoc_example_divider_coffin
+    \coffin_join:NnnNnnnn\l_tmpa_coffin{l}{vc}%
+                         \l__skdoc_example_result_coffin{r}{vc}%
+                         {0pt}{0pt}
+    \coffin_join:NnnNnnnn\l_tmpa_coffin{r}{vc}%
+                         \l__skdoc_example_code_coffin{l}{vc}%
+                         {0pt}{0pt}
+    \coffin_typeset:Nnnnn\l_tmpa_coffin{T}{l}{0pt}{0pt}
+    \bool_gset_false:N\g__skdoc_in_example_bool%
+    \vspace*{\c__skdoc_example_margin_dim}\par
+}
 %    \end{macrocode}
 % \end{environment}
 %
@@ -1294,7 +2008,7 @@
     \IfBooleanTF{#1}{
         \IfNoValueTF{#3}{}{
             \int_compare:nNnTF{#3}>{0}{
-                \cs:w use_none:\prg_replicate:nn{#3}{n}\cs_end:
+                \use:c{use_none:\prg_replicate:nn{#3}{n}}
             }{}
         }
     }{
@@ -1322,7 +2036,7 @@
     \IfBooleanTF{#1}{
         \IfNoValueTF{#3}{}{
             \int_compare:nNnTF{#3}>{0}{
-                \cs:w use_none:\prg_replicate:nn{#3}{n}\cs_end:
+                \use:c{use_none:\prg_replicate:nn{#3}{n}}
             }{}
         }
     }{
@@ -1447,11 +2161,14 @@
 % \cs{marginnote} rather than in an \cs{fbox}.
 % \begin{macro}{\PrintEnvImplName}[1]
 %   {The environment name to be printed}
+% \changes{1.3}{Fixed incorrect spacing}
 %    \begin{macrocode}
 \def\PrintEnvImplName#1{%
-    \par\mbox{}
-    \marginnote{\llap{\implstyle{#1}}}
-    \par
+    \par\leavevmode\null
+    \hbox{%
+        \marginnote{\llap{\implstyle{#1\strut}}}%
+    }
+    \null
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1524,19 +2241,26 @@
 % \end{macro*}
 %
 % \subsection{The index}
-%    \begin{macrocode}
-\prg_new_conditional:Nnn\__skdoc_do_index:{p}{
-    \iftoggle{skdoc@impl}{
+% \begin{macro*}{\__skdoc_if_do_index:T}
+% \begin{macro*}{\__skdoc_if_do_index:F}
+% \begin{macro*}{\__skdoc_if_do_index:TF}
+% \begin{macro}{\__skdoc_if_do_index_p:}
+%    \begin{macrocode}
+\prg_new_conditional:Nnn\__skdoc_if_do_index:{p,T,F,TF}{
+    \bool_if:nTF{
+        \__skdoc_if_print_code_p: &&
+        !\g__skdoc_no_index_bool
+    }{
         \prg_return_true:
     }{
-        \iftoggle{skdoc@in@impl}{
-            \prg_return_false:
-        }{
-            \prg_return_true:
-        }
+        \prg_return_false:
     }
 }
 %    \end{macrocode}
+% \end{macro}
+% \end{macro*}
+% \end{macro*}
+% \end{macro*}
 % The index is based on \pkg{glossaries}, and as such the whole
 % process of adding entries to the index is reduced to adding
 % glossary entries. This is done through two wrapper macros around
@@ -1551,9 +2275,9 @@
 % index entry.
 %    \begin{macrocode}
 \DeclareDocumentCommand\@index@{mm}{
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \@index@@{#1}{#2}
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1599,7 +2323,7 @@
     \ifglsentryexists{index-\skdoc@temp}{}{
         \@index@{#3}{\cs*{#3}}
     }
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \IfBooleanTF{#2}{
             \glsadd[types=index,format=hyperul]{index-\skdoc@temp}
         }{
@@ -1609,7 +2333,7 @@
                 \glsadd[types=index]{index-\skdoc@temp}
             }
         }
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1623,7 +2347,7 @@
     \ifglsentryexists{index-\skdoc@temp}{}{
         \@index@{\string#3}{\env*{\string#3}~(environment)}
     }
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \IfBooleanTF{#2}{
             \glsadd[types=index,format=hyperul]{index-\skdoc@temp}
         }{
@@ -1633,7 +2357,7 @@
                 \glsadd[types=index]{index-\skdoc@temp}
             }
         }
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1647,7 +2371,7 @@
     \ifglsentryexists{index-\skdoc@temp}{}{
         \@index@{\string#3}{\opt*{\string#3}~(option)}
     }
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \IfBooleanTF{#2}{
             \glsadd[types=index,format=hyperul]{index-\skdoc@temp}
         }{
@@ -1657,7 +2381,7 @@
                 \glsadd[types=index]{index-\skdoc@temp}
             }
         }
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1672,7 +2396,7 @@
     \ifglsentryexists{index-\skdoc@temp}{}{
         \@index@{#3}{\bib*{#3}~(\hologoRobust{BibTeX}~entry~type)}
     }
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \IfBooleanTF{#2}{
             \glsadd[types=index,format=hyperul]{index-\skdoc@temp}
         }{
@@ -1682,7 +2406,7 @@
                 \glsadd[types=index]{index-\skdoc@temp}
             }
         }
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1696,7 +2420,7 @@
     \ifglsentryexists{index-\skdoc@temp}{}{
         \@index@{\string#3}{\thm*{\string#3}~(theme)}
     }
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \IfBooleanTF{#2}{
             \glsadd[types=index,format=hyperul]{index-\skdoc@temp}
         }{
@@ -1706,7 +2430,7 @@
                 \glsadd[types=index]{index-\skdoc@temp}
             }
         }
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1720,7 +2444,7 @@
     \ifglsentryexists{index-\skdoc@temp}{}{
         \@index@{\string#3}{\pkg*{\string#3}~(package)}
     }
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \IfBooleanTF{#2}{
             \glsadd[types=index,format=hyperul]{index-\skdoc@temp}
         }{
@@ -1730,7 +2454,7 @@
                 \glsadd[types=index]{index-\skdoc@temp}
             }
         }
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1744,7 +2468,7 @@
     \ifglsentryexists{index-\skdoc@temp}{}{
         \@index@{\string#3}{\file*{\string#3}~(file)}
     }
-    \if_predicate:w\__skdoc_do_index_p:
+    \__skdoc_if_do_index:T{
         \IfBooleanTF{#2}{
             \glsadd[types=index,format=hyperul]{index-\skdoc@temp}
         }{
@@ -1754,7 +2478,7 @@
                 \glsadd[types=index]{index-\skdoc@temp}
             }
         }
-    \fi:
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -1779,14 +2503,14 @@
     \glossarystyle{indexgroup}
     \renewcommand*{\glspostdescription}{\unskip\leaders\hbox to 2.9mm{\hss.}\hfill\strut}
     \renewenvironment{theglossary}{
-        \toggletrue{skdoc@noindex}
+        \bool_gset_true:N\g__skdoc_no_index_bool
         \begin{multicols}{2}
         \setlength{\parindent}{0pt}
         \setlength{\parskip}{0pt plus 0.3pt}
         \let\item\@idxitem
     }{
         \end{multicols}
-        \togglefalse{skdoc@noindex}
+        \bool_gset_false:N\g__skdoc_no_index_bool
     }
     \renewcommand*{\glossaryentryfield}[5]{
         \item\glsentryitem{##1}\glstarget{##1}{##2}
@@ -1811,13 +2535,14 @@
 \AtBeginDocument{\makeglossaries}
 %    \end{macrocode}
 % \begin{macro}{\PrintIndex}
+% \changes{1.2}{Fixed incorrect reference to boldfaced text}
 % Finally, we define a command \cs{PrintIndex} that prints the index.
 % Note the preamble that describes how the index page numbers work.
 %    \begin{macrocode}
 \providecommand*\PrintIndex{%
     \begingroup
     \renewcommand*{\glossarypreamble}{
-        Numbers~written~in~boldface~refer~to~the~page~where~the~
+        Numbers~written~in~italic~refer~to~the~page~where~the~
         corresponding~entry~is~described;~numbers~underlined~refer~
         to~the~page~were~the~implementation~of~the~corresponding~
         entry~is~discussed.~Numbers~in~roman~refer~to~other~
@@ -1955,11 +2680,11 @@
 \newglossarystyle{changelog}{
     \glossarystyle{altlist}
     \renewenvironment{theglossary}{
-        \toggletrue{skdoc@noindex}
+        \bool_gset_true:N\g__skdoc_no_index_bool
         \begin{multicols}{2}\begin{description}
     }{
         \end{description}\end{multicols}
-        \togglefalse{skdoc@noindex}
+        \bool_gset_false:N\g__skdoc_no_index_bool
     }
     \renewcommand*{\glossaryentryfield}[5]{
         \par\vspace{5\p@}\relax
@@ -2001,42 +2726,37 @@
 % must force a page break between what's before the implementation and
 % what's after, which might look horrible.
 %
-% Anyway, we define two toggles that keep track of things. One keeps
-% track of wether to (not) hide the implementation, and one keeps track 
-% of wether we are in the implementation or not. These are provided with
-% sensible defaults (\emph{i.e.} true and false, respectively).
-% We also define a counter in which we save the page number we had when
+% We define a counter in which we save the page number we had when
 % the implementation started.
 %    \begin{macrocode}
-\newtoggle{skdoc@impl}
-\newtoggle{skdoc@in@impl}
-\toggletrue{skdoc@impl}
-\togglefalse{skdoc@in@impl}
 \newcounter{skdoc@impl@page}
 %    \end{macrocode}
 % Then we define the shipout hook. Fairly straight-forward.
 %    \begin{macrocode}
 \AtBeginShipout{
-    \iftoggle{skdoc@impl}{}{
-        \iftoggle{skdoc@in@impl}{\AtBeginShipoutDiscard}{}
-    }
+    \__skdoc_if_print_code:F{\AtBeginShipoutDiscard}
 }
 %    \end{macrocode}
 % \begin{macro}{\OnlyDescription}
 % The \cs{OnlyDescription} macro simply toggles the appropriate toggle.
 %    \begin{macrocode}
-\DeclareDocumentCommand\OnlyDescription{}{\togglefalse{skdoc@impl}}
+\DeclareDocumentCommand\OnlyDescription{}{
+    \bool_gset_false:N\g__skdoc_with_implementation_bool
+}
 %    \end{macrocode}
 % \end{macro}
 % \begin{macro}{\Implementation}
+% \changes{1.1a}{Hide references used in the hidden implementation}
 % The \cs{Implementation} macro defines all the sectioning commands
 % to be empty (saving the old ones), clears the page, saves the page
-% number and toggles the appropriate toggle.
+% number and toggles the appropriate toggle. If \pkg{biblatex} is
+% loaded, we start a new \env{refsection} so that we can hide
+% references used in the implementation from the final bibliography.
 %    \begin{macrocode}
 \DeclareDocumentCommand\Implementation{}{
-    \iftoggle{skdoc@impl}{}{
+    \bool_if:NF\g__skdoc_with_implementation_bool{
         \clearpage
-        \toggletrue{skdoc@in@impl}
+        \bool_gset_true:N\g__skdoc_in_implementation_bool
         \let\skdoc@old@part\part
         \DeclareDocumentCommand\part{som}{}
         \let\skdoc@old@section\section
@@ -2049,19 +2769,24 @@
         \DeclareDocumentCommand\paragraph{som}{}
         \let\skdoc@old@subparagraph\subparagraph
         \DeclareDocumentCommand\subparagraph{som}{}
+        \cs_if_exist:NTF\refsection{\refsection}{}
         \setcounter{skdoc@impl@page}{\value{page}}
     }
 }
 %    \end{macrocode}
 % \end{macro}
 % \begin{macro}{\Finale}
+% \changes{1.1a}{Hide references used in the hidden implementation}
 % The \cs{Finale} macro basically just undoes what the 
-% \cs{Implementation} macro did.
+% \cs{Implementation} macro did. If \pkg{biblatex} is used, the
+% \env{refsection} environment is ended and the (local) bibliography
+% is printed.
 %    \begin{macrocode}
 \DeclareDocumentCommand\Finale{}{
-    \iftoggle{skdoc@impl}{}{
+    \bool_if:NF\g__skdoc_with_implementation_bool{
+        \cs_if_exist:NTF\refsection{\printbibliography\endrefsection}{}
         \clearpage
-        \togglefalse{skdoc@in@impl}
+        \bool_gset_false:N\g__skdoc_in_implementation_bool
         \let\part\skdoc@old@part
         \let\section\skdoc@old@section
         \let\subsection\skdoc@old@subsection
@@ -2348,11 +3073,11 @@
 %    \begin{macrocode}
 \let\old@tableofcontents\tableofcontents
 \DeclareDocumentCommand\tableofcontents{}{
-    \toggletrue{skdoc@noindex}
+    \bool_gset_true:N\g__skdoc_no_index_bool
     \microtypesetup{protrusion=false}
     \old@tableofcontents
     \microtypesetup{protrusion=true}
-    \togglefalse{skdoc@noindex}
+    \bool_gset_false:N\g__skdoc_no_index_bool
 }
 %    \end{macrocode}
 % \end{macro}
@@ -2443,12 +3168,14 @@
 \DisableLigatures{family = tt*}
 %    \end{macrocode}
 % We also want numbers on the bibliography headings, if we are loading
-% \pkg{biblatex}.
+% \pkg{biblatex}. If we happen to be loading \pkg{bibtex}, we issue a
+% warning instead.
 %    \begin{macrocode}
 \AtBeginDocument{
     \ifdefined\defbibheading
         \defbibheading{bibliography}[\bibname]{\section{#1}}
     \fi
+    \@ifpackageloaded{bibtex}{\msg_warning:nn{skdoc}{bibtex-unsupported}}{}
 }
 %    \end{macrocode}
 % Oh, and we want \cs{marginpar}s on the left, not on the right.
@@ -2464,10 +3191,21 @@
 %</class>
 % \fi
 % \Finale
-%
-% \iffalse
-% \section{Known issues}
-% \fi
+% \section{Installation}
+% The easiest way to install this package is using the package
+% manager provided by your \LaTeX\ installation if such a program
+% is available. Failing that, provided you have obtained the package
+% source (\file{skdoc.dtx} and \file{Makefile}) from either CTAN
+% or Github, running \texttt{make install} inside the source directory
+% works well. This will extract the documentation and code from
+% \file{skdoc.dtx}, install all files into the TDS tree at
+% \texttt{TEXMFHOME} and run \texttt{mktexlsr}.
+%
+% If you want to extract code and documentation without installing
+% the package, run \texttt{make all} instead. If you insist on not
+% using \texttt{make}, remember that \file{skdoc.cls} is generated
+% by running \texttt{tex}, while the documentation is generated by
+% running \texttt{pdflatex}.
 %
 % \PrintChanges
 % \PrintIndex
-- 
cgit v1.2.3

