TeX - LaTeX Asked on May 20, 2021
This question has been significantly EDITED, as I learned more of the problem.
If I was good, I would be able to create macros with multiple optional arguments, but not only can’t I, but in this case, I’m trying to adapt an existing structure. I wrote the boxhandler
package to be able to tune figure/table captions layouts (in particular, to a strange style my organization has). That aside, the syntax for a figure is
bxfigure[htbp]{caption}{figure content}
Someone has requested the ability to use caption
‘s optional argument, which this present structure does not allow. So I thought I could provide a syntax that works with the above syntax or with the following
bxfigure[htbp]{[LOF caption]full caption}{figure content}
The code I thought would have done that is
documentclass{article}
usepackage{boxhandler}
usepackage{etoolbox}
makeatletter
renewcommandbx@caption[1]{%
expandafteroptcaptionexpandafter[#1]relax%
}
defoptcaption[#1]#2relax{%
ifstrempty{#2}{caption{#1}}{caption[@gobble#1]{striptrailingbracket#2}}}
%ifstrempty{#2}{Full caption is fbox{#1}}
% {LOF caption is fbox{@gobble#1} Full caption is fbox{striptrailingbracket#2}}}
defstriptrailingbracket#1]{#1}
makeatother
begin{document}
listoffigures
%defx{my caption}
%expandafteroptcaptionexpandafter[x]relax
defx{[LOF caption]my caption}
%expandafteroptcaptionexpandafter[x]relax
bxfigure[h]{my caption}{fbox{TEXT}}
bxfigure[h]{[LOF caption]my caption}{fbox{TEXT}}
bxfigure[h]{x}{fbox{TEXT}}
%optcaption[[LOF caption]my caption]relax
end{document}
but as you see, the optcaption
parser does not extract the bracketed content from the argument, and always thinks the #1
argument of defoptcaption[#1]#2relax{}
is without a right bracket.
To make the problem simpler, I studied the behavior of optcaption
specifically, apart from including it in bxfigure
. And here,
documentclass{article}
usepackage{boxhandler}
usepackage{etoolbox}
makeatletter
renewcommandbx@caption[1]{%
expandafteroptcaptionexpandafter[#1]relax%
}
defoptcaption[#1]#2relax{%
%ifstrempty{#2}{caption{#1}}{caption[@gobble#1]{striptrailingbracket#2}}}
ifstrempty{#2}{Full caption is fbox{#1}}
{LOF caption is fbox{@gobble#1} Full caption is fbox{striptrailingbracket#2}}}
defstriptrailingbracket#1]{#1}
begin{document}
All of these work...par
bx@caption{[LOF caption]my caption}par
defx{my caption}
bx@caption{x}par
defx{[LOF caption]my caption}par
bx@caption{x}par
~The following does not work (and boxhandler passes the caption via a
csname; this is the root of the problem)par
bx@caption{csname xendcsname}par
~This fixes it, but it requires me to change the code that calls bx@captionpar
expandafterbx@captionexpandafter{csname xendcsname}
end{document}
we see that it is able to detect the ]
and extract the optional argument, even when that argument is passed by way of a macro x
, but not when it is passed as csname xendcsname
.
So I suppose I can go back and change the boxhandler
calls to bx@caption
to pre-expand the csname
as I did in my last example (see my answer below).
But if anyone can rewrite bx@caption
to be able to properly digest a csname
argument (without patching ReciteFigure
), I will accept that answer.
LaTeX optional arguments are a delimited argument defined via deffoo[#1]{...}
(unless you define them via latex3 declarations) so []
are not matched and the argument ends at the first ]
optcaption[[LOF caption]my caption]relax
#1
is [LOF caption
To use []
in an optional argument you need
optcaption[{[LOF caption]my caption}]relax
The LaTeX3 declarations define the command to use a slower, more careful way of picking up the optional argument that does match []
.
It is not clear what
caption[@gobble#1]
is intended to do but it almost certainly does the wrong thing.
If #1
is [LOF caption]full caption
then the above is
caption[@gobble[LOF caption]full caption]
so the optional argument of caption
is @gobble[LOF caption
and @gobble
will gobble the [
however the following mandatory argument of caption
is then just f
. and ull caption]
are left as trailing tokens that do whatever they do.
In your edited question you need to expand twice, or simpler expand until there is an unexpandable token before looking for [
so
renewcommandbx@caption[1]{%
expandafteroptcaptionexpandafter[romannumeral-`x#1]relax%
}
Correct answer by David Carlisle on May 20, 2021
Well, once I determined the problem was with digesting a csname
that was passed to bx@caption
, I determined that one solution was to patch boxhandler
to pre-expand the argument that was being passed. Using the definitions in my first example, and patching the calls to bx@caption
took care of it.
If anyone else can solve this problem without resorting to xpatch
, I will accept that answer.
David's edit of using the romannumeral
trick,
renewcommandbx@caption[1]{%
expandafteroptcaptionexpandafter[romannumeral-`x#1]relax%
}
instead of what I have in this answer, alleviates the need for xpatch
, so he gets the points! Thank you, David.
documentclass{article}
usepackage{xpatch}% http://ctan.org/pkg/etoolbox
usepackage{boxhandler}
usepackage{etoolbox}
makeatletter
xpatchcmd{ReciteFigure}% <cmd>
{bx@caption}% <search>
{expandafterbx@captionexpandafter}% <replace>
{}{}% <success><failure>
xpatchcmd{ReciteTable}% <cmd>
{bx@caption}% <search>
{expandafterbx@captionexpandafter}% <replace>
{}{}% <success><failure>
renewcommandbx@caption[1]{%
expandafteroptcaptionexpandafter[#1]relax%
}
defoptcaption[#1]#2relax{%
ifstrempty{#2}{caption{#1}}{caption[@gobble#1]{striptrailingbracket#2}}}
defstriptrailingbracket#1]{#1}
makeatother
begin{document}
listoffigures
bxfigure[ht]{my caption}{fbox{TEXT}}
bxfigure[ht]{[LOF caption]my caption}{fbox{TEXT}}
end{document}
Answered by Steven B. Segletes on May 20, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP