2

I'm trying to style itemize lists that appear in tabular environments (specifically in a longtable). Ideally, I'd like to remove the left margin from lists that appear in tables while maintaining the margin on lists outside of tables.

There are several answers here already about how to use the enumitem package to change the margins of lists: you can set leftmargin=* on specific lists, or you can create a new custom itemize environment and use it specifically inside tables.

However, I am using pandoc to convert Markdown into TeX, so I have no control over the resulting TeX output—I can't add \begin{itemize}[leftmargin=*] or use a custom \begin{marginlessitemize}. enumitem has a \setlist macro that lets you set list settings globally, and \setlist[itemize]{leftmargin=*} removes the left margin from all lists, which isn't ideal, since I'm only trying to target lists inside tables.

Is there a way to apply \setlist{...} only to itemize environments that are nested inside tabular environments? In a perfect world, it'd be cool to use some sort of logic in the preamble: if itemize is in a table, use no margin; otherwise use a margin.


Here's a MWE…

(The messy longtable output comes from this Markdown table, which pandoc converts into TeX):

+-----------+-----------+
| Thing     | List      |
+===========+===========+
| Thing 1   | - Item 1  |
|           | - Item 2  |
+-----------+-----------+
| Thing 2   | - Item 3  |
|           | - Item 4  |
+-----------+-----------+

This TeX file…

\documentclass[11pt,article,oneside]{memoir}

\usepackage{longtable}

\begin{document}

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

\begin{itemize}
\tightlist
\item
  Item 1
\item
  Item 2
\end{itemize}

\begin{longtable}[]{@{}ll@{}}
\caption{This is a table.}\tabularnewline
\toprule
\begin{minipage}[b]{0.21\columnwidth}\raggedright
Thing
\end{minipage} & \begin{minipage}[b]{0.27\columnwidth}\raggedright
List
\end{minipage}\tabularnewline
\midrule
\endfirsthead
\toprule
\begin{minipage}[b]{0.21\columnwidth}\raggedright
Thing
\end{minipage} & \begin{minipage}[b]{0.27\columnwidth}\raggedright
List
\end{minipage}\tabularnewline
\midrule
\endhead
\begin{minipage}[t]{0.21\columnwidth}\raggedright
Thing 1
\end{minipage} & \begin{minipage}[t]{0.27\columnwidth}\raggedright
\begin{itemize}
\tightlist
\item
  Item 1
\item
  Item 2
\end{itemize}
\end{minipage}\tabularnewline
\begin{minipage}[t]{0.21\columnwidth}\raggedright
Thing 2
\end{minipage} & \begin{minipage}[t]{0.27\columnwidth}\raggedright
\begin{itemize}
\tightlist
\item
  Item 3
\item
  Item 4
\end{itemize}
\end{minipage}\tabularnewline
\bottomrule
\end{longtable}

\end{document}

…generates this PDF:

Margins in and out of the table

If I add this to the preamble…

\usepackage{enumitem}
\setlist[itemize]{leftmargin=*}

…the left margin in the list inside the table disappears, but it also disappears in the list outside the table:

No margins anywhere

If I create a custom itemize environment, I can use it in the table:

\newlist{marginlessitemize}{itemize}{1}
\setlist[marginlessitemize]{label=\textbullet,leftmargin=*}

...

% Inside a table cell...
\begin{marginlessitemize}
\item
  Item 1
\item
  Item 2
\end{marginlessitemize}

No margin in, yes margin out

That works, but because the TeX is generated automatically, I can't use the custom environment without manually editing the converted file. Hence the need to somehow automatically set no margin on lists inside tables.

Andrew
  • 497

2 Answers2

4

Here is (hopefully) a solution with enumitem and etoolbox. If you don't want the small vertical space between 2nd and 3rd row, replace after=\vspace*{\dimexpr1ex-\baselineskip} with after=vspace*{-\baselineskip}:

\documentclass[11pt, article, oneside]{memoir}%
\usepackage{longtable}
\usepackage{enumitem}

\usepackage{etoolbox}
\AtBeginEnvironment{longtable} {\setlist[itemize]{nosep, wide=0pt, leftmargin=*, before=\vspace*{-\baselineskip}, after=\vspace*{\dimexpr1ex-\baselineskip}}}

\begin{document}

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

\begin{itemize}
\tightlist
\item
  Item 1
\item
  Item 2
\end{itemize}

%%%%%%%%%%%%%%%%%%%%%%
\begin{longtable}{@{}>{\raggedright\arraybackslash}p{0.21\linewidth}>{\raggedright\arraybackslash}p{0.27\linewidth}@{}}%
\caption{This is a table.}\tabularnewline
\toprule
Thing & List
\tabularnewline
\midrule
\endfirsthead
\toprule
Thing & List
\tabularnewline
\midrule
\endhead
Thing 1
 &\begin{itemize}
\item
 Item 1
\item
 Item 2
\end{itemize}
\tabularnewline
Thing 2
 & \begin{itemize}
\item
 Item 3
\item
 Item 4
\end{itemize}
\tabularnewline
\bottomrule
\end{longtable}

\end{document} 

enter image description here

Bernard
  • 271,350
  • very nice and clean, @Bernard! – Zarko Jul 04 '17 at 19:27
  • Ooh, I like this a lot. Redefining the longtable environment with \AtBeginEnvironment is nice and simple. – Andrew Jul 04 '17 at 19:33
  • Thanks@Zarko! I had tested >{\compress}p{...} found on this site (it fools LaTeX, making it believe one is at the beginning of a minipage, so the before=vspace*{-1\baselineskip}is not necessary), but it doesn't seem to work withlongtable`. – Bernard Jul 04 '17 at 19:33
  • @Andrew: Note the after= setting supposes there's nothing else in the cell after \end{itemize}. – Bernard Jul 04 '17 at 19:35
  • Ah, good to know. Pandoc supports other paragraphs, etc. inside table cells after itemized lists. I can just rely on \renewcommand\arraystretch{X} to get spacing between rows (since pandoc does allow inline LaTeX) – Andrew Jul 04 '17 at 19:39
  • In this case, just define a new list environment based on itemize, which you can call, say,tabitemize with the parameters I set, use it if there's nothing afterwards, and in case there's something else after the list, set the same parameters for itemize, except after=.... – Bernard Jul 04 '17 at 19:44
  • @Bernard but the creation of tabitemize is something which he doesn't want. Still nice solution (I should definitely look into etoolbox). – Skillmon Jul 04 '17 at 19:49
  • Well, pandoc supports minimal inline latex, that is. I can modify arraystretch before the table, like this: https://gist.github.com/andrewheiss/10d88605e98275c2073a54bcf7be9ca2 - but I can't modify anything in the table – Andrew Jul 04 '17 at 19:49
3

The following works (just for longtable) if you place it in your preamble:

\makeatletter
\let\LT@arraybak\LT@array
\def\LT@array{\setlist[itemize]{leftmargin=*,after=\strut}\LT@arraybak}
\makeatother

Complete MWE:

\documentclass[11pt,article,oneside]{memoir}

\usepackage{longtable}
\usepackage{enumitem}
\makeatletter
\let\LT@arraybak\LT@array
\def\LT@array{\setlist[itemize]{leftmargin=*,after=\strut}\LT@arraybak}
\makeatother



\begin{document}

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

\begin{itemize}
\tightlist
\item
  Item 1
\item
  Item 2
\end{itemize}

\begin{longtable}[]{@{}ll@{}}
\caption{This is a table.}\tabularnewline
\toprule
\begin{minipage}[b]{0.21\columnwidth}\raggedright
Thing
\end{minipage} & \begin{minipage}[b]{0.27\columnwidth}\raggedright
List
\end{minipage}\tabularnewline
\midrule
\endfirsthead
\toprule
\begin{minipage}[b]{0.21\columnwidth}\raggedright
Thing
\end{minipage} & \begin{minipage}[b]{0.27\columnwidth}\raggedright
List
\end{minipage}\tabularnewline
\midrule
\endhead
\begin{minipage}[t]{0.21\columnwidth}\raggedright
Thing 1
\end{minipage} & \begin{minipage}[t]{0.27\columnwidth}\raggedright
\begin{itemize}
\tightlist
\item
  Item 1
\item
  Item 2
\end{itemize}
\end{minipage}\tabularnewline
\begin{minipage}[t]{0.21\columnwidth}\raggedright
Thing 2
\end{minipage} & \begin{minipage}[t]{0.27\columnwidth}\raggedright
\begin{itemize}
\tightlist
\item
  Item 3
\item
  Item 4
\end{itemize}
\end{minipage}\tabularnewline
\bottomrule
\end{longtable}

\end{document}

improved spacing

For a short explanation: The start of the longtable-environment is defined as:

macro:->\par \ifx \multicols \@undefined \else \ifnum \col@number
>\@ne \@twocolumntrue \fi \fi \if@twocolumn \LT@err {longtable not
in 1-column mode}\@ehc \fi \begingroup \@ifnextchar [\LT@array {\LT@array
[x]} 

So after evaluating some stuff it calls the \LT@array macro in which we inject our code which alters the itemize-environment and because it is inside of a \begingroup...\endgroup construct the changes made are local.

EDIT: To improve the vertical spacing I added after=\strut to the \setlist.

Skillmon
  • 60,462
  • Oh cool! What's the logic behind this? Is LT@array a specific element of a longtable? – Andrew Jul 04 '17 at 18:05
  • @Andrew see my edit for a short explanation. – Skillmon Jul 04 '17 at 18:28
  • regardless, that you solve OP problem, I would newer use such ugly table. rather use different itemize environments and concise code (which I just now delete) :) – Zarko Jul 04 '17 at 18:38
  • @Zarko it might be ugly, but first: you can still alter the \setlist-call to include some spacing enhancements. And second: it works without any retouch of the file (except for the insertion of the redefinition). – Skillmon Jul 04 '17 at 18:40
  • @Zarko, @Andrew: I've made a small edit which improves the vertical spacing of the itemize inside of longtable. – Skillmon Jul 04 '17 at 18:47
  • @Skillmon, now is far better, I will try incorporate your solution in my deleted solution. Is it possible to generalized your solution to be aware of any type of table, not only for longtable? – Zarko Jul 04 '17 at 19:01
  • @Zarko that's kinda hard to do. You could hack into \@tabarray which would at least work for tabular but it wouldn't work for longtable since longtable doesn't call it. I didn't look whether it would work for tabularx or tabu. – Skillmon Jul 04 '17 at 19:13
  • @Zarko another solution could be to alter the itemize-environment to check in which environment it is called and compare that to a list of known table-environments. But that's not a clean solution either, I guess -- and would fail if you have to nest it inside of a minipage like in tabular. – Skillmon Jul 04 '17 at 19:14
  • @Skillmon, i succeed to incorporate your solution in my answer. I afraid, that generalization is not simple or even possible. For my needs, I would be happy, if it would be possible to identify column tape p, X and X derivation for left aligned cells' contents. (+1) for your answer. – Zarko Jul 04 '17 at 19:24