I would like to define a macro for defining further macros to display sequences/lists/tuples of elements by specifying the following parameters:
- The name of the new command.
- What to display for an empty sequence/list/tuple.
- How to open a singleton sequence/list/tuple.
- How to close a singleton sequence/list/tuple.
- How to open a sequence/list/tuple with more than one element.
- How to close a sequence/list/tuple with more than one element.
- What to display as separating object between two elements in the sequence/list/tuple.
I had a look at the following questions and corresponding answers:
- When to use \edef, \noexpand, and \expandafter?
- What exactly do \csname and \endcsname do?
- Defining a newcommand, with variable name, inside another newcommand
- variable-name \newcommand with parameters within another \newcommand
So I tried to code my command and came up with the following two versions (the second one is outcommented in the code below). Unfortunately, none of them works and I cannot figure out what the problem is:
\documentclass{article}
\makeatletter
\newcommand{\definelistcommand}[7]{%
\expandafter\newcommand\csname @start#1\endcsname{\expandafter\@ifnextchar\csname @stop#1\endcsname{#2\csname @end#1\endcsname}{\csname @first#1\endcsname}}%
\expandafter\newcommand\csname @first#1\endcsname[1]{\expandafter\@ifnextchar\csname @stop#1\endcsname{#3##1#4\csname @end#1\endcsname}{#5##1\csname @next#1\endcsname}}%
\expandafter\newcommand\csname @next#1\endcsname[1]{#7##1\expandafter\@ifnextchar\csname @stop#1\endcsname{#6\csname @end#1\endcsname}{\csname @next#1\endcsname}}%
\expandafter\newcommand\csname @end#1\endcsname[1]{}% consumes the \stop command
\expandafter\newcommand\csname #1\endcsname[1]{\csname @start#1\endcsname##1\csname @stop#1\endcsname}%
}
\makeatother
% \makeatletter
% \edef\definelistcommand#1#2#3#4#5#6#7{%
% \noexpand\newcommand\expandafter\noexpand\csname @start#1\endcsname{\noexpand\@ifnextchar\expandafter\noexpand\csname @stop#1\endcsname{#2\expandafter\noexpand\csname @end#1\endcsname}{\expandafter\noexpand\csname @first#1\endcsname}}%
% \noexpand\newcommand\expandafter\noexpand\csname @first#1\endcsname[1]{\noexpand\@ifnextchar\expandafter\noexpand\csname @stop#1\endcsname{#3##1#4\expandafter\noexpand\csname @end#1\endcsname}{#5##1\expandafter\noexpand\csname @next#1\endcsname}}%
% \noexpand\newcommand\expandafter\noexpand\csname @next#1\endcsname[1]{#7##1\noexpand\@ifnextchar\expandafter\noexpand\csname @stop#1\endcsname{#6\expandafter\noexpand\csname @end#1\endcsname}{\expandafter\noexpand\csname @next#1\endcsname}}%
% \noexpand\newcommand\expandafter\noexpand\csname @end#1\endcsname[1]{}% consumes the \stop command
% \noexpand\newcommand\expandafter\noexpand\csname #1\endcsname[1]{\expandafter\noexpand\csname @start#1\endcsname##1\expandafter\noexpand\csname @stop#1\endcsname}%
% }
% \makeatother
\definelistcommand{mylist}{empty}{[}{]}{(}{)}{,}
\begin{document}
\mylist{{a}{b}{c}}
\mylist{{a}{b}}
\mylist{a}
\mylist{{b}}
\mylist{}
\end{document}
The desired output would be:
(a,b,c)
(a,b)
[a]
[b]
empty
For the first version, I get this error message:
! Missing \endcsname inserted.
<to be read again>
\let
l.27 \mylist{{a}{b}{c}}
For the second version, I get this:
! Undefined control sequence.
l.27 \mylist
{{a}{b}{c}}
What are the errors in my commands and how would a correct solution work?
EDIT (to point future readers to the fact that the accepted answer is not the only interesting one):
Although I accepted the answer by Christian Hupfer (since it contains an explanation and fix for my attempt), the other answers also contain valuable contributions. In particular, I will use egreg's solution as it allows a key-value pair specification of my desired parameters. Unfortunately, I cannot accept two answers.
Best Answer
Here's a
expl3
version withseq
variables.The command
\NewListCommand
declares the command list macro named like the first argument and uses a globalseq
variable with some prefix, see\g_cryingshadow_mynewlist_seq
etc.This is filled by the
\mynewlist
command and the content displayed depending on the content of the other parameters from #3 to #6. The 7th. parameter is used as a delimiterSome notes: The
empty
parameter could be an optional one.Edit: Here's the working version for usual LaTeX: