# Create simple repetitive macro with optional argument

I would like the simplest (in terms of length of characters) way to create a macro that does something or, optionally, does something n times.

In fact, all I want to do is to create something like --------X where the -s go from 1 to n. I do not want to have to supply 1 to the macro as that is default and the most used case.

So

\dash{X} gives -X
\dash[3]{X} gives ---X
or
\dash{X}[3] gives ---X
or
\dash{X}{3} gives ---X
or
\dash{3}{X} gives ---X


I don't care about the syntax. Just that it is short and works as intended and should be efficient. I probably don't want to have nested groups used because there would be no point and it would be inefficient, but either way doesn't matter.

I'd like to use as little extra packages as possible unless some package does this well to make it pretty short.

Something like

\newcommand{\dash}[2][1]{\directlua{for i=1,#1 do tex.print('-') end}#2}%


works with LuaLaTeX but tex.print seems to add a space after/before each dash resulting in - - - -X.

• Since it appears you have problems with the given images, could you please add some more information about intended usage? – egreg Feb 5 '17 at 11:09
• @egreg huh? I assume you are talking about the spacing? If so, I am simply trying to reduce the space between the symbols(-, +, x, y, or whatever) because I use these things in a large table and can only fit so much information in it. The symbol's touching or closer than normal does not cause any problems in my case but having too much space, like - - X will use far to much space creating a table that won't fit on a page, etc. It's not a huge deal, I can shrink the table... but only so far. Luckily I was able to get a reasonable result with the default space. – AbstractDissonance Feb 5 '17 at 11:16
• That's caused by math mode automatic spacing: if you use Werner's \dash: fix Werner's code by doing \prg_replicate:nn {#1}{{#2\kern0pt}}#3 – egreg Feb 5 '17 at 11:20

Using xparse (with options):

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\dash}{O{1} O{-} m}{%
\prg_replicate:nn {#1} {#2}#3
}
\ExplSyntaxOff

\begin{document}

\dash{X}

\dash[2]{X}

\dash[15][{{-}}]{X}

\dash[7][a]{X}

\end{document}


Reference: Repeat characters n times

• Why does using a + cause a space/gap between each one? Same with - one of your examples. Similar to my directlua example. I want to use +++ to have no spaces between them similar to your ------- example. In my code the +'s have almost the a whole space ' ' between them(seems like it). This might just be a property of the characters but the -'s have no space in your example yet for length of 2. When I use your example with a rep of 15 there are no spaces, unlike yours. I need to minimize space between these characters so give me the room I need for other things. – AbstractDissonance Feb 5 '17 at 5:36
• - is special, since pairs of dashes are turned into an endash, and 3 dashes become an emdash. If you want to remove the spaces between + (say), try with \def\bsp{\def\bsp{$\!$}} \dash[15][\bsp+]{X}. – Werner Feb 5 '17 at 5:53
• When I use this in my real document I get errors. When I use it in the demo document it works. I put \bsp in the macro you provide, e.g., \bsp#2 and it works as expected. In my code, the only real difference is I'm using the macros in a tikzpicture environment(a matrix). Any idea why it would fail? – AbstractDissonance Feb 5 '17 at 6:17
• @AbstractDissonance Sorry, no. Not sure what it could be. – Werner Feb 5 '17 at 6:54
• I believe it is because you are using matrix a matrix of math nodes. (which, one would assume would remove the space but it doesn't...). I tried removing the  but nothing changed. Is there a way to create a new normal symbol like + and - that simply do not have space or is space something that tex adds after the fact? – AbstractDissonance Feb 5 '17 at 7:09

Just use one of David Kastrup's good old \replicate-macros that are described here:

Example:

\documentclass{article}

\makeatletter
\newcommand\xii[2]{\if#2m#1\expandafter\xii\else\expandafter\@gobble\fi{#1}}
\newcommand\xiii{}\long\def\xiii#1\relax#2{\xii{#2}#1\relax}
\newcommand\replicate[1]{\expandafter\xiii\romannumeral\number\number#1 000\relax}
%
\newcommand\dash[1][1]{\replicate{#1}{-}\@firstofone}
%
% You can avoid consecutive dashes yielding en-dash-ligatures and em-dash-ligatures
% by wrapping the single dash into braces---\hyphendash yields hyphens:
%
\newcommand\hyphendash[1][1]{\replicate{#1}{{-}}\@firstofone}
\makeatother

\begin{document}

\verb|\dash[0]{X}| should yield X and indeed yields \dash[0]{X}

\verb|\dash{X}| should yield -X and indeed yields \dash{X}

\verb|\dash[1]{X}| should yield -X and indeed yields \dash[1]{X}

\verb|\dash[2]{X}| should yield --X and indeed yields \dash[2]{X}

\verb|\dash[3]{X}| should yield ---X and indeed yields \dash[3]{X}

\verb|\hyphendash[0]{X}| should yield X and indeed yields \hyphendash[0]{X}

\verb|\hyphendash{X}| should yield {-}X and indeed yields \hyphendash{X}

\verb|\hyphendash[1]{X}| should yield {-}X and indeed yields \hyphendash[1]{X}

\verb|\hyphendash[2]{X}| should yield {-}{-}X and indeed yields \hyphendash[2]{X}

\verb|\hyphendash[3]{X}| should yield {-}{-}{-}X and indeed yields \hyphendash[3]{X}

\end{document}


If it is only about dashes/hyphens and if you don't want dashes/hyphens to be broken across lines, you can probably also fill a horizontal box of predetermined width with horizontal \leaders:

\documentclass{article}

\makeatletter
\newbox\mytempbox
\newcommand\nobreakhyphendash[1][1]{%
\begingroup
\setbox\mytempbox\hbox{-}%
\endgroup
\@firstofone
}
\makeatother

\begin{document}

\verb|\nobreakhyphendash[0]{X}| should yield X and indeed yields \nobreakhyphendash[0]{X}

\verb|\nobreakhyphendash{X}| should yield {-}X and indeed yields \nobreakhyphendash{X}

\verb|\nobreakhyphendash[1]{X}| should yield {-}X and indeed yields \nobreakhyphendash[1]{X}

\verb|\nobreakhyphendash[2]{X}| should yield {-}{-}X and indeed yields \nobreakhyphendash[2]{X}

\verb|\nobreakhyphendash[3]{X}| should yield {-}{-}{-}X and indeed yields \nobreakhyphendash[3]{X}

\verb|\nobreakhyphendash[15]{X}| should yield {-}{-}{-}{-}{-}{-}{-}{-}{-}{-}{-}{-}{-}{-}{-}X and indeed yields \nobreakhyphendash[15]{X}

\end{document}


You might enjoy this generalization:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\pattern}{>{\SplitList{,}}m}
{
\ProcessList{#1}{\MakePattern}
}
\NewDocumentCommand{\MakePattern}{m}
{
\MakePatternAux #1 \MakePatternAux
}
\NewDocumentCommand{\MakePatternAux}{O{1}u{\MakePatternAux}}
{
\prg_replicate:nn { #1 } { {#2} }
}
\ExplSyntaxOff

\begin{document}

\pattern{[3]-,X,-,Y,[5]abc}

$\pattern{[3]-,X,-,Y,[5]+}$

\end{document}


You describe a pattern by a comma separated list of items: X means “print one copy of X”, while [5]Y means “print five copies of Y). The additional braces make TeX into not adding automatic spacing between atoms, because all are treated as ordinary atoms. Items can be more than one token.

• Just a side comment: is it appropriate to use NewDocumentCommand` for definitions that aren't intended to be author-level? – Sean Allred Feb 5 '17 at 17:47
• @SeanAllred Why not? – egreg Feb 5 '17 at 18:53
• I dunno… 'new document command' does seem to imply it will be document-/author-level. – Sean Allred Feb 5 '17 at 18:54
• @SeanAllred Probably there should be an inner interface also for reading optional arguments. – egreg Feb 5 '17 at 18:57