summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/skdoc
diff options
context:
space:
mode:
authorNorbert Preining <preining@logic.at>2013-05-27 01:20:56 +0000
committerNorbert Preining <preining@logic.at>2013-05-27 01:20:56 +0000
commitbddefbf234bbe8889456b2e1b09cce68cf590891 (patch)
tree76869528777f4951ab78a9b15d1e15f593721418 /Master/texmf-dist/source/latex/skdoc
parentf07b7c015a77f69963eb08048aba8c5621cdb0c1 (diff)
skdoc 5/27
git-svn-id: svn://tug.org/texlive/trunk@30697 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/skdoc')
-rw-r--r--Master/texmf-dist/source/latex/skdoc/skdoc.dtx1046
1 files changed, 892 insertions, 154 deletions
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