% -------------------------------------------------------------------------- % the CNLTX bundle % % LaTeX source code and output % % -------------------------------------------------------------------------- % Clemens Niederberger % Web: https://github.com/cgnieder/cnltx/ % E-Mail: contact@mychemistry.eu % -------------------------------------------------------------------------- % Copyright 2013 Clemens Niederberger % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- \RequirePackage{cnltx-base} \ProvidesPackage{cnltx-example}[\cnltx@@date\space \cnltx@@version\space \cnltx@@info] \RequirePackage{cnltx-listings} \cnltx@create@bundle@message{example}{Error} \cnltx@create@bundle@message{example}{Warning} \cnltx@create@bundle@message{example}{WarningNoLine} \cnltx@create@bundle@message{example}{Info} % -------------------------------------------------------------------------- \RequirePackage{translations} \PassOptionsToPackage{framemethod=tikz}{mdframed} \RequirePackage{mdframed} \RequirePackage{idxcmds} % -------------------------------------------------------------------------- % who knows what they might be good for -- well, for indexing: \newrobustcmd*\cnltxat{@} \let\cnltxletterat\cnltxat \makeatother \newrobustcmd*\cnltxotherat{@} \makeatletter \newrobustcmd*\cnltxbang{!} \newrobustcmd*\cnltxequal{=} % -------------------------------------------------------------------------- % \code \newrobustcmd*\code[1]{\begingroup\codefont#1\endgroup} \newcommand*\verbcode{\lstinline[style=cnltx-inline]} \newcommand*\codefont{\ttfamily} \pgfkeys{ cnltx/.cd, code-font/.code = \def\codefont{#1} , } % -------------------------------------------------------------------------- % command descriptions: % \cs \newidxcmd\cs{\code{\textbackslash\textcolor{cs}{#1}}} % \env \newidxcmd\env{\code{#1}}[\ (\GetTranslation{cnltx-environment})] % \begin, \end \newidxcmd\beginend{\code{\textbackslash\textcolor{beginend}{#1}}} \def\beginenv{\@ifstar{\beginend*{begin}}{\beginend{begin}}} \def\endenv{\@ifstar{\beginend*{end}}{\beginend{end}}} % -------------------------------------------------------------------------- % option descriptions: \def\cnltx@isvalue{% \nobreak\hskip.3333em plus .1667em =\hskip.3333em plus .1667em } % \option \newidxcmd\option{\code{\textcolor{option}{#1}}} \newidxcmd\module{\code{\textcolor{module}{#1}}} \newcommand*\key{\@ifstar{\cnltx@key@star}{\cnltx@key@nostar}} \def\cnltx@key@star{% \cnltx@ifdash {\cnltx@key@aux*\meta} {\cnltx@key@aux*\marg}% } \def\cnltx@key@nostar{% \cnltx@ifdash {\cnltx@key@aux{}\meta} {\cnltx@key@aux{}\marg}% } \def\cnltx@key@aux#1#2#3#4{% \code{\option#1{#3}\cnltx@isvalue#2{#4}}% } \newcommand*\keyis{% \@ifstar {\cnltx@key@aux*\@firstofone} {\cnltx@key@aux{}\@firstofone}% } % \DeclareListParser*\cnltx@choices{|} \newcommand*\choices[1]{% \def\cnltx@choice@sep{\def\cnltx@choice@sep{|\hskip\z@}}% \forcsvlist{\cnltx@choice@sep\code}{#1}% } \RequirePackage[normalem]{ulem} \newcommand*\default[1]{\uline{#1}} \pgfkeys{ cnltx/.cd, default-value/.code = \def\default##1{#1{##1}} } \newcommand*\choicekey{% \@ifstar {\cnltx@choicekey@star} {\cnltx@choicekey@nostar}% } \def\cnltx@choicekey@star#1#2{% \code{\option*{#1}\cnltx@isvalue\choices{#2}}} \def\cnltx@choicekey@nostar#1#2{% \code{\option{#1}\cnltx@isvalue\choices{#2}}} \newcommand*\boolkey{% \@ifstar {\cnltx@boolkey@star} {\cnltx@boolkey@nostar}% } \def\cnltx@boolkey@star#1{\choicekey*{#1}{\default{true},false}} \def\cnltx@boolkey@nostar#1{\choicekey{#1}{\default{true},false}} % -------------------------------------------------------------------------- % argument descriptions: % \meta \newcommand*\meta[1]{% $\langle$% \textcolor{meta}{{\argumentformat#1}}% $\rangle$% } % arguments: \newcommand*\argumentformat{\normalfont\itshape} \pgfkeys{ cnltx/.cd, arg-format/.code = \renewcommand*\argumentformat{#1} , } \newcommand*\newarg[4][\meta]{% \newcommand*#2[1]{% \code{\textcolor{argument}{% #3\textnormal{\ifblank{##1}{}{#1{##1}}}#4}}% }% } \newarg\marg{\{}{\}} \newarg[\code]\Marg{\{}{\}} \newarg\oarg{[}{]} \newarg[\code]\Oarg{[}{]} \newarg\darg{(}{)} \newarg[\code]\Darg{(}{)} \newcommand*\sarg{\textcolor{argument}{\code{*}}} % -------------------------------------------------------------------------- % source code examples: % format of the source code: \newcommand*\sourceformat{\codefont\small} % format of the iput example: \newcommand*\exampleformat{} \pgfkeys{ cnltx/.cd, source-format/.code = \renewcommand*\sourceformat{#1} , expl-format/.code = \renewcommand*\exampleformat{#1} , } % see http://tex.stackexchange.com/a/114580/5049 for reference on the `nolig' % trick, thanks to @egreg! \newrobustcmd\cnltx@treat@lst@index[2]{% \newrobustcmd#1[1]{% \begingroup \let\lst@nolig\@empty \def\cnltx@tmp@index{##1}% \expandafter\cnltx@replace@all \expandafter\cnltx@tmp@index \expandafter{\cnltxotherat}{\cnltxat}% \cnltx@replace@all\cnltx@tmp@index{@}{\cnltxat}% \expandafter#2\expandafter{\cnltx@tmp@index}% \endgroup }% } \cnltx@treat@lst@index{\indexcs}{\csidx} \cnltx@treat@lst@index{\indexenv}{\envidx} % this command is undocumented and not used; it requires `cnltx-tools': \newcommand\cnltx@copyablespace{% \cnltx@accsupp{00A0}{method=hex,unicode}{\ }% } \lst@RequireAspects{writefile} \providecommand*\MakePercentComment{\catcode`\%14\relax} \def\cnltx@gobble{2} % listings style for source code: \def\cnltx@listings@style{ language = [AlLaTeX]TeX, alsolanguage = [plain]TeX, basicstyle = {\sourceformat}, numbers = left, numberstyle = \tiny, xleftmargin = 1em, numbersep = .75em, gobble = \cnltx@gobble , columns = fullflexible, literate = {ä}{{\"a}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 {Ä}{{\"A}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 {ß}{{\ss}}1 , breaklines = true, keepspaces = true, breakindent = 1em, commentstyle = \color{comment}, keywordstyle = \color{cs}, deletetexcs = { a,o,u,A,O,U, begin, center, description,document, end,enumerate, figure,flushleft,flushright, itemize,list, otherlanguage, table,tabu,tabular }, deletekeywords = { a,o,u,A,O,U, begin, center, description,document, end,enumerate, figure,flushleft,flushright, itemize,list, otherlanguage, table,tabu,tabular }, % \begin, \end: texcsstyle = [2]\color{beginend}, index = [2][texcs2], indexstyle = [2]\@gobble, moretexcs = [2]{begin,end}, % added environments that'll be indexed: texcsstyle = [3]\color{env}, index = [3][texcs3], indexstyle = [3]\indexenv, % environments that won't be indexed: texcsstyle = [4]\color{env}, index = [4][texcs4], indexstyle = [4]\@gobble, % control sequences that'll be indexed: texcsstyle = [5]\color{cs}, index = [5][texcs5], indexstyle = [5]\indexcs, % control sequences that won't be indexed: texcsstyle = [6]\color{cs}, index = [6][texcs6], indexstyle = [6]\@gobble } \def\cnltx@bibtex@listings@style{ language = BiBTeX, basicstyle = {\sourceformat}, numbers = left, numberstyle = \tiny, xleftmargin = 1em, numbersep = .75em, gobble = \cnltx@gobble , columns = fullflexible, literate = {ä}{{\"a}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 {Ä}{{\"A}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 {ß}{{\ss}}1 , breaklines = true, keepspaces = true, breakindent = 1em, commentstyle = \color{comment}, keywordstyle = \color{bibentry} , keywordstyle = [2]\color{bibentryfield}\itshape , showstringspaces = false , } \def\cnltx@makeindex@listings@style{ language = makeindex, basicstyle = {\sourceformat}, numbers = left, numberstyle = \tiny, xleftmargin = 1em, numbersep = .75em, gobble = \cnltx@gobble , columns = fullflexible, literate = {ä}{{\"a}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 {Ä}{{\"A}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 {ß}{{\ss}}1 , breaklines = true, keepspaces = true, breakindent = 1em, commentstyle = \color{comment}, keywordstyle = \color{makeidxkey}\bfseries , stringstyle = \color{makeidxstring} , showstringspaces = false , } \cnltx@expandargs(nx)\lstdefinestyle {cnltx} {\expandonce\cnltx@listings@style} \cnltx@expandargs(nx)\lstdefinestyle {cnltx-bibtex} {\expandonce\cnltx@bibtex@listings@style} \cnltx@expandargs(nx)\lstdefinestyle {cnltx-makeindex} {\expandonce\cnltx@makeindex@listings@style} \lstdefinestyle {cnltx-inline} { style=cnltx, basicstyle = \codefont } \def\cnltx@addcmds#1{% \cnltx@expandargs(nx)\lstdefinestyle {cnltx} {\expandonce\cnltx@listings@style,\unexpanded{moretexcs={[5]#1}}}% \edef\cnltx@listings@style{% \expandonce\cnltx@listings@style,\unexpanded{moretexcs={[5]#1}}% }% } \def\cnltx@addsilentcmds#1{% \cnltx@expandargs(nx)\lstdefinestyle {cnltx} {\expandonce\cnltx@listings@style,\unexpanded{moretexcs={[6]#1}}}% \edef\cnltx@listings@style{% \expandonce\cnltx@listings@style,\unexpanded{moretexcs={[6]#1}}% }% } \cnltx@expandargs(o)\cnltx@addsilentcmds{\cnltx@predefined@control@sequences} \def\cnltx@addenvs#1{% \cnltx@expandargs(nx)\lstdefinestyle {cnltx} {\expandonce\cnltx@listings@style,\unexpanded{moretexcs={[3]#1}}}% \edef\cnltx@listings@style{% \expandonce\cnltx@listings@style,\unexpanded{moretexcs={[3]#1}}% }% } \def\cnltx@addsilentenvs#1{% \cnltx@expandargs(nx)\lstdefinestyle {cnltx} {\expandonce\cnltx@listings@style,\unexpanded{moretexcs={[4]#1}}}% \edef\cnltx@listings@style{% \expandonce\cnltx@listings@style,\unexpanded{moretexcs={[4]#1}}% }% } \cnltx@expandargs(o)\cnltx@addsilentenvs{\cnltx@predefined@environments} \def\cnltx@addlistingsoptions#1{% \cnltx@expandargs(nx)\lstdefinestyle {cnltx} {\expandonce\cnltx@listings@style,\unexpanded{#1}}% \edef\cnltx@listings@style{% \expandonce\cnltx@listings@style,\unexpanded{#1}% }% } \def\cnltx@local@listings@options{} \pgfkeys{ cnltx/.cd, gobble/.code = \def\cnltx@gobble{#1} , add-cmds/.code = \cnltx@addcmds{#1} , add-silent-cmds/.code = \cnltx@addsilentcmds{#1} , add-listings-options/.code = \cnltx@addlistingsoptions{#1} , listings-options/.code = \lstdefinestyle{cnltx}{#1} , add-envs/.code = \cnltx@addenvs{#1} , add-silent-envs/.code = \cnltx@addsilentenvs{#1} , sourcecode-options/.code = \def\cnltx@local@listings@options{#1} , } \def\cnltx@mdframed@options { backgroundcolor = cnltxbg , linecolor = cnltx , roundcorner = 5pt } \cnltx@expandargs(nx)\mdfdefinestyle {cnltx} {\expandonce\cnltx@mdframed@options} \def\cnltx@addmdframedoptions#1{% \cnltx@expandargs(nx)\mdfdefinestyle {cnltx} {\expandonce\cnltx@mdframed@options,\unexpanded{#1}}% } \newbool{cnltx@sidebyside} \newbool{cnltx@codeleft} \booltrue{cnltx@codeleft} \newbool{cnltx@codeonly} \newsavebox\cnltx@example@box \newcommand*\cnltx@examplesep{\hrulefill} \newcommand*\cnltx@pre@source@hook{} \newcommand*\cnltx@after@source@hook{} \newcommand*\cnltx@pre@example@hook{} \newcommand*\cnltx@after@example@hook{} \pgfkeys{ cnltx/.cd, side-by-side/.is if = cnltx@sidebyside , code-only/.is if = cnltx@codeonly , code-left/.is if = cnltx@codeleft , code-sep/.code = \def\cnltx@examplesep{#1} , pre-code/.code = \def\cnltx@pre@source@hook{#1} , after-code/.code = \def\cnltx@after@source@hook{#1} , pre-output/.code = \def\cnltx@pre@example@hook{#1} , after-output/.code = \def\cnltx@after@example@hook{#1} , add-frame-options/.code = \cnltx@addmdframedoptions{#1} , frame-options/.code = \mdfdefinestyle{cnltx}{#1} , gobble/.code = \def\cnltx@gobble{#1} , } \newcommand*\cnltx@example@input[1]{% \trivlist\item\relax % don't know why this is necessary but it is: \catcode`\^^M=5\relax \makeatother \MakePercentComment % want special formatting for the input example: \exampleformat % we're in a list so the first paragraph is not indented; let's make the % input example be the second paragraph: \if@minipage\else \par\mbox{}\par\vskip-\baselineskip\relax \fi \input{#1}% \endtrivlist } \newcommand*\cnltx@source@input@start[1]{% \ifboolexpr{ bool {cnltx@sidebyside} and not bool {cnltx@codeonly} } {\setbox\cnltx@example@box=\hbox\bgroup}{\cnltx@pre@source@hook}% \lst@BeginAlsoWriteFile{#1}% } \newcommand*\cnltx@source@input@end{% \lst@EndWriteFile \ifboolexpr{ bool {cnltx@sidebyside} and not bool {cnltx@codeonly} } {\egroup}{\cnltx@after@source@hook}% } % \newcommand*\cnltx@example@start[1]{% \pgfqkeys{/cnltx}{#1}% \cnltx@expandargs(x)\lstset{ style=cnltx, \expandonce\cnltx@local@listings@options }% \ifbool{cnltx@sidebyside} {\mdframed[style=cnltx,nobreak=true]} {\mdframed[style=cnltx,nobreak=false]}% } \newcommand*\cnltx@example@end[1]{% \ifblank{#1}{\booltrue{cnltx@codeonly}}{} \ifbool{cnltx@codeonly} {} {% \ifbool{cnltx@sidebyside} {% \ifbool{cnltx@codeleft} {% \minipage[c]{% \dimexpr .49\linewidth -.75\lst@xleftmargin \relax }% \cnltx@pre@source@hook \unhbox\cnltx@example@box \cnltx@after@source@hook \endminipage\hfill \minipage[c]{% \dimexpr .49\linewidth -.75\lst@xleftmargin \relax }% \cnltx@pre@example@hook \cnltx@example@input{#1}% \cnltx@after@example@hook \endminipage } {% \minipage[c]{% \dimexpr .49\linewidth -.75\lst@xleftmargin \relax }% \cnltx@pre@example@hook \cnltx@example@input{#1}% \cnltx@after@example@hook \endminipage\hfill \minipage[c]{% \dimexpr .49\linewidth -.75\lst@xleftmargin \relax }% \cnltx@pre@source@hook \unhbox\cnltx@example@box \cnltx@after@source@hook \endminipage }% } {% \par\noindent\cnltx@examplesep \cnltx@pre@example@hook \cnltx@example@input{#1}% \cnltx@after@example@hook }% }% \endmdframed \ignorespacesafterend } \def\cnltx@new@sourcecode@env#1#2{% \lstnewenvironment{#2}[1][] {% \cnltx@example@start{##1,#1}% \cnltx@source@input@start{\jobname.cnltx.code}% } {% \cnltx@source@input@end \cnltx@example@end{\jobname.cnltx.code}% % see http://tex.stackexchange.com/a/136264/5049 % for the reasoning behind this: \if@nobreak \@nobreakfalse \fi }% } \newrobustcmd\newsourcecodeenv[2][]{% \cnltx@new@sourcecode@env{#1}{#2}% } \def\cnltx@input@sourcecode@file#1#2{% \begingroup \cnltx@example@start{#1}% \lstinputlisting{#2}% \cnltx@example@end{#2}% \endgroup } \def\cnltx@new@input@source@file#1#2{% \newcommand#2[2][]{\cnltx@input@sourcecode@file{#1,##1}{##2}}% } \newrobustcmd*\newinputsourcefilecmd[2][]{% \cnltx@new@input@source@file{#1}{#2}% } \newsourcecodeenv{example} \newsourcecodeenv[side-by-side]{sidebyside} \newsourcecodeenv[code-only]{sourcecode} \newinputsourcefilecmd\inputexample \newinputsourcefilecmd[side-by-side]\inputsidebyside \newinputsourcefilecmd[code-only]\inputsourcecode \newrobustcmd*\implementation[2][]{% \lstinputlisting[style=cnltx,#1]{#2}% } % -------------------------------------------------------------------------- % packages and classes: \newcommand*\packageformat{\sffamily} \newcommand*\classformat{\sffamily} \newcommand*\bundleformat{\sffamily} \newidxcmd\pkg{{\packageformat#1}}[\ (\GetTranslation{cnltx-package})] \newidxcmd\cls{{\classformat#1}}[\ (\GetTranslation{cnltx-class})] \newidxcmd\bnd{{\bundleformat#1}}[\ (\GetTranslation{cnltx-bundle})] \pgfkeys{ cnltx/.cd, pkg-format/.code = \renewcommand*\packageformat{#1} , cls-format/.code = \renewcommand*\classformat{#1} } % disable indexing commands in PDF strings: \AtBeginDocument{% \providecommand\pdfstringdefDisableCommands[1]{}% \pdfstringdefDisableCommands{% \def\code#1{#1}% \def\cs*#1{\textbackslash#1}% \def\env*{}% \def\option*{}% \def\pkg*{}% \def\cls*{}% \def\bnd*{}% \def\key*#1#2{#1 = #2}% }% } \DeclareTranslationFallback{cnltx-package}{package} \DeclareTranslation{English}{cnltx-package}{package} \DeclareTranslation{German}{cnltx-package}{Paket} \DeclareTranslationFallback{cnltx-environment}{environment} \DeclareTranslation{English}{cnltx-environment}{environment} \DeclareTranslation{German}{cnltx-environment}{Umgebung} \DeclareTranslationFallback{cnltx-class}{class} \DeclareTranslation{English}{cnltx-class}{class} \DeclareTranslation{German}{cnltx-class}{Klasse} \DeclareTranslationFallback{cnltx-bundle}{bundle} \DeclareTranslation{English}{cnltx-bundle}{bundle} \DeclareTranslation{German}{cnltx-bundle}{Bundle} \endinput % -------------------------------------------------------------------------- HISTORY: 2013/09/08 v0.1 - first working version 2013/09/10 v0.2 - added \keyis - lot's of improvements on the source code example environments - disable indexing commands in PDF strings - added hooks to the source example environments - added possibility for internationalization - new macro \verbcode - added optional argument to \newarg - new macros \Marg, \Oarg, \Darg - option for formatting the \default command 2013/09/12 v0.3 - added \module - added \newsourcecodeenv and \newinputsourcefilecmd - added \inputexample, \inputsidebyside and \inputsourcecode - renamed `example*' into `sidebyside' 2013/09/15 v0.4 - new listings style `cnltx-bibtex' 2013/09/20 v0.5 - new command \implementation - fixed wrong indexing behaviour: keywords in the silent lists are now correctly indexed if added with `add-cmds' or `add-envs' 2013/09/30 v0.7 - added listings style `cnltx-makeindex' 2013/10/04 v0.7a - new command \cnltx@treat@lst@index - changed \envidx in listings into \indexenv - added \bnd for package bundles