5

As the following example showes, there are an extra line-feed which is not needed. Is there a way to eliminate?

Example:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\def\mylist{str1,str2,str3}

\framebox{
  \parbox{4em}{%
    \foreach \x in \mylist {%
      \makebox[4em][s]{\x}\\%
    }%
  }
}

\end{document}

enter image description here

lyl
  • 2,727

5 Answers5

6

A listofitems alternative...

\documentclass{article}
\usepackage{listofitems}
\begin{document}
\readlist*\mylist{str1,str2,str3}
\framebox{%
  \parbox{4em}{%
    \foreachitem\x\in\mylist[]{%
      \makebox[4em][l]{\x}%
      \ifnum\xcnt<\mylistlen\relax\\\fi%
    }%
  }%
}
\end{document}

enter image description here

or switch the test order:

\documentclass{article}
\usepackage{listofitems}
\begin{document}
\readlist*\mylist{str1,str2,str3}
\framebox{%
  \parbox{4em}{%
    \foreachitem\x\in\mylist[]{%
      \ifnum\xcnt=1\relax\else\\\fi%
      \makebox[4em][l]{\x}%
    }%
  }%
}
\end{document}
6

The problem is that you issue a \\ at the end of each line. You can avoid it e.g. with

\documentclass{article}
\usepackage{tikz}

\begin{document}
\def\mylist{str1,str2,str3}

\framebox{
  \parbox{4em}{%
    \foreach \X [count=\Y]in \mylist {%
      \ifnum\Y=1
        \makebox[4em][s]{\X}
      \else 
        \\ \makebox[4em][s]{\X}%
      \fi
    }%
  }
}

\end{document}

enter image description here

  • 1
    A simple and exactly what I want solution! Thank you! – lyl Feb 17 '19 at 04:44
  • @lyl You're welcome! –  Feb 17 '19 at 05:04
  • Normally, \parbox has not the ability to spread align. In this question, we just achieve it by manually add \\ to ensure spread align only for those lengh shorter than defined width. I wonder if there are solutions to spread align text in \parbox autometically? – lyl Feb 17 '19 at 05:58
  • @lyl What do you mean by "spread align"? Something like justify? (BTW, will go hibernate now.) –  Feb 17 '19 at 06:00
  • Yes, just like the option[s] in \makebox. Ok, I'll post another question to illustrate my meaning. Have a nice evening! – lyl Feb 17 '19 at 06:04
2

With a conditionnal (minimum code text)

\documentclass{article}
\usepackage{tikz}

\begin{document}

\def\mylist{str1,str2,str3}
\framebox{
  \parbox{4em}{%
    \foreach \x[count=\n] in \mylist {%
      \ifnum \n >1 \\ \fi
      \makebox[4em][s]{\x}%
    }%
  }
}

\end{document}

With an array (just for the fun of it)

\documentclass{article}
\usepackage{tikz}

\begin{document}
\def\mylist{str1,str2,str3}
\def\before{{"\noexpand\\",{}}}
\framebox{
  \parbox{4em}{%
    \foreach \x[count=\n from 0] in \mylist {%
      \pgfmathparse{\before[!\n]}\pgfmathresult
      \makebox[4em][s]{\x}%
    }%
  }
}

\end{document}

Without any conditional ....

\documentclass{article}
\usepackage{tikz}

\begin{document}
\def\mylist{str2,str3}

\framebox{
  \parbox{4em}{%
   str1
    \foreach \x in \mylist {%
      \\\makebox[4em][s]{\x}%
    }%
  }
}

\end{document}
AndréC
  • 24,137
1

With the general purpose macro suggested in https://tex.stackexchange.com/a/475291/4427 (slightly modified):

\documentclass[12pt,a4paper]{article}

\usepackage{xparse}
\usepackage{amsmath}

\ExplSyntaxOn

% a general purpose macro for defining other macros
% \makemultiargument* will do a one step expansion of the second argument
\NewDocumentCommand{\makemultiargument}{smmmmm}
 {
  \IfBooleanTF { #1 }
   {
    \projetmbc_multiarg:nonnn { #2 } { #3 } { #4 } { #5 } { #6 }
   }
   {
    \projetmbc_multiarg:nnnnn { #2 } { #3 } { #4 } { #5 } { #6 }
   }
 }

% allocate a private variable
\seq_new:N \l__projetmbc_generic_seq

% the internal version of the general purpose macro
\cs_new_protected:Nn \projetmbc_multiarg:nnnnn
 {% #1 = separator
  % #2 = multiargument
  % #3 = code before
  % #4 = code between
  % #5 = code after

  % a group allows nesting
  \group_begin:
  % split the multiargument into parts
  \seq_set_split:Nnn \l__projetmbc_generic_seq { #1 } { #2 }
  % execute the <code before>
  #3
  % deliver the items, with the chosen material between them
  \seq_use:Nn \l__projetmbc_generic_seq { #4 }
  % execute the <code after>
  #5
  % end the group started at the beginning
  \group_end:
 }
\cs_generate_variant:Nn \projetmbc_multiarg:nnnnn { no }

\ExplSyntaxOff

% separator: ,; before: empty; between: \\, after: empty
\newcommand{\fboxstack}[2][4em]{% #1=width, #2=items
  \fbox{\parbox{#1}{%
    \makemultiargument*{,}{#2}{}{\\}{}%
  }}%
}

\begin{document}

\newcommand{\mylist}{str1,str2,str3}

\fboxstack{\mylist}\qquad\fboxstack[8em]{\mylist}

\end{document}

enter image description here

A variant suggested by your last questions How to make a macro like \parbox with a style of spread align and Automatically justify text in \parbox

\documentclass[12pt,a4paper]{article}

\usepackage{xparse}
\usepackage{amsmath}

\ExplSyntaxOn

% a general purpose macro for defining other macros
% \makemultiargument* will do a one step expansion of the second argument
\NewDocumentCommand{\makemultiargument}{smmm+mm}
 {
  \IfBooleanTF { #1 }
   {
    \projetmbc_multiarg:nonnn { #2 } { #3 } { #4 } { #5 } { #6 }
   }
   {
    \projetmbc_multiarg:nnnnn { #2 } { #3 } { #4 } { #5 } { #6 }
   }
 }

% allocate a private variable
\seq_new:N \l__projetmbc_generic_seq

% the internal version of the general purpose macro
\cs_new_protected:Nn \projetmbc_multiarg:nnnnn
 {% #1 = separator
  % #2 = multiargument
  % #3 = code before
  % #4 = code between
  % #5 = code after

  % a group allows nesting
  \group_begin:
  % split the multiargument into parts
  \seq_set_split:Nnn \l__projetmbc_generic_seq { #1 } { #2 }
  % execute the <code before>
  #3
  % deliver the items, with the chosen material between them
  \seq_use:Nn \l__projetmbc_generic_seq { #4 }
  % execute the <code after>
  #5
  % end the group started at the beginning
  \group_end:
 }
\cs_generate_variant:Nn \projetmbc_multiarg:nnnnn { no }

\ExplSyntaxOff

% separator: ,; before: empty; between: \\, after: empty
\newcommand{\fboxstack}[2][4em]{% #1=width, #2=items
  \fbox{\parbox{#1}{%
    \setlength{\parfillskip}{0pt}%
    \hbadness 10000 % no warning about underfull boxes
    \makemultiargument*{,}{#2}{}{\par}{}%
  }}%
}

\begin{document}

\newcommand{\mylist}{test ab,ab cd,de fg}

\fboxstack{\mylist}\qquad\fboxstack[8em]{\mylist}

\end{document}

enter image description here

egreg
  • 1,121,712
1

This is an answer to an old question, but since all the previous answers use counter-based conditionals, I propose, for the sake of completeness, a solution based on redefining macros.

\documentclass[varwidth, border=7pt]{standalone}
\usepackage{pgffor}

\begin{document} \def\mylist{str1,str2,str3}

\framebox{ \parbox{4em}{% \foreach[remember=\newline as \mynewline (initially \relax)] \x in \mylist {% \mynewline\makebox[4em][s]{\x}% }% } } \end{document}

enter image description here

And the same result can be obtained with classical \def & \gdef.

\documentclass[varwidth, border=7pt]{standalone}
\usepackage{pgffor}

\begin{document} \def\mylist{str1,str2,str3}

\framebox{ \parbox{4em}{% \def\mynewline{}% \foreach \x in \mylist {% \mynewline\makebox[4em][s]{\x}% \gdef\mynewline{\newline}% }% } } \end{document}

Note: the \gdef is need here because \foreach creates a group. If we want to avoid this we can use the first solution or another loop, like \xintFor.

Kpym
  • 23,002