8

I'm trying to write a key:value environment which would allow me to create a dual columns tables where the columns are separated by colons.

Typically, I've implemented this using parbox in my own class file:

\makeatletter
\newenvironment{keylist}{\global\setlength{\parindent}{0pt}}{}
\newlength{\@keyvalueXposition}
\setlength{\@keyvalueXposition}{0.5\textwidth}
\newcommand{\keyvalue}[2]{
    \parbox[t]{\@keyvalueXposition}{#1}
    :
    \parbox[t]{\@keyvalueXposition}{#2}
    \\
}
\makeatother

Which is typically used like this on the user-side:

\begin{keylist}
    \keyvalue{Foo que lorem ipsum          } {Foofoo                           }
    \keyvalue{Bar foobar                   } {Bar bar ipsum                    }\\
    \keyvalue{Baz norf                     } {Bazbaz                           }
    \keyvalue{Qux lorem ipsum              } {Qux lorem qux                    }
\end{keylist}

Soon I realized my implementation was lacking this use case: allow lines to have only one element without printing the colon. Also, I began to use, in my class file, tabularx with booktabs to have great spaced lines in my tables.

\begin{tabularx}{\textwidth}{ X@{ : }X }\toprule
    Foo que lorem ipsum & Foofoo\\\midrule
    Bar foobar & Bar bar ipsum\\[\baselineskip]
    Baz norf & Bazbaz\\
    Qux lorem ipsum & Qux lorem qux\\\bottomrule
\end{tabularx}

* where [\baselineskip] is used to simulate linebreaks, implemented simply using \\ in the previous implementation using parbox.

While this was working nice up to now, this was quite a hassle to use. I decided to replace the above solution by an environment alias, defined like this:

\newenvironment{keylisting}
{\tabularx{\textwidth}{ X@{ : }X }}
{\endtabularx}

which would give me

\begin{keylisting}\toprule
    Foo que lorem ipsum & Foofoo\\\midrule
    Bar foobar & Bar bar ipsum\\[\baselineskip]
    Baz norf & Bazbaz\\
    Qux lorem ipsum & Qux lorem qux\\\bottomrule
\end{keylisting}

In the case where a line has only one item, we need to create an empty item for the second column, like this

Foo bar &\\

However, a colon is printed between both columns. According to what I found in the documentation, using \multicolumn{2}{l}{Foo bar}\\ is the solution. However, for a reason I don't know when we prefix that statement by [\baselineskip], the latter isn't interpreted by the LaTeX kernel. If you use the following example, you will see the differences between the two lines with [\baselineskip]]: the first one is not interpreted. I prefixed the statement by 10 to clearly see it isn't interpreted.

    \documentclass{report}
    \usepackage[margin=2cm]{geometry}
    \linespread{1.2}
    \usepackage{tabularx}
    \usepackage{booktabs}
    \usepackage{float}
    \newenvironment{keyval}
    { \tabularx{\textwidth}{ X@{ : }X } }
    { \endtabularx }
    \begin{document}
    \begin{keyvalue}
        Foo bar lorem ipsum           & Lorem ipusm que \\
        Some number                   & 12 3456 789  8  \\
        \multicolumn{2}{l}{This is some comment}  \\[10\baselineskip]
        Yet some number               & 987 65432 1     \\
        Foo bar                       & 163883495778    \\[\baselineskip]
        Bar lorem ipsum               & 2013-04-12      \\
    \end{keyvalue}
    \end{document}

Thanks for your help.

8
  • 2
    the tabularx documentation is explcit that you can not use \begin{tabularx} in an environment definition, you can with lots restrictions, use \tabularx \end{tabularx Feb 7, 2015 at 23:41
  • 1
    \global\setlength is not supported syntax (and will blow up spectacularly if the standard calc package is used). Feb 7, 2015 at 23:42
  • @DavidCarlisle Indeed. First issue solved. Thanks Yet the two other points.
    – wget
    Feb 7, 2015 at 23:55
  • 1
    every question should have a complete document that demonstrates the problem, if you only post unusable fragments, it's only possible to answer the easy bits you can see by eye. Feb 8, 2015 at 0:06
  • @DavidCarlisle Done. I added a working example and not simply a snippet.
    – wget
    Feb 8, 2015 at 0:27

2 Answers 2

12

You need

  \\[10\normalbaselineskip]

as \baselineskip is 0pt in tabular enviornments so that rows (and especially vertical rules) have no gaps.

It sort of works by accident if the final column is a p (or here X) column as locally within that column the baseline is reset for normal typesetting. Note however you are picking up that local setting, if the text in the cell is \small you would pick up a value of a small \baselineskip.

I'm tempted to say that

    Foo bar                       & 163883495778    \\[\baselineskip]

increasing the space is a latex bug (in which case it's been there since the beginning and unreported for 30 years or something....)

5
  • Thanks again! Yet the last point of my question (some aliases) and I can mark the question as solved (and rewrite a proper complete answer).
    – wget
    Feb 8, 2015 at 0:47
  • @wget Note that the site operates a one question per... well, per question policy. If you have 3 different questions, you have 3 different questions and not 1.
    – cfr
    Feb 8, 2015 at 0:54
  • @wget the site works best if you ask one question per question:-) I actually don't understand the last part at all, do you want to omit \\ in all lines, which is possible but only by giving end of line in the file magic behaviour like \obeylines or verbatim, so is only possible in restricted circumstances (in particular not in the argument to another command) and I can't guess what kind of alias you mean. you can use \newcommand \bls{\[\normalbaselineskip]} if it's just a shorter command you mean? Feb 8, 2015 at 0:55
  • @DavidCarlisle Sorry I'm still a newbie ;-). I've added more details about the last point of my question. Do I need to rewrite a dedicated question for each of them? Thanks again.
    – wget
    Feb 8, 2015 at 1:02
  • @wget sorry I still don't know what you mean by alias. (It's late and I don't really care, going to bed:-) I should just forget about the \tabularx part, you could ask a question but it's almost certainly a duplicate so would get closed. this part is interesting as it's arguably a latex bug (I'm just wondering if we should fix it or not) the third part I haven't really a clue other then setting \obeylines and defining \par to be \\ but i don't know what you mean by alias. In any case I'd delete it from here and ask a new question about that. with an example of the input form you'd like. Feb 8, 2015 at 1:12
1

I have a somewhat different approach to your mixed problem. Below I use a list-like setting of a table and utilize array's functionality for inserting content in the beginning of a column via >{<stuff>} - acting like a column separation mechanism. This latter approach only sets <stuff> if the column is used, leaving no <stuff> if the column isn't used.

enter image description here

\documentclass{article}
\usepackage{tabularx,booktabs,environ}

\NewEnviron{keylisting}{%
  \let\olditem\item% Save \item
  \par\noindent
  \begin{tabularx}{\textwidth}{ X @{\hspace{\tabcolsep}} >{\leavevmode\llap{: }}X }
    \toprule
    % https://tex.stackexchange.com/q/227142/5764
    \ifdim\hfuzz=\maxdimen % During tabularx trial
      \gdef\item{\\}
    \else% During tabularx final
      \gdef\item{\gdef\item{\\\midrule\gdef\item{\\}}}
      \gdef\bigskip{\gdef\item{\\[\normalbaselineskip]\gdef\item{\\}}}
    \fi
    \BODY \\
    \bottomrule
  \end{tabularx}
  \let\item\olditem% Restore \item
}

\begin{document}

\begin{keylisting}
  \item Foo que lorem ipsum & Foofoo 
  \item Bar foobar & Bar bar ipsum \bigskip
  \item Baz norf & Bazbaz
  \item Something with only one column
  \item Qux lorem ipsum & Qux lorem qux
\end{keylisting}

\end{document}

The above definitions of \item assumes that the first row will be a header row. As such, the first \item is defined to do nothing. The second \item inserts \midrule, while subsequent \items insert a traditional \\. \bigskip is also redefined to be an alias for \\[\normalbaselineskip] (actually via a redefinition of \item again), for the sake of convenience. One can define additional skips to act in a similar way, if need be.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.