0

I am writing a macro with many arguments, many of which may be optional. Example of how I imagine it:

\newcommand{\mycommand}[width, height, density=1, joy=0]{Only \texttt{width} of value #width is used.}

\mycommand[width=10, joy=-1, height=2]

I know that LaTeX supports optional arguments, but I can't refer to them by name, what in more complicated macros is a great deal for readability. Also, if I want to remove an argument from the middle, I would need to renumerate all arguments used in the macro's body, which is a pain.

What are the most convenient and sensible ways to accomplish this? I prefer a LaTeX solution, but I can switch to another engine if it would significantly improve the experience.

radrow
  • 123
  • I suspect you are coming from a language where you think of keyvals as separate optional arguments. In (La)TeX terms, here you have one optional argument (the square brackets), which you are then interpreting as a set of keyvals. That's a common form in LaTeX, so it's quite doable - am I right in my reading of your question? – Joseph Wright Feb 15 '22 at 14:20
  • Yes, you got it right. From your comment I guess I am looking for something that would parse arguments? – radrow Feb 15 '22 at 14:26
  • 1
    Exactly. There is a number of packages to this end. The most basic one is keyval. – AlexG Feb 15 '22 at 14:30
  • Someone should also mention pgfkeys. – John Kormylo Feb 15 '22 at 14:44
  • 2
    @JohnKormylo I think if this is 'how to parse keyvals', we likely want to mark as a dupe of https://tex.stackexchange.com/questions/26771/a-big-list-of-every-keyval-package, which does cover pgfkeys :) – Joseph Wright Feb 15 '22 at 15:03

1 Answers1

3

I will do a demo using l3keys, as follows ...

\documentclass{article}
\usepackage{l3draw}
\ExplSyntaxOn
\keys_define:nn{rectangle}
{
  width.dim_set:N        = \l_width_dim,
  width.default:n        = 2cm,
  width.initial:n        = 2cm,
  height.dim_set:N       = \l_height_dim,
  height.default:n       = 3cm,
  height.initial:n       = 3cm,
  linewidth.dim_set:N    = \l_linewidth_dim,
  linewidth.default:n    = 1pt,
  linewidth.initial:n    = 1pt,
  color.tl_set:N         = \l_color_tl,
  color.default:n        = cyan,
  color.initial:n        =cyan
}
\NewDocumentCommand{\rectangle}{O{}}
{
  \group_begin: 
  \keys_set:nn{rectangle}{#1}
  \draw_begin:
    \draw_linewidth:n{\dim_use:N \l_linewidth_dim}
    \draw_path_rectangle:nn{0,0}{\dim_use:N \l_width_dim,\dim_use:N \l_height_dim}
    \color_select:x{\tl_use:N\l_color_tl}
    \draw_path_use:n { stroke }
  \draw_end:
  \group_end:
}
\cs_generate_variant:Nn\color_select:n{x}
\ExplSyntaxOff
\begin{document}

\rectangle\par \rectangle [ width = 3cm, height = 2cm, color = red ]

\end{document}

enter image description here

ljguo
  • 1,213
  • 1
  • 4
  • 12