1

I'm trying to use xparse and generic TeX/LaTeX commands to write a macro (that takes no arguments) to define another macro that does take arguments:

\documentclass{minimal}
\RequirePackage{xparse,fmtcount}

\newcounter{mycounter}

\NewDocumentCommand{\mycounterHex}{O{1}}{}

\providecommand{\enableCounterCommands}{ \RenewDocumentCommand{\mycounterHex}{O{1}}{\padzeroes[#1]{\hexadecimal{mycounter}}} }

\begin{document} \end{document}

When I compile this document with pdflatex --interaction=nonstopmode, I get the following error message:

! Illegal parameter number in definition of \enableCounterCommands.
<to be read again> 
                   1
l.11 }

I believe that the problem is that TeX thinks I'm trying to refer to the (nonexistent) first argument of \enableCounterCommands, but I'm actually trying to reference the optional-with-default-value first argument of \mycounterHex. How can I indicate to TeX that I am referencing the argument of \mycounterHex?

  • 2
    Have you tried to double #? ...\padzeroes[##1]... – gernot Jun 30 '23 at 16:17
  • 1
    related: https://tex.stackexchange.com/q/527577 https://tex.stackexchange.com/q/42463 – cabohah Jun 30 '23 at 16:27
  • The double # seems to work well. Do you know if xparse's \RenewDocumentCommand can be used to make a global redefinition from inside of another macro definition? – Ben Zelnick Jun 30 '23 at 16:44

1 Answers1

1

You want ##1 in the replacement text.

On the other hand I don't see why defining \mycounterHex that way, when it's not difficult to have an expandable version using any counter.

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\paddedhex}{O{0}m} {% #1 = size to pad with zeros to, #2 = counter name \zelnick_paddedhex:nn { #1 } { #2 } }

\cs_new:Nn \zelnick_paddedhex:nn { \int_compare:nT { #1-\str_count:e { \int_to_Hex:n { \value{#2} } } > 0 } {% we want to pad \prg_replicate:nn { #1-\str_count:e { \int_to_Hex:n { \value{#2} } } } { 0 } } \int_to_Hex:n { \value{#2} } }

\ExplSyntaxOff

\newcounter{mycounter}

\begin{document}

\setcounter{mycounter}{42}

\paddedhex{mycounter}

\paddedhex[4]{mycounter}

\setcounter{mycounter}{1234567}

\paddedhex{mycounter}

\paddedhex[4]{mycounter}

\paddedhex[8]{mycounter}

\edef\temp{\paddedhex[8]{mycounter}}

\texttt{\meaning\temp}% show full expandability

\end{document}

We first convert the counter's value to hexadecimal, count the number of characters and, if it's less than the stated size to pad to, we add the required number of zeros.

enter image description here

Full expandability means that you can for instance say

\renewcommand{\themycounter}{\paddedhex[4]{mycounter}}

You could have your section numbers in hexadecimal padded to four digits with

\renewcommand{\thesection}{\paddedhex[4]{section}}

and this would work with \label and \ref.

You wouldn't be able to with fmtcount facilities.

egreg
  • 1,121,712