From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/gmutils/gmcommand.sty | 2432 ++++++++++++++++++++++++++++ 1 file changed, 2432 insertions(+) create mode 100644 macros/latex/contrib/gmutils/gmcommand.sty (limited to 'macros/latex/contrib/gmutils/gmcommand.sty') diff --git a/macros/latex/contrib/gmutils/gmcommand.sty b/macros/latex/contrib/gmutils/gmcommand.sty new file mode 100644 index 0000000000..f83fc8a2c1 --- /dev/null +++ b/macros/latex/contrib/gmutils/gmcommand.sty @@ -0,0 +1,2432 @@ +%% +%% \iffalse ^^A we skip the debug setting +\IfFileExists{\string~/bin/gen_and_xela}{\errorcontextlines=1000 }{} +%% \fi +%% ^^A $Id: TheUltimateMaster.gmd,v 0.352 2011/10/12 15:19:42 natror Exp natror $ +%% This is file “gmcommand.sty” generated with the DocStrip utility. +%% +%% +%% The original source files were: +%% +%% gmutils/gmutils.gmd (with options: `command') +%% +%% +%% Copyright © +%% by Grzegorz ‘Natror’ Murzynowski +%% natror (at) gmail (dot) com +%% +%% This program is subject to the LaTeX Project Public License. +%% See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html +%% for the details of that license. +%% +%% LPPL status: "author-maintained". +%% +%% +%% +%% For documentation please refer to the file(s) +%% gmutils.{gmd,pdf}. +%% +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{gmcommand} + [2011/10/12 v0.996 definition of \string \DeclareCommand \string &al. based on the ancient xparse (pre-expl3) (GM)] + + +%% +%% +%% ^^A\typeout{\unexpanded{#4}}%% + +\RequirePackage{gmbase} % we require the low-level macros. + +\unless\ifcsname ifgmu@quiet\endcsname +\Name\newif {ifgmu@quiet}% % it has to be at least (at highest) in + % \CH{2010/09/06 v0.993 moved here from + % % \pk{gmutils.sty} (a bug fix)} +\fi + + +\unless\ifdefined\@temptokenb +\newtoks\@temptokenb +\fi + +\newif\if@dc@alllong@ % for an option of all arguments long (it's + % stronger than |GroteLang| defined later (the + % latter is |\let| it). +\newif\if@dc@quiet@ % for suppressing the message of using of + +\newif\ifDCMessages % a~global switch to suppress the message about + +\newtoks\@dc@arguments % the register for storing parsed + % |\\command {#1}›…{⁄}|. + +\newcount\c@dc@catchernum +\newcount\c@dc@argnum + +\newif\if@dc@ignore@ +\newif\if@dc@GroteNegere@ % for “gross” ignoring +\newif\if@dc@GroteLang@ % for “gross” longness + +\newif\if@dc@long@ + +\newif\if@dc@BareSpace@ + + +\def\@dc@long@letter{% +\if@dc@long@ P\fi +} + +\newif\if@dc@xadefault + +\def\@nx@xa{\@nx\@xa} +\def\@xa@nx{\@xa\@nx} +\def\@xa@xa{\@xa\@xa} + +\newif\if@dc@xadefault@i@ +\newif\if@dc@xadefault@ii@ +\newif\if@dc@xaeacher@ + +\def\@dc@falsify@xadefaults{% + \@dc@xadefaultfalse + \@dc@xadefault@i@false + \@dc@xadefault@ii@false +} + +\lpdef\DeclareCommand#1#2#3{% ^^B It's the draft version just + % ^^B~to declare the true one, which is defined in line + % \ref{DC:final}. + % + % \begin{enumargs} + % \item command to be defined, + % \item arguments specification, + % \item definition body. + % \end{enumargs} + % \chgs[\DeclareCommand]{2008/12/05 v0.98 added the \env{S}/\env{T} + % spec parsing, the + % \env{s} spec parsing rewritten to be a~shorthand for + % \env{S\{*\}}, unused code removed} + % \chgs{2010/04/15 v0.993 implemented the \cmd\SameAs feature} + % + % + % +\@dc@alllong@true + \@dc@ResetParseAuxilia + % + \@dc@ParseNextSpecifier #2% + \@dc@buckstopshere% it's the sentinel of parsing. Doesn't have to be + % defined since the test performs a strings comparison. + \protected\edef#1{% + \@nx\@dc@ {\the\toks@}% + \@xanxcs{\@dc@InnerName{#1}}% + \@nx #1% + }% + \edef\gmu@DeclareCommand@resa{% + \long\def\@xanxcs{\@dc@InnerName{#1}}% + \@xau\@dc@innerhashes{% + \unexpanded{#3}}% + }% of resa + \gmu@DeclareCommand@resa +}% of the ‘draft’ |\DeclareCommand|. + +\long\def\@dc@ + #1% the argument catchers in a~pair of braces (their arguments + % may contain \incmd\par\ so the macro is long). + #2% |\\thecommand\| + #3% |\thecommand| + {% + \ifx\protect\@typeset@protect + \@xa\@firstofone + \else + \protect#3\@xa\@gobble + \fi + {\@dc@arguments{#2}#1\the\@dc@arguments}% +} + +\newtoks \@dc@ParsedSpecs + +\def\@dc@ResetParseAuxilia{% + % + \@dc@ParsedSpecs={}% + % + \c@dc@catchernum\z@ % the count of catchers + \c@dc@argnum\z@ % the count of arguments (inner arity) (it may be + % smaller than the above if we ignore some arguments) + % + \toks@{}% in this register we will store the created sequence of + % argument catchers. + % + % And for the |M⁄m| specifiers: + \@dc@Mmode@false + % + \emptify\@dc@innerhashes % in this macro we will store the sequence of + % \inverb|#1#2…|. + % + \@dc@GroteNegere@false + \let\if@dc@GroteLang@\if@dc@alllong@ +} + +\newif \if@dc@Mmode@ +\def\@dc@Ms@num {\z@}% + +\def\@dc@Ms@init{% + \@dc@Mmode@true + \def\@dc@Ms@num {\z@}% + \edef\@dc@Ms@initial@listate{% + \@dc@Ms@listate + }% of edef +} + +\def\@dc@Ms@listate{% + \boolstobin{{@dc@long@}{@dc@ignore@}}% +} + +\def\@dc@Ms@shipout {% + \gmu@if {num} {\@dc@Ms@num>\z@}% + {\@xa\dc@addtoParsed@\@xa{\@dc@Ms@num}% + \def\@dc@Ms@num{\z@}% + \@dc@Mmode@false + }% + {}% +} + +\def\@dc@ResetStepAuxilia {% + % We set the local ignorance switch to its “gross” value + \let\if@dc@ignore@ =\if@dc@GroteNegere@ + \let\if@dc@long@ = \if@dc@GroteLang@ + % and reset the expandaftering switches + \@dc@falsify@xadefaults + \@dc@BareSpace@false +} + +\def\@dc@argtypes{% + =\gobblespace \loop \lostwax \SameAs \Scope + AaBbCcDdGgKkMmOo% + QqSs*TtUuWw% + \drs +} + +\def\@dc@drses{\drs} % decimal respecting space + +\@ifXeTeX +{\addtomacro\@dc@argtypes{ďĎŤťǓǔÔô}% + \addtomacro\@dc@drses{ďĎ}% +} +{} + +\def\@dc@ParseSpecifier #1{% The main inner macro parsing argument + \gmu@CASE {stribs}{{#1}\@dc@buckstopshere}% + {% + \@dc@Ms@shipout + \edef\@dc@innerhashes {% + \gmu@hashes 1{\numexpr\c@dc@argnum +\@ne}% + }% + }% + \gmu@CASE {stribs}{{#1}>}% + {% + \grab@prefix }% + \@XA{% + \gmu@CASEsbnone{#1}}\@xa{% + \@dc@argtypes + }% + {\IgnInfo{gmcommand}{while parsing arg specifiers}{#1}% + \@dc@ParseNextSpecifier }% + \gmu@CASE {stribs}{{#1}\SameAs}% + {\@dc@SameAs}% + \gmu@ifsbnone {#1}{Mm}% + {\@dc@Ms@shipout }% + {}% + \gmu@if {@dc@Mmode@}{}% + {}% + {% + \gmu@ifsbany{#1}{=\gobblespace}{\@dc@ignore@true}{}% + \gmu@ifsw {@dc@BareSpace@}% + {\@dc@addtoparsed@BareSpace } + {}% + % + % + \gmu@ifsw {@dc@long@}% + {\@dc@addtospecs@bare{>P}} + {}% + % + \gmu@ifsw {@dc@ignore@}% + {\@dc@addtoparsed@Ignore }% + {}% + % + \@dc@addtospecs@bare {#1}% + % + \@xa\addtotoks\@xa\toks@\@xa{% + \csname ArgumentCatcher@\@dc@long@letter + \strip@bslash{#1}% + \endcsname + }% of toks' text. + \advance\c@dc@catchernum\@ne + }% of if not |M|-mode + \gmu@notif {@dc@ignore@}{}% + {\@dc@addinnerhash }% \label{@dc@addinnerhash} + {}% (empty “not-else” branch of ignoring) + \gmu@CASEsbany {#1}{Mm}% + {\@dc@process@ms}% + \gmu@CASEsbany {#1}{Kk}% + {\@dc@define@K}% + \gmu@CASEsbany {#1}{\gobblespace}% + {\@dc@ParseNextSpecifier}% + \gmu@CASEsbany{#1}{=\Scope AaBbCcDdOoSs*}% + {\grab@optparam{#1}}% + \@XA{\gmu@CASEsbany{#1}}\@xa{\@dc@drses}% + {\grab@optparam{#1}}% + \gmu@CASEsbany{#1}{UuǓǔWw\lostwax}% + {\@dc@grab@Loop #1}% putting the specifier's letter as |#1| for the + % grabber suppresses adding it to the parsed specifiers' list. + \gmu@lastCASE + {% + \grab@twoparams{#1}}% + \gmu@ESAC + % +}% of |\@dc@ParseSpecifier| + +\def\@dc@addtoparsed@Ignore{% + \addtotoks\toks@{\@dc@ignorearg}% + \@dc@addtospecs@bare{>i}% +} + +\def\@dc@addinnerhash{% + \advance\c@dc@argnum\@ne +} + +\def\@dc@addtoparsed@BareSpace{% + \addtotoks\toks@{\@dc@BareSpaceArg }% + \@dc@addtospecs@bare{>\BareSpace }% +} + +\def\@dc@process@ms{% + \gmu@if {@dc@Mmode@}{}% + {\gmu@if {num}{\@dc@Ms@initial@listate=\@dc@Ms@listate}% + {\@dc@process@ms@grabnum }% of if the state has'nt been changed + {\@dc@Ms@shipout + % Remember however that we've increased number of arguments so now we + % set it back: + \advance\c@dc@argnum\m@ne + \@dc@ParseSpecifier m% + }% of if the state has been changed + }% of if |M|-mode + {\@dc@Ms@init + \@dc@process@ms@grabnum + }% of not if |M|-mode. +}% of \@dc@process@ms + +\def \@dc@process@ms@grabnum {% + \@ifnextanyIS {\bgroup \@ne \tw@ \thr@@ 123456789}% + {% + \@dc@process@ms@fin}% + {% + \@dc@process@ms@fin \@ne}% +} + +\def \@dc@process@ms@fin #1{% + \edef\@dc@processms@hash {\the\numexpr#1}% + \edef\@dc@processms@left {\the\numexpr 9-\c@dc@argnum+\@ne}% + % + \gmu@AND {% + {num} {\@dc@processms@hash >\z@} + {num} {\@dc@processms@hash <\numexpr + \@dc@processms@left+1 \relax }% + }% + {\stepnummacro \@dc@Ms@num \@dc@processms@hash + \edef\@dc@hashgoal {% + \the\numexpr\c@dc@argnum +% + \@dc@processms@hash-1}% minus 1 because one + \@whilenum \c@dc@argnum<\@dc@hashgoal \do{% + \@dc@addinnerhash + }% + % + \@dc@ParseNextSpecifier + }% of if all conds.\ satisfied + {% some of the conds.\ not satisfied + \PackageError{gmcommand}{% + The argument to the M or m specifier, if any, has to be ^^J% + a number between 1 and \@dc@processms@left ^^J% + (there is/are \the\c@dc@argnum\space arg(s) declared + already).^^J% + I ignore this m/M.}% + {}% + \gmu@passbraced \@dc@ParseNextSpecifier {#1}% + }% +}% of |\@dc@process@ms| + +\def\@dc@ParseNextSpecifier{% + \@dc@ResetStepAuxilia + \@dc@ParseSpecifier +} + +\lpdef\@dc@AddAndParse#1{% + \dc@addtoParsed@{#1}% + \@dc@falsify@xadefaults + \@dc@ParseNextSpecifier +} + + +\def\grab@optparam #1{% arg specifier + \@ifnextchar\bgroup{\@dc@AddAndParse}% + {% + \edef\@dc@tempa{% + \gmu@if {csname}% + {@dc@optparam@deft@\strip@bslash{#1}\endcsname}% + {\@xaucs {@dc@optparam@deft@\strip@bslash{#1}}}% + {\@nx \NoValue}% + }% + \@xa\@dc@AddAndParse\@xa{\@dc@tempa}% + }% +} + + +\long\def\@dc@DeclareDefault #1#2{% + \uppercase{% + \Name\edefU{\strip@bslash{\@dc@optparam@deft@}\strip@bslash{#1}}{#2}}% + % + \lowercase{% + \Name\edefU{@dc@optparam@deft@\strip@bslash{#1}}{#2}}% +} + +\@dc@DeclareDefault D{0} +\@dc@DeclareDefault d{0} + +\@ifXeTeX {% + \@dc@DeclareDefault Ď{0}% +} +{} + +\@xa\@dc@DeclareDefault \@xa\Scope\@xa{\all@stars} + +\@dc@DeclareDefault = {\@tempcnta} + + +\@dc@DeclareDefault Q {\NoValue} + +\@ifXeTeX {% + \@dc@DeclareDefault Ô{\NoValue}% +} +{} + +\@dc@DeclareDefault U {\NoValue} + +\long\def\@dc@maybe@expandafter #1{% + \gmu@if {@dc@xadefault}{}% + {\gmu@ifutokens{#1}{\NoValue}% + {\@secondoftwo}{\@firstoftwo}% + }% if we are to expandafter |#1|. + {\@secondoftwo}% if we don't expandafter |#1| +} + +\long\def\dc@addtotoks@ #1{% + \@dc@maybe@expandafter {#1}% + % + {\toks@\@xa\@xa\@xa{\@xa\the\@xa\toks@\@xa{#1}}}% + {\toks@\@xa{\the\toks@{#1}}}% +} + +\long\def\@dc@addtospecs #1{% + \@dc@maybe@expandafter {#1}% + {\@xa \addtotoks \@xa\@dc@ParsedSpecs\@xa{\@xa{#1}}% + }% + {\addtotoks\@dc@ParsedSpecs{{#1}}}% +} + +\long\def\dc@addtoParsed@ #1{% + \dc@addtotoks@{#1}% + \@dc@addtospecs{#1}% +} + +\long\def\@dc@addtospecs@bare #1{% + \addtotoks\@dc@ParsedSpecs{#1}% +} + +\long\def\@dc@addtotoks@bare #1{% + \addtotoks\toks@ {#1}% +} + +\long\def\@dc@addtoParsed@bare #1{% + \@dc@addtotoks@bare {#1}% + \@dc@addtospecs@bare {#1}% +} + +\long\def\grab@twoparams +#1% the specifier +#2% first parameter, which is mandatory +{% default default (when default is absent) + \if@dc@xadefault@i@\@dc@xadefaulttrue\fi + \dc@addtoParsed@{#2}% + \if@dc@xadefault@ii@ + \@dc@falsify@xadefaults\@dc@xadefaulttrue + \fi + \grab@optparam{#1}% +} + +\long\def\@dc@addargum#1{% + \addtotoks\@dc@arguments{#1}% +\@iwruif {@@@@@@ @dc@arguments: »\the\@dc@arguments«}% +} + +\Store@Macro\@dc@addargum + +\pdef\@dc@ignorearg{% + \long\def\@dc@addargum##1{% + \Restore@Macro\@dc@addargum}% +} + +\StoreMacro@nocat\gmu@passbraced + +\pdef\@dc@BareSpaceArg{% + \let \gmu@passbraced \gmu@passbracedNotSp + \def\@dc@addargum {% + \Restore@Macro\@dc@addargum + \Restore@Macro\gmu@passbraced + \@dc@addargum + }% +} + + +\def\grab@prefix@CASE{% just a shorthand + \@xa\gmu@CASEsbany\gmu@forarg +} + +\long\def\grab@prefix #1{% + %% \CH{2010/07/26 v0.993 made for-eaching to make it behave as + %% expected, i.e.\ that latter settings prævalent over the former} + % + \gmu@foreach#1\gmu@foreach@delim {% + % + \grab@prefix@CASE + {\long!lL\par Pp}% + {\@dc@long@true}% + % + \grab@prefix@CASE + {Ii}% + {\@dc@ignore@true}% + % + \grab@prefix@CASE + {\@xa\expandafter}% + {\@dc@xadefaulttrue}% + % + \grab@prefix@CASE + {\@xa \@xa@nx \@xa@xa \expandafter \@xanx \xanx \xaxa}% + {\@dc@xadefault@i@true}% + % + \grab@prefix@CASE + {\@xa \@nx@xa \@xa@xa \expandafter \@nxxa \nxxa}% + {\@dc@xadefault@ii@true}% + % + \grab@prefix@CASE + {\@xaeacher \xaeacher \xaEacher \xaE }% + {\@dc@xadefault@ii@true}% + % + \grab@prefix@CASE + {\GroteNegere \GrossIgnore \GroteN \GrossI} + {\@dc@GroteNegere@true + \@dc@ignore@true}% + % + \grab@prefix@CASE + {\GroteNegereStop\GrossIgnoreStop + \GroteNStop\GrossIStop} + {\@dc@GroteNegere@false + \@dc@ignore@false}% + % + \grab@prefix@CASE + {\GroteLang\GrossLong\GroteL\GrossL} + {\@dc@GroteLang@true + \@dc@long@true}% + % + \grab@prefix@CASE + {\GroteLangStop\GrossLangStop + \GroteLStop\GrossLStop}% + {% + \let\if@dc@GroteLang@=\if@dc@alllong@ + \let\if@dc@long@=\if@dc@alllong@ + }% + % + \grab@prefix@CASE + {\BareSpace} + {\@dc@BareSpace@true} + % + % + \gmu@EatCases + {\IgnInfo{gmcommand}{while parsing arg specifiers}{#1}}% + \gmu@ESAC + % + }% of for each + \@dc@ParseSpecifier % +}% of |\grab@prefix| + +\long\def\dc@DefParseNext#1{% + % This is to allow hashes in the defaults. + \edefU\@dc@parse@next{#1}% +} + +\def\@dc@Alias +#1% |\lowercase| or |\firstofone| +#2% left side of the assignment +#3% right side of the assignment +#4% |Lower| or empty +{% + \gmu@if {csname}% + {ArgumentCatcher@\strip@bslash #3\endcsname}% + {#1{% + \@xa\let\csname\strip@bslash\ArgumentCatcher@ + \strip@bslash #2\@xa\endcsname}% + \csname ArgumentCatcher@\strip@bslash #3\endcsname + }{\PackageError{gmutils/gmcommand}{% + You're trying to #4Alias the »\unexpanded{#3}« catcher^^J% + but it is not defined!}{}% + }% +} + +\def\@dc@LowerAliases #1{% + % To provide lowercase aliases of the catchers: + \@dc@Alias \lowercase {#1}{#1}{Lower}% + \@dc@Alias \lowercase {\P#1}{\P#1}{Lower}% we provide »P« as a \CS + % to avoid lowercase'ing it. +} + +\def\@dc@AliasCatcher +#1% left side of the assignment +#2% right side of the assignment +{% + \@dc@Alias \firstofone {#1}{#2}{}% +} + +\def\@dc@AliasPLower +#1% specifier to alias +{\@dc@AliasCatcher {P#1}{#1}% + \@dc@LowerAliases{#1}% +} + +\long\def\ArgumentCatcher@B +#1% default value +#2% tail of args catchers. +\@dc@arguments % delimiter +{% + \@ifnextcat\bgroup + {\dc@DefParseNext{#2}\ArgumentCatcher@m@i }% + {\@dc@addargum {{#1}}#2\@dc@arguments }% +} + +\long\def\ArgumentCatcher@PB +#1% default value +#2% tail of args catchers. +\@dc@arguments % delimiter +{\@ifnextcat\bgroup + {\dc@DefParseNext{#2}\ArgumentCatcher@Pm@i }% + {\@dc@addargum {{#1}}#2\@dc@arguments }% +} + +\@dc@LowerAliases B + +\long\def\ArgumentCatcher@T@ % parsing of a~single \textbf Token + % continued: +#1% kind of test (|strings| or |StrX| so far (2010/12/28, 7.24)) +#2% the list to search |#4| on, +#3% the default value, +#4% the tail of args parsers, +#5% the token we search in |#1| (it's an unbraced +{% + #1 #5{#2}% + {\@dc@addargum {{#5}}#4\@dc@arguments}% + {\@dc@addargum {{#3}}#4\@dc@arguments#5}% +} + +\long\def\ArgumentCatcher@T % parsing of a~ single \textbf Token. It's +#1% the list we search optional token on, +#2% the default value, +#3% the tail of args parser. +\@dc@arguments{% + \@ifnextnotgroup + % \label{dc@S:bgroup} + {\ArgumentCatcher@T@ \gmu@ifStrXany {#1}{#2}{#3}}% + {\@dc@addargum {{#2}}#3\@dc@arguments}% if we parse an + % opening or closing brace, then we are sure it's not any expected + % Single. +} + +\@dc@AliasPLower T + +\long\def\ArgumentCatcher@Ť #1#2#3% as in |›…@T| +{% one-token catcher that respects space. + \ArgumentCatcher@Loop + {StrX}{\any}{#1}{\any}{}{1}{#2}{% empty eacher + }{#3}% +} + +\@dc@AliasPLower Ť + + +\edef\ArgumentCatcher@S +#1% default value +{% + \@nx\ArgumentCatcher@T {\@xa\@nx\all@stars}{#1}}% the |s| arg spec is + +\@dc@AliasPLower S +\@dc@AliasCatcher * S + +\newif\if@debugacro@ + +\long\def\ArgumentCatcher@Loop %^^A >>>>>>>loop +#1% kind of test (|StrX| or |str| or anything else for what +#2% “sign” of match for iteration: |\any| or |\none| +#3% list of tokens |\@let@token| will be matched against with |#1| +#4% test for “drainers” (allowed values as for |#1|) +#5% list of “drainers”: if |\@let@token| satisfies the |#3| test, +#6% upper bound of number of items (may be empty or negative to turn +#7% default value (if empty sequence is parsed), |\NoValue| by default. +#8% an “eacher”—stuff to be put before each token/text added to the +#9% the tail of args parser +\@dc@arguments % delimiter +{% + \dc@DefParseNext{#9}% + \emptify\@dc@seQuence + \c@dc@Loop@bound=\numexpr(\gmu@ifempty{#6}{-1}{#6})*1\relax + \gmu@if {num}{\c@dc@Loop@bound<\z@}% + {\c@dc@Loop@bound=-\c@dc@Loop@bound + \let\@dc@Loop@countby\z@ + }% + {\let\@dc@Loop@countby\m@ne}% + % + \gmu@ifempty{#3}% + {\gmu@if {strings}{\none #2}% + {\@dc@Loop@iteralltrue}% it's an additional switch for better + % performance in a special case: when we wish + % only count the items and iterate over anything + {% + \Store@Macro\ArgumentCatcher@Loop@defcheck + \def\ArgumentCatcher@Loop@defcheck{% + \Restore@Macro\ArgumentCatcher@Loop@defcheck + \ArgumentCatcher@Loop@shipout}% + }% of if |#2| str-is |\any| + }% of if |#3| empty + {\@dc@Loop@iterallfalse}% when |#2| nonempty, we \emph{have} to + % perform matching. \rrthis + % + \gmu@ifempty{#5}% + {\gmu@if {strings} {\none #4}% + {\@dc@Loop@addallfalse\@dc@Loop@drainalltrue}% + {\@dc@Loop@addalltrue\@dc@Loop@drainallfalse}% + }% of if |#5| empty + {\@dc@Loop@addallfalse\@dc@Loop@drainallfalse}% when |#4| nonempty, + % we \emph{have} to perform matching. \rrthis + % + \edef\ArgumentCatcher@Loop@afterpeep{% + \gmu@if {@dc@Loop@iterall}{}% + {\firstoftwo}% + {\unexpanded{% + \@dc@Loop@test + {#1}#2{#3}% if the next token StrX-is/is not on |#2|, + % then… \label{h1.@let@token.h2} + }% of |\unexpanded| + }% of if we don't iterate over all (of preparation of iteration test) + {\gmu@if {@dc@Loop@addall}{}% + {\@nx \ArgumentCatcher@Loop@add}% + {\gmu@if {@dc@Loop@drainall}{}% + {\@nx \ArgumentCatcher@Loop@drain}% + {\unexpanded{% + \@dc@Loop@test + {#1}#4{#5}% if the next token satisfies |#4|-direction StrX/str + % match against |#5|, then we discard it, + % otherwise we add it. + \ArgumentCatcher@Loop@drain + \ArgumentCatcher@Loop@add + }% of |\unexpanded| + }% of not drain all + }% of if not add all + }% + {\gmu@if {@dc@Loop@iterall}{}% + {}% + {\@nx \ArgumentCatcher@Loop@shipout}% + }% + \unexpanded{{#7}{#8}}% + }% of |\ArgumentCatcher@Loop@afterpeep| + % + \ArgumentCatcher@Loop@defcheck {#7}{#8}% + \ArgumentCatcher@Loop@check +}% of |\ArgumentCatcher@Loop| + +\newcount\c@dc@Loop@bound + +\newif\if@dc@Loop@iterall +\newif\if@dc@Loop@addall +\newif\if@dc@Loop@drainall + +\long\def\@dc@Loop@test +#1% kind of test (|StrX| or |str| so far (2010/12/28, 7.51)) +#2% |\any| or |\none| +#3% list of tokens to match against +#4% what if \OK +#5% what if not \OK. +{% remember we are in the argument of |\gmu@peep@next| so we are after + % peep. + \gmu@if {defined}{\@def@token} + {\csname gmu@if#1\strip@bslash #2\@xa\endcsname + \@def@token }% + {\csname + gmu@if% + \gmu@ifdetokens {#1}{str}% + {NX}% + {x}% + \strip@bslash #2% + \endcsname + \@let@token }% + {#3}{#4}{#5}% +} + +\@dc@AliasCatcher {PLoop} {Loop} + +\long\def\ArgumentCatcher@Loop@defcheck +#1% default, +#2% “eacher” +{% + \edefU\ArgumentCatcher@Loop@check{% + \gmu@if {num}{\c@dc@Loop@bound>\z@} + {\advance \c@dc@Loop@bound \@dc@Loop@countby + \gmu@peep@next + \ArgumentCatcher@Loop@afterpeep } + {\ArgumentCatcher@Loop@shipout {#1}{#2}}% of if num bound reached + }% of |\ArgumentCatcher@Loop@check| +}% of |\ArgumentCatcher@Loop@defcheck| + +\lpdef\@dc@Loop@CareOfSpace +#1% a macro with all the arguments except last +{\gmu@ifpeeped x \gmu@letspace + {\edef\@dc@Loop@careofspace@aas{% + \unexpanded{#1{ }}% + }% edef unexpanded to allow |#| tokens in |#1| + \afterassignment\@dc@Loop@careofspace@aas + \let\gmu@drain= }% after |=| is a space. + {#1}% next not space, so just |#1| and let it process the next token + % its way. +} + +\StoreMacro@nocat\@dc@Loop@CareOfSpace + +\lpdef\@dc@Loop@CareOfSpace@NoBraces +#1% a macro with all the arguments except last +{% +\gmu@ifpeeped x \gmu@letspace + {\edef\@dc@Loop@careofspace@aas{% + \unexpanded{#1 }% note the space + }% edef unexpanded to allow |#| tokens in |#1| + \afterassignment\@dc@Loop@careofspace@aas + \let\gmu@drain= }% after |=| is a space. + {#1}% next not space, so just |#1| and let it process the next token + % its way. +} + + +\lpdef\@dc@Loop@CareOfSpaceAndGroup +#1% as in the previous macro +{\@iwruif {Care of both: @let@token: »\meaning\@let@token«}% + \@dc@Loop@CareOfSpace{% + \gmu@passbraced{#1}% + }% +}% of “take care of both” + +\long\def\ArgumentCatcher@Loop@add +#1% default +#2% eacher +{\@dc@Loop@CareOfSpaceAndGroup + {\ArgumentCatcher@Loop@add@{#2}}% +} + +\long\def\ArgumentCatcher@Loop@add@ +#1% eacher +#2% token/text to be added +{\addtomacro\@dc@seQuence{#1#2}% + \@iwruif {@@@@@@ Q-add: »\the\@dc@arguments«}% + \ArgumentCatcher@Loop@check +}% of |\ArgumentCatcher@Loop@add@| + +\long\def\ArgumentCatcher@Loop@drain +#1% default +#2% eacher +{% + \@iwruif{@@@@@@ Q-drain: »\the\@dc@arguments«}% + \@dc@Loop@CareOfSpaceAndGroup + {\@xa\ArgumentCatcher@Loop@check\@gobble}% +} + +\long\def\ArgumentCatcher@Loop@shipout +#1% default +#2% eacher +{% + \gmu@if x{\@dc@seQuence\@empty}% + {\def\@dc@seQuence{#1}% + \gmu@if x{\@dc@seQuence\@empty}% + {}{\prependtomacro\@dc@seQuence{#2}}% + }% + {}% if |\@dc@seQuence| is nonempty, we don't modify it. + \@xa\@dc@addargum\@xa{\@xa{\@dc@seQuence}}% + \@iwruif {@@@@@@ Q-finish: »\the\@dc@arguments«}% + \@dc@parse@next\@dc@arguments +}% of |\ArgumentCatcher@Loop@shipout| + +\long\def\ArgumentCatcher@Q +#1% list +#2% default (|\NoValue| by default, as in previous versions). +{% + \ArgumentCatcher@Loop + {StrX}% + \any + { #1}% note the space before |#1|—settheory sum of |#1| and drainers. + \any + { }% we ignore spaces—it's a legacy setting, maybe we'll optionise + % it in the future + \m@ne % we allow any number of tokens + {#2}% default, by default |\NoValue|, as defined in line \ref{Q-arg deft.} + {}% empty eacher +}% + +\@dc@AliasPLower Q + +\@ifXeTeX {% + \long\def\ArgumentCatcher@Ô + #1% list + #2% default (|\NoValue| by default, as in previous versions). + {% + \@dc@BareSpaceArg + \ArgumentCatcher@Loop + {str}% + \any + { #1}% note the space before |#1|—settheory sum of |#1| and drainers. + \any + { }% we ignore spaces—it's a legacy setting, maybe we'll optionise + % it in the future + \m@ne % we allow any number of tokens + {#2}% default, by default |\NoValue|, as defined in line \ref{Q-arg deft.} + {}% empty eacher + }% + + \@dc@AliasPLower Ô + +}{}% of if \XeTeX + +\def\ArgumentCatcher@D{% decimal argument (useful for dates e.g.) + \ArgumentCatcher@Q + {-+0123456789}% + % the default value will be delivered by the defaults' catcher +} + +\@dc@AliasPLower D + +\@ifXeTeX +{% + \def\ArgumentCatcher@Ď + #1% default value, 0 by default + {% decimal argument + \ArgumentCatcher@Loop + {StrX}% + \any + {-+0123456789}% + \any + {}% + \m@ne + {#1}% + {}% + }% + +\@dc@AliasPLower Ď + +}{}% of if \XeTeX + +\def\ArgumentCatcher@U {% + \ArgumentCatcher@Loop {StrX}% +} + +\@dc@AliasPLower U + +\@dc@AliasCatcher W {U} + +\@dc@AliasPLower W + +\@dc@AliasCatcher {lostwax} U % ^^A Catcher@lostwax + +\long\def\ArgumentCatcher@item +#1% “sign” of matching +#2% list to match against +#3% default value +#4% eacher (which in this case will be applied to \emph{the} (one) +{% + \ArgumentCatcher@Loop + {StrX}% + #1% + {#2}% + \none {}% we add all that matches + 1 % at most one item + {#3}% + {#4}% +} + +\if@XeTeX + + \def\ArgumentCatcher@Ǔ{% + \@dc@BareSpaceArg + \ArgumentCatcher@Loop {StrX}% + } + + \@dc@AliasPLower Ǔ + +\fi + + +\long\def\ArgumentCatcher@genM +#1% the letter »P« (for long catcher) or nothing (for the short version) +#2% number of undelimited parametrs to catch (arabic) +#3% tail of parsers +\@dc@arguments{% + \dc@DefParseNext{#3}% + \csname ArgumentCatcher@#1m@% + \romannumeral#2% + \endcsname +} + + +\def\ArgumentCatcher@M{\ArgumentCatcher@genM {}} +\def\ArgumentCatcher@PM{\ArgumentCatcher@genM P} + +\@dc@AliasCatcher {m} {M} +\@dc@AliasCatcher {Pm} {PM} + +\@dc@AliasCatcher {ms} {M} +\@dc@AliasCatcher {Pms} {PM} + +\@tempcnta=\@ne +\@whilenum\@tempcnta<9\do{% + % + \edef\gmu@tempa{% + % + % The short catchers of mandatories: + \def\@xanxcs{% + ArgumentCatcher@m@\romannumeral\@tempcnta}% + \gmu@hashes1{\numexpr\@tempcnta+1}% + {\@nx\@dc@addargum{% + \gmu@hashesbraced 1{\numexpr\@tempcnta+1}}% + \@nx\@dc@parse@next\@nx\@dc@arguments + }% of \incs{ArgumentCatcher@m@\}. + % + % And the long ones: + \long \def\@xanxcs{% + ArgumentCatcher@Pm@\romannumeral\@tempcnta}% + \gmu@hashes1{\numexpr\@tempcnta+1}% + {\@nx\@dc@addargum{% + \gmu@hashesbraced 1{\numexpr\@tempcnta+1}}% + \@nx\@dc@parse@next\@nx\@dc@arguments + }% of \incs{ArgumentCatcher@Pm@\}. + % + }% of |\edef|. + \gmu@tempa + \advance\@tempcnta1\relax +}% of the loop. + +\if 1 1 +\@tempcnta\@ne +\@whilenum\@tempcnta<9\do{% + \typeout{\bslash ArgumentCatcher@m@\romannumeral\@tempcnta: ^^J% + \Name\meaning{ArgumentCatcher@m@\romannumeral\@tempcnta}^^J}% + \typeout{\bslash ArgumentCatcher@Pm@\romannumeral\@tempcnta : ^^J% + \Name\meaning + {ArgumentCatcher@Pm@\romannumeral\@tempcnta}^^J^^J^^J% + }% + \advance\@tempcnta\@ne +} + +\fi + +\def\ArgumentCatcher@m@ix +#1#2#3#4#5#6#7#8#9{% + \@dc@addargum{% + {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}% + \the \@dc@arguments +} + +\long\def\ArgumentCatcher@Pm@ix +#1#2#3#4#5#6#7#8#9{% + \@dc@addargum{% + {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}% + \the \@dc@arguments +} + +\long\def\ArgumentCatcher@K % a~Knuthian delimited or undelimited +#1% the particular Knuthian macro +#2% the tail of args parser. +\@dc@arguments % tail delimiter +{\dc@DefParseNext{#2}#1} + +\@dc@AliasPLower K + +\long\def\gmu@twostring#1#2{\string#1\string#2} + +\long\def\ArgumentCatcher@G@longorshort +#1% longness prefix (|\long| or nothing) +#2% left and right delimiters +#3% default value +#4% the tail of args parser. +\@dc@arguments % tail delimiter +{% + \edef\@dc@Gname{ArgumentCatcher@G\gmu@twostring#2}% + \gmu@if {csname}{\@dc@Gname \endcsname}% + {}% + {#1\Name\def{\@dc@Gname \@xa}% + \@dc@Gparams#2{\@dc@addargum{{##2}}##1\@dc@arguments}% + }% + \@xa\@ifEUnextchar\@firstoftwo#2% + {\def\dc@parse@next{#4}% we hide possible |\par|s. + \csname \@dc@Gname \endcsname\dc@parse@next}% + {\@dc@addargum{{#3}}#4\@dc@arguments}% +} + +\long\def\@dc@Gparams#1#2{##1#1##2#2} + +\lpdef\ArgumentCatcher@G % short general catcher +#1% left and right delimiters +#2% default value +{\ArgumentCatcher@G@longorshort{}{#1}{#2}} + +\lpdef\ArgumentCatcher@PG % long general catcher +#1% left and right delimiter +#2% default value +{\ArgumentCatcher@G@longorshort{\long}{#1}{#2}} + +\def\@dc@DefAsGeneral +#1% specifier +#2% delimiters +{\Name\lpdef{ArgumentCatcher@\strip@bslash{#1}}% + ##1% default value + {\ArgumentCatcher@G{#2}{##1}}% + \Name\lpdef{ArgumentCatcher@P\strip@bslash{#1}}% + ##1% default value + {\ArgumentCatcher@PG{#2}{##1}}% »P« was missing. Fixed 2011/03/22, 16.14. + % + \gmu@if {cat}{a\@nx#1}% + {\@dc@LowerAliases #1}{}% +} + +\@dc@DefAsGeneral A{<>} + +\@dc@DefAsGeneral O{[]} + + +\def\DCnocoordinate{\@dc@DefAsGeneral C{()}} +\DCnocoordinate + +\edefU\DCcoordinate{% + % + \long\def\ArgumentCatcher@C + #1% default value + #2% tail of parsers + \@dc@arguments % tail's delimiter + {% + \@ifEUnextchar(%^^A) + {\dc@DefParseNext{#2}\ArgumentCatcher@c@}% + {\@dc@addargum{{#1}}#2\@dc@arguments}% + }% + % + \let\ArgumentCatcher@c\ArgumentCatcher@C + \let\ArgumentCatcher@Pc\ArgumentCatcher@PC + % + \long\def\ArgumentCatcher@PC#1#2\@dc@arguments{% + \@ifEUnextchar(%^^A) + {\dc@DefParseNext{#2}\ArgumentCatcher@Pc@}% + {\@dc@addargum{{#1}}#2\@dc@arguments}% + }% + % + \def\ArgumentCatcher@c@(#1){% + \gmu@ifxany,{#1}% + {\@xa\@dc@addargum\@dc@commasep#1\@dc@commasep}% + {\@dc@addargum{{#1}}}\@dc@parse@next\@dc@arguments + }% + % \stanza + \def\@dc@commasep#1,#2\@dc@commasep{{{{#1}{#2}}}}% + % \stanza + \long\def\ArgumentCatcher@Pc@(#1){% + \gmu@ifxany,{#1}% + {\@xa\@dc@addargum\@dc@commasep#1\@dc@commasep}% + {\@dc@addargum{{#1}}}\@dc@parse@next\@dc@arguments + }% +} + + +\def\@dc@Scope@shipout#1{% + \ifx\@dc@seQuence\@empty\def\@dc@seQuence{#1}\fi + \@xa \gmu@ifxany\@xa \global\@xa{\@dc@seQuence}% + {\@dc@addargum{{\global}}}% + {\@dc@addargum{{\relax}}}% + \@dc@parse@next\@dc@arguments +} + +\def\ArgumentCatcher@Scope +#1% the separator(s) +{\let\@dc@seQuence@shipout@@\@dc@seQuence@shipout + \let\@dc@seQuence@shipout\@dc@Scope@shipout + \ArgumentCatcher@Q{\global\relax}{\relax}% + \let\@dc@seQuence@shipout\@dc@seQuence@shipout@@ + \@dc@ignorearg + \ArgumentCatcher@T{#1}{\NoValue}% +} + +\@dc@AliasCatcher {PScope} \Scope + + +\long\def\gmuIfNoValueTF#1{% % \chgs{2008/12/1 v0.98 the \pk{xparse} tests for + % the presence of value redefined and much simplified (43 \CS'es + % less). Moreover, they are now fully expandable: \cmd\gmuIfNoValueTF, + % \cmd\gmuIfNoValueT, \cmd\gmuIfNoValueF, \cmd\gmuIfValueTF, \cmd\gmuIfValueT, + % \cmd\gmuIfValueF} + % + % \chgs{2010/05/27 v0.993 bug fix: order of \cmd\NoValue and + % \cs{@firstofmany} reversed after a catastrophal |{11}{11}| argument} + \@xa\ifx\@xa\NoValue\@firstofmany#1\@empty\@nil \afterfi\@firstoftwo + \else\afterfi\@secondoftwo + \fi} + +\long\def\gmuIfNoValueT#1#2{\gmuIfNoValueTF{#1}{#2}\@empty} + +\long\def\gmuIfNoValueF#1#2{\gmuIfNoValueTF{#1}\@empty{#2}} + +\long\def\gmuIfValueTF#1#2#3{\gmuIfNoValueTF{#1}{#3}{#2}} + +\long\def\gmuPutIfValue#1{\gmuIfValueT{#1}{#1}} + +\let\gmuIfValueT\gmuIfNoValueF + +\let\gmuIfValueF\gmuIfNoValueT + +\long\pdef\IfLong#1{%\ + % \begin{enumargs} + % \item the argument to check for |\par|, + % \item what if |\par| found, + % \item what if |\par| not found. + % \end{enumargs} + % + \edef\gmu@IfLong@resa{\detokenize{#1}}% + \edef\gmu@IfLong@resa{% + \IfAmong\string\par\@nx\among{\gmu@IfLong@resa}}% + \gmu@IfLong@resa} + + +\long\@namedef{ArgumentCatcher@=}% +#1% register used in the assignment +#2% the tail of args parser. +\@dc@arguments{% + \dc@DefParseNext{% + \@dc@addargum\NoValue % to make ignoring mechanism work + #2\@dc@arguments}% + \afterassignment\@dc@parse@next + #1}% optional space and |=| is left at user's discretion. In fact, + +\n@melet{ArgumentCatcher@P=}{ArgumentCatcher@=} + + +\long\def\ArgumentCatcher@gobblespace +{\ArgumentCatcher@T {\dc@gobblespace@dummy}{\NoValue}} + +\let\ArgumentCatcher@Pgobblespace\ArgumentCatcher@gobblespace + +\def\dc@gobblespace@dummy{\dc@gobblespace@dummy} + +\let\gobblespace\dc@gobblespace@dummy + + +\errorcontextlines=100 + +\long\def\@dc@InnerName#1{% + \bslash@or@ac{#1}% + \bslash +}% + +\long\def\@dc@InnerEndName #1{% version for the end-macros of environments + \bslash end\strip@bslash{#1}% +}% + +%% \CH{2010/07/26 v0.993 This strikingly simple idea of storing the +%% specifiers' sequence in a macro came to my head only after some +%% three years of developing \cmd\DeclareCommand} +\long\edef\@dc@SpecsArName#1{% + Specs \string& arity of + \@nx\bslash@or@ac{#1}% +}% + +\pdef\@dc@messages {% + \gmu@notif {@dc@quiet@}{}% + {% + \gmu@if {DCMessages}{}% + {\PackageInfo{gmcommand}{^^J% + Parsing arguments for \dc@innername^^J% + [specified as: + \unexpanded + \@xa\@xa\@xa \@xa\@xa\@xa \@xa{% + \@xa\@xa\@xa\@secondofmany + % + % not |\@secondofthree| because first use of this definition is for + % |\DeclareCommand| not having its specifiers' carrier. + % + \csname \@dc@specsname\endcsname {}{}\@nil }% + \space ]^^J% + [in file: \@currname.\@currext\space ]}% of info message + }% of if \ac DC messages + {}% of if not |DCMessages| + }% of if not |@dc@quiet@| + {}% of if not not |@dc@quiet@| +}% of |\@dc@messages| + + +\edefU\@dc@DCbody {% +{% \label{DC:final} % + % \chgs{2008/12/05 v0.98 added the \cs{@bsphack}---\cs{@esphack} option} + % \chgs{2008/12/07 v0.98 added the \env{Q\arg{tokens}} argument type + % (a~word over the alphabet \)} + \edef\dc@innername {\@dc@InnerName #1}% we'll use it in |K|-type arg.\ catcher and + \edef\@dc@specsname {\@dc@SpecsArName{#1}}% + \gmu@ifCSdefined {#1}% + {\gmu@if{DCMessages}{}% + {\PackageWarning{gmcommand}{% + ^^J% + Redefining command \dc@innername\space + with \string\DeclareCommand}% + }% + {}% + }% + {\gmu@if {DCMessages}{}% + {\PackageInfo{gmcommand}{^^J% + \string\DeclareCommand-ing \dc@innername\space (new)^^J}% + }% + {}% + }% + \@dc@alllong@false + \@dc@quiet@false + % + \emptify\@dc@Specs@tempa + % + \gmu@ifsbintersect{#2}{\long!lL}{% + \addtomacro\@dc@Specs@tempa{\long}% + \@dc@alllong@true}% + {}% + % + \gmu@ifsbintersect{#2}{.qQ\quiet}{% + \addtomacro\@dc@Specs@tempa{\quiet}% + \@dc@quiet@true}% + {}% + % + \gmu@ifsbintersect{#2}{iIwW\sphack}% + {% if `invisibility' is specified: \UnDef + \addtomacro\@dc@Specs@tempa{\sphack}% + \def\@dc@bsphack@{\@nx\@bsphack}% \UnDef + \def\@dc@esphack@{\@nx\@esphack}% + }% + {\emptify\@dc@bsphack@ + \emptify\@dc@esphack@}% if `invisibility' is not specified. + % + \gmu@ifsbany\envhack{#2}% + {% but if we define an environment: + \addtomacro\@dc@Specs@tempa{\envhack}% + \emptify\@dc@bsphack@ + \emptify\@dc@esphack@ + \edef\@dc@setThrowArgs{% + \dc@ThrowArgs{\string#1}}% if our command is used + }% + {% and if we don't define an environment: + \emptify\@dc@setThrowArgs + }% + % + \relaxen\@dc@global@ + \relaxen\@dc@outer@ + % + \gmu@ifsbany\outer{#2}% + {\addtomacro\@dc@Specs@tempa{\outer}% + \let\@dc@outer@\outer}% + {}% + % + \gmu@ifsbany\global{#2}{% + \addtomacro\@dc@Specs@tempa {\IAmDeclaredGlobally}% + \let\@dc@global@\global}% + {}% + % + \@xa\Name \@xa\edefU + \@xa\@dc@specsname + \@xa{\@xa{\@dc@Specs@tempa}}% + \@dc@ResetParseAuxilia + % + \@dc@ParseNextSpecifier #3% + \@dc@buckstopshere % it's the sentinel of parsing. Since the test + % + \@xa \Name \@xa \addtomacro \@xa \@dc@specsname + \@xa {\@xa{\the\@dc@ParsedSpecs}}% + % + \@xa\Name\@xa\addtomacro\@xa\@dc@specsname + \@xa{\@xa{\the \c@dc@argnum}}% + % + \@dc@outer@\@dc@global@ % possibly the prefixes, +%%%%% +%%%%%% Here comes the definition of the coating macro, named the +%%%%%% same as the command: + \protected\edef#1{% always |\protected| \balsmiley( ;-) + \@dc@bsphack@ % perhaps |\@bsphack| + % + \@dc@messages + % + \@nx\@dc@{\the\toks@}% in the braces appear the argument catchers. + \@xanxcs{\dc@innername}% + \ifx\@dc@outer@\outer + \@xanxcs{\@xa\gobble\string#1 }% note the blank + \else \@nx #1% + \fi + }% of main coating macro's |\edef|. \UnDef + % + \edef\gmu@DeclareCommand@resa{% + \@dc@global@ % perhaps |\global| + \long\def\@xanxcs{\@dc@InnerName{#1}}% for a~command + \@xau\@dc@innerhashes % it's |#1#2#3…| + {% the body of the inner ‘|\\⁄\|’ macro: + \@dc@setThrowArgs + \unexpanded{#4}% + \@dc@esphack@}% + }% of |\edef|. + \gmu@DeclareCommand@resa +}% of |\DeclareCommand|'s body. +} + +\def\@dc@DCprefixQlist{\global\protected\outer\long + \relax % for the somewhat perverse case when |\@dc@global| may be + !lL.qQiIwW\sphack\envhack} + +\long\def\ShowCommand #1{% + \@iwruJ + \@iwru{»\string#1« is »\meaning#1«}% + \@iwruJ + \@iwru{»\Name\string{\@dc@InnerName{#1}}« is + »\Name\meaning{\@dc@InnerName{#1}}«}% + \@iwruJ + \@iwru{»\Name\string{\@dc@SpecsArName{#1}}« is + »\Name\meaning{\@dc@SpecsArName{#1}}«}% + \@iwruJ + \show\show +} + +\@XA{\DeclareCommand\DeclareCommand % This is the final version by now.\ +{ + #1 >Pm % command to be defined (may be even \incs{par} if you + #2 >\@xa Q{\@dc@DCprefixQlist}{} %\ + #3 >Pm % arguments specification (may contain \incmd\par), + #4 >Pm % the definition body; may contain nearly anything including +}}\@dc@DCbody + + +\@XA{\DeclareCommand \DeclareCommand \long + {m >\@xa Q{\@dc@DCprefixQlist}{} mm}}% +\@dc@DCbody + + +\long\def\dc@EAName#1{% Env.\ arguments' toks' name + \if\bslash#1\else#1\fi's_args} + +\pdef\dc@ThrowArgs#1{% + \gmu@if{csname}{\dc@EAName{#1}\endcsname} + {}% if it's defined, we do nothing (we assume it's defined by us and + % is toks register.) + {% else we define it as a new toks + % \label{'s args} + \@xa\newtoks\csname\dc@EAName{#1}\endcsname + }% + \csname\dc@EAName{#1}\endcsname=% + \@xa\@xa\@xa{\@xa\@gobble\the\@dc@arguments}% +}% + + +\def\@dc@K@defaultrepl{##1} + +\DeclareCommand\@dc@define@K \long {mb}{% \label{K@parse} + % First we add the particular \CS to the toks register:\nostanza + \edef\gmu@tempa{% + \unexpanded{\toks@\@xa}% + {\@nx\the\toks@{% + \@xanxcs{\dc@innername @K\the\c@dc@catchernum}% + }% + }% + % here we add to the parsers toks list a \CS\ named + % |\⁄@K⁄| (the particular Knuthian catcher) + }\gmu@tempa + % and define this macro: \nostanza + \edef\gmu@tempa{% + % And now we define that particular Knuthian catcher. + \def\@xanxcs{\dc@innername @K\the\c@dc@catchernum}% + \gmu@if {@dc@xadefault@i@}{}% + {\@xau{#1}}% + {\unexpanded{#1}}% + {% + \@nx\@dc@addargum{{% + \gmuIfValueTF{#2}{% + \gmu@if{@dc@xadefault@ii@}{}% + {\@xau{#2}}% + {\unexpanded{#2}}% + }{\@xau{\@dc@K@defaultrepl}}% + }}% we add the Knuthian + % replacement to the toks register as \inhash n. + \@nx \@dc@parse@next \@dc@arguments + }% and continue parsing. + }% of |\edef|. Now we execute this temporary macro, which means we \incmd\def|\⁄@K⁄| + \@dc@global@ % set properly before |\@dc@ParseNextSpecifier #3⁄|. + \if P\@dc@long@letter\relax\long\fi + \gmu@tempa + % + \@dc@addtospecs {#1}% + % + \gmuIfValueTF{#2}{% + \gmu@if{@dc@xadefault@ii@}{}% + {\@xa\@dc@addtospecs\@xa{#2}}% + {\@dc@addtospecs{#2}}% + } + {\@xa\@dc@addtospecs\@xa{\@dc@K@defaultrepl}}% + % + % Now we clean up and continue construction of arguments parser. \nostanza + \@dc@ParseNextSpecifier +}% of |\@dc@define@K| + +\DeclareCommand\@dc@grab@Loop \long {% + #1 T{\any \none Uu\U \u Ǔǔ\Ǔ \ǔ Ww\W \w \lostwax} % the “sign” of matching for adding; use of + % the letters suppresses adding them to the + % parsed specifiers' list, which is crucial for + % |\SameAs| copying of specifiers: the “until” and “while” loops + % don't shift their arguments. + % + #2 >Pm % list of tokens to match for/against iteration + % + >i T{\drain \drop \Drain \Drop \lost \Lost} + #3 T{\any \none }{\any} % the “sign” of matching for draining + % + #4 b{} % list of drainers, empty by default + % + >i T{\count \ubound} + #5 D{\m@ne} % upper bound of iterations + % + >i T{\default \Default} + #6 b % default value (|\NoValue| by default) + % + #7 T{\eacher \Eacher \defEacher} % default is |\NoValue| and that's no + % harm since we test if |#7| == |\defEacher|. + #8 B{} % eacher, empty by default +}{% + % + \@dc@process@matchsign {#1} {##1}% + % + \dc@addtoParsed@{#2}% + % + \gmu@if {strings}{\lostwax#1}% + {\gmu@if {@dc@xadefault}{}% + {\@xa\edefU\@xa\@dc@LostWaxList\@xa{#2}}% + {\edefU\@dc@LostWaxList{#2}}% + }% + {}% + % + \@dc@process@matchsign {#3} {##3}% + % + \dc@addtoParsed@{#4}% + % + \@xa \@dc@addtospecs@bare \@xa{\the\numexpr #5}% + \@dc@addtotoks@bare{{#5}}% to ignore possible expandafter. + % + \dc@addtoParsed@ {#6}% + % + \gmu@if {strings}{\defEacher#7} + {% + \Name\def{\dc@innername/defdEacher/\the\c@dc@argnum}% + ##1{#8}% + % + \Name \dc@addtoParsed@ + {\dc@innername/defdEacher/\the\c@dc@argnum}% + } + {\gmu@if {@dc@xaeacher@}{} + {\@dc@xadefaulttrue}{\@dc@xadefaultfalse}% + \dc@addtoParsed@ {#8}% + }% + % + \gmu@if {strings}{\lostwax#1} + {\grab@LostWax} + {\@dc@ParseNextSpecifier}% +} + +\DeclareCommand\grab@LostWax { + >iT{\lost \Lost} + #1 b{\lostwax@NoVal} + >iT {\count \ubound} + #2 D{1} + >iT{\endlost \EndLost} +}{% + % We build an ignored “while” catcher. + % + \def\@dc@LostWaxA{>iw}% + % + \gmu@ifdetokens {\lostwax@NoVal}{#1} + {% + % if no particular value of the “lost wax” is provided, we assume + % the same as the “until” delimiter(s). + % + \prependtomacro\@dc@LostWaxA{>\@xa}% + \addtomacro\@dc@LostWaxA{\@dc@LostWaxList}% + }% + % + % Otherwise first we check whether “lost wax” provided has nonempty + % intersection with the “until” delimiters. + {% + \@xa\gmu@ifstrintersect + \@xa{\@dc@LostWaxList}{#1} + {\addtomacro\@dc@LostWaxA{{#1}}}% + {\PackageError{gmutils/gmcommand}{^^J% + You try to declare a "Lost Wax" catcher^^J% + with the "Lost" list disjoint with the "Until" list.^^J% + I assume sum of them}% + {}% + % + \@xa \addtomacro\@xa\@dc@LostWaxA + \@xa{\@xa{\@dc@LostWaxList #1}}% + }% + }% + % + \addtomacro\@dc@LostWaxA{ \count #2 \relax}% + % + \@xa\@dc@ParseNextSpecifier \@dc@LostWaxA +}% of |\grab@LostWax|. + +\def\@dc@process@matchsign +#1% the argument +#2% its numeral in human language (for the error message) +{% + \gmu@CASE {strings} {{#1}\any } + {\@dc@addtoParsed@bare {\any }}% + % + \gmu@CASEsbany {#1} {Ww} + {\@dc@addtotoks@bare {\any}}% + % + \gmu@CASE {strings} {{#1}\none} + {\@dc@addtoParsed@bare {\none }}% + % + \gmu@CASEsbany {#1} {UuǓǔ\lostwax } + {\@dc@addtotoks@bare {\none }}% + % + \gmu@lastCASE + {\PackageError{gmcommand}{% + You *have* to declare »\string\any« or »\string\none« ^^J% + as the #2 argument for the »\string\loop« catcher}{}% + }% + \gmu@ESAC +} + +\long\pdef\UnDeclareCommand#1{% + \let#1\@undefined + \ifcsname\@dc@InnerName{#1}\endcsname + \n@melet{\@dc@InnerName{#1}}{@undefined}% + \fi + \ifcsname\@dc@SpecsArName{#1}\endcsname + \n@melet{\@dc@SpecsArName{#1}}{@undefined}% + \fi +} + + +\edef\gmu@tempa{% + \def\@nx\gmu@ifHashless@##1% + \detokenize{macro:}##2->##3\@nx\@nil}% +\gmu@tempa +{\gmu@if {}{\gmu@ifempty{#2}{1}{0}\gmu@ifempty{#3}{2}{1}}} + +\long\edef\gmu@ifHashlessMacro +#1% a \CS, name or active char +{% + \edef\@nx\gmu@WHL@arg{\@nx\@xanxtri{#1}}% + \unexpanded{\@xa\@xa\@xa\gmu@ifHashless@ + \@xa\meaning\gmu@WHL@arg}% + \relax % to ensure that |#3| of |\gmu@ifHashless@| is nonempty + % if match for the delimiters is found earlier + \detokenize{macro:***->}\@nx\@nil % the sentinels +} + +\long\def\gmu@ifDeclared#1{% + % \begin{enumargs} + % \item a \CS or csname or an active char, + % \item true branch, + % \item false branch % + % \end{enumargs} + \let\gmu@ifDe@next\@secondoftwo + % + % + \gmu@CASEnot {csname} {\@dc@SpecsArName{#1}\endcsname}% + {}% + % + \gmu@CASEnot {csname}{\@dc@InnerName{#1}\endcsname}% + {}% + % + \gmu@EatCases + {\gmu@ifHashlessMacro{#1}% + {\edef\gmu@ifDe@resa{% + \@nx\gmu@ifxany\@xanxcs{\@dc@InnerName{#1}}% + {\unexpanded\@xa\@xa\@xa{\gmu@WHL@arg}}% + % Above: to get the contents of the outer macro we use the macro + % carrying conversion of possible name into a \CS and expand + % it twice. Then we freeze it with |\unexpanded|. + {\let\@nx\gmu@ifDe@next\@nx\@firstoftwo}% if the inner macro + % is present in the + % contents of |#1|, we take the first implicit argument + {}% otherwise we do nothing (taking the second implicit is + % already set) + }% of edef + \gmu@ifDe@resa + }% of if a hashless macro + {}% of if not a hasless macro + }% + % + \gmu@ESAC + \gmu@ifDe@next +}% of |\gmu@ifDeclared| + +\long\def\@dc@SameAs#1{% + \gmu@ifDeclared {#1}% + {% + \@xa\@xa\@xa \@xa\@xa\@xa \@xa + \@dc@ParseNextSpecifier + \@xa\@xa\@xa \@secondofthree + \csname \@dc@SpecsArName{#1}\endcsname + }% + {% + \PackageError{gmcommand}{% + Command \@nx#1 ^^J% + is not declared with \DeclareCommand. ^^J% + I can't repeat its parameters in current command declaration}% + {}% + }% +}% of |\@dc@SameAs| + +\DeclareCommand\DCUse{ + #1 >Pm % the command +}{% ^^A with star we automatically pass the + \gmu@ifDeclared{#1}% + {% + \@dc@arguments\@xa{\@xa + \csname \@dc@InnerName{#1}\endcsname + }% + % + \csname ArgumentCatcher@Pm@\romannumeral + \@xa \@xa \@xa \@thirdofthree + \csname \@dc@SpecsArName{#1}\endcsname % of arity carrier + \endcsname % of the catcher + }% + {\DC@EndNotDeclaredErr{#1}}% +}% + +\pdef \DC@EndNotDeclaredErr #1{% + \PackageError{gmcommand}{% + Command \bslash end\strip@bslash{#1} ^^J% + is not declared with \DeclareCommand. ^^J% + Therefore I can't use its DC-inner macro (because of its nonexistence).^^J}% + {}% +} + +\DeclareCommand\DCUseEnd{ + #1 >Pm % the command (without “end”) +}{% + \gmu@ifDeclared{end\strip@bslash{#1}}% + {% + \@dc@arguments\@xa{\@xa + \csname \@dc@InnerEndName{#1}\endcsname + }% + % + \csname ArgumentCatcher@Pm@\romannumeral + \@xa \@xa \@xa \@thirdofthree + \csname \@dc@SpecsArName{#1}\endcsname % of arity carrier + \endcsname % of the catcher + }% + {\DC@EndNotDeclaredErr{#1}}% +}% + + +\DeclareCommand\DeclareEnvironment \long +{ + #1--#4 \SameAs \DeclareCommand + % We repeat the specifiers, but the role of |#4| is slightly + % different here: here it's the |\begin| part definition. + % + #5 m % the end definition; it \emph{can} contain any + % \inverb|#|\---the arguments of the environment are passed + % to it, too. +}{% + \def\gmu@DeclareEnvironment@resa{\envhack}% we add the information we define an + % environment. + \gmuIfValueT{#2}% + {\addtomacro\gmu@DeclareEnvironment@resa{#2}}% we pass all the ‘prefixes’ to + % \incs{Decl\+are\+Comm\+and} + % \stanza + \@xa\DeclareCommand\csname#1\@xa\endcsname + \gmu@DeclareEnvironment@resa{#3}{#4}% + % + %\nostanza Now the begin definition is done. Let's get down to the + %end definition. \nostanza + % + \let\@dc@env@endglobal=\@dc@global@ % note this \CS was for sure redefined by the last + % \incs{Decl\+are\+Com\+m\+and} (and by nothing else) and that's + % exactly what we want. + \edef\gmu@DeclareEnvironment@resb{% + \@nx\@xa + \@xanxcs{\bslash end#1}% + \@nx\the + \@xanxcs{\dc@EAName{#1}}% + }% of |\edef|. It reuslts in + % \[|\@xa \\end⁄ \the\\⁄'s_args|\] + % which does not collide with the inner macro of the |\end›…| + % command, since the latter is |\\end›…\|. +\gmu@if{csname}{\dc@EAName{#1}\endcsname}{\gmu@namelet\global{\dc@EAName{#1}}{@undefined}}{}% + \edef\gmu@DeclareEnvironment@resa{% \UnDef + \@dc@global@\long\def % the inner end macro is always \incmd\long\ + % and perhaps defined \incmd\global ly. + \@xanxcs{\bslash end#1}% + \@xau\@dc@innerhashes % it's |#1#2#3›…|---the inner end macro takes the + % same number of parameters as the begin macro. + {% the definition body + \unexpanded{#5}}% + }% of |\edef›…@resa|. + \gmu@DeclareEnvironment@resa + \edef\gmu@DeclareEnvironment@resc{% + \DeclareCommand\@xanxcs{end#1}% + \@dc@env@endglobal + {}% no parameters + {\@xau {\gmu@DeclareEnvironment@resb + \@ignoretrue}% + }% + }% + \gmu@DeclareEnvironment@resc + % + % +}% of |\DeclareEnvironment| + +\DeclareCommand\NewCommand +{\SameAs\DeclareCommand} +{% + \gmu@ifCSdefined {#1} + {\DCUse\DeclareCommand#1{#2}{#3}{#4}}% + {\PackageError{gmcommand}% + {Command \@nx#1 already defined \on@line!}% + {}% + }% +} + +\DeclareCommand\RenewCommand +{\SameAs\DeclareCommand} +{% + \gmu@ifCSdefined {#1} + {\DCUse\DeclareCommand#1{#2}{#3}{#4}}% + {\PackageError{gmcommand}% + {Command \@nx#1 not yet defined \on@line!}% + {}% + }% +} + +\DeclareCommand\ProvideCommand +{\SameAs\DeclareCommand} +{% + \gmu@ifCSdefined {#1} + {} + {\DCUse\DeclareCommand#1{#2}{#3}{#4}}% +} + +\DeclareCommand\NewEnvironment +{\SameAs\DeclareEnvironment} +{% + \gmu@ifdefined{#1} + {\DCUse\DeclareEnvironment{#1}{#2}{#3}{#4}{#5}}% + {\PackageError{gmcommand} + {Environment #1 already defined \on@line!}{}% + }% +} + +\DeclareCommand\RenewEnvironment +{\SameAs\DeclareEnvironment} +{% + \gmu@ifdefined {#1} + {\DCUse\DeclareEnvironment{#1}{#2}{#3}{#4}{#5}}% + {\PackageError{gmcommand} + {Environment #1 not yet defined \on@line!}{}% + }% +} + + +\DeclareCommand\XeTeXthree{o}{% \ + % \changes{v0.90}{2008/8/4}{adjusted + % to the redefinition of + % \cs{verb} in \pk{xlxtra} 2008/07/29} + \@ifXeTeX{% + \gmuIfValueT{#1}{\PassOptionsToPackage{#1}{fontspec}}% + \@ifpackageloaded{gmverb}% + {% + \Store@Macro\verb + \StoreEnvironment{verbatim}% + \StoreEnvironment{verbatim*}% + }{}% + \RequirePackage{xltxtra}% since v 0.4 (2008/07/29) this package + % redefines |\verb| and \env{verbatim*}, + % and quite elegantly provides an option + % to suppress the redefinitions, but + % unfortunately that option excludes also + % a~nice definition of |\xxt@visiblespace| + % which I~fancy. + \@ifpackageloaded{gmverb}% + {% + \Restore@Macro\verb + \RestoreEnvironment{verbatim}% + \RestoreEnvironment{verbatim*}% + }{}% + % + \AtBeginDocument{% + \@ifpackageloaded{gmlogos}{% + \Restore@Macro\LaTeX\Restore@MacroSt{LaTeX }% my version of the + % \LaTeX\ logo has been stored just + % after defining, in line \ref{SMLaTeX}. \ilrr + \Restore@Macro\eTeX}% + {}% + }% + % \stanza + \pdef\adddefaultfontfeatures##1{% + \addtomacro\zf@default@options{#1,}} + }% of |\@ifXeTeX|'s first argument, + {}% |\@ifXeTeX|'s second argument, +}% of |\XeTeXthree|'s body. + +\DeclareCommand\setspaceskip{% + A{1}% optional factor for all three components + O{\fontdimen2\font}% + >is + O{\fontdimen3\font}% + >is + O{\fontdimen4\font}} +{\spaceskip=\glueexpr\dimexpr#2*#1\relax plus\dimexpr #3*#1\relax + minus\dimexpr#4*#1\relax\relax} + +\pdef\unsetspaceskip{% + \spaceskip=\z@skip +} + +\def\makestarlow{% + \begingroup\lccode`\~=`\*\lowercase{%% \Define** + \endgroup\def~{\gmu@lowstar}}% 2009/10/19 |\let| changed to + % \inverb|\def| to allow redefinitions of \incmd\gmu@lowstar. + \catcode`\*=\active + \defLowStarFake +} + +\DeclareCommand\defLowStarFake{% + Q{+-0123456789,.}{0,5}% fraction of fontchar depth of the star glyph +}% +{% + \def\gmu@lowstarfake{% + \leavevmode\vbox{\hbox{*}\kern#1\fontchardp\font`*}% + }% +} + +\def\gmu@lowstarfake{*} % useful for next command where normal star is + +\DeclareCommand\enoughpage{% + #1 D{\NoValue} % (optional short version (number of + % |\baselineskip|s)) Before 2010/9/10 the default + % value was the |D|-default, i.e., 0, which lead to + % improper working of this command. + #2 B{2\baselineskip}% (2) optional (formerly mandatory) long version of + % required room on a page + >is + #3 >PB{} % (3) what if the room is enough + >is + #4 >PB{\newpage} % (4) what if there's to little room on a page +}{% + % \chgs{2009/03/18 v0.98 made \eTeX-ish} + % \chgs{2009/05/25 v0.98 made ifthenelse-like with ‘then’ and ‘else’ + % optional default \ and \cmd\newpage resp.} + % \chgs{2009/10/21 v0.98 \cmd\par\ removed since to let it be used + % for \cmd\pagebreak\ inside a paragraph} + \gmu@if {num} + {\numexpr + \ifdim + % if the space left is less than we wish then 1, otherwise 0. + \gmu@pageremain + <% + \dimexpr + (\gmuIfValueTF{#1}{#1\baselineskip}{#2})*1% + \endexpr + % + % \CH{2010/06/28 v0.993 I added |(›…)*1| to assure that |\relax| + % really delimits the dimexpr} + % + 1\else 0% + \fi + *% + \ifdim \gmu@pageremain >-1sp + 1% if the room left on current page is nonnegative, + % then we indeed are on current page so “enough” and + % “not enough” does make sense: Enough is enough. + \else 0% otherwise we are on next page (or further) and assume + % there is enough room for our purpose. + \fi + *% + \ifdim \pagegoal <\maxdimen + 1 % if there are some boxes on current page, so checking room + % does make sense. + \else 0% otherwise (no boxes on current page) assume there's + % enough room + \fi + >\z@ + }% of condition + {\typeout{@@@@@ not enough page \on@line}% + #4% + }% + {#3}% +} + +\long\def\gmu@LC@LetInners +#1% scope prefix (|\global| or |\relax| +#2% left side +#3% right side of the assignment +{% + \edef\gmu@LC@InnerLeft{\@dc@InnerName{#2}}% + \edef\gmu@LC@InnerRight{\@dc@InnerName{#3}}% + % + \gmu@namelet{#1}{\gmu@LC@InnerLeft}{\gmu@LC@InnerRight}% + \edef\gmu@LC@InnerLeft{\@dc@SpecsArName{#2}}% + \edef\gmu@LC@InnerRight{\@dc@SpecsArName{#3}}% + % + \gmu@namelet{#1}{\gmu@LC@InnerLeft}{\gmu@LC@InnerRight}% +} + +\long\def\gmu@CL@PrepareArg +#1% left/right +#2% |\@xa| or |\edef|, maybe sth.\ more in the future +#3% a \CS, text of a name or an active char +{% + \Name\let{gmu@CL@#1}\@undefined + \ifx\@xa#2\Name\edef{gmu@CL@#1}{\@xau{#3}}\fi + \ifx\edef#2\Name\edef{gmu@CL@#1}{#3}\fi + \unless\ifcsname gmu@CL@#1\endcsname + \Name\edef{gmu@CL@#1}{% + \gmu@if{cat}{\@nx~\@nx#3}% + {\@nx#3}{\strip@bslash{#3}}% + }% + \fi +} + +\DeclareCommand\CommandLet \long {% + \Scope % (1) + T{\@xa\edef} % (2) whether left side should be |\expandaftered| + m % (3) left side of assignment + >iT{=} % pro forma + T{\@xa\edef} % (4) whether right side should be |\expandaftered| + m % (5) right side of the asssignment +}{% + % + \gmu@CL@PrepareArg{left}#2{#3}% + \gmu@CL@PrepareArg{right}#4{#5}% + % + \@xa\gmu@ifDeclared\@xa{\gmu@CL@right}{% + \edef\gmu@LC@resa{% + \DeclareCommand % + \@xa\@xanxtri\@xa{\gmu@CL@left}% + #1% scope prefix + {\@nx\SameAs\@xa\@xanxtri\@xa{\gmu@CL@right}}% args. spec + {}% the body of the command will be |\let| via letting inners. + }% + % + \gmu@LC@resa + \@XA{\@xa\gmu@LC@LetInners\@xa#1% + \@xa{\gmu@CL@left}}\@xa{\gmu@CL@right}% + }% of if Declared + {% if not Declared, we just |\let|: +\if\@nx#3ѥ\typeout{@@@@@ »\@xa\@dc@InnerName\@xa{\gmu@CL@right}« is not + Declared?: \Name\meaning{\@xa\@dc@InnerName\@xa{\gmu@CL@right}}% +}% +\show\NotDeclared +\fi + \@XA{\@xa\tri@let\@xa#1% + \@xa{\gmu@CL@left}}\@xa{\gmu@CL@right}% + }% +} + +\DeclareCommand\envirlet \long{\Scope mm}{% for |\let|ting environments. + \CommandLet #1{#2}{#3}% + \CommandLet #1{end#2}{end#3}% +} + +\DeclareCommand\@fornum{% + m% (1) initial (least) num. value + m% (2) limit (last iterated over) num. value + O{1}% (3) step of iteration + m% (4) body of the loop +}% +{\edef\gmu@fornum@min{\the\numexpr #1}% + \edef\gmu@fornum@lim{\the\numexpr #2}% + \let\gmu@fornum@curr\gmu@fornum@min + \@whilenum\gmu@fornum@curr<\gmu@fornum@lim + \do{#4% + \edef\gmu@fornum@curr{% + \the\numexpr\gmu@fornum@curr+#3}% + }% of |\@whilenum|'s body. +}% of |\@fornum|. + +\pdef\StoreCommand{% + \begingroup + %\label{SC begr} + \MakePrivateLetters + \@StoreCommand +} + +\long\def\gmu@SC@StorageName +#1% a \CS, name or active char +#2% group level +{% + \gmu@storeprefix/% + \ifnum\numexpr#2>-1 \the\numexpr(#2)*1\relax\fi + \bslash@or@ac {#1}% +}% + +\def\gmu@SC@setgrouplevel +#1% |+›⁄|-⁄|\NoValue| +#2% a decimal number +{\edef\gmu@SC@grouplevel{% + \the\numexpr + \gmuIfValueTF{#1}% + {\currentgrouplevel#1#2+1}{#2}% + }% of the grouplevel-carrying macro +} + +\DeclareCommand\@StoreCommand +{% + #1 T{+-}% grouplevel shift indicator + #2 d % group level or shift (the latter relative to the current g.l.) + #3 >Pm% name or \CS +}{% + \endgroup %we close the group opened in line \ref{SC begr}. + \gmu@SC@setgrouplevel{#1}{#2}% + % + \edef\gmu@SC@resa{% + \gmu@SC@StorageName{#3}{\gmu@SC@grouplevel}}% + % + \let\gmu@SC@scope\relax + \ifnum\gmu@SC@grouplevel>\currentgrouplevel + \let\gmu@SC@scope\global + \fi + \@xa\CommandLet\@xa\gmu@SC@scope\@xa{\gmu@SC@resa}{#3}% +} + +\pdef\StoreEnvironment{% + \begingroup + \MakePrivateLetters + \@StoreEnvironment +} + +\def\@StoreEnvironment#1{% + \@StoreCommand{#1}% + \begingroup + \@StoreCommand{end#1}% +} + +\pdef\RestoreEnvironment{% + \begingroup + \MakePrivateLetters + \@RestoreEnvironment +} + +\def\@RestoreEnvironment#1{% + \endgroup + \RestoreCommand{#1}% + \RestoreCommand{end#1}% +} + +\pdef\UseStored{% + \begingroup + \MakePrivateLetters + \@UseStored} + + +\DeclareCommand\@UseStored \long{% + #1 T{+-}% (1) indicator of grouplevel shift (in distiction from an absolute + % group level) + #2 d % (2) optional grouplevel or shift (0 by default) + #3 O{\@gobble}% (3) stuff to be put before the |#4| \CS, e.g., an + #4 m % (4) a \CS or csname to be taken from the storage liquid +}{% \chgs{2010/06/23 v0.993 added} + \endgroup + \gmu@SC@setgrouplevel{#1}{#2}% + \edef\gmu@SC@grouplevel{% + \the\numexpr\gmu@SC@grouplevel+1}% for the first turn of loop + % + \loop + \edef\gmu@SC@grouplevel{% + % we decrease the group level number + \the\numexpr\gmu@SC@grouplevel-1}% + % + \edef\gmu@SC@currname{% + % define the cs' storage name for that level + \gmu@SC@StorageName{#4}{\gmu@SC@grouplevel}}% + \ifnum + % and check the conjunction of conditions: the group level is >=-1… + \unless\ifnum\gmu@SC@grouplevel<-1 1\else 0\fi + % and the csname remains not defined. + \unless\ifcsname \gmu@SC@currname \endcsname 1\else 0\fi + =11 + \repeat + \gmu@if{csname}{\gmu@SC@currname\endcsname}% + {% + % ^^A \s how\ExecutingTrueBranch + \@XA{#3{#4}}\csname \gmu@SC@currname\endcsname}% first + {% + % ^^A \s how\ExecutingFalseBranch + #3{#4}\@undefined}% second +}% of |\@UseStored| + +\DeclareCommand\RestoreCommand{\Scope d}{% + \UseStored #2[\CommandLet #1*]% +} + + +\newbox\gmu@smashbox + +\DeclareCommand\set@smashbox{% + \Scope + T{hv}{h} +}{#1\setbox\gmu@smashbox =\csname #2box\endcsname }% + +\def\smash@box{\smash{\box\gmu@smashbox}} + + +\newbox\gmu@boxA +\newbox\gmu@boxB +\newdimen\gmu@dima +\newdimen\gmu@dimb + +\DeclareCommand\gmu@extremebox { + #1 m % a dimen register (will be assigned the extr.\ value) or a + % \CS (will be defined as |\the| extreme value) + #2 T {\min\max}{\max} % kind of extreme + #3 T {\wd\ht\dp\totalheight}{\wd} % dimension to compare, the last two for total |\ht|+|\dp|. + #4 \lostwax {\global\relax} \eacher{\gmu@dimextreme@step} \lost{\relax} + #5 T{\global}{} % scope of assignment +}{% + \gmu@if x {\max#2} + {\gmu@dimb=-\maxdimen + \def\gmu@dimextreme@comp{<}% + } + {\gmu@dimb=\maxdimen + \def\gmu@dimextreme@comp{>}% + }% + % + \long \def\gmu@dimextreme@step ##1{% + \setbox\gmu@boxA=\hbox{##1}% + % + \gmu@dima= \gmu@if x {\totalheight#3} + {\dimexpr \ht\gmu@boxA +\dp\gmu@boxA\relax} + {#3\gmu@boxA}% + \relax + % + \gmu@if {dim} + {\gmu@dimb\gmu@dimextreme@comp \gmu@dima } + {\gmu@if {dim} {\gmu@dima>\z@} + {\gmu@dimb=\gmu@dima } + {}% + } + {}% + % + }% + % + #4% + \IfIs #1\dimen + {#5#1=\gmu@dimb} + {#5\edef #1{\the\gmu@dimb }}% +}% + +\pdef\gmu@getht +#1% box register +#2% dimen (or glue) register to assign the (substitute) height to +{% + \setbox\gmu@boxA=\copy#1\relax + \ifvbox\gmu@boxA + \vbadness@M + \setbox\gmu@boxB=\vsplit\gmu@boxA to \maxdimen + \vbadness@Restore + % + % chcemy rzeczywiście pomierzyć, a nie być może odrzucić odstępy, + % kerny i grzywny. + \setbox\gmu@boxB=\vbox{\splitdiscards }% + \ifdim \ht\gmu@boxB >\z@ + \setbox \gmu@boxA=\vbox{ + \unvbox\gmu@boxB + \unvbox\gmu@boxA + }% + \fi + \else + \setbox\gmu@boxA=\box\voidb@x + \fi + % + \ifvoid\gmu@boxA + #2=\ht#1\relax + \else + #2=\maxdimen + \fi +}% of |\gmu@getht| + + + +\DeclareCommand\enlargefsize{ + #1 m % enlargement (dim(expr)) for font size + #2 b % enlargement (dim(expr)) for baselineskip (if absent, |#1| is used) +}{\edef\gmu@tempa{% + \@nx\fontsize{\the\dimexpr\f@size pt+#1}% + {\the\dimexpr 1\baselineskip+ \gmuIfValueTF{#2}{#2}{#1}}% + }\gmu@tempa\selectfont +} + +\DeclareCommand\scalefsize { + #1 m % scale for font size + #2 b % scale for baselineskip (if absent, |#1| is used) + \gobblespace +}{\edef\gmu@tempa{% + \@nx\fontsize{\the\dimexpr #1\dimexpr\f@size pt\relax}% + {\the\dimexpr \gmuIfValueTF{#2}{#2}{#1}\baselineskip}% + }\gmu@tempa\selectfont +} + +\let\gmu@discretionaryhyphen\- % for the cases when we don't redefine + % \incs\- but use \incs\UrlFix + +\DeclareCommand\bihyphen{ + O{*} % token that'll make the discretionary hyphen |\-| allow other break-points +}{% + \DeclareCommand\gmu@discretionaryhyphen{% + T{#1}% + G{&&}% + a + }{% + \gmuIfValueT{##2}{% + \gmu@ifempty{##2}{}{% + \def\gmu@bihyphen@char{##2}}% + }% + \gmuIfValueT{##3}{% + \gmu@ifempty{##3}{}{% + \def\gmu@bihyphen@corr{##3}}% + }% + % + % Depending on |#1| we allow (if present, then we take |\discre|) + % hyphenation of the word's before- and + % after-parts or forbid it (if absent, then we take + % |\discretionary|). + \gmuIfValueTF{##1}\discre\discretionary + {% before break + \gmuIfValueTF{##2} + {% + \gmu@ifempty{##2}{\gmu@bihyphen@char}{##2}% + }% + {% + \ifnum\hyphenchar\font>\z@ + \char\hyphenchar\font + \fi}% + }% end of before break + {%after break + \gmuIfValueT{##3}{% + \gmu@ifempty{##3}{\gmu@bihyphen@corr}{##3}% + }% + }% + {% without break + }% almost as in \TB: unlike \TB, we allow hyphenchars + % $\ge255$ as we are \XeTeX. + }% of |\DeclareCommand\-| + \gmu@storeifnotyet\-% original |\-| is a~\TeX's + % primitive, therefore we should store it. + \CommandLet\-\gmu@discretionaryhyphen + \CommandLet\@dischyph\gmu@discretionaryhyphen % to override + % \pk{framed.sty} + \pdef\gmu@flexhyphen{\gmu@discretionaryhyphen#1\relax}% +}% of |\bihyphen| + +\relaxen\gmu@bihyphen@corr + +\@ifXeTeX{% + \DeclareCommand\gmshowlists { + >iT{\depth} + Ď{1}% + >iT{\breadth} + Ď{10000000} + }% +}{% not in \XeTeX\ we use legacy |D| arg.\ specifiers: + \DeclareCommand\gmshowlists { + >iT{\depth} + D{1}% + >iT{\breadth} + D{10000000} + }% +} +{\tracingonline=\@ne + \showboxdepth=#1\relax % how many levels of + % box nesting should be shown + \showboxbreadth=#2\relax % after how many elements »etc.« will be put + \showlists +} + +\DeclareCommand\gmtracingoutput { + \SameAs\gmshowlists +} +{\tracingonline=\@ne + \tracingoutput=\@ne + \showboxdepth=#1\relax % how many levels of + % box nesting should be shown + \showboxbreadth=#2\relax % after how many elements »etc.« will be put +} + + +\newcount\c@FiBreakPenalty + +\DeclareCommand \AllowFiBreak {% + % The defaults are as in DEK's |\filbreak|. + Q{l}{l} + = {\c@FiBreakPenalty } +} +{% + \penalty\@M + \csname vfi#1\endcsname + \penalty \c@FiBreakPenalty + \csname vfi#1neg\endcsname +} + + +\DeclareCommand \IgnorePars {m Q{\par}} {#1} + +\DeclareCommand\putpenalty {=} +{% + \gmu@iflastglue + {\@tempskipa=\lastskip + \mode@skip -\@tempskipa + \penalty \@tempcnta + \mode@skip \@tempskipa + }% + {\gmu@iflastkern + {\@temdima=\lastkern + \kern-\@temdima + \penalty \@tempcnta + \kern \@temdima + } + {% + \penalty\@tempcnta + }% + }% +} + +\newskip \gmu@TrashSkip + +\pdef \mode@skip {% + \ifvmode \vskip + \else + \ifhmode \hskip + \else + \ifmmode \mskip + \else + \gmu@TrashSkip + \fi + \fi + \fi +} + + +\endinput +%% +%% End of file `gmcommand.sty'. -- cgit v1.2.3