|
@@ -0,0 +1,361 @@
|
|
1
|
+% \iffalse meta-comment
|
|
2
|
+%
|
|
3
|
+% File: boxgrab.dtx Copyright (C) 2018 Jonathan P. Spratte
|
|
4
|
+%
|
|
5
|
+% It may be distributed and/or modified under the conditions of the LaTeX
|
|
6
|
+% Project Public License (LPPL), either version 1.3c of this license or (at your
|
|
7
|
+% option) any later version. The latest version of this license is in the file
|
|
8
|
+%
|
|
9
|
+% https://www.latex-project.org/lppl.txt
|
|
10
|
+%
|
|
11
|
+% ------------------------------------------------------------------------------
|
|
12
|
+%
|
|
13
|
+%<*driver>
|
|
14
|
+\def\nameofplainTeX{plain}
|
|
15
|
+\ifx\fmtname\nameofplainTeX\else
|
|
16
|
+ \expandafter\begingroup
|
|
17
|
+\fi
|
|
18
|
+\input l3docstrip.tex
|
|
19
|
+\askforoverwritefalse
|
|
20
|
+\preamble
|
|
21
|
+
|
|
22
|
+--------------------------------------------------------------
|
|
23
|
+boxgrab -- utilities to get an argument as a box
|
|
24
|
+E-mail: jspratte@yahoo.de
|
|
25
|
+Released under the LaTeX Project Public License v1.3c or later
|
|
26
|
+See http://www.latex-project.org/lppl.txt
|
|
27
|
+--------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+Copyright (C) 2018 Jonathan P. Spratte
|
|
30
|
+
|
|
31
|
+This work may be distributed and/or modified under the conditions of the
|
|
32
|
+LaTeX Project Public License (LPPL), either version 1.3c of this license or
|
|
33
|
+(at your option) any later version. The latest version of this license is in
|
|
34
|
+the file:
|
|
35
|
+
|
|
36
|
+ http://www.latex-project.org/lppl.txt
|
|
37
|
+
|
|
38
|
+This work is "maintained" (as per LPPL maintenance status) by
|
|
39
|
+ Jonathan P. Spratte.
|
|
40
|
+
|
|
41
|
+This work consists of the file boxgrab.dtx
|
|
42
|
+and the derived files boxgrab.pdf and
|
|
43
|
+ boxgrab.sty.
|
|
44
|
+
|
|
45
|
+\endpreamble
|
|
46
|
+% stop docstrip adding \endinput
|
|
47
|
+\postamble
|
|
48
|
+\endpostamble
|
|
49
|
+\generate{\file{boxgrab.sty}{\from{boxgrab.dtx}{pkg}}}
|
|
50
|
+\ifx\fmtname\nameofplainTeX
|
|
51
|
+ \expandafter\endbatchfile
|
|
52
|
+\else
|
|
53
|
+ \expandafter\endgroup
|
|
54
|
+\fi
|
|
55
|
+%</driver>
|
|
56
|
+%
|
|
57
|
+%<*driver>
|
|
58
|
+\ProvidesFile{boxgrab.dtx}
|
|
59
|
+ [%
|
|
60
|
+ \csname boxgrab@date\endcsname\
|
|
61
|
+ utilities to get an argument as a box%
|
|
62
|
+ ]
|
|
63
|
+\documentclass{l3doc}
|
|
64
|
+\usepackage{duckuments}
|
|
65
|
+\usepackage{boxgrab}
|
|
66
|
+\author{Jonathan P. Spratte\thanks{Email: jspratte@yahoo.de}}
|
|
67
|
+\title{The \pkg{boxgrab} package}
|
|
68
|
+\makeatletter
|
|
69
|
+\date{\boxgrab@date\ v\boxgrab@version}
|
|
70
|
+\renewcommand*{\thefootnote}{\fnsymbol{footnote}}
|
|
71
|
+\makeatother
|
|
72
|
+\begin{document}
|
|
73
|
+ \DocInput{boxgrab.dtx}
|
|
74
|
+\end{document}
|
|
75
|
+%</driver>
|
|
76
|
+%<*pkg>
|
|
77
|
+\newcommand*\boxgrab@date{2018-10-17}
|
|
78
|
+\newcommand*\boxgrab@version{1.0}
|
|
79
|
+\ProvidesPackage{boxgrab}
|
|
80
|
+ [\boxgrab@date\ v\boxgrab@version\ utilities to get an argument as a box]
|
|
81
|
+\RequirePackage{xparse}
|
|
82
|
+%</pkg>
|
|
83
|
+% \fi
|
|
84
|
+%
|
|
85
|
+% \begin{center}
|
|
86
|
+% \LARGE The \pkg{boxgrab} package\\[\bigskipamount]
|
|
87
|
+% \large
|
|
88
|
+% \setcounter{footnote}{1}%
|
|
89
|
+% Jonathan P. Spratte\footnotemark\\[\medskipamount]
|
|
90
|
+% Version \csname boxgrab@version\endcsname\\[\smallskipamount]
|
|
91
|
+% Released \csname boxgrab@date\endcsname
|
|
92
|
+% \end{center}
|
|
93
|
+% \footnotetext{E-mail: jspratte@yahoo.de}
|
|
94
|
+%
|
|
95
|
+% \tableofcontents
|
|
96
|
+%
|
|
97
|
+% \begin{documentation}
|
|
98
|
+%
|
|
99
|
+% \section{Introduction}
|
|
100
|
+%
|
|
101
|
+% This package provides \cs{boxgrab} to grab an argument inside of a box. The
|
|
102
|
+% used mechanism allows category code changes in that argument as long as it is
|
|
103
|
+% used in a place allowing category code changes (so not inside of another
|
|
104
|
+% argument).
|
|
105
|
+%
|
|
106
|
+% It is written as a docstrip file: executing |latex boxgrab.dtx| generates the
|
|
107
|
+% \file{boxgrab.sty} file and typesets this documentation; execute
|
|
108
|
+% |tex boxgrab.dtx| to only generate \file{boxgrab.sty}.
|
|
109
|
+%
|
|
110
|
+% \section{The macro}
|
|
111
|
+%
|
|
112
|
+% \begin{function}{\boxgrab}
|
|
113
|
+% \begin{syntax}
|
|
114
|
+% \cs{boxgrab}\meta{*}
|
|
115
|
+% \marg{box register}\oarg{inject pre}\marg{box type}\oarg{inject post}
|
|
116
|
+% \marg{next}\oarg{save args}
|
|
117
|
+% \end{syntax}
|
|
118
|
+% Grabs the next braced argument inside of the box \meta{box register}. The
|
|
119
|
+% box is of \meta{box type}, which should be either \cs{hbox} or \cs{vbox}.
|
|
120
|
+% \meta{inject pre} will be injected at the beginning of the box and can
|
|
121
|
+% affect its contents, \meta{inject post} will be injected after the box but
|
|
122
|
+% can't be affected by stuff inside of \meta{inject pre}. Unless the \meta{*}
|
|
123
|
+% is given leading and trailing spaces will be stripped from the box. After
|
|
124
|
+% the box is read in \meta{next} will be executed. The usage is therefore
|
|
125
|
+% similar to the one of \cs{@ifstar}. You can specify arguments which should
|
|
126
|
+% be given to \meta{next} using \meta{save args}. The stuff you provide in
|
|
127
|
+% \meta{save args} will be given as is to \meta{next}, so if you want to give
|
|
128
|
+% an argument you should delimit it like with braces, like \verb|[{#1}]|, or
|
|
129
|
+% if you want to give two arguments, like \verb|[{#1}{#2}]|.
|
|
130
|
+%
|
|
131
|
+% All assignments are made local. Currently it is not save to nest macros
|
|
132
|
+% which use \cs{boxgrab}.
|
|
133
|
+% \end{function}
|
|
134
|
+%
|
|
135
|
+% \section{Useless Example!}
|
|
136
|
+%
|
|
137
|
+% First we need to reserve us a box register for this example:
|
|
138
|
+%
|
|
139
|
+%\begin{verbatim}
|
|
140
|
+% \newsavebox\ourbox
|
|
141
|
+%\end{verbatim}
|
|
142
|
+%
|
|
143
|
+% Next we define a macro which takes some arguments and uses our macro:
|
|
144
|
+%
|
|
145
|
+%\begin{verbatim}
|
|
146
|
+% \newcommand\examplecmd[2]
|
|
147
|
+% {%
|
|
148
|
+% \begingroup
|
|
149
|
+% \boxgrab\ourbox[\itshape]\hbox[ \sffamily is]\examplecmdOut[{#1}{#2}]
|
|
150
|
+% }
|
|
151
|
+%\end{verbatim}
|
|
152
|
+%
|
|
153
|
+% And we need our helper macro which is executed after \cs{boxgrab}:
|
|
154
|
+%
|
|
155
|
+%\begin{verbatim}
|
|
156
|
+% \newcommand\examplecmdOut[3]
|
|
157
|
+% {%
|
|
158
|
+% \begin{tabular}[t]{@{}ll@{}}
|
|
159
|
+% Arg1: & #1\\
|
|
160
|
+% Arg2: & #2\\
|
|
161
|
+% Box: & \unhbox\ourbox\\
|
|
162
|
+% Arg3: & #3
|
|
163
|
+% \end{tabular}%
|
|
164
|
+% \endgroup
|
|
165
|
+% }
|
|
166
|
+%\end{verbatim}
|
|
167
|
+%
|
|
168
|
+% The result is a macro that takes two ordinary arguments, after those a
|
|
169
|
+% box in horizontal mode and finally another ordinary argument. If we use this
|
|
170
|
+% macro we get the following:
|
|
171
|
+% \begin{center}
|
|
172
|
+% \newsavebox\ourbox
|
|
173
|
+% \newcommand\examplecmd[2]
|
|
174
|
+% {%
|
|
175
|
+% \begingroup
|
|
176
|
+% \boxgrab\ourbox[\itshape]\hbox[ \sffamily is]\examplecmdOut[{#1}{#2}]
|
|
177
|
+% }%
|
|
178
|
+% \newcommand\examplecmdOut[3]
|
|
179
|
+% {%
|
|
180
|
+% \begin{tabular}[t]{@{}ll@{}}
|
|
181
|
+% Arg1: & #1\\
|
|
182
|
+% Arg2: & #2\\
|
|
183
|
+% Box: & \unhbox\ourbox\\
|
|
184
|
+% Arg3: & #3
|
|
185
|
+% \end{tabular}%
|
|
186
|
+% \endgroup
|
|
187
|
+% }%
|
|
188
|
+% \examplecmd{Hi,}{my}{\verb|name|}{Steve!}
|
|
189
|
+% \end{center}
|
|
190
|
+% One can see, that the \verb|\sffamily is| of \meta{inject post} is not
|
|
191
|
+% affected by the |\itshape| in \meta{inject pre}.
|
|
192
|
+% The used code to generate that table was:
|
|
193
|
+%
|
|
194
|
+%\begin{verbatim}
|
|
195
|
+% \examplecmd{Hi,}{my}{\verb|name|}{Steve!}
|
|
196
|
+%\end{verbatim}
|
|
197
|
+%
|
|
198
|
+% \section{Useful Example?}
|
|
199
|
+%
|
|
200
|
+% This example provides a macro which typesets its mandatory argument in a block
|
|
201
|
+% of a definable number of lines, it is meant for a single paragraph.
|
|
202
|
+%
|
|
203
|
+%\begin{verbatim}
|
|
204
|
+% % Getting a box register:
|
|
205
|
+% \newsavebox\RectangleBox
|
|
206
|
+% % Defining the main macro
|
|
207
|
+% \newcommand\Rectangle[1][4]
|
|
208
|
+% {%
|
|
209
|
+% \begingroup
|
|
210
|
+% \boxgrab\RectangleBox\hbox\RectangleOut[{#1}]
|
|
211
|
+% }
|
|
212
|
+% % Defining the secondary macro
|
|
213
|
+% \newcommand\RectangleOut[1]
|
|
214
|
+% {%
|
|
215
|
+% \begin{minipage}{\dimexpr\wd\RectangleBox/#1\relax}
|
|
216
|
+% \parfillskip0pt
|
|
217
|
+% \unhbox\RectangleBox
|
|
218
|
+% \end{minipage}%
|
|
219
|
+% \endgroup
|
|
220
|
+% }
|
|
221
|
+%\end{verbatim}
|
|
222
|
+%
|
|
223
|
+% And a usage example of our new macro (with the \pkg{duckuments} package
|
|
224
|
+% loaded):
|
|
225
|
+%
|
|
226
|
+%\begin{verbatim}
|
|
227
|
+% \begin{center}
|
|
228
|
+% \Rectangle[9]{\blindduck}
|
|
229
|
+% \end{center}
|
|
230
|
+%\end{verbatim}
|
|
231
|
+% Results:
|
|
232
|
+% \newsavebox\RectangleBox
|
|
233
|
+% \newcommand\Rectangle[1][4]
|
|
234
|
+% {%
|
|
235
|
+% \begingroup
|
|
236
|
+% \boxgrab\RectangleBox\hbox\RectangleOut[{#1}]
|
|
237
|
+% }%
|
|
238
|
+% \newcommand\RectangleOut[1]
|
|
239
|
+% {%
|
|
240
|
+% \begin{minipage}{\dimexpr\wd\RectangleBox/#1\relax}
|
|
241
|
+% \parfillskip0pt
|
|
242
|
+% \unhbox\RectangleBox
|
|
243
|
+% \end{minipage}%
|
|
244
|
+% \endgroup
|
|
245
|
+% }%
|
|
246
|
+% \begin{center}
|
|
247
|
+% \Rectangle[9]{\blindduck}
|
|
248
|
+% \end{center}
|
|
249
|
+%
|
|
250
|
+% \end{documentation}
|
|
251
|
+%
|
|
252
|
+% \begin{implementation}
|
|
253
|
+%
|
|
254
|
+% \section{Implementation}
|
|
255
|
+%
|
|
256
|
+% \begin{macrocode}
|
|
257
|
+%<*pkg>
|
|
258
|
+% \end{macrocode}
|
|
259
|
+%
|
|
260
|
+% \begin{macrocode}
|
|
261
|
+\@ifdefinable{\if@boxgrab@spaces@}{\newif\if@boxgrab@spaces@}
|
|
262
|
+\newcommand*\boxgrab@args{}%
|
|
263
|
+\NewDocumentCommand \boxgrab { s m +O{} m +O{} m }
|
|
264
|
+ {%
|
|
265
|
+ \IfBooleanTF{#1}
|
|
266
|
+ {\@boxgrab@spaces@true}
|
|
267
|
+ {\@boxgrab@spaces@false}%
|
|
268
|
+ \def\boxgrab@name{#2}%
|
|
269
|
+ \if@boxgrab@spaces@
|
|
270
|
+ \def\boxgrab@into@pre{#3}%
|
|
271
|
+ \else
|
|
272
|
+ \def\boxgrab@into@pre{#3\ignorespaces}%
|
|
273
|
+ \fi
|
|
274
|
+ \def\boxgrab@type{#4}%
|
|
275
|
+ \def\boxgrab@into@post{#5}%
|
|
276
|
+ \def\boxgrab@final{#6}%
|
|
277
|
+ \@ifnextchar[
|
|
278
|
+ {\boxgrab@get@args}
|
|
279
|
+ {\def\boxgrab@args{}\boxgrab@a}
|
|
280
|
+ }
|
|
281
|
+\newcommand \boxgrab@get@args {}
|
|
282
|
+\long\def\boxgrab@get@args#1]
|
|
283
|
+ {%
|
|
284
|
+ \expandafter\boxgrab@get@args@a\expandafter{\@gobble#1}%
|
|
285
|
+ }
|
|
286
|
+\newcommand \boxgrab@get@args@a [1]
|
|
287
|
+ {%
|
|
288
|
+ \boxgrab@check@bracket #1[\endboxgrab@check@bracket
|
|
289
|
+ {\def\boxgrab@args{#1}\boxgrab@a}%
|
|
290
|
+ {\boxgrab@get@args@grabon{#1]}}%
|
|
291
|
+ }
|
|
292
|
+\newcommand \boxgrab@get@args@grabon {}
|
|
293
|
+\long\def\boxgrab@get@args@grabon#1#2]
|
|
294
|
+ {%
|
|
295
|
+ \boxgrab@check@bracket #2[\endboxgrab@check@bracket
|
|
296
|
+ {\def\boxgrab@args{#1#2}\boxgrab@a}
|
|
297
|
+ {\boxgrab@get@args@grabon{#1#2]}}%
|
|
298
|
+ }
|
|
299
|
+\newcommand \boxgrab@check@bracket {}
|
|
300
|
+\long\def\boxgrab@check@bracket #1[#2\endboxgrab@check@bracket
|
|
301
|
+ {%
|
|
302
|
+ \if\relax\detokenize{#2}\relax
|
|
303
|
+ \expandafter\@firstoftwo
|
|
304
|
+ \else
|
|
305
|
+ \expandafter\@secondoftwo
|
|
306
|
+ \fi
|
|
307
|
+ }
|
|
308
|
+\newcommand* \boxgrab@a
|
|
309
|
+ {%
|
|
310
|
+ \afterassignment\boxgrab@intermediate
|
|
311
|
+ \setbox\boxgrab@name\boxgrab@type
|
|
312
|
+ }
|
|
313
|
+\newcommand*\boxgrab@intermediate
|
|
314
|
+ {%
|
|
315
|
+ \aftergroup\boxgrab@after
|
|
316
|
+ \boxgrab@into@pre
|
|
317
|
+ }
|
|
318
|
+\newcommand*\boxgrab@after
|
|
319
|
+ {%
|
|
320
|
+ \if@boxgrab@spaces@
|
|
321
|
+ \setbox\boxgrab@name\boxgrab@type
|
|
322
|
+ {%
|
|
323
|
+ \boxgrab@unpack
|
|
324
|
+ \boxgrab@into@post
|
|
325
|
+ }%
|
|
326
|
+ \else
|
|
327
|
+ \setbox\boxgrab@name\boxgrab@type
|
|
328
|
+ {%
|
|
329
|
+ \boxgrab@unpack
|
|
330
|
+ \ifhmode\unskip\fi
|
|
331
|
+ \boxgrab@into@post
|
|
332
|
+ }%
|
|
333
|
+ \fi
|
|
334
|
+ \expandafter\boxgrab@final@exp@args\expandafter{\boxgrab@args}%
|
|
335
|
+ }
|
|
336
|
+\newcommand*\boxgrab@unpack
|
|
337
|
+ {%
|
|
338
|
+ \csname
|
|
339
|
+ un%
|
|
340
|
+ \expandafter\expandafter\expandafter\@gobble
|
|
341
|
+ \expandafter\string\boxgrab@type
|
|
342
|
+ \endcsname
|
|
343
|
+ \boxgrab@name
|
|
344
|
+ }
|
|
345
|
+\newcommand\boxgrab@final@exp@args[1]
|
|
346
|
+ {%
|
|
347
|
+ \def\boxgrab@args{}%
|
|
348
|
+ \boxgrab@final#1%
|
|
349
|
+ }
|
|
350
|
+
|
|
351
|
+% \end{macrocode}
|
|
352
|
+%
|
|
353
|
+% \begin{macrocode}
|
|
354
|
+\endinput
|
|
355
|
+% \end{macrocode}
|
|
356
|
+%
|
|
357
|
+% \end{implementation}
|
|
358
|
+%
|
|
359
|
+% \begin{macrocode}
|
|
360
|
+%</pkg>
|
|
361
|
+% \end{macrocode}
|