TransWikia.com

Different Behaviors Digesting csname xendcsname and Digesting x (expansion issue)

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}

enter image description here

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}

enter image description here

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.

2 Answers

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}

enter image description here

Answered by Steven B. Segletes on May 20, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP