summaryrefslogtreecommitdiff
path: root/macros/generic/dowith/dowith.sty
blob: a4625aade3965201cfee3ea3ae8b423f29d55f04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
\def\filename{dowith}     \def\fileinfo{simple list loop (UL)}
\def\filedate{2012/11/05} \def\fileversion{v0.3}
%%
%% Copyright (C) 2011 2012 Uwe Lueck,
%% http://www.contact-ednotes.sty.de.vu
%% -- author-maintained in the sense of LPPL below --
%%
%% This file can be redistributed and/or modified under
%% the terms of the LaTeX Project Public License; either
%% version 1.3c of the License, or any later version.
%% The latest version of this license is in
%%     http://www.latex-project.org/lppl.txt
%% We did our best to help you, but there is NO WARRANTY.
%%
%% Please report bugs, problems, and suggestions via
%%
%%   http://www.contact-ednotes.sty.de.vu
%%
%% == Proceeding without \LaTeX ==
%% v0.3 mainly replaces imitating the 
%% \CtanPkgRef{german}{german.sty} approach to genericity 
%% by \ctanpkgref{plainpkg}:
\input plainpkg
\ProvidesPackage{\filename}[\filedate\space 
                 \fileversion\space \fileinfo]
\PushCatMakeLetterAt
%% If \LaTeX\ is not present ... 
\ifltx \else
%% ... an old version of its `\in@' is introduced. 
%% It is bad as a subword test 
%% (false positive cases, cf. \CtanPkgRef{nicetext}{fifinddo} 
%%  documentation), but 'dowith' will check for single tokens only. 
%% If \LaTeX\ \emph{is} present, 
%% on the other hand, `\ifin@' is recognized while skipping 
%% `false' parts of conditionals, without being matched 
%% by some `\fi' before the next `\else', so I hide it by `\csname':
  \expandafter\newif\csname ifin@\endcsname
  \def\in@#1#2{%
    \def\in@@##1#1##2##3\in@@{%
      \ifx\in@##2\in@false\else\in@true\fi}%
    \in@@#2#1\in@\in@@}
\fi
%% 
%% == Applying a Command ==                             %% 2011/11/07
%% \label{sec:apply}
%% === Core ===
%% \label{sec:core}
%% |\DoWith{<cmd>}<list>\StopDoing| applies <cmd> to all elements 
%% of <list>. An element of <list> (after tokenizing) 
%% may be either a single token or a group `{<balanced>}'.
\def\DoWith#1#2{%
    \ifx\StopDoing#2\empty
%% The previous `\empty' (replacing `%') is a bug fix as of v0.22 
%% (June 2012),                                             %% 2012/11/05
%% while in my extension draft I already had it in January 2012. 
%% It allows ``empty" arglist items \qtd{\lbtok\rbtok}. 
%% Before v0.22, such an empty brace group would have resulted 
%% in comparing `\StopDoing' with `\else', so \qtd{\lbtok\rbtok}
%% would have had the same effect as `\StopDoing', the token text 
%% after `\else' until `\fi' would have been skipped. 
%% Instead, the user may have a reason to allow empty arguments\slash
%% brace groups.
        \else#1{#2}\expandafter\DoWith\expandafter#1\fi}
%% |\StopDoing| delimits the list: 
\let\StopDoing\DoWith
%% ... something arbitrary that is not expected to occur in a list.
%% With \[`\let\StopDoing*'\] instead, the star would end lists.
%%
%% |\DoWithAllOf{<cmd>}{<list>}| works like 
%% \[`\DoWith{<cmd>}<list>\StopDoing':\]
\def\DoWithAllOf#1#2{\DoWith#1#2\StopDoing}
%% 
%% === `&\do' being the Command ===
%% \label{sec:do}
%% When the <list> is worked at a single time in the \TeX\ run 
%% where assignments are possible, instead of introducing a new 
%% macro name for <cmd> you can use `\do' for <cmd> as a 
%% ``temporary" macro and define it right before 
%% \[`\DoWith{\do}<list>\StopDoing'\] 
%% However, we provide \[|\DoDoWith{<cmd>}<list>\StopDoing|\] 
%% as a substitute for the former line that at least saves one token. 
%% For the definition of `\do', we provide
%% |\setdo{<def-text>}|.
%% It works similarly to \[`\renewcommand{\do}[1]{<def-text>}',\] 
%% so <def-text> should contain a `#1': 
\def\setdo{\long\def\do##1}
%% With |\letdo<cmd>| that is provided next where <cmd> is defined 
%% elsewhere, you could type 
%% \[`\letdo<cmd>\DoDoWith<list>\StopDoing'\]
%% It seems to me, however, that you better type 
%% \[`\dowith<cmd><list>\StopDoing'\] instead. 
%% So I provide `\letdo' although I consider it useless here. 
%% It is provided somewhat for the sake of ``completeness," 
%% thinking that it might be useful at other occasions such as 
%% preceding `\dospecials'.
\def\letdo{\let\do}
%% |\DoDoWith| has been described above:
\def\DoDoWith{\DoWith\do}
%% By analogy to `\DoWithAllOf', we provide 
%% |\DoDoWithAllOf{<list>}|:
\def\DoDoWithAllOf{\DoWithAllOf\do}
%%
%% === Expand List Macro ===
%% The former facilities may be quite useless
%% as such a <list> will not be typed at a single place in the 
%% source code, rather the items to run <cmd> on may be collected 
%% occasionally when some routines run. The elements may be collected 
%% in a macro <list-macro> expanding to <list>. 
%% So we provide \[|\DoWithAllIn{<cmd>}{<list-macro>}|\]
%% (or `\DoWithAllIn<cmd><list-macro>').
%% There is no need to type `\StopDoing' here:
\def\DoWithAllIn#1#2{%
    \expandafter\DoWith\expandafter#1#2\StopDoing}
%% |\DoDoWithAllIn{<list-macro>}| saves a backslash or token 
%% for `\do' as above in Sec.~\ref{sec:do}:
\def\DoDoWithAllIn{\DoWithAllIn\do}
%% 
%% 
%% == Handling List Macros ==
%% === Initializing ===
%% Here is some advanced `\let<cmd>\empty', perhaps a little 
%% irrelevant for practical purposes. Both
%% \[|\InitializeListMacro{<list-macro>}|\] and 
%% \[|\ReInitializeListMacro{<list-macro>}|\] attempt to ``empty" 
%% <list-macro>, and when we don't believe that \LaTeX\ has been 
%% loaded, both do the same indeed. Otherwise the first one 
%% complains when <list-macro> seems to have been used earlier 
%% while the second complains when <list-macro> seems \emph{not} to 
%% have been used before:
\ifltx                                                  %% v0.3
  \def\InitializeListMacro#1{\@ifdefinable#1{\let#1\empty}}
  \def\ReInitializeListMacro#1{%
    \edef\@tempa{\expandafter\@gobble\string#1}%
    \expandafter\@ifundefined\expandafter{\@tempa}%
        {\@latex@error{\noexpand#1undefined}\@ehc}%
        {\let#1\empty}}
\else
  \def\InitializeListMacro#1{\let#1\empty} %% not \@empty 2011/11/07
  \let\ReInitializeListMacro\InitializeListMacro
\fi
%% |\ToListMacroAdd{<list-macro>}{<cmd-or>}|
%% appends <cmd-or> to the replacement token list of <list-macro>. 
%% <cmd-or> may either be tokenized into a single token,
%% or it is some `{<balanced>}'.
\def\ToListMacroAdd#1#2{\DefExpandStart#1{#1#2}}
\def\DefExpandStart#1{\expandafter\def\expandafter#1\expandafter}
%% 
%% === Testing for Occurrence of a Token ===
%% |\TestListMacroForToken{<list-macro>}{<cmd>}|
%% sets `\in@true' when <cmd> occurs in <list-macro> 
%% and sets `\in@false' otherwise:                      %% 2011/11/07
\def\TestListMacroForToken#1#2{%
    \expandafter \in@ \expandafter #2\expandafter{#1}}
%% Indeed I removed an earlier `\IfTokenInListMacro', 
%% now it's a kind of compromise between having a shorthand macro 
%% below and a generalization for users of the package.
%% 
%% === Adding and Removing ===
%% |\FromTokenListMacroRemove{<list-macro>}{<cmd>}| 
%% removes the token corresponding to <cmd> from the list 
%% stored in <list-macro> 
%% (our parsing method does not work with braces):      %% 2011/11/07
\def\FromTokenListMacroRemove#1#2{%
%% I am not happy about defining \emph{two} parser macros, 
%% but for now ...
    \TestListMacroForToken#1#2%
    \ifin@
      \def\RemoveThisToken##1#2{##1}%
      \expandafter \DefExpandStart
        \expandafter #1\expandafter {%
          \expandafter\RemoveThisToken #1}% 
%% TODO warning otherwise?
   \fi}
%% %% 2011/11/07:
%% ... but this only removes a single occurrence ... 
%% \[|\InTokenListMacroProvide{<list-macro>}{<cmd>}|\]
%% avoids multiple entries of a token 
%% by \emph{not} adding anything when <cmd>
%% already occurs in <list-macro> (again, this does not work with 
%% braces, try `\in@{{}}{{}}').
\def\InTokenListMacroProvide#1#2{%
    \TestListMacroForToken#1#2%
    \ifin@ \else                    %% TODO warning?
        \ToListMacroAdd#1#2%
    \fi}
%%
%%
%% == Leaving and History ==
\PopLetterCatAt                                         %% v0.3
\endinput

VERSION HISTORY 
v0.1    2011/06/23/28  stored separately
v0.2    2011/11/02     simpler, documented
        2011/11/03     corrected \if/\else for init
        2011/11/07     \TestListMacroForToken, \InListMacroProvide; 
                       doc.: \pagebreak, structure
        2011/11/19     modified LaTeX supplements
v0.21   2012/05/14     fix for "generic" and `typeoutfileinfo': 
                       @ before ...!
v0.21a  2012/05/19     \labels sec:apply, sec:core; \pagebreak?
v0.22   2012/06/04     allow {} items
v0.3    2012/11/05     updating copyright, using `plainpkg', 
                       rewording documentation there