% !TeX root = ../easyfloats.tex % Copyright © 2020 E. Zöllner % Alternatively to the terms of the LPPL, at your choice, % you can redistribute and/or modify this file under the % terms of the Do What The Fuck You Want To Public License, Version 2, % as published by Sam Hocevar. See http://www.wtfpl.net/about/. % Defines an environment to typeset LaTeX code: % \begin{examplecode} % \let\do=\@makeother % \dospecials % \end{examplecode} % @ is treated as letter. % % A starred version takes one argument, TeX code to be executed inside of the group. % It can be used to change catcodes or to define escape characters. % \begin{examplecode*}{\ExamplecodeEscapeinside $ $} % a long$\\$long line % \end{examplecode*} % % \ExamplecodeEscapeinside takes two arguments % characters between which the code is executed normally. % % \ExamplecodeNoBox % disables the tcolorbox % % \ExamplecodeLinenumbers % enables line numbers % % \ExamplecodeVerbDelimiter| % code between | is treated as verbatim % \ExamplecodeVerbDelimiterOff % no code is treated as verbatim % % \ExampleCodeEscapeInside{...} % can be used to set \ExamplecodeVerbDelimiter in the example code % % \\ is redefined to cause a linebreak marked with \ExamplecodePostBreakText. \makeatletter % ---------- settings --------- \usepackage{xcolor} \usepackage{tcolorbox} \tcbuselibrary{breakable,skins} \usepackage{latexsym} \usepackage{textcomp} % taken from /usr/lib/python3/dist-packages/pygments/styles/default.py \definecolor{math}{RGB}{"BA,"21,"21} \definecolor{aligntab}{RGB}{"00,"80,"00} \definecolor{parameter}{RGB}{"19,"17,"7C} \colorlet{superscript}{black} \colorlet{subscript}{superscript} \colorlet{brace}{aligntab} \colorlet{controlsequence}{aligntab} \definecolor{comment}{RGB}{"40,"80,"80} \colorlet{verb}{black} \definecolor{codebackground}{rgb}{0.9,0.9,1} \colorlet{codeborder}{codebackground!50!black} \colorlet{codelinkcolor}{white} \newtcolorbox{examplecodebox}{breakable, skin=enhanced, colback = codebackground, colframe = codeborder, size = fbox, % normal|title|small|fbox|tight|minimal %left = 0pt, right = 0pt, %top = 0pt, bottom = 0pt, %boxrule = 1pt, %arc = 3pt, } \newcommand{\ExamplecodeNoBox}{% \let\examplecodebox=\par \let\endexamplecodebox=\par } \newcommand{\NewExamplecodeFormatMandatoryArgument}[2]{% #1: control sequence, #2: replacement text where ##1 is the unprocessed argument \expandafter\newcommand\csname @examplecode@formatarg\detokenize{#1}\endcsname[1]{\ExamplecodeProcessBeginGroup{\{}#2\ExamplecodeProcessEndGroup{\}}\ExamplecodeAllowLinebreakBeforeNext\@examplecode@loop}% } \newcommand{\NewExamplecodeFormatOptionalArgument}[4]{% #1: control sequence, #2: bracket open, #3: bracket close, #4: replacement text where ##1 is the unprocessed argument \expandafter\def\csname @examplecode@formatoptarg\detokenize{#1}#2\endcsname##1#3{\ExamplecodeProcessBracket{#2}#4\ExamplecodeProcessBracket{#3}\ExamplecodeAllowLinebreakBeforeNext\@examplecode@loop}% } \NewExamplecodeFormatMandatoryArgument\begin{\ExamplecodeProcessEnv{#1}\ExamplecodeSetCmd{#1}} \NewExamplecodeFormatMandatoryArgument\end{\ExamplecodeProcessEnv{#1}\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument\usepackage{\ExamplecodeProcessPkg{#1}\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument{object}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument{tableobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument{figureobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument{subobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument\objectset{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatOptionalArgument\includegraphicobject[]{\ExamplecodeParseKeys{}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatOptionalArgument\includegraphicsubobject[]{\ExamplecodeParseKeys{}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument\NewObjectStyle{\ExamplecodeParse\relax\relax\ExamplecodeEndParseKeys#1\ExamplecodeEndParseKeys\ExamplecodeSetCmd{\NewObjectStyle2}} \NewExamplecodeFormatMandatoryArgument{\NewObjectStyle2}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} % custom styles defined in example \NewExamplecodeFormatMandatoryArgument{tikzobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \NewExamplecodeFormatMandatoryArgument{tikz3dobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} \newcommand{\ExamplecodeFormatMeta}[1]{{\normalfont\meta{#1}}} \newcommand{\ExamplecodePrint}[1]{#1} \newcommand{\ExamplecodePostBreakSymbol}{\footnotesize$\hookrightarrow$\quad} \newcommand{\ExamplecodeIndentation}{}% don't change this, it is overwritten later to always contain the indentation of the current line \newcommand{\ExamplecodePostBreakText}{\hbox{\ExamplecodeIndentation\ExamplecodePostBreakSymbol}} \newcommand{\ExamplecodeAllowLinebreak}{\discretionary{}{\ExamplecodePostBreakText}{}} \newcommand{\ExamplecodeAllowLinebreakBeforeNext}{\@examplecode@allowlinebreakbeforenexttrue} \newcommand{\ExamplecodeLinebreak}{\newline\ExamplecodePostBreakText} \ExplSyntaxOn \newcommand{\ExamplecodeFormatCmd}[1]{ { \leavevmode \color{controlsequence} % do not try to link macros in expl syntax \tl_if_in:nnTF {#1}{\textunderscore} {\string#1} {\LinkUnformattedKeyword{cs}{\detokenize{#1}}{\string#1}} } \ExamplecodeAllowLinebreakBeforeNext } % catcode 0/16 \ExplSyntaxOff \newcommand{\ExamplecodeFormatEnv}[1]{\LinkUnformattedKeyword{env}{#1}{#1}} \newcommand{\ExamplecodeFormatPkg}[1]{\LinkUnformattedKeyword{pkg}{#1}{#1}} \newcommand{\ExamplecodeFormatBeginGroup}[1]{\textcolor{brace}{#1}} % catcode 1 \newcommand{\ExamplecodeFormatEndGroup}[1]{\textcolor{brace}{#1}\ExamplecodeAllowLinebreakBeforeNext} % catcode 2 \newcommand{\ExamplecodeFormatMathShift}[1]{\textup{#1}} % catcode 3, see \ExamplecodeFormatMath \newcommand{\ExamplecodeFormatAlignmentTab}[1]{\textcolor{aligntab}{#1}} % catcode 4 % catcode 5: \ExamplecodeEndOfLine \newcommand{\ExamplecodeFormatParameter}[1]{\textcolor{parameter}{#1}} % catcode 6 \newcommand{\ExamplecodeFormatSuperscript}[1]{\textcolor{superscript}{#1}} % catcode 7 \newcommand{\ExamplecodeFormatSubscript}[1]{\textcolor{subscript}{#1}} % catcode 8 % catcode 9: ignored % catcode 10: \ExamplecodeSpace, \ExamplecodeTab \newcommand{\ExamplecodeFormatText}[1]{% \ifx`#1% \textasciigrave \else\ifx'#1% \textquotesingle \else #1% \fi\fi } % catcode 11, 12 \newcommand{\ExamplecodeFormatBracket}[1]{#1} % catcode 11 % catcode 13: active (uses \ExamplecodeFormatCmd, too) % in contrast to the other format macros this does % *not* take an argument. Instead it applies the % format for the rest of the group. \newcommand{\ExamplecodeFormatComment}{% \leavevmode \color{comment}% \itshape \let\color=\@gobble } % catcode 14 \newcommand{\ExamplecodeFormatMath}{% \leavevmode \color{math}% \itshape \let\color=\@gobble \ExamplecodeForbidLinebreaks } \newcommand{\ExamplecodeForbidLinebreaks}{% \let\discretionary=\@thirdofthree } % catcode 3 % catcode 15: invalid \newcommand{\ExamplecodeSpaceSymbol}{\space} \newcommand{\ExamplecodeTabSymbol}{\qquad} \newcommand{\ExamplecodeIndentationSpace}{\EnsureHMode\nobreak\space} \newcommand{\ExamplecodeIndentationTab}{\EnsureHMode\nobreak\qquad} \newcommand{\ExamplecodeNormalSpace}{\discretionary{}{\ExamplecodePostBreakText}{\hbox{\ExamplecodeSpaceSymbol}}} \newcommand{\ExamplecodeNormalTab}{\discretionary{}{\ExamplecodePostBreakText}{\hbox{\ExamplecodeTabSymbol}}} \newcommand{\ExamplecodeEndOfLine}{\EnsureHMode\par} \newcommand{\ExamplecodeTabsize}{4} \newcommand{\ExamplecodeAllowLinebreakAfter}[1]{\expandafter\def\csname @examplecode@breakafter@#1\endcsname{\ExamplecodeAllowLinebreakBeforeNext}} \ExamplecodeAllowLinebreakAfter] \newcommand\ExampleCodeEscapeInside{\PackageError{examplecode}{\string\ExampleCodeEscapeInside\ should not be called outside of examplecode}{}} \newcommand{\ExamplecodeVerbDelimiter}[1]{% \let\@examplecode@verb@delimiter=#1% } \newcommand{\ExamplecodeVerbDelimiterOff}{% \let\@examplecode@verb@delimiter=\relax } \ExamplecodeVerbDelimiterOff \newcommand{\ExamplecodeFormatVerbDelimiter}[1]{\textcolor{brace}{#1}} \newcommand{\ExamplecodeFormatVerb}{\color{verb}} % ---------- process --------- \newif\ifExamplecodeInAlign \newcounter{@examplecode@grouplevel} \gdef\@examplecode@grouplevel@mathenter{-1} \newcommand{\ExamplecodeProcessCmd}[1]{\ExamplecodePrint{\ExamplecodeFormatCmd{#1}}} % catcode 0/16 \newcommand{\ExamplecodeProcessEnv}[1]{\ExamplecodePrint{\ExamplecodeFormatEnv{#1}}} \newcommand{\ExamplecodeProcessPkg}[1]{\ExamplecodePrint{\ExamplecodeFormatPkg{#1}}} \newcommand{\ExamplecodeProcessBeginGroup}[1]{% \stepcounter{@examplecode@grouplevel}% \ExamplecodePrint{\ExamplecodeFormatBeginGroup{#1}}% } % catcode 1 \newcommand{\ExamplecodeProcessEndGroup}[1]{% \ifnum \value{@examplecode@grouplevel} = \@examplecode@grouplevel@mathenter \relax \@examplecode@math@end \fi \addtocounter{@examplecode@grouplevel}{-1}% \ExamplecodePrint{\ExamplecodeFormatEndGroup{#1}}% } % catcode 2 \newcommand{\ExamplecodeProcessMathShift}[1]{\ExamplecodePrint{\ExamplecodeFormatMathShift{#1}}} % catcode 3 \newcommand{\ExamplecodeProcessBeginMath}{\ExamplecodePrint{\begingroup\ExamplecodeFormatMath}} % catcode 3 \newcommand{\ExamplecodeProcessEndMath}{\ExamplecodePrint{\endgroup}} \newcommand{\ExamplecodeProcessAlignmentTab}[1]{\ExamplecodePrint{% \ifExamplecodeInAlign \endgroup \fi \ExamplecodeAllowLinebreak \begingroup \ExamplecodeInAligntrue \ExamplecodeForbidLinebreaks \ExamplecodeFormatAlignmentTab{#1}% }} % catcode 4 \newcommand{\ExamplecodeProcessEndOfLine}{\ExamplecodePrint{% \ifExamplecodeInAlign \endgroup \fi \ExamplecodeEndOfLine }} % catcode 5 \newcommand{\ExamplecodeProcessParameter}[1]{\ExamplecodePrint{\ExamplecodeFormatParameter{#1}}} % catcode 6 \newcommand{\ExamplecodeProcessSuperscript}[1]{\ExamplecodePrint{\ExamplecodeFormatSuperscript{#1}}} % catcode 7 \newcommand{\ExamplecodeProcessSubscript}[1]{\ExamplecodePrint{\ExamplecodeFormatSubscript{#1}}} % catcode 8 % catcode 9: ignored \newcommand{\ExamplecodeProcessSpace}{\ExamplecodePrint{\ExamplecodeSpace}\ExamplecodeAppendIndentation{\ExamplecodeSpace}} % catcode 10 \newcommand{\ExamplecodeProcessTab}{\ExamplecodePrint{\ExamplecodeTab}\ExamplecodeAppendIndentation{\ExamplecodeTab}} % catcode 10 \newcommand{\ExamplecodeProcessText}[1]{\ExamplecodePrint{\ExamplecodeFormatText{#1}}} % catcode 11, 12 \newcommand{\ExamplecodeProcessBracket}[1]{\ExamplecodePrint{\ExamplecodeFormatBracket{#1}}} % catcode 11 % catcode 13: active (uses \ExamplecodeProcessCmd, too) \newcommand{\ExamplecodeProcessBeginComment}{\ExamplecodePrint{\begingroup\ExamplecodeFormatComment}} % catcode 14 \newcommand{\ExamplecodeProcessEndComment}{\ExamplecodePrint{\endgroup}} % catcode 15: invalid \newcommand{\ExamplecodeProcessCleanup}{\ExamplecodePrint{% \ifExamplecodeInAlign \endgroup \fi }} \newcommand{\ExamplecodeProcessMeta}[1]{\ExamplecodePrint{\ExamplecodeFormatMeta{#1}}} % ---------- key=value options --------- \newcommand{\ExamplecodeParseKeys}[1]{% #1: key path \ExamplecodeParse {\@examplecode@prepare@parsekeys{#1}}% {\@examplecode@cleanup@parsekeys}% \ExamplecodeEndParseKeys } \newcommand{\@examplecode@prepare@parsekeys}[1]{% #1: key path \let\@examplecode@print@original=\ExamplecodePrint \ExamplecodeNoCmd \def\@examplecode@key@cmd{\key@withopt@unformatted}% \def\@examplecode@keypath{#1}% \let\@examplecode@pathsep=\@empty \def\ExamplecodeProcessText##1{% ##1: current token \ifx,##1% \ifExamplecodeInAlign \endgroup \fi \@examplecode@endkey \let\@examplecode@beginkey=\@examplecode@beginkey@bak \@examplecode@print@original{\ExamplecodeFormatText{##1}}% \else\ifx=##1% \@examplecode@endkey \let\@examplecode@beginkey=\relax \@examplecode@print@original{\ExamplecodeFormatText{##1}}% \else\ifx/##1% \@examplecode@beginkey \@examplecode@appendpathsep{##1}% \else\ifx.##1% \unless \ifx \@examplecode@pathsep \@empty \@examplecode@endkey \expandafter\@examplecode@print@original\expandafter{\expandafter\ExamplecodeFormatText\expandafter{\@examplecode@pathsep}}% \fi \@examplecode@beginkey \ifx \@examplecode@key \@empty \def\@examplecode@key@cmd[####1]####2{\LinkUnformattedKeyword{handler}{####2}{####2}}% \fi \@examplecode@appendkey{##1}% \else \@examplecode@beginkey \@examplecode@appendkey{##1}% \fi \fi \fi \fi }% \def\@examplecode@appendkey##1{% \ExamplecodePrint{\ExamplecodeFormatText{##1}}% }% \def\@examplecode@appendpathsep##1{% \ExamplecodePrint{\ExamplecodeFormatText{##1}}% }% \def\ExamplecodeProcessBeginComment{% \@examplecode@endkey \begingroup \let\@examplecode@beginkey=\relax \let\@examplecode@beginkey@bak=\relax \@examplecode@print@original{\begingroup\ExamplecodeFormatComment}% \let\ExamplecodePrint=\@examplecode@print@original }% \def\ExamplecodeProcessEndComment{% \@examplecode@print@original{\endgroup}% \endgroup }% \def\ExamplecodeProcessBeginGroup##1{% \begingroup \let\@examplecode@beginkey=\relax \let\@examplecode@beginkey@bak=\relax \ExamplecodePrint{\ExamplecodeFormatBeginGroup{##1}}% }% \def\ExamplecodeProcessEndGroup##1{% \ExamplecodePrint{\ExamplecodeFormatEndGroup{##1}}% \endgroup }% } \newcommand{\@examplecode@cleanup@parsekeys}{% \@examplecode@endkey \ExamplecodeProcessCleanup } \newcommand{\@examplecode@beginkey}{% \begingroup \def\@examplecode@key{}% \let\@examplecode@keyspace=\@empty \def\@examplecode@appendkey##1{% \unless \ifx \@examplecode@keyspace \@empty \appto\@examplecode@key{ }% \let\@examplecode@keyspace=\@empty \fi \@examplecode@applypathsep \appto\@examplecode@key{##1}% }% \def\@examplecode@appendpathsep##1{% \unless \ifx \@examplecode@keyspace \@empty \appto\@examplecode@key{ }% \let\@examplecode@keyspace=\@empty \fi \appto\@examplecode@pathsep{##1}% }% \def\@examplecode@applypathsep{% \unless \ifx \@examplecode@pathsep \@empty \eappto\@examplecode@key{\@examplecode@pathsep}% \let\@examplecode@pathsep=\@empty \fi }% \def\ExamplecodePrint##1{% \@examplecode@endkey \@examplecode@print@original{##1}% }% \def\ExamplecodeProcessSpace{% \@examplecode@applypathsep \appto\@examplecode@keyspace{\ExamplecodeSpace}% }% \let\@examplecode@beginkey=\relax \def\@examplecode@endkey{% \edef\@examplecode@do{\noexpand\@examplecode@print@original{% \expandafter\noexpand\@examplecode@key@cmd[\@examplecode@keypath]{\@examplecode@key}% \expandonce{\@examplecode@pathsep}% \expandonce{\@examplecode@keyspace}% }}% \@examplecode@do \endgroup }% } \let\@examplecode@beginkey@bak=\@examplecode@beginkey \newcommand{\@examplecode@endkey}{} \newcommand{\ExamplecodeEndParseKeys}{\PackageError{examplecode}{This should never be expanded}{}} % ---------- parsing command --------- \newcommand{\ExamplecodeParse}[3]{% #1: prepare, #2: cleanup, #3: end token \begingroup #1% \let\@examplecode@endtoken=#3% \def\@examplecode@checkend##1{#2\@examplecode@beforeline\endgroup}% \@examplecode@loop } % WARNING: reads end token before changing catcodes % compares end token with \ifx in case it is a control sequence % => does not find end token if it's catcode is changed % => \xc`...` does not work directly but inside of macro \newcommand{\@xc@prepare}{% \def\ExamplecodeNormalSpace{\ExamplecodeSpaceSymbol}% \def\ExamplecodeNormalTab{\ExamplecodeTabSymbol}% \@examplecode@setcatcodes \@examplecode@state@normal \let\ExamplecodeAllowLinebreak=\relax \gdef\@xc@code{}% \def\ExamplecodePrint{\gappto\@xc@code}% }% \newcommand{\@xc@afterend}{% \formatcode{\@xc@code}% } \newcommand{\xc}{% \ExamplecodeParse{% \@xc@prepare }{% \ExamplecodeProcessCleanup \@xc@afterend }% } \newcommand{\xckey}{% \ExamplecodeParse{% \@xc@prepare \@examplecode@prepare@parsekeys{}% }{% \@examplecode@cleanup@parsekeys \@xc@afterend }% } % ---------- escape inside --------- \newcommand{\ExamplecodeEscapeinside}[2]{% #1: begin token, #2: end token \def\@examplecode@escapeinside#1##1#2{##1\@examplecode@loop}% \let\@examplecode@escapeinside@startchar=#1% } % ---------- line numbers --------- \newcounter{ExamplecodeLinecounter} \newcommand{\ExamplecodeLinenumbers}{% \setcounter{ExamplecodeLinecounter}{1}% \let\@examplecode@beforeline@hook=\@examplecode@insertlinenumber } \newcommand\@examplecode@insertlinenumber{% \makebox[0pt][r]{{\ExamplecodeFormatLinenumber{\theExamplecodeLinecounter}}\quad}% \stepcounter{ExamplecodeLinecounter}% } \newcommand\ExamplecodeFormatLinenumber[1]{% \normalfont \footnotesize #1% } % ---------- parsing environment --------- \newenvironment{examplecode}{% \csname examplecode*\endcsname{}% }{% \csname endexamplecode*\endcsname{}% } \newenvironment{examplecode*}[1]{% \let\@examplecode@envname=\@currenvir \@examplecode@setcatcodes \let\@examplecode@endtoken=\end #1% \begin{examplecodebox}% \colorlet{linkcolor}{codelinkcolor}% \raggedright \ttfamily \leavevmode \parskip=0pt \parindent=0pt\relax \let\\=\ExamplecodeLinebreak \setcounter{@examplecode@grouplevel}{0}% \@examplecode@state@firstindent \@examplecode@gobblefirsteol }{% \end{examplecodebox}% } \newenvironment{examplecodekey}{% \csname examplecodekey*\endcsname{}% }{% \csname endexamplecodekey*\endcsname{}% } \newenvironment{examplecodekey*}[1]{% \csname examplecode*\endcsname{% \@examplecode@prepare@parsekeys{}% #1% }% }{% \@examplecode@cleanup@parsekeys \csname endexamplecode*\endcsname } \newcommand{\@examplecode@setcatcodes}{% \@makeother\^^M% end of line \@makeother\^^I% tab \@makeother\ % space \@makeother\%% \makeatletter % changed \@makeother*% \@makeother`% } \begingroup \@makeother\^^M % \@makeother\^^I % \@firstofone{% \endgroup% \let\EolOther=^^M% \let\TabOther=^^I% } \begingroup\@makeother\%\@firstofone{\endgroup\let\PercentOther=%} \newcommand{\@examplecode@error@catcodes@indentation}{\PackageError{examplecode}{failed to change catcodes, indentation will be screwed up}{}} \newcommand{\@examplecode@error@mixedtabsandspaces}{\PackageWarning{examplecode}{mixed use of tabs and spaces}} \newcount\@examplecode@count@outerindent \newcount\@examplecode@count@gobbledindent \newif\if@examplecode@allowlinebreakbeforenext \newcommand{\EnsureHMode}{\leavevmode\@examplecode@beforeline\let\EnsureHMode\relax}% \let\@EnsureHMode@bak=\EnsureHMode \newcommand{\@examplecode@beforeline}{% \@examplecode@beforeline@hook \let\@examplecode@beforeline=\relax } \let\@examplecode@beforeline@bak=\@examplecode@beforeline \let\@examplecode@beforeline@hook=\relax \newcommand{\@examplecode@state@firstindent}{% \@examplecode@beforeline \let\@examplecode@check@spaces=\@examplecode@check@firstindent } \newcommand{\@examplecode@state@gobbleindent}{% \let\@examplecode@beforeline=\@examplecode@beforeline@bak \let\@examplecode@state@normal=\@examplecode@state@normal@bak \ifnum \@examplecode@count@outerindent > 0 \@examplecode@count@gobbledindent=0 \let\@examplecode@check@spaces=\@examplecode@check@gobbleindent \else \@examplecode@state@indent \fi \let\EnsureHMode=\@EnsureHMode@bak } \newcommand{\@examplecode@state@indent}{% \let\@examplecode@check@spaces=\@examplecode@check@normalspaces \let\ExamplecodeSpace=\ExamplecodeIndentationSpace \let\ExamplecodeTab=\ExamplecodeIndentationTab \def\ExamplecodeAppendIndentation##1{\eappto\ExamplecodeIndentation{\expandonce{##1}}}% \let\ExamplecodeIndentation=\@empty } \newcommand{\@examplecode@state@normal}{% \@examplecode@beforeline \let\@examplecode@check@spaces=\@examplecode@check@normalspaces \let\ExamplecodeSpace=\ExamplecodeNormalSpace \let\ExamplecodeTab=\ExamplecodeNormalTab \let\@examplecode@state@normal=\relax \let\ExamplecodeAppendIndentation=\@gobble } \let\@examplecode@state@normal@bak=\@examplecode@state@normal \newcommand{\@examplecode@gobblefirsteol}[1]{% \ifx \EolOther #1\relax \else \PackageError{examplecode}{unexpected code on same line after \string\begin{examplecode}}{}% \detokenize{#1}% \fi \@examplecode@loop } \newcommand{\@examplecode@loop}{% \futurelet \@examplecode@nexttoken \@examplecode@check } \newcommand{\@examplecode@check}{% \ifx \@examplecode@nexttoken \@examplecode@endtoken \expandafter \@examplecode@checkend \else \if@examplecode@allowlinebreakbeforenext \ExamplecodeAllowLinebreak \@examplecode@allowlinebreakbeforenextfalse \fi \expandafter \@examplecode@check@i \fi } \newcommand{\@examplecode@check@i}{% \ifx \@examplecode@nexttoken \ExampleCodeEscapeInside \def\@examplecode@do##1##2{##2\@examplecode@loop}% \expandafter \@gobble \else \expandafter \@firstofone \fi {\ifx \@examplecode@verb@delimiter \relax \def\@examplecode@do{\@examplecode@check@ii}% \expandafter \@gobble \else \expandafter \@firstofone \fi % I cannot nest the if statments because \@examplecode@nexttoken can be an if {\ifx \@examplecode@nexttoken \@examplecode@verb@delimiter \def\@examplecode@do{\@examplecode@handle@verb}% \else \def\@examplecode@do{\@examplecode@check@ii}% \fi}}% \@examplecode@do } \newcommand{\@examplecode@handle@verb}[1]{% \ExamplecodeFormatVerbDelimiter{\string#1}% \begingroup \ExamplecodeFormatVerb \@examplecode@handle@verb@loop } \newcommand{\@examplecode@handle@verb@loop}{% \futurelet \@examplecode@nexttoken \@examplecode@handle@verb@check } \newcommand{\@examplecode@handle@verb@check}{% \ifx \@examplecode@nexttoken \@examplecode@verb@delimiter \def\@examplecode@do{\@examplecode@handle@verb@end}% \else \ifx \@examplecode@nexttoken \bgroup \def\@examplecode@do{\{\afterassignment\@examplecode@handle@verb@loop\let\@examplecode@trash=}% \else \ifx \@examplecode@nexttoken \egroup \def\@examplecode@do{\}\afterassignment\@examplecode@handle@verb@loop\let\@examplecode@trash=}% \else \def\@examplecode@do##1{\string##1\@examplecode@handle@verb@loop}% \fi \fi \fi \@examplecode@do } \newcommand{\@examplecode@handle@verb@end}[1]{% \ExamplecodeFormatVerbDelimiter{\string#1}% \endgroup \@examplecode@loop } \newcommand{\@examplecode@check@ii}{% \ifcat \noexpand\@examplecode@nexttoken \relax \def\@examplecode@do{\@examplecode@handle@cs}% \else \def\@examplecode@do{\@examplecode@check@spaces}% \fi \@examplecode@do } \newcommand{\@examplecode@handle@cs}[1]{% \ifx\ExplSyntaxOn#1 \@examplecode@explsyntaxon \fi \ifx\ExplSyntaxOff#1 \@examplecode@explsyntaxoff \fi \ExamplecodeSetCmd{#1}% \@examplecode@state@normal \ExamplecodeProcessCmd{#1}% \@examplecode@loop } \let \@examplecode@handle@cs@normal = \@examplecode@handle@cs \newcommand{\@examplecode@explsyntaxon}{% \let \@examplecode@handle@cs = \@examplecode@handle@cs@expl } \newcommand{\@examplecode@explsyntaxoff}{% \let \@examplecode@handle@cs = \@examplecode@handle@cs@normal } \newcommand{\@examplecode@handle@cs@expl}[1]{% \def\@examplecode@tmp@csname{#1}% \@examplecode@handle@cs@expl@loop } \newcommand{\@examplecode@handle@cs@expl@loop}{% \futurelet \@examplecode@nexttoken \@examplecode@handle@cs@expl@check } \newcommand{\@examplecode@handle@cs@expl@check}{% \ifx \@examplecode@nexttoken _% \def\@examplecode@do##1{\appto\@examplecode@tmp@csname{\textunderscore}\@examplecode@handle@cs@expl@loop}% \else\ifx \@examplecode@nexttoken :% \def\@examplecode@do##1{\appto\@examplecode@tmp@csname{##1}\@examplecode@handle@cs@expl@loop}% \else\ifcat \noexpand\@examplecode@nexttoken a% \def\@examplecode@do##1{\appto\@examplecode@tmp@csname{##1}\@examplecode@handle@cs@expl@loop}% \else \def\@examplecode@do{\expandafter\@examplecode@handle@cs@normal\expandafter{\@examplecode@tmp@csname}}% \fi\fi\fi \@examplecode@do } \newcommand{\ExamplecodeSetCmd}[1]{\edef\@examplecode@cs{\detokenize{#1}}} \newcommand{\ExamplecodeNoCmd}{\def\@examplecode@cs{}} \ExamplecodeNoCmd \newcommand{\@examplecode@check@normalspaces}{% \ifcat \noexpand\@examplecode@nexttoken \space \def\@examplecode@do##1{\ExamplecodeProcessSpace\@examplecode@loop##1}% \else\if \noexpand\@examplecode@nexttoken \space \def\@examplecode@do##1{\ExamplecodeProcessSpace\@examplecode@loop}% \else\ifx \@examplecode@nexttoken \TabOther \def\@examplecode@do##1{\ExamplecodeProcessTab\@examplecode@loop}% \else \def\@examplecode@do{\@examplecode@check@iv}% \fi \fi \fi \@examplecode@do } % count the indentation of the first line \newcommand{\@examplecode@check@firstindent}{% \ifcat \noexpand\@examplecode@nexttoken \space \@examplecode@error@catcodes@indentation \advance\@examplecode@count@outerindent by 1 \def\@examplecode@do##1{\@examplecode@loop##1}% \else\if \noexpand\@examplecode@nexttoken \space \advance\@examplecode@count@outerindent by 1 \def\@examplecode@do##1{\@examplecode@loop}% \else\ifx \@examplecode@nexttoken \TabOther \advance\@examplecode@count@outerindent by \ExamplecodeTabsize \def\@examplecode@do##1{\@examplecode@loop}% \else \def\@examplecode@do{\@examplecode@check@iv}% \fi \fi \fi \@examplecode@do } % gobble indentation as far as the first line was indented \newcommand{\@examplecode@check@gobbleindent}{% \ifcat \noexpand\@examplecode@nexttoken \space \@examplecode@error@catcodes@indentation \@examplecode@gobbleindent{1}% \def\@examplecode@do##1{\@examplecode@loop##1}% \else\if \noexpand\@examplecode@nexttoken \space \@examplecode@gobbleindent{1}% \def\@examplecode@do##1{\@examplecode@loop}% \else\ifx \@examplecode@nexttoken \TabOther \@examplecode@gobbleindent{\ExamplecodeTabsize}% \def\@examplecode@do##1{\@examplecode@loop}% \else \def\@examplecode@do{\@examplecode@check@iv}% \fi \fi \fi \@examplecode@do } \newcommand{\@examplecode@gobbleindent}[1]{% \advance\@examplecode@count@gobbledindent by #1 \ifnum \@examplecode@count@gobbledindent = \@examplecode@count@outerindent \@examplecode@state@indent \else\ifnum \@examplecode@count@gobbledindent > \@examplecode@count@outerindent \@examplecode@error@mixedtabsandspaces \@examplecode@state@indent \fi \fi } \newcommand{\@examplecode@check@iv}{% \def\@examplecode@do{\@examplecode@check@v}% \unless\ifx \@examplecode@escapeinside@startchar \relax \if \noexpand\@examplecode@nexttoken \noexpand\@examplecode@escapeinside@startchar \def\@examplecode@do{\@examplecode@escapeinside}% \fi \fi \@examplecode@do } \newcommand{\@examplecode@check@v}{% \ifcat \noexpand\@examplecode@nexttoken \bgroup% catcode 1 \def\@examplecode@do{\@examplecode@handlebgroup}% \else\ifcat \noexpand\@examplecode@nexttoken \egroup% catcode 2 \def\@examplecode@do{\expandafter\@examplecode@handlespecialtoken\expandafter\ExamplecodeProcessEndGroup\string}% \else\ifcat \noexpand\@examplecode@nexttoken $% catcode 3 \def\@examplecode@do{\@examplecode@handlemathshift}% \else\ifcat \noexpand\@examplecode@nexttoken &% catcode 4 \def\@examplecode@do{\@examplecode@handlespecialtoken\ExamplecodeProcessAlignmentTab}% \else\ifx \@examplecode@nexttoken \EolOther% catcode 5 \@examplecode@endcomment \def\@examplecode@do##1{% \ExamplecodeProcessEndOfLine \@examplecode@state@gobbleindent \@examplecode@loop }% \else\ifcat \noexpand\@examplecode@nexttoken ##% catcode 6 \def\@examplecode@do{\@examplecode@handleparameter}% \else\ifcat \noexpand\@examplecode@nexttoken ^% catcode 7 \def\@examplecode@do{\@examplecode@handlespecialtoken\ExamplecodeProcessSuperscript}% \else\ifcat \noexpand\@examplecode@nexttoken _% catcode 8 \def\@examplecode@do{\@examplecode@handlespecialtoken\ExamplecodeProcessSubscript}% % catcode 9: ignored characters % catcode 10: space, handled in \@examplecode@check@spaces % catcode 11: letter, handled in \else % catcode 12: other, handled in \else \else\ifx \@examplecode@nexttoken <% \def\@examplecode@do{\@examplecode@handlepossiblemeta}% % catcode 13: active, handled in \@examplecode@check@ii (after \futurelet it's indistinguishable from a control sequence) \else\ifx \@examplecode@nexttoken \PercentOther% catcode 14 \@examplecode@state@normal \ExamplecodeProcessBeginComment \def\@examplecode@endcomment{\ExamplecodeProcessEndComment}% \def\@examplecode@do{\@examplecode@handlenormaltoken}% % catcode 15: invalid characters \else% catcode 11, 12 \def\@examplecode@do{\@examplecode@handlenormaltoken}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \@examplecode@do } \newcommand{\@examplecode@endcomment}{} \newcommand{\@examplecode@handlebgroup}{% \ifcsundef{@examplecode@formatarg\@examplecode@cs}{% \expandafter\@examplecode@handlespecialtoken\expandafter\ExamplecodeProcessBeginGroup\string }{% \csname @examplecode@formatarg\@examplecode@cs\endcsname }% } \newcommand{\@examplecode@handlenormaltoken}[1]{% \@examplecode@state@normal \ifcsundef{@examplecode@formatoptarg\@examplecode@cs#1}{% \csname @examplecode@breakafter@#1\endcsname \ExamplecodeProcessText{#1}% \@examplecode@loop }{% \csname @examplecode@formatoptarg\@examplecode@cs#1\endcsname }% } \newcommand{\@examplecode@handlespecialtoken}[2]{% \@examplecode@state@normal #1{\string#2}% \@examplecode@loop } \newcommand{\@examplecode@handlemathshift}[1]{% \@examplecode@math@begin \ExamplecodeProcessMathShift{\string#1}% \@examplecode@math@end \@examplecode@loop } \newcommand{\@examplecode@math@begin}{% \xdef\@examplecode@grouplevel@mathenter{\the@examplecode@grouplevel}% \@examplecode@state@normal \begingroup \let\@examplecode@handlemeta=\@examplecode@handlenormaltoken \ExamplecodeProcessBeginMath \let\@examplecode@math@begin=\relax \def\@examplecode@math@end{\def\@examplecode@math@end{\ExamplecodeProcessEndMath\endgroup\gdef\@examplecode@grouplevel@mathenter{-1}}}% } \newcommand{\@examplecode@handleparameter}[1]{% \edef\@examplecode@parameter{\string#1}% \@examplecode@parameterloop } \newcommand{\@examplecode@parameterloop}{% \futurelet \@examplecode@nexttoken \@examplecode@parametercheck } \newcommand{\@examplecode@parametercheck}{% \ifcat \noexpand\@examplecode@nexttoken ##% \def\@examplecode@do##1{% \edef\@examplecode@parameter{\@examplecode@parameter\string##1}% \@examplecode@parameterloop }% \else\ifcat \noexpand\@examplecode@nexttoken 1% \def\@examplecode@do##1{% \edef\@examplecode@parameter{\@examplecode@parameter##1}% \expandafter\ExamplecodeProcessParameter\expandafter{\@examplecode@parameter}% \@examplecode@loop }% \else \def\@examplecode@do{% \expandafter\ExamplecodeProcessParameter\expandafter{\@examplecode@parameter}% \@examplecode@check }% \fi \fi \@examplecode@do } \newcommand{\@examplecode@handlepossiblemeta}[1]{% \def\@examplecode@tmp{#1}% \futurelet \@examplecode@nexttoken \@examplecode@checkmeta } \newcommand{\@examplecode@checkmeta}{% \ifcat \@examplecode@nexttoken a% \def\@examplecode@do{\@examplecode@handlemeta}% \else \def\@examplecode@do{\@examplecode@handlenormaltoken}% \fi \expandafter\@examplecode@do\@examplecode@tmp } \def\@examplecode@handlemeta<#1>{% \ExamplecodeProcessMeta{#1}% \@examplecode@loop } \newcommand{\@examplecode@checkend}[2]{% \def\@examplecode@arg{#2}% \ifx \@examplecode@arg \@examplecode@envname \expandafter \@firstoftwo \else \expandafter \@secondoftwo \fi{% \end{#2}% }{% \@examplecode@state@normal \ExamplecodeProcessCmd{#1}% \ExamplecodeProcessBeginGroup{\{}% \ExamplecodeProcessEnv{#2}% \ExamplecodeProcessEndGroup{\}}% \@examplecode@loop }% }% % ---------- input command --------- \begingroup\@examplecode@setcatcodes\gdef\@examplecode@magic@comment@prefix{% !}\gdef\@examplecode@empty@line{ }\gdef\@examplecode@input@testmarkup{\input{preamble/testmarkup} }\endgroup \ExplSyntaxOn \newcommand\inputexamplecode[1]{% \group_begin: \@examplecode@setcatcodes \ior_open:Nn \g_tmpa_ior {#1} \tl_clear:N \l_file_contents_tl \bool_set_false:N \l_tmpa_bool \ior_map_inline:Nn \g_tmpa_ior { \bool_if:NF \l_tmpa_bool { \tl_set:Nx\l_tmpa_tl{\tl_range:nnn{##1}{1}{3}} \tl_if_eq:NNTF \@examplecode@magic@comment@prefix \l_tmpa_tl { % do nothing }{\tl_if_eq:NNTF \@examplecode@empty@line \l_tmpa_tl { % do nothing }{\tl_if_eq:NNTF \@examplecode@input@testmarkup \l_tmpa_tl { % do nothing }{ \bool_set_true:N \l_tmpa_bool }}} } \bool_if:NT \l_tmpa_bool { \tl_put_right:Nn \l_file_contents_tl {##1} } } \ior_close:N \g_tmpa_ior \def\l_tmpa_tl{\begin{examplecode}\EolOther} \expandafter \l_tmpa_tl \l_file_contents_tl \end{examplecode} \group_end: } \ExplSyntaxOff \makeatother