4

For convenience (and also to deepen my LaTeX knowledge), I'm trying to define a list in a simple manner: \mylist(First, Second, Third, ...)

Replacing the commas by something else (in this case by \texttt{,} works, but I have trouble to convert the ellipsis at the end. When there is a single dot in any part, my solution brakes.

This is my MWE:

\documentclass[a4paper]{article} \makeatletter \def\mylist (#1){% \begingroup% \begingroup\lccode`~=`, \lowercase{\endgroup\def~}{\texttt{,} }% \begingroup\lccode`~=`. \lowercase{\endgroup\def~~~}{\texttt{...}}% \catcode`,=\active% \catcode`.=\active% \texttt{(}\scantokens{#1}\texttt{)}% \endgroup% }% \makeatother \begin{document} % This works: \mylist(First, Second, Third, ...) % This should always work: Some text with ... dots ... that \ldots should not be changed. Dots in \textbf{.} commands should also work. % This does not work: % Expected: \texttt{(}First\texttt{,} Second\texttt{, } Th.rd\texttt{, }\texttt{...}\texttt{)} % Error: ! Use of . doesn't match its definition. \mylist(First, Second, Th.rd, ...) \end{document} 

Also, if you have any other suggestions for improvements, feel free to tell me.

8
  • 1
    Welcome to TeX.SE. Commented Mar 6, 2024 at 19:53
  • 3
    Is there some reason why you do not use \textellipsis for the three dots? Or, if you are compiling with a utf8-aware engine (such as lualatex you can simply past the ellipsis from a character map. Commented Mar 6, 2024 at 20:06
  • 3
    @rallg The only reason why I'd prefer to use ... is because it is the most natural way for me to write an incomplete list. Also, I'd like to understand how I could do it to deepen my understanding of TeX. Commented Mar 6, 2024 at 20:11
  • 1
    if you do this things will break, just use \ldots Commented Mar 7, 2024 at 0:11
  • 1
    if you globally make . active it is hard not to break some uses in numbers etc, if you keep it restricted to the list macro and never use that macro in the argument of any other command and never have any math or lengths inside the list then it's perhaps safe enough, but that's a lot of ifs to use a syntax that will confuse any human readers of the source and confuse some conversions to html etc. Commented Mar 7, 2024 at 14:03

3 Answers 3

2

You can check if a next dot follows by the \futurelet TeX primitive:

\def\mylist (#1){% \begingroup% \catcode`,=\active \catcode`.=\active \texttt{(}\scantokens{#1}\texttt{)}% \endgroup% }% \begingroup\lccode`~=`, \lowercase{\endgroup\def~}{\texttt{,} } \begingroup\lccode`~=`. \lowercase{\endgroup \def~{\threedots} \def\threedots{\futurelet\next\threedotsA} \def\threedotsA{\ifx\next~\expandafter\threedotsB \else .\fi} \def\threedotsB~~{\texttt{...}} }% end \lowercase 

In the \lowercase scope is ~ replaced by active dot when the macros are defined. The . itself is non-active dot.

2
  • Is there a reason why you have the definitions for , and \threedots outside of the defintion of \mylist? I have it inside the definition of \mylist, which still works. Also, thank you for your solution! Commented Mar 7, 2024 at 12:45
  • Maybe, you will run \mylist more than once in the document. We can do these definitions only once and not to run definitions repeatedly for each \mylist. Commented Mar 7, 2024 at 18:51
2

No \scantokens.

\documentclass[a4paper]{article} \ExplSyntaxOn \NewDocumentCommand{\mylist}{r()} { \tl_set:Nn \l_tmpa_tl { #1 } \tl_replace_all:Nnn \l_tmpa_tl { , } { \texttt{,} } \tl_replace_all:Nnn \l_tmpa_tl { ... } { \texttt{...} } \texttt{(} \tl_use:N \l_tmpa_tl \texttt{)} } \ExplSyntaxOff \begin{document} \mylist(First, Second, Third, ...) \mylist(First, Second, Th.rd, ...) \end{document} 

enter image description here

2
  • Your solution works. I am very unfamiliar with the "new" syntax. Is there an advantage not to use \scantokens? Commented Mar 7, 2024 at 12:43
  • @E_3 Not using active characters is always an advantage Commented Mar 7, 2024 at 15:43
1

Here is an approach with parsing accomplished via listofitems:

\documentclass{article} \usepackage{listofitems} \setsepchar{,/...} \def\mylist(#1){\readlist*\mylistitems{#1}% \foreachitem\z\in\mylistitems{% \ifnum\zcnt=1\else\texttt{, }\fi \ifnum\listlen\mylistitems[\zcnt]=1\relax\z\else\texttt{\z}\fi }% } \begin{document} \mylist(First, Second, Third, ...) \mylist(First, Second, Th.rd, ...) \end{document} 

enter image description here

1
  • Thank you ... your solutions works. Yet, I'd prefer not to use another package. Commented Mar 7, 2024 at 12:42

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.