2

I want to draw time axes to illustrate time calculations. When I place this macro defined here by @egreg I have these error:

! Undefined control sequence. \LaTeX3 error: Missing * inserted.

Here is the result I got with a foreach loop alone, without this macro.

\foreach \h/\min in {1/15,4/45,9/30}
    {\draw (\h,.15)--++(0,-.3)node[below]{\h\,h \min\,min};
    }

screenshot

\documentclass{article}
\usepackage{tikz}
\usepackage[french]{babel}
\usetikzlibrary{babel}
% from https://tex.stackexchange.com/a/511874/138900
\usepackage{xparse}
\usepackage{siunitx}

\sisetup{locale=FR}

\ExplSyntaxOn

\NewDocumentCommand{\hms}{ o m }
 {
  \ensuremath
   {
    \IfNoValueTF { #1 }
     {
      \andrec_hms:Ve \l_andrec_hms_sep_str { \tl_to_str:n { #2 } }
     }
     {
      \andrec_hms:ee { \tl_to_str:n { #1 } } { \tl_to_str:n { #2 } }
     }
   }
 }
\NewDocumentCommand{\sethmssep}{m}
 {
  \str_set:Nn \l_andrec_hms_sep_str { #1 }
 }

\cs_new_protected:Nn \andrec_hms:nn
 {
  \group_begin:
  \seq_set_split:Nnn \l__andrec_hms_seq { #1 } { #2 }
  % normalize the sequence to have three (or more!) items
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 1 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 2 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  % print
  \bool_set_false:N \l__andrec_hms_thinspace_bool
  \__andrec_hms_print:nn { 1 } { h }
  \__andrec_hms_print:nn { 2 } { m }
  \__andrec_hms_print:nn { 3 } { s }
  \group_end:
}
\cs_generate_variant:Nn \andrec_hms:nn { Ve,ee }

\cs_new_protected:Nn \__andrec_hms_print:nn
 {
  \fp_compare:nF { 0\seq_item:Nn \l__andrec_hms_seq { #1 } = 0 }
   {
    \bool_if:NT \l__andrec_hms_thinspace_bool { \, }
    \num{\fp_eval:n { 0\seq_item:Nn \l__andrec_hms_seq { #1 } }} \, \mathrm{#2}
    \bool_set_true:N \l__andrec_hms_thinspace_bool
   }
 }
\ExplSyntaxOff

\sethmssep{:}
\begin{document}
\begin{tikzpicture}
\draw[->] (-.5,0)--(10,0);
\foreach \h/\min in {1/15,4/45,9/30}
    {\draw (\h,.15)--++(0,-.3)%node{$\hms{\h:\min}$};%<- this dont work !
    node[below]{\h\,h \min\,min};
    }
\end{tikzpicture}
\end{document}

Is it possible to improve this macro for writing sexagesimal durations so that it can be used in a foreach loop?

2

Get rid of \tl_to_str:n in the argument -- this prevents expansion of the argument which is what you need. I only changed two lines in the code, which I have marked with comments.

\documentclass{article}
\usepackage{tikz}
\usepackage[french]{babel}
\usetikzlibrary{babel}
% from https://tex.stackexchange.com/a/511874/138900
\usepackage{xparse}
\usepackage{siunitx}

\sisetup{locale=FR}

\ExplSyntaxOn

\NewDocumentCommand{\hms}{ o m }
 {
  \ensuremath
   {
    \IfNoValueTF { #1 }
     {
      \andrec_hms:Ve \l_andrec_hms_sep_str { #2 } % Used to say \tl_to_str:n { #2 }
     }
     {
      \andrec_hms:ee { \tl_to_str:n { #1 } } { #2 } % Used to say \tl_to_str:n { #2 }
     }
   }
 }
\NewDocumentCommand{\sethmssep}{m}
 {
  \str_set:Nn \l_andrec_hms_sep_str { #1 }
 }

\cs_new_protected:Nn \andrec_hms:nn
 {
  \group_begin:
  \seq_set_split:Nnn \l__andrec_hms_seq { #1 } { #2 }
  % normalize the sequence to have three (or more!) items
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 1 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 2 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  % print
  \bool_set_false:N \l__andrec_hms_thinspace_bool
  \__andrec_hms_print:nn { 1 } { h }
  \__andrec_hms_print:nn { 2 } { m }
  \__andrec_hms_print:nn { 3 } { s }
  \group_end:
}
\cs_generate_variant:Nn \andrec_hms:nn { Ve,ee }

\cs_new_protected:Nn \__andrec_hms_print:nn
 {
  \fp_compare:nF { 0\seq_item:Nn \l__andrec_hms_seq { #1 } = 0 }
   {
    \bool_if:NT \l__andrec_hms_thinspace_bool { \, }
    \num{\fp_eval:n { 0\seq_item:Nn \l__andrec_hms_seq { #1 } }} \, \mathrm{#2}
    \bool_set_true:N \l__andrec_hms_thinspace_bool
   }
 }
\ExplSyntaxOff

\sethmssep{:}
\begin{document}
\begin{tikzpicture}
\draw[->] (-.5,0)--(10,0);
\foreach \h/\min in {1/15,4/45,9/30}
    {
        \draw (\h,.15)--++(0,-.3) node{$\hms{\h:\min}$};
    }
\end{tikzpicture}
\end{document} 
|improve this answer|||||
  • Your solution is compatible with the calculations made in egreg's previous answer. So what is the use of this function that you have deleted if it is possible to do without it? – AndréC Nov 18 '19 at 17:47
  • You would have to ask egreg, but my guess is that he was concerned that the colon could be assigned some unusual category code. For instance, \ExlSyntaxOn sets the catcode of : to be letter, so with my definition \ExplSyntaxOn\hms{1:20}\ExplSyntaxOff throws an error "\LaTeX3 error: Missing ? inserted for ?:." where the original wouldn't. – Hood Chatham Nov 18 '19 at 20:10
  • However, it seems to me that the your use case where you want to use the function with a variable might be a bit more common than wanting to use it with a weird category code. It's possible that Babel might set : to be active in some cases, I don't know anything about Babel but I know it makes some extra active characters. There is a \scantokens approach that could deal with that and still allow macros in the argument. – Hood Chatham Nov 18 '19 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.