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?

3
  • 2
    Have you tried to double #? ...\padzeroes[##1]...
    – gernot
    Commented Jun 30, 2023 at 16:17
  • 1
    related: tex.stackexchange.com/q/527577 tex.stackexchange.com/q/42463
    – cabohah
    Commented Jun 30, 2023 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? Commented Jun 30, 2023 at 16:44

1 Answer 1

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .