%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%% % % % Copyright (c) 2013 - Michiel Helvensteijn (www.mhelvens.net) % % % % 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 Michiel Helvensteijn. % % % % This work consists of the files withargs.tex and withargs.sty. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%% % \CheckSum{115} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \subsection{Package Info} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \ProvidesExplPackage{withargs}{2013/10/11}{0.0.2} {an inline construct for passing token lists as TeX parameters} % \end{macrocode} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \subsection{Required Packages} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % We just need some expl3-ish packages. % % \begin{macrocode} \RequirePackage{xparse} \RequirePackage{l3regex} % \end{macrocode} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \subsection{\LaTeX3 Functions} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{macro}{\withargs:nn,\withargs:nnn,\withargs:nnnn,\withargs:nnnnn,\withargs:nnnnnn, % \withargs:nnnnnnn,\withargs:nnnnnnnn,\withargs:nnnnnnnnn} % \(\overbrace{\hbox{\marg1 \marg2 \marg3 \marg4 \marg5 \marg6 \marg7 \marg8}}^{1-8}\) % \marg{body} %%% \\[-.5\belowdisplayskip]\nopagebreak % % \noindent These are the |expl3| API versions of the |\withargs| command. % The implementation is quite straight-forward. This technique has to % be used by any library command that accepts \TeX-style parameters. % % \begin{macrocode} \cs_new_protected:Nn \withargs:nn { \cs_set:Npn \__withargs:n ##1 {#2} \__withargs:n {#1} } \cs_new_protected:Nn \withargs:nnn { \cs_set:Npn \__withargs:nn ##1##2 {#3} \__withargs:nn {#1}{#2} } \cs_new_protected:Nn \withargs:nnnn { \cs_set:Npn \__withargs:nnn ##1##2##3 {#4} \__withargs:nnn {#1}{#2}{#3} } \cs_new_protected:Nn \withargs:nnnnn { \cs_set:Npn \__withargs:nnnn ##1##2##3##4 {#5} \__withargs:nnnn {#1}{#2}{#3}{#4} } \cs_new_protected:Nn \withargs:nnnnnn { \cs_set:Npn \__withargs:nnnnn ##1##2##3##4##5 {#6} \__withargs:nnnnn {#1}{#2}{#3}{#4}{#5} } \cs_new_protected:Nn \withargs:nnnnnnn { \cs_set:Npn \__withargs:nnnnnn ##1##2##3##4##5##6 {#7} \__withargs:nnnnnn {#1}{#2}{#3}{#4}{#5}{#6} } \cs_new_protected:Nn \withargs:nnnnnnnn { \cs_set:Npn \__withargs:nnnnnnn ##1##2##3##4##5##6##7 {#8} \__withargs:nnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7} } \cs_new_protected:Nn \withargs:nnnnnnnnn { \cs_set:Npn \__withargs:nnnnnnnn ##1##2##3##4##5##6##7##8 {#9} \__withargs:nnnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} } % \end{macrocode} % %%% \end{macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \subsection{Document Level Command} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{macro}{\__withargs_var:x} \marg{argument specifier} %%% \\[-.5\belowdisplayskip]\nopagebreak % % \noindent This is a convenience command for generating % and using a |\withargs:| variant in one go. I only use it % for the document-level command, since those users can't % roll their own. % % |#1| should be the number of optional |\withargs| arguments % and |#2| should be a \LaTeX3 argument specification not % longer than |#1| --- a prefix. % % \begin{macrocode} \cs_new:Nn \__withargs_var:nx { \cs_generate_variant:cx { withargs : \prg_replicate:nn{#1}{n} n } { #2 n } \use:c { withargs : #2 \prg_replicate:nn{#1-\tl_count:n{#2}}{n} n } } % \end{macrocode} % \uninteresting\begin{macrocode} \cs_generate_variant:Nn \cs_generate_variant:Nn {cx} % \end{macrocode} % %%% \end{macro} \vspace{-2mm} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{macro}{\__withargs_process_uniquecsname:n} % \marg{argument} %%% \\[-.5\belowdisplayskip]\nopagebreak % % \noindent An |xparse| processor function to pass a unique % control sequence name if the argument given was '|\uniquecsname|'. % % \begin{macrocode} \cs_new_protected:Nn\__withargs_process_uniquecsname:n{ \tl_if_eq:nnTF {#1} {\uniquecsname} { \int_gincr:N \g__with_unique_int \tl_set:Nx \ProcessedArgument { Unique-CS-Name-( \int_use:N\g__with_unique_int ) } }{ \tl_set:Nn \ProcessedArgument {#1} } } \int_new:N \g__with_unique_int % \end{macrocode} % %%% \end{macro} \vspace{-2mm} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{macro}{\__withargs_remove_spaces:n} % \marg{argument} %%% \\[-.5\belowdisplayskip]\nopagebreak % % \noindent An |xparse| processor function to remove all % spaces from the argument. % % \begin{macrocode} \cs_new_protected:Nn\__withargs_remove_spaces:n{ \tl_set:Nn \ProcessedArgument {#1} \tl_remove_all:Nn\ProcessedArgument {~} } % \end{macrocode} % %%% \end{macro} \vspace{-2mm} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \pagebreak %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{macro}{\withargs} % \texttt{\bfseries(}\meta{argument specification}\texttt{\bfseries)} % \oarg{1} \oarg{2} \oarg{3} \oarg{4} \oarg{5} \oarg{6} \oarg{7} % \marg{body} %%% \\[-.5\belowdisplayskip]\nopagebreak % % \noindent This is the document version of the |\withargs| command. % % \changes{0.0.2}{2013/10/11} % {made the first argument optional and delimited by parentheses} % % \begin{macrocode} \NewDocumentCommand {\withargs} { >{\__withargs_remove_spaces:n} D(){} % argument spec >{\__withargs_process_uniquecsname:n} +o % up to 7 optional args >{\__withargs_process_uniquecsname:n} +o >{\__withargs_process_uniquecsname:n} +o >{\__withargs_process_uniquecsname:n} +o >{\__withargs_process_uniquecsname:n} +o >{\__withargs_process_uniquecsname:n} +o >{\__withargs_process_uniquecsname:n} +o +m } { % the body to execute % \end{macrocode} % % We first check if the argument specification is valid. % It has to be between 0 and 7 characters long and each % symbol has to be one of `|noxfcv|'. Otherwise: error! % The variants `|N|' and `|V|' are not supported (yet) because % they collect arguments differently than the others, and frankly, % I didn't want to bother. % % \begin{macrocode} \regex_match:nnF {^[nofxcv]{0,7}$} {#1} { \msg_critical:nnn{withargs}{invalid-parameter-specs}{#1} } % \end{macrocode} % % The next bit counts the number of optional arguments provided % using binary search. % If |#1| specifies \emph{more} arguments than were provided: error! % % \begin{macrocode} \int_set:Nn \l__with_arg_int { \IfNoValueTF {#5} { \IfNoValueTF {#3} { \IfNoValueTF{#2} 0 1 } { \IfNoValueTF{#4} 2 3 } } { \IfNoValueTF {#7} { \IfNoValueTF{#6} 4 5 } { \IfNoValueTF{#8} 6 7 } } } \int_compare:nNnT {\tl_count:n{#1}} > {\l__with_arg_int} { \msg_error:nnxxx{withargs}{invalid-parameter-number} { \tl_count:n{#1} } { \int_use:N \l__with_arg_int } { #1 } } % \end{macrocode} % % We can then call the right variant of |\withargs:|. % % \begin{macrocode} \int_case:nnn {\l__with_arg_int} { {1} { \__withargs_var:nx1{#1} {#2} {#9} } {2} { \__withargs_var:nx2{#1} {#2}{#3} {#9} } {3} { \__withargs_var:nx3{#1} {#2}{#3}{#4} {#9} } {4} { \__withargs_var:nx4{#1} {#2}{#3}{#4}{#5} {#9} } {5} { \__withargs_var:nx5{#1} {#2}{#3}{#4}{#5}{#6} {#9} } {6} { \__withargs_var:nx6{#1} {#2}{#3}{#4}{#5}{#6}{#7} {#9} } {7} { \__withargs_var:nx7{#1} {#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9} } }{} % \end{macrocode} % \uninteresting\begin{macrocode} } \int_new:N \l__with_arg_int % \end{macrocode} % %%% \end{macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \noindent The following is the error message displayed % if the argument specification is ill-formed: % % \begin{macrocode} \msg_new:nnnn{withargs}{invalid-parameter-specs}{ The~argument~specification~'#1'~is~not~valid. }{ The~argument~specification~should~consist~of~between~one~ and~seven~of~the~letters~'n',~'o',~'f',~'x',~'c',~'v'. } % \end{macrocode} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \noindent This is the error message displayed if the % number of provided optional arguments is inconsistent % with the provided argument specification. % % \begin{macrocode} \msg_new:nnnn{withargs}{invalid-parameter-number}{ You~specified~#1~arguments~but~provided~#2. }{ Your~argument~specification~is~'#3',~which~means~you~should~ provide~#1~optional~arguments.~However,~you~provided~#2.~ You~should~fix~that. } % \end{macrocode} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%