3

I want to create a macro in order to create the following effect:

Let's suppose this command is called command. Then I want the commands below to provide the image I've put after.

\command{}
\command{}{$40$}{}
\command{$20$}{$10$}{$5$}{}{$3$}
\command{$100$}{$80$}{$50$}

enter image description here

Is there a way to make such a command?

  • 4
    The way (La)TeX's macro processing works, defining commands with a variable number of arguments can become quite tricky and may lead to unexpected results in some cases. Why not just something like \cmd{100}\cmd{80}\cmd{50} instead? – siracusa Apr 2 '19 at 3:01
  • 1
    Or you could make it work with a comma-separated list like \command{20,10,5,,3}. – user121799 Apr 2 '19 at 4:21
2

It's much better to have one argument consisting of a comma separated list.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\overnumbers}{O{3}m}
 {% #1 = number of digits (optional), #2 = list of numbers
  \italo_overnumbers:nn { #1 } { #2 }
 }

\int_new:N \l__italo_overnumbers_digits_int
\seq_new:N \l__italo_overnumbers_list_seq
\tl_new:N \l__italo_overnumbers_first_tl

\cs_new_protected:Nn \italo_overnumbers:nn
 {
  \int_set:Nn \l__italo_overnumbers_digits_int { #1 }
  \__italo_overnumbers_prepare:n { #2 }
  \int_incr:N \l__italo_overnumbers_digits_int
  \__italo_overnumbers_print:
 }

\cs_new_protected:Nn \__italo_overnumbers_prepare:n
 {
  \seq_set_split:Nnn \l__italo_overnumbers_list_seq { , } { #1 }
  \seq_map_inline:Nn \l__italo_overnumbers_list_seq
   {
    \int_set:Nn \l__italo_overnumbers_digits_int
     {
      \int_max:nn { \l__italo_overnumbers_digits_int } { \tl_count:n { ##1 } }
     }
   }
 }

\cs_new_protected:Nn \__italo_overnumbers_print:
 {
  \seq_pop_left:NN \l__italo_overnumbers_list_seq \l__italo_overnumbers_first_tl  
  \__italo_overnumbers_make:V \l__italo_overnumbers_first_tl
  \seq_map_inline:Nn \l__italo_overnumbers_list_seq
   {
    \hspace*{0.5em}
    \__italo_overnumbers_make:n { ##1 }
   }
 }
\cs_new_protected:Nn \__italo_overnumbers_make:n
 {
  \ensuremath{\overline{
    \makebox[\dim_eval:n { (0.5em)*\l__italo_overnumbers_digits_int}]
     {
      $#1\vphantom{0}$
     }
  }}
 }
\cs_generate_variant:Nn \__italo_overnumbers_make:n { V }

\ExplSyntaxOff

\begin{document}

\overnumbers{}

\medskip

\overnumbers{,40,}

\medskip

\overnumbers{20,10,5,,3}

\medskip

\overnumbers{100,80,50}

\medskip

\overnumbers[4]{100,80,50}

\medskip

\overnumbers[2]{80,,50}

\medskip

\overnumbers{20080,50}

\end{document}

The optional argument (default 3) is for the number of digits, but it's automatically updated to accommodate bigger numbers, see the last example.

enter image description here

  • Would there be a practical way of adding numbers on the top of the line along with the bottom ones? – Italo Marinho Apr 12 '19 at 0:04
  • Another problem I've been having is that it doesn't autoscale the lines when I use \text{}. Am I doing something wrong? – Italo Marinho Apr 12 '19 at 0:14
  • @ItaloMarinho Sorry, but you didn't specify the details. For instance, you didn't tell where the line should go with respect to the base line, nor the context where you want to use this. Please, open a new question and try to be more specific. – egreg Apr 12 '19 at 6:20
3

I mean that usage of \command{a,b,c} instead \command{$a$}{$b$}{$c$} is better.

\def\ruleabove{\vrule width15pt height.8pt}
\def\command#1{\hbox{\commandA#1,\end,\unskip}}
\def\commandA#1,{\ifx\end#1\relax \else 
   \vtop{\halign{\hfil##\hfil\cr\ruleabove\cr\noalign{\kern-2pt}$#1$\cr}}\quad
   \expandafter\commandA\fi}

\command{21, 10, 5, , 3}

\bye
2

If you are willing to consider a comma-separated list instead, here is one of many options to do something along the lines you suggest. (Otherwise, as pointed out by siracusa, things may become more involved.)

\documentclass{article}
\usepackage{amsmath}
\usepackage{pgffor}
\newcommand{\multioverline}[1]{\foreach \X[count=\Y] in {#1}
{\pgfmathsetmacro{\mywidth}{max(12pt,width("\X")+3pt)}
\ifnum\Y=1
\ensuremath{\overline{\mathstrut\makebox[\mywidth pt][c]{\X}}}%
\else
~\ensuremath{\overline{\mathstrut\makebox[\mywidth pt][c]{\X}}}%
\fi}}
\begin{document}
\multioverline{20,10,5,,3}
\end{document}

enter image description here

1

I assume the OP wants the width of the overlined units to be fixed, rather than to grow with the argument. Thus, if larger numbers are to be accommodated, then merely increase the 1.8em rule length in the macro.

The rule thickness, length and overset gap are all specified lengths in the macro, which can be changed to suit.

\documentclass{article}
\usepackage{stackengine,listofitems}
\newcommand\moverline[1]{%
  \setsepchar{,}%
  \readlist*\mynums{ #1}%
  \foreachitem\x\in\mynums[]{%
    \stackengine{0pt}{\,\,\rule[.95\ht\strutbox]{1.8em}{.6pt}\,\,}{\x}{O}{c}{F}{T}{L}%
  }%
}
\parskip=1.5ex
\begin{document}
\moverline{}

\moverline{,40,}

\moverline{20,10,5,,3}

\moverline{100, 80,  50}

\moverline{100,20000,300} $<$--- perhaps adjust rule length
\end{document}

enter image description here

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.