You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

grabbox.dtx 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. % \iffalse meta-comment
  2. %
  3. % File: grabbox.dtx Copyright (C) 2018-2019 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. grabbox -- utilities to get an argument as a box
  23. E-mail: jspratte@yahoo.de
  24. Released under the LaTeX Project Public License v1.3c or later
  25. See http://www.latex-project.org/lppl.txt
  26. --------------------------------------------------------------
  27. Copyright (C) 2018-2019 Jonathan P. Spratte
  28. This work may be distributed and/or modified under the conditions of the
  29. LaTeX Project Public License (LPPL), either version 1.3c of this license or
  30. (at your option) any later version. The latest version of this license is in
  31. the file:
  32. http://www.latex-project.org/lppl.txt
  33. This work is "maintained" (as per LPPL maintenance status) by
  34. Jonathan P. Spratte.
  35. This work consists of the file grabbox.dtx
  36. and the derived files grabbox.pdf and
  37. grabbox.sty.
  38. \endpreamble
  39. % stop docstrip adding \endinput
  40. \postamble
  41. \endpostamble
  42. \generate{\file{grabbox.sty}{\from{grabbox.dtx}{pkg}}}
  43. \ifx\fmtname\nameofplainTeX
  44. \expandafter\endbatchfile
  45. \else
  46. \expandafter\endgroup
  47. \fi
  48. %</driver>
  49. %
  50. %<*driver>
  51. \ProvidesFile{grabbox.dtx}
  52. [%
  53. \csname grabbox@date\endcsname\space
  54. utilities to get an argument as a box%
  55. ]
  56. \expandafter\def\csname @classoptionslist\endcsname{}
  57. \RequirePackage[british]{babel}
  58. \documentclass{l3doc}
  59. \usepackage{duckuments}
  60. \usepackage{microtype}
  61. \usepackage{grabbox}
  62. \renewcommand*{\thefootnote}{\fnsymbol{footnote}}
  63. \let\metaOrig\meta
  64. \renewcommand\meta[1]
  65. {%
  66. \texttt{\metaOrig{#1}}%
  67. }
  68. \begin{document}
  69. \DocInput{grabbox.dtx}
  70. \end{document}
  71. %</driver>
  72. %<*pkg>
  73. \newcommand*\grabbox@date{2019-05-08}
  74. \newcommand*\grabbox@version{1.4}
  75. \ProvidesPackage{grabbox}
  76. [%
  77. \grabbox@date\space v\grabbox@version\space utilities to get an argument as
  78. a box%
  79. ]
  80. %</pkg>
  81. % \fi
  82. %
  83. % \begin{center}
  84. % \LARGE The \pkg{grabbox} package\\[\bigskipamount]
  85. % \large
  86. % \setcounter{footnote}{1}%
  87. % Jonathan P. Spratte\footnotemark\\[\medskipamount]
  88. % Version \csname grabbox@version\endcsname\\[\smallskipamount]
  89. % Released \csname grabbox@date\endcsname
  90. % \end{center}
  91. % \footnotetext{E-mail: jspratte@yahoo.de}
  92. %
  93. % \tableofcontents
  94. %
  95. % \begin{documentation}
  96. %
  97. % \section{Introduction}
  98. %
  99. % Sometimes I happen to write macros and environments which don't care for the
  100. % exact contents of an argument but only for that contents' typeset
  101. % representation and its dimensions. In that case I personally dislike the fact
  102. % that those arguments couldn't contain verbatim material if coded straight
  103. % forward for macros. For environments this is quite easy to create thanks to
  104. % \env{lrbox}, for macros this approach unfortunately doesn't work without the
  105. % enduser's cooperation. Thus the macros distributed hereby came into existence.
  106. %
  107. % This package provides \cs{grabbox} to grab an argument inside of a box. The
  108. % used mechanism allows category code changes in that argument as long as it is
  109. % used in a place allowing category code changes (so not inside of another
  110. % argument).
  111. %
  112. % It is written as a docstrip file: executing |latex grabbox.dtx| generates the
  113. % \file{grabbox.sty} file and typesets this documentation; execute
  114. % |tex grabbox.dtx| to only generate \file{grabbox.sty}.
  115. %
  116. % \section{Acknowledgement}
  117. %
  118. % I want to thank Enrico Gregorio for helping me develop first versions of the
  119. % used mechanisms for the second iteration of my \pkg{ducksay} package. If he
  120. % hadn't helped me back then, I wouldn't have considered the used method
  121. % further -- because the user interface would've been too clumsy and require
  122. % strange markup like |\foo arg}| -- and therefore this package wouldn't have
  123. % been created.
  124. %
  125. % Additionally I want to thank David Carlisle for helping me making \cs{grabbox}
  126. % respect surrounding text colours.
  127. %
  128. % \section{The macro}
  129. %
  130. % \begin{function}{\grabbox}
  131. % \begin{syntax}
  132. % \cs{grabbox}\meta{*}\oarg{inject pre pre}\ignorespaces^^A
  133. % \marg{box register}\oarg{inject pre}\marg{box type}\ignorespaces^^A
  134. % \oarg{inject post}\marg{afterwards}
  135. % \end{syntax}
  136. % grabs the next braced argument and stores it inside of the box \meta{box
  137. % register}. The box is of \meta{box type}, which should be one of \cs{hbox}
  138. % or \cs{vbox} or \cs{vtop}. The contents of the box except for
  139. % \meta{inject pre pre} and \meta{inject post} will be contained in an
  140. % additional level of grouping to ensure colour safety (similar to \LaTeX's
  141. % \cs{sbox}). \meta{inject pre pre} will be injected at the beginning of the
  142. % box before this additional group is opened, \meta{inject pre} will be
  143. % injected at the beginning of the box and can affect its contents,
  144. % \meta{inject post} will be injected at the end of the box but can't be
  145. % affected by stuff inside of \meta{inject pre} or added content unless they
  146. % are using global definitions -- \meta{inject pre pre} however can affect the
  147. % contents of \meta{inject post}.
  148. % Unless the \meta{*} is given leading and trailing spaces will be stripped
  149. % from the box. After the box is read in \meta{afterwards} will be inserted.
  150. % The complete contents of the box will be something like:
  151. % \begin{center}
  152. % \csname verbatim@font\endcsname
  153. % \meta{inject pre pre}^^A
  154. % \{\cs{set@color}\meta{inject pre}\meta{argument}\}^^A
  155. % \meta{inject post}
  156. % \end{center}
  157. % \end{function}
  158. %
  159. % \smallskip
  160. % All assignments are made local. Currently it is not safe to nest macros
  161. % which use \cs{grabbox}. It should become safe if your macros use
  162. % \cs{grabbox} inside of a group, so the inner \cs{grabbox} doesn't affect the
  163. % outer one.
  164. %
  165. % \cs{grabbox} uses \cs{afterassignment} and \cs{aftergroup} to do its magic.
  166. % The former should be safe where it is used, the latter is used inside of the
  167. % boxed argument before any contents are inserted.
  168. %
  169. % Since \cs{grabbox} works by setting a boxregister using \cs{setbox} (and a
  170. % bunch of temporary macros), it is of course not expandable and defined
  171. % \cs{protected}.
  172. %
  173. % \begin{function}{\@grabbox}
  174. % \begin{syntax}
  175. % \cs{@grabbox}\meta{*}\marg{inject pre pre}\ignorespaces^^A
  176. % \marg{box register}\marg{inject pre}\marg{box type}\ignorespaces^^A
  177. % \marg{inject post}\marg{afterwards}
  178. % \end{syntax}
  179. % This is a variant of \cs{grabbox} that should be faster because it doesn't
  180. % parse for optional arguments. Instead every argument is mandatory except for
  181. % the star, just leave the arguments empty if you'd otherwise not use the
  182. % corresponding optional argument in \cs{grabbox}.
  183. % \end{function}
  184. %
  185. % \section{Useless Example!}
  186. %
  187. % First we need to reserve us a box register for this example:
  188. % \begin{verbatim}
  189. % \newsavebox\ourbox
  190. % \end{verbatim}
  191. % Next we define a macro which takes some arguments and uses \cs{grabbox}:
  192. % \begin{verbatim}
  193. % \newcommand\examplecmd[2]
  194. % {%
  195. % \begingroup
  196. % \grabbox\ourbox[\itshape]\hbox[ \sffamily is]{\examplecmdOut{#1}{#2}}
  197. % }
  198. % \end{verbatim}
  199. % And we need our helper macro which is executed after \cs{grabbox}:
  200. % \begin{verbatim}
  201. % \newcommand\examplecmdOut[3]
  202. % {%
  203. % \begin{tabular}[t]{@{}ll@{}}
  204. % Arg1: & #1\\
  205. % Arg2: & #2\\
  206. % Box: & \unhbox\ourbox\\
  207. % Arg3: & #3
  208. % \end{tabular}%
  209. % \endgroup
  210. % }
  211. % \end{verbatim}
  212. %
  213. % The result is a macro that takes two ordinary arguments, after those a
  214. % box in horizontal mode and finally another ordinary argument. If we use this
  215. % macro we get the following:
  216. % \begin{center}
  217. % \newsavebox\ourbox
  218. % \newcommand\examplecmd[2]
  219. % {%
  220. % \begingroup
  221. % \grabbox\ourbox[\itshape]\hbox[ \sffamily is]{\examplecmdOut{#1}{#2}}
  222. % }%
  223. % \newcommand\examplecmdOut[3]
  224. % {%
  225. % \begin{tabular}[t]{@{}ll@{}}
  226. % Arg1: & #1\\
  227. % Arg2: & #2\\
  228. % Box: & \unhbox\ourbox\\
  229. % Arg3: & #3
  230. % \end{tabular}%
  231. % \endgroup
  232. % }%
  233. % \examplecmd{Hi,}{my}{\verb|\name|}{Steve!}
  234. % \end{center}
  235. % One can see that \verb|\sffamily is| in \meta{inject post} is not affected by
  236. % the |\itshape| in \meta{inject pre}. The used code to generate that table was:
  237. %
  238. % \begin{verbatim}
  239. % \examplecmd{Hi,}{my}{\verb|\name|}{Steve!}
  240. % \end{verbatim}
  241. %
  242. % \section{Useful Example?}
  243. %
  244. % This example provides a macro which typesets its mandatory argument in a block
  245. % of a definable number of lines, it is meant for a single paragraph.
  246. %
  247. % \begin{verbatim}
  248. % % Getting a box register:
  249. % \newsavebox\RectangleBox
  250. % % Defining the main macro:
  251. % \newcommand\Rectangle[1][4]
  252. % {%
  253. % \begingroup
  254. % \grabbox\RectangleBox\hbox
  255. % {%
  256. % % Since we don't want to read more arguments after the box,
  257. % % we don't need a second macro and can put the output routine
  258. % % here.
  259. % \begin{minipage}{\dimexpr\wd\RectangleBox/#1\relax}
  260. % \parfillskip0pt
  261. % \unhbox\RectangleBox
  262. % \end{minipage}%
  263. % \endgroup
  264. % }%
  265. % }
  266. % \end{verbatim}
  267. %
  268. % As you can see, this macro uses \cs{grabbox} in a group delimited by
  269. % \cs{begingroup} and \cs{endgroup} -- like the useless example. It should
  270. % therefore be safe to nest it inside other macros using \cs{grabbox}.
  271. %
  272. % Finally a usage example of our new macro (with the \pkg{duckuments} package
  273. % loaded):
  274. %
  275. % \begin{verbatim}
  276. % \begin{center}
  277. % \Rectangle[9]{\blindduck}
  278. % \end{center}
  279. % \end{verbatim}
  280. % Results in:
  281. % \begin{center}
  282. % \newsavebox\RectangleBox
  283. % \newcommand\Rectangle[1][4]
  284. % {%
  285. % \begingroup
  286. % \grabbox\RectangleBox\hbox
  287. % {%
  288. % \begin{minipage}{\dimexpr\wd\RectangleBox/#1\relax}
  289. % \parfillskip0pt
  290. % \unhbox\RectangleBox
  291. % \end{minipage}%
  292. % \endgroup
  293. % }%
  294. % }
  295. % \Rectangle[9]{\blindduck}
  296. % \end{center}
  297. %
  298. % \end{documentation}
  299. %
  300. % \begin{implementation}
  301. %
  302. % \section{Implementation}
  303. %
  304. % \begin{macrocode}
  305. %<*pkg>
  306. % \end{macrocode}
  307. %
  308. % \begin{macrocode}
  309. \@ifdefinable{\if@grabbox@spaces@}{\newif\if@grabbox@spaces@}
  310. \@ifdefinable{\grabbox@def}
  311. {\long\def\grabbox@def#1#2#{\grabbox@def@a{}#1{#2}}}
  312. \@ifdefinable{\grabbox@ldef}
  313. {\long\def\grabbox@ldef#1#2#{\grabbox@def@a\long#1{#2}}}
  314. \@ifdefinable{\grabbox@def@a}
  315. {%
  316. \protected\long\def\grabbox@def@a#1#2#3#4%
  317. {\@ifdefinable#2{\protected#1\def#2#3{#4}}}%
  318. }
  319. \newcommand\grabbox@def@step[4]
  320. {%
  321. \grabbox@def#1##1{\def#2{##1}\grabbox@opt#3#4}%
  322. }
  323. \grabbox@def\grabbox@opt#1#2%
  324. {%
  325. \@ifnextchar[
  326. {\grabbox@opt@get#1#2}
  327. {\def#1{}#2}%
  328. }
  329. \grabbox@ldef\grabbox@opt@get#1#2[#3]%
  330. {%
  331. \def#1{#3}#2%
  332. }
  333. \grabbox@def\grabbox@set@color
  334. {%
  335. \@ifundefined{set@color}{}
  336. {\global\let\grabbox@set@color\set@color\grabbox@set@color}%
  337. }
  338. \AtBeginDocument
  339. {%
  340. \@ifundefined{set@color}
  341. {\gdef\grabbox@set@color{}}
  342. {\global\let\grabbox@set@color\set@color}%
  343. }%
  344. \newcommand*\grabbox@unskip@space
  345. {%
  346. \ifhmode\unskip\fi
  347. }
  348. \grabbox@def\grabbox
  349. {%
  350. \@ifstar
  351. {\@grabbox@spaces@true\grabbox@a}
  352. {\@grabbox@spaces@false\grabbox@a}%
  353. }
  354. \grabbox@def\grabbox@a
  355. {%
  356. \grabbox@opt\grabbox@into@prepre\grabbox@b
  357. }
  358. \grabbox@def@step\grabbox@b\grabbox@name\grabbox@into@pre\grabbox@c
  359. \grabbox@def@step\grabbox@c\grabbox@type\grabbox@into@post\grabbox@d
  360. \grabbox@ldef\grabbox@d#1%
  361. {%
  362. \def\grabbox@final{#1}%
  363. \afterassignment\grabbox@intermediate
  364. \setbox\grabbox@name\grabbox@type
  365. }
  366. \grabbox@def\@grabbox
  367. {%
  368. \@ifstar
  369. {\@grabbox@spaces@true\@grabbox@a}
  370. {\@grabbox@spaces@false\@grabbox@a}%
  371. }
  372. \grabbox@ldef\@grabbox@a#1#2#3#4#5%
  373. {%
  374. \def\grabbox@into@prepre{#1}%
  375. \def\grabbox@name {#2}%
  376. \def\grabbox@into@pre {#3}%
  377. \def\grabbox@type {#4}%
  378. \def\grabbox@into@post {#5}%
  379. \grabbox@d
  380. }
  381. \grabbox@def\grabbox@intermediate
  382. {%
  383. \grabbox@into@prepre
  384. \bgroup
  385. \if@grabbox@spaces@
  386. \else
  387. \aftergroup\grabbox@unskip@space
  388. \fi
  389. \grabbox@set@color
  390. \aftergroup\grabbox@after
  391. \grabbox@into@pre
  392. \if@grabbox@spaces@
  393. \else
  394. \ignorespaces
  395. \fi
  396. }
  397. \newcommand*\grabbox@after@aux@b[1]
  398. {%
  399. \grabbox@after@aux@a
  400. }
  401. \grabbox@def\grabbox@after@aux@a
  402. {%
  403. \@ifnextchar\reset@color
  404. {\reset@color\grabbox@after@aux@b}
  405. {\egroup\grabbox@final}%
  406. }
  407. \grabbox@def\grabbox@after
  408. {%
  409. \grabbox@into@post
  410. \endgraf
  411. \grabbox@after@aux@a
  412. }
  413. % \end{macrocode}
  414. %
  415. % \begin{macrocode}
  416. \endinput
  417. % \end{macrocode}
  418. %
  419. % \end{implementation}
  420. %
  421. % \begin{macrocode}
  422. %</pkg>
  423. % \end{macrocode}