# Fixing a keyval problem

This is my first attempt at a keyval macro. I have a more complicated macro that boils down to the MWE given below. The idea is to typeset a paragraph in multiple columns where the number of columns is an optional named parameter. When I state the number of columns then it works, but I would like a default of one column when no option is stated.

\documentclass{article}

\usepackage{keyval}
\usepackage{lipsum}
\usepackage{multicol}

\makeatletter

\def\printparagraph{\@ifnextchar[\@printparagraph{\@printparagraph[]}}
\def\@printparagraph[#1]{{\setkeys{pp}{#1}}}
\define@key{pp}{columns}{\begin{multicols}{#1}\lipsum[1]\end{multicols}}

\makeatother

\begin{document}

\printparagraph % this doesn't work, doesn't print anything!
\printparagraph[columns=2] % this works
\printparagraph[columns=3] % this works

\end{document}

• just delete \@printparagraph[] so you do nothing in the default case. (or actually what you have is equivalent). it works (and has the default one column setting but you have no text) in that case. note you can't do \begin{multicols{1} so you need to not start multicols at all in that case and you only have \lipsum in the multicols – David Carlisle Oct 25 '17 at 19:27

You just need to print your dummy text in the default case:

\documentclass{article}

\usepackage{keyval}
\usepackage{lipsum}
\usepackage{multicol}

\makeatletter

\def\printparagraph{\@ifnextchar[\@printparagraph{\lipsum}}
\def\@printparagraph[#1]{{\setkeys{pp}{#1}}}
\define@key{pp}{columns}{\begin{multicols}{#1}\lipsum[1]\end{multicols}}

\makeatother

\begin{document}

\printparagraph %
\printparagraph[columns=2] % this works
\printparagraph[columns=3] % this works

\end{document}

• Many thanks! Let's say that \begin{multicols{1} worked, where would I then put the default 1? – Geoff Oct 25 '17 at 19:39
• @Geoff \def\printparagraph{\@ifnextchar[\@printparagraph{\@printparagraph[1]} or more simply \newcommand\printparagraph[1][1]{{\setkeys{pp}{#1}} – David Carlisle Oct 25 '17 at 19:44

\begin{multicols{1} doesn't work, but beside this: I wouldn't put the multicols in the key definition but use it only to store the value. Then it is easy to set a default (I would also use l3keys instead of keyval, but that's another question):

\documentclass{article}

\usepackage{keyval}
\usepackage{lipsum}
\usepackage{multicol}

\makeatletter
\newcount\my@columns@cnt
\def\printparagraph{\@ifnextchar[\@printparagraph{\@printparagraph[]}}

\def\@printparagraph[#1]{{%
\setkeys{pp}{columns,#1}%
\ifnum\my@columns@cnt=1
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\lipsum[1]}
{\begin{multicols}{\the\my@columns@cnt}\lipsum[1]\end{multicols}}}}

\define@key{pp}{columns}[1]{\my@columns@cnt=#1\relax}

\makeatother

\begin{document}

\printparagraph % this doesn't work, doesn't print anything!
\printparagraph[columns=2] % this works
\printparagraph[columns=3] % this works

\end{document}

• Thanks for the answer. I see the sense of using the key to only store the counter, but am I correct to say, that the extra complication is due to the fact that \begin{mutlicols}{1} doesn't work? – Geoff Oct 25 '17 at 19:56
• Yes, multicol insists to have at least two columns, so you need the \ifnum-test for the value 1. But even without this complication I wouldn't put a complete multicols environment in a key definition. At the end it is much easier to first collect the key values and then do something -- and it doesn't explode if someone uses a key twice. – Ulrike Fischer Oct 25 '17 at 20:00