# Defining a macro with combine many options to one bracket

I am beginner in writing macros with multi options. What I want to do, is to combine many options to one pair of brackets.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\def\DLineS{%
\@ifnextchar[%
{\DLineS@i}
{\DLineS@i[1.25]}%
}
\def\DLineS@i[#1]{%
\@ifnextchar[%
{\DLineS@ii{#1}}
{\DLineS@ii{#1}[-0.25]}%
}
\def\DLineS@ii#1[#2]#3#4{%
\draw[latex-latex] ($(#3)!#2!(#4)$) -- ($(#3)!#1!(#4)$)
}
\makeatother
\begin{document}
\begin{tikzpicture}
\coordinate[label=below:{\small $A$}] (A) at (0,0);
\coordinate[label=below:{\small $B$}] (B) at (1,1);
\filldraw (A) circle (1.5pt);
\filldraw (B) circle (1.5pt);
\DLineS[1.5][-0.75]{A}{B};
% I want this line is \DLineS[1.5,-0.75]{A}{B};
\end{tikzpicture}
\end{document}

• You want to have a macro with two options? or just the splitting of the first [,] ? – user31729 Sep 8 '14 at 7:23
• Maybe \DLineS[a]{A}{B}->\DLineS@ii{a}[-.25]{A}{B} while \DLineS[a,b]{A}{B}->\DLineS@ii{a}[b]{A}{B}. But \DLineS[a]{A}{B}->\DLineS@ii{a}[1-a]{A}{B} also makes sense. – Symbol 1 Sep 8 '14 at 9:07

It is not recommended to play with \def unless you know what you are doing. If so, you can do the following. Otherwise consider egreg's answer using xparse.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\def\DLineS{\@ifnextchar[%
{\DLineS@i}{\DLineS@i[1.25]}}
\def\DLineS@i[#1]{\@ifnextchar[%
{\DLineS@ii{#1}}{\DLineS@iii#1,;}}
\def\DLineS@ii#1[#2]#3#4{%
\draw[latex-latex]($(#3)!#2!(#4)$)--($(#3)!#1!(#4)$)}
\def\DLineS@iii#1,#2;#3#4{\def\temp{#2}\ifx\temp\empty%
\DLineS@ii#1[-.25]{#3}{#4}\else\DLineS@iv[#1][#2]{#3}{#4}\fi}
\def\DLineS@iv[#1][#2,]{\DLineS@ii#1[#2]}
\makeatother
\begin{document}
\begin{tikzpicture}
\coordinate[label=below:{\small $A$}](A)at(0,0);
\coordinate[label=below:{\small $B$}](B)at(1,1);
\coordinate[label=below:{\small $C$}](C)at(2,0);
\coordinate[label=below:{\small $D$}](D)at(3,1);
\coordinate[label=below:{\small $E$}](E)at(4,0);
\coordinate[label=below:{\small $F$}](F)at(5,1);
\coordinate[label=below:{\small $G$}](G)at(6,0);
\coordinate[label=below:{\small $H$}](H)at(7,1);
\filldraw(A)circle(1.5pt)(B)circle(1.5pt)(C)circle(1.5pt)(D)circle(1.5pt)(E)circle(1.5pt)(F)circle(1.5pt)(G)circle(1.5pt)(H)circle(1.5pt);
\DLineS[1.5][-0.75]{A}{B};
\DLineS[1.5,-0.75]{C}{D};
\DLineS[1.5]{E}{F};
\DLineS{G}{H};
\end{tikzpicture}
\end{document}

• Yes, this is good solution. Thanks for your attention. – somkiat_t Sep 9 '14 at 0:30

You can do it with xparse:

\documentclass{article}
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{calc}

\NewDocumentCommand{\DLineS}{>{\SplitArgument{1}{,}}O{1.25,-0.25}mm}{%
% no optional argument is like calling [1.25,-0.25]
\DLineSaux#1{#2}{#3}%
}

\NewDocumentCommand{\DLineSaux}{mmmm}{%
\IfNoValueTF{#2}%
{\DLineSaux{#1}{-0.25}{#3}{#4}}% no comma in the optional argument, use -0.25
{\draw[latex-latex] ($(#3)!#2!(#4)$) -- ($(#3)!#1!(#4)$)}%
}

\begin{document}

\begin{tikzpicture}
\coordinate[label=below:{\small $A$}] (A) at (0,0);
\coordinate[label=below:{\small $B$}] (B) at (1,1);
\filldraw (A) circle (1.5pt);
\filldraw (B) circle (1.5pt);
\DLineS[1.5,-0.75]{A}{B};
\end{tikzpicture}
\begin{tikzpicture}
\coordinate[label=below:{\small $A$}] (A) at (0,0);
\coordinate[label=below:{\small $B$}] (B) at (1,1);
\filldraw (A) circle (1.5pt);
\filldraw (B) circle (1.5pt);
\DLineS{A}{B};
\end{tikzpicture}
\begin{tikzpicture}
\coordinate[label=below:{\small $A$}] (A) at (0,0);
\coordinate[label=below:{\small $B$}] (B) at (1,1);
\filldraw (A) circle (1.5pt);
\filldraw (B) circle (1.5pt);
\DLineS[1.5]{A}{B};
\end{tikzpicture}
\end{document}


We do three steps; in the first step we just pass control to \DLineSaux after splitting the optional argument at the comma; if no optional argument is given, [1.25,-0.25] is passed; if just the first part is present (see third example), xparse passes -NoValue- to the next stage, so in this case we simply recall \DLineSaux with -0.25 as the second argument.

• @eqreg: Thanks so much for your advice. This is basic knowledge for me in the future. I don't want other package (xparse). – somkiat_t Sep 9 '14 at 0:55
• @eqreg:I do not understand how to use the command \DlineSaux. – somkiat_t Sep 9 '14 at 1:09
• @somkiat_t You don't use it explicitly; it is just an auxiliary command run by \DLineS. – egreg Sep 9 '14 at 9:50