2

To avoid typing subscripts and extra parentheses and brackets, I want to define a command, say \disk, that may be used with a comma-separated list of either 2 or 3 arguments, like this:

$\disk{r,x}$
$\disk{r,x,d}$

that will produce, respectively, the same output as would directly typing:

$D_{r}(x)$
$D_{r}(x;d)$

[The r, x, and d could, of course, by any letter or number, etc. For example, I might use \disk{\epsilon, 0, D}, etc.]

Using xparse or otherwise, how might this be done?

Although I am aware that the two different outputs could be obtained by using an optional argument, that would require typing the 3rd, optional argument inside brackets; and in any case even for the case of only two arguments, I want to speed up typing by using just the comma-separated list {x, d} rather than {x}{d}.

4

You have to assume there are three items; if there aren't, the missing ones are automatically passed to the inner macro as “No Value”.

Then the inner macro can check for the value being given.

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\disk}{ >{\SplitArgument{2}{,}} m }{\printdisk#1}
\NewDocumentCommand{\printdisk}{mmm}{D_{#1}(#2\IfValueT{#3}{;#3})}

\begin{document}

$\disk{r,x}$

$\disk{r,x,s}$

\end{document}

enter image description here

A different implementation:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\disk}{m}
 {
  % split the input at commas
  \seq_set_split:Nnn \l_murray_disk_input_seq { , } { #1 }
  % remove the leftmost item
  \seq_pop_left:NN \l_murray_disk_input_seq \l_murray_disk_radius_tl
  % print; _ is not available here
  D\c_math_subscript_token{\l_murray_disk_radius_tl}
    (\seq_use:Nn \l_murray_disk_input_seq { ; })
 }
\seq_new:N \l_murray_disk_input_clist
\tl_new:N \l_murray_disk_radius_tl
\ExplSyntaxOff

\begin{document}

$\disk{r,x}$

$\disk{r,x,s}$

\end{document}
  • 3
    However, typing $D_{r}(x;s)$ seems easier – egreg Aug 28 '16 at 20:07
  • Not easier to type for me! Without the macro, the direct way requires a separate finger reach for _ and either typing the pair of braces around the subscript or else (in TeXShop) moving the cursor beyond the automatically supplied pair of braces. With the macro, I don't have to stop each time to think whether I want a comma or a semicolon before the 3rd item (the metric), and should I change my mind about that style, I can do it just once, within the macro definition. – murray Aug 28 '16 at 20:26
  • The real trick in the Answer is that \printdisk uses the triple-m expression mmm even when I use \disk with only 2 items in the comma-separated list. – murray Aug 28 '16 at 20:28
  • Oops, doesn't work for something like $\disk{\epsilon,(1,2),\rho}$. My workaround for that is $\disk{\epsilon,{(1,2)},\rho}$ -- a slight annoyance of extra braces. – murray Aug 28 '16 at 20:36
  • @murray If you plan to use something like (1,2), then change the delimiter in the argument, say ; – egreg Aug 28 '16 at 20:38
4

We can do this at TeX primitive level without any xparse or another package. Note, there are only two lines of code.

\def\disk#1{\diskA#1,,\end}
\def\diskA#1,#2,#3,#4\end{D_{#1}\ifx,#3,(#2)\else (#2;#3)\fi}

$\disk{r,x}$

$\disk{r,x,s}$

\end

If you need to do something like this $\disk{\epsilon,(1,2),\rho}$ then add one line of code:

\def\disk#1{\diskA#1()\end}
\def\diskA#1(#2)#3\end{\ifx\end#3\end\diskB#1,,\end \else\diskA#1{(#2)}#3\end \fi}
\def\diskB#1,#2,#3,#4\end{D_{#1}\ifx,#3,(#2)\else (#2;#3)\fi}

$\disk{r,x}$

$\disk{r,x,s}$

$\disk{\epsilon,(1,2),\rho}$

\end
  • Hard now for me to choose which answer to accept: your pure TeX method is nicely terse, yet the more complicated LaTeX (with xparse) seemingly leaves things at the higher level of abstraction that avoids TeX primitives. Wish I could accept both! – murray Aug 30 '16 at 20:18

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.