3

This question already has an answer here:

After developing a custom environment that has both table-like data and paragraph data, I noticed some interesting effects. The glue (I think) is messing with the alignment of the text around each description. I am still learning about the switching between horizontal vertical modes.

I wrapped the paragraph data in a \parbox, which I guess is adding glue. You will notice that the spacing around the description under GPU is different than around the others' descriptions. I would like all descriptions to be top-aligned and there to be a slight space separating the description from the next "row".

I've managed to:

  • block floats from coming in between the "table" (although unsure if implemented correctly) using placeins
  • prevent page breaks in awkward places (in header row, after header row, after second to last row) by applying penalties in the appropriate places.
  • allow for an arbitrary number of arguments (provided that the left two are always left-aligned, a criterion that falls within my acceptability)
  • using [t] or [b] as args to \parbox also results in whitespace, which leads me to believe there is something implicit going on here.

Problem

How can I remove the glue around the descriptions? I'd like to fix the spacing between them. I suppose I could deal with a little glue after each description, but not much! The pseudo-table should look uniform.

The solution should take aesthetics into account:

  • descriptions have a left uniform indent
  • descriptions have a right uniform indent

Code

Please note that, in hindsight, I am aware that my table contains acronyms, NOT abbreviations ;)

\documentclass{article}
\usepackage{fontspec}% because XeLaTeX
\usepackage{xparse}% for the LaTeX3 syntax
\usepackage{environ}% for capturing everything within an environment in \BODY
\usepackage{booktabs}% for the \heavyrulewidth and \midrulewidth
\usepackage{lipsum}% for the dummy text
\usepackage{placeins}% to keep floats out of ifodescriptionlist

% Counters
\newcounter{ifodescriptionlistcounter}
% Lengths
\newlength{\originalparskip}
\setlength{\parindent}{0pt}

\ExplSyntaxOn
\DeclareDocumentCommand{\ifoitemx}{ O{} m }
  {% The redefinition of ithitem. Optional:comma list of values; mandatory:description. For use inside of ifodescriptionlist
  \par\noindent\doithitemargs:n{#1}% Handle comma list with LaTeX3 xparse
  \par\nobreak
  \hspace{5mm}\hangindent=5mm{\parbox{\dimexpr\textwidth-2cm\relax}{\footnotesize #2}\par}% This #2 represents the descriptions
  \addtocounter{ifodescriptionlistcounter}{-1}% descrease count while it is increased
  \ifnum\value{ifodescriptionlistcounter}<2 \nobreak \fi
  }%
\ExplSyntaxOff

\ExplSyntaxOn
\NewDocumentEnvironment{ifodescriptionlist}{ O{} O{} }
  {% See ifodescriptionlistBODY to capture contents (\BODY) of environment
  \FloatBarrier % Prevent floats to break this environment
  \setcounter{ifodescriptionlistcounter}{0}% Reset counter
  \par\bigskip %paragraph ensures start of fresh paragraph, bigskip adds vertical padding after new paragraph (related to vspace below table caption)
  \setlength{\originalparskip}{\parskip}% save the value
  \setlength{\parskip}{1pt plus 0pt minus 0pt}% remove the \parskip glue
  \hrule height\heavyrulewidth\nobreak%\noindent\rule{\textwidth}{\heavyrulewidth}
  \smallskip\nobreak
  \hbox to \hsize{\bf #1}\nobreak
  \smallskip\nobreak
  \hrule height\lightrulewidth\nobreak  %\noindent\rule[2mm]{\textwidth}{\lightrulewidth}\par\nobreak
  \medskip\nobreak
  \ifodescriptionlistBODY\endifodescriptionlistBODY% Capture contents (\BODY) and localize with {}
  }
  {
  \medskip
  \hrule height\heavyrulewidth
  \nobreak
  \smallskip
  {\tiny #2}
  \setlength{\parskip}{\originalparskip}% restore the value
  \FloatBarrier % Prevent floats to break this environment
  \par
  }
\NewEnviron{ifodescriptionlistBODY}% from environ Package NewEnviron
  {% environ package is the only way I know how to grab the body like in TeX
    \def\ifoitem[##1]##2{\addtocounter{ifodescriptionlistcounter}{1}}% Define ithitem to add 1 to counter each call
    \interlinepenalty=10000 % Change interlinepenalty for this local environment (all ithitems)
    \typeout{**** Value ifodescriptionlistcounter (before first call of body): \the\value{ifodescriptionlistcounter}} % Log+Terminal entry
    \BODY % Typeset body of env (empty), just calls ithitems within contained within \BODY.
    \typeout{**** Value ifodescriptionlistcounter (after first call of body): \the\value{ifodescriptionlistcounter}} % Log+Terminal entry
    \let\ifoitem=\ifoitemx% Redefine ithitem to ithitemx
    \BODY % Retypeset body of env with new definition of \ifoitem
    % The rest continues in the main environment
  }{}
% --------------------------------------------------------------------------------------------------
% LaTeX3 expl3 processing
%
\ExplSyntaxOn % Handler for ifodescriptionlist
\clist_new:N\ifoitemargs % Initialize comma list
\cs_new_protected:Nn\doithitemargs:n
  {
    {%
      \clist_set:Nn \ifoitemargs {#1}%
      \textbf{\clist_item:Nn \ifoitemargs {1}},~\clist_item:Nn \ifoitemargs {2} \hfill \int_step_inline:nnnn {3}{1}{\clist_count:N \ifoitemargs}
      {%
        \int_compare:nTF { ##1 = \clist_count:N \ifoitemargs }% Decide whether or not last item has been reached.
          {\clist_item:Nn \ifoitemargs {##1}}
          {\clist_item:Nn \ifoitemargs {##1},~}
      }
    }
  }%
\ExplSyntaxOff

\begin{document}
\begin{ifodescriptionlist}[Abbreviation, Name \hfill B/S, Rep\#][B~=~Big, S~=~Small, Rep\#~=~Whether or not a rep number has been assigned.]

\ifoitem[RIS, Radiological Information System, B, N]
  {\lipsum[1]}
\ifoitem[CORBA, Common Object Request Broker Architecture, B, N]
  {\lipsum[2]}
\ifoitem[GPU, Ground Power Unit, B, Y]
  {Which one of these things is not like the other?}
\ifoitem[PACS, Picture Archiving Communication System , S, Y]
  {\lipsum[3]}
\ifoitem[SCP, Service Class Provider, S, N]
  {\lipsum[4]}
\end{ifodescriptionlist}
\end{document}

Output

enter image description here

Output with \parbox[t]

You'll notice that the descriptions seemed "pushed" downwards to the next row. Doesn't t stand for top-aligned? Where is this whitespace coming from?

enter image description here

Output with \parbox[b]

You'll notice that the space is uneven again, maybe because the parbox is bottom-aligned.

enter image description here

marked as duplicate by egreg spacing Jan 13 '16 at 10:34

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • @egreg The solution to the other question does not solve my issue. I already tried using parameters with \parbox. Some mysterious whitespace remains. I also tried resetting the \prevdepth. Are you sure that applies to my situation? Please see edits. Maybe they warrant reopening this question. – Jonathan Komar Jan 13 '16 at 13:12
  • Yes, it surely solves the issue: this is the picture of what I get with a proper redefinition of the macro, basically \parbox[t]{\dimexpr\textwidth-2cm\relax}{\footnotesize #2\par\xdef\tpd{\the\prevdepth}}\par\prevdepth=\tpd – egreg Jan 13 '16 at 13:21
  • @egreg Ah! Of course! The \par\xdef\tpd{\the\prevdepth} must happen within the scope of \footnotesize in order to capture its \lineskip value (or something, davidcarlisle explained it to me once). That means the mysterious whitespace above was caused by the larger \lineskip value of the normal font. Could you confirm this? – Jonathan Komar Jan 13 '16 at 13:43
  • @egreg I think the culprit was the \par\noindent before the \hspace{5mm}\hangindent=5mm{\parbox... – Jonathan Komar Jan 13 '16 at 14:11