2

I need to get the first length in a list of lengths and store it in a variable.

This is what I got so far:

\documentclass[12pt,a4paper]{article}

\newlength{\mylength}

%% does not work at all
%\usepackage{xstring}
%\newcommand{\mylengthlist}[1]{
%   \noexpandarg%
%   \def\firstitem{\StrBefore{#1}{,}}%
%   \setlength{\mylength}{\firstitem}% 
%}

% works, but this seems to much processing for this task
\usepackage{xparse}
\NewDocumentCommand{\mylengthlist}{
    >{\SplitList{,}} m
}{
    \thisisthefirsttrue
    \ProcessList{#1}{\myfirst}
}
\newif\ifthisisthefirst
\newcommand{\myfirst}[1]{
    \ifthisisthefirst
        \setlength{\mylength}{#1}
        \thisisthefirstfalse
    \fi
}
    

\begin{document}
  \mylengthlist{2in, 2cm, 10pt}
  Test 1: \rule{\mylength}{1pt}\par
  \mylengthlist{0.8\textwidth, 2cm, 10pt}
  Test 2: \rule{\mylength}{1pt}
\end{document}

The macro \mylengthlist gets a comma separated list of lengths (one or more) and sets \mylength to the value of the first item.

Unfortunately I think I'm doing too much processing just to get the first item.

I tried using the package xstring, but what I get is not recognized as a length by \setlength.

I hope someone can help me with a better solution.

3 Answers 3

1

It's a one-liner with expl3:

\documentclass[12pt,a4paper]{article}

\newlength{\mylength}

\ExplSyntaxOn
\NewDocumentCommand{\mylengthlist}{m}
 {
  \setlength{\mylength}{ \clist_item:nn { #1 } { 1 } }
 }
\ExplSyntaxOff

\begin{document}

\mylengthlist{2in, 2cm, 10pt}
Test 1: \rule{\mylength}{1pt}

\mylengthlist{0.8\textwidth, 2cm, 10pt}
Test 2: \rule{\mylength}{1pt}

\end{document}

enter image description here

Bonus: you can add an optional argument and choose what list item to use.

\documentclass[12pt,a4paper]{article}

\newlength{\mylength}

\ExplSyntaxOn
\NewDocumentCommand{\mylengthlist}{O{1}m}
 {
  \setlength{\mylength}{ \clist_item:nn { #2 } { #1 } }
 }
\ExplSyntaxOff

\begin{document}

\mylengthlist{2in, 2cm, 10pt}
Test 1: \rule{\mylength}{1pt}

\mylengthlist{0.8\textwidth, 2cm, 10pt}
Test 2: \rule{\mylength}{1pt}

\mylengthlist[2]{0.8\textwidth, 2cm, 10pt}
Test 3: \rule{\mylength}{1pt}

\end{document}

enter image description here

3
  • I marked this one as the accepted answer firstly because I'm already using lists and secondly because I can understand it better (some aspects of TeX are a total mystery to me yet...). I'll try to take a closer look at the other answers in order to learn more!
    – Jander
    Jun 29, 2021 at 14:08
  • Just noticed you should add \usepackage{xparse}, right? :-) With pdflatex it's needed anyway.
    – Jander
    Nov 23, 2021 at 13:47
  • @Jander Not if you use the current LaTeX
    – egreg
    Nov 23, 2021 at 15:13
2

enter image description here

\documentclass{article}

\newlength\mylength
\def\mylengthlist#1{\afterassignment\zmylengthlist\mylength#1!}\def\zmylengthlist#1!{}


\begin{document}
  \mylengthlist{2in, 2cm, 10pt}
  Test 1: \rule{\mylength}{1pt}\par
  \mylengthlist{0.8\textwidth, 2cm, 10pt}
  Test 2: \rule{\mylength}{1pt}
\end{document}

\end{document}

1
\documentclass{article}
\newlength\mylength
\newcommand\mylengthlist[1]{\mllaux#1,\relax}
\def\mllaux#1,#2\relax{\setlength\mylength{#1}}
\begin{document}
  \mylengthlist{2in, 2cm, 10pt}
  Test 1: \rule{\mylength}{1pt}\par
  \mylengthlist{0.8\textwidth, 2cm, 10pt}
  Test 2: \rule{\mylength}{1pt}
\end{document}

If you want an optional argument to specify which length in the list to use, there is this:

\documentclass{article}
\newlength\mylength
\newcommand\mylengthlist[2][1]{\iftrue\mllaux{#1}#2,\fi}
\def\mllaux#1#2,#3\fi{\fi\ifnum#1=1 \setlength\mylength{#2}%
  \else\expandafter\mllaux\expandafter{\numexpr#1-1}#3\fi}
\begin{document}
  \mylengthlist{2in, 2cm, 10pt}
  Test 1: \rule{\mylength}{1pt}\par
  \mylengthlist{0.8\textwidth, 2cm, 10pt}
  Test 2: \rule{\mylength}{1pt}\par
  \mylengthlist[2]{0.8\textwidth, 2cm, 10pt}
  Test 3: \rule{\mylength}{1pt}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .