TeX - LaTeX Asked on January 25, 2021
There is an answer explaining how to convert numbers to text here. But if I use a ref
output in the command convertdigits
, it throws the error Missing number, treated as zero.
even if the ref output is a one-digit number. The code below is taken from that site.
documentclass{article}
makeatletter
newcommand{convertdigits}[1]{expandafterconvert@digits#1convert@digits}
defconvert@digits#1{%
ifx#1convert@digits
expandafter@gobble
else
expandafter@firstofone
fi
{convert@@digits#1}%
}
defconvert@@digits#1{%
ifnum9=9#1%
expandafter@gobble
else
expandafter@firstofone
fi
{convert@@digit#1}convert@digits
}
defconvert@@digit#1{%
ifcase#1%
zeroor
oneor
twoor
threeor
fouror
fiveor
sixor
sevenor
eightor
ninefi
}
makeatother
begin{document}
section{a}
subsection{a1}label{key}
subsection{a2}
section{b}
subsection{b1}
subsection{b2}
subsubsection{b3}
ref{key}
defmyvar{2}
convertdigits{2}
convertdigits{myvar}
convertdigits{ref{key}} % ERROR
end{document}
My question: Can I convert the last digit of the ref{key}
to string.
For example, if
the output of ref{key}
is 2.3
then
the output of convertdigits{ref{key}}
should be three
.
You can use the macro getrefbykeydefault
from the refcount-package for extracting that sequence of tokens that yield the text-string of the reference.
Assuming that expansion will not significantly change that sequence, you can take these tokens for a list of .
-separated elements and extract the last one thereof. (When writing "significantly change that sequence" I think about scenarios like expansion leading to the removal of some of the dot-separated elements.)
If it is ensured that expanding the last dot-separated element yields only a valid ⟨number⟩-quantity denoting a non-negative number, it can be "fed", e.g, to the numberstringnum
-macro of the fmtcount-package.
With the example below checking whether expanding it yields only a valid TeX-⟨number⟩-quantity denoting a non-negative number is omitted because no such test is known to me which is not flawed in some way.
(Any such test must be flawed/ will work out only for some restricted subset of possible user-input:
When attempting to implement an algorithm for such a test, then you are facing the halting-problem:
At the time of expanding them, the tokens forming the last dot-separated element of the text-string of the reference may form an arbitrary expansion-based algorithm. Having an algorithm check whether such an algorithm in the end yields a valid TeX-⟨number⟩-quantity (denoting a non-negative number) implies having an algorithm check whether an other arbitrary algorithm terminates at all/terminates without error-messages. This is the halting-problem. Alan Turing proved that it is not possible to implement an algorithm which for any arbitrary algorithm can "decide" whether that algorithm will ever terminate.)
documentclass{article}
usepackage{hyperref}
usepackage{refcount}
usepackage{fmtcount}
makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafter@secondoftwostring{expandafter
@secondoftwoexpandafter{expandafter{string#1}expandafter
@secondoftwostring}expandafter@firstoftwoexpandafter{expandafter
@secondoftwostring}@firstoftwoexpandafter{} @secondoftwo}%
{@firstoftwoexpandafter{} @firstoftwo}%
}%
%-------------------------------------------------------------------------
@ifdefinableUD@gobbletofirstdot{longdefUD@gobbletofirstdot#1.{}}%
@ifdefinableUD@keeptofirstdot{longdefUD@keeptofirstdot#1.{#1}}%
newcommandUD@PassFirstToSecond[2]{#2{#1}}
newcommandextractlastdotitem[3]{romannumeral0extractlastdotitemloop{#1.}{#2}{#3}}%
newcommandextractlastdotitemloop[3]{%
expandafterUD@CheckWhetherNullexpandafter{UD@gobbletofirstdot#1}{%
expandafterexpandafterexpandafterUD@PassFirstToSecond
expandafterexpandafterexpandafter{expandafter@gobbleUD@keeptofirstdotrelax#1}{ #2}#3%
}{%
expandafterextractlastdotitemloopexpandafter{UD@gobbletofirstdot#1}{#2}{#3}%
}%
}%
newcommandconvertdigitsoflabel[1]{%
IfRefUndefinedBabel{#1}{@ifundefined{hyperref}{ref}{ref*}{#1}}{%
begingroupprotected@edef@tempa{getrefbykeydefault{#1}{}{0}}%
expandafterextractlastdotitemexpandafter{@tempa}{endgroupnumberstringnum}{[m]}%
}%
}%
makeatother
begin{document}
section{a}
subsection{a1}label{a1}
subsection{a2}
subsection{a3}
subsection{a4}
subsection{a5}
subsection{a6}
subsection{a7}
subsection{a8}
subsection{a9}
subsection{a10}
subsection{a11}label{a11}
section{b}
subsection{b1}
subsection{b2}
subsubsection{b3}
bigskiphrulebigskip
ref{a1}
ref{a11}
convertdigitsoflabel{a1}
convertdigitsoflabel{a11}
hyperref[{a1}]{convertdigitsoflabel{a1}}
hyperref[{a11}]{convertdigitsoflabel{a11}}
end{document}
Answered by Ulrich Diez on January 25, 2021
You can use refcount
and its expandable getrefnumber
.
In order to isolate the final part of the input string, you can use regex_split:nnN
that will store the parts separated by periods into different items of a sequence and take the last item.
documentclass{article}
usepackage{xparse}
usepackage{refcount}
ExplSyntaxOn
NewDocumentCommand{convertdigits}{m}
{
mert_convertdigits:e { #1 }
}
cs_new_protected:Nn mert_convertdigits:n
{
regex_split:nnN { . } { #1 } l__mert_convertdigits_seq
__mert_digit:e { seq_item:Nn l__mert_convertdigits_seq { -1 } }
}
cs_generate_variant:Nn mert_convertdigits:n { e }
cs_new:Nn __mert_digit:n
{
str_case:nnF { #1 }
{
{0}{zero}
{1}{one}
{2}{two}
{3}{three}
{4}{four}
{5}{five}
{6}{six}
{7}{seven}
{8}{eight}
{9}{nine}
}
{#1}% not a digit
}
cs_generate_variant:Nn __mert_digit:n { e }
ExplSyntaxOff
begin{document}
section{a}
subsection{a1}label{key}
subsection{a2}
section{b}
subsection{b1}
subsection{b2}label{key2}
subsubsection{b3}
ref{key}, ref{key2}
defmyvar{2}
convertdigits{2}
convertdigits{myvar}
defmyvar{2.3}
convertdigits{myvar}
convertdigits{getrefnumber{key}}
convertdigits{getrefnumber{key2}}
end{document}
If you want to continue to use ref
in that context, you can change the main definition to
NewDocumentCommand{convertdigits}{m}
{
group_begin:
cs_set_eq:NN ref getrefnumber
mert_convertdigits:e { #1 }
group_end:
}
Answered by egreg on January 25, 2021
You can do something like this:
{defhbox#1{}defprotect#1empty{??}xdefreftext{ref{key}empty}}
convertdigits{reftext}
Answered by wipet on January 25, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP