4

I have a longish document which isn't written in LaTeX but structures for markup are easily identified. I can write a Perl script to translate most of the document into LaTeX.

However, lists present a bit of a headache because it's not always clear where such an environment should begin or end. Fortunately, the vast majority (if not all) listed items to appear in the document consist of single paragraphs each. So, I thought I could write a simple macro that would simulate the appearance of a list item.

Here's the code that I came up with on my first run.

\documentclass{article}

\makeatletter

\newcounter{aelistcnt}
\newcommand\alist{\ae@list}
\def\ae@list{%%
  \refstepcounter{aelistcnt}%%
  \par
  \vskip 2ex plus 0pt minus 2ex
  \let\ae@par\par
  \let\par\ae@@par
  \parshape 1 2em \dimexpr\columnwidth-4em\relax
  \noindent
  \makebox[0pt][r]{(\arabic{aelistcnt})\hspace{0.5em}}%%
}

\def\ae@@par{%%
  \ae@par
  \vskip 1ex plus 0pt minus 1ex
  \let\par\ae@par}

\makeatother

\def\aevbox{%%
  \raisebox{0pt}[0pt][0pt]{\makebox[0pt]{\rule{1pt}{4ex}}}}

\usepackage{lipsum}

\begin{document}

\lipsum[13]

\alist \aevbox Pr
\alist b

\alist \lipsum[11]
\alist \aevbox\lipsum[39]
\alist \lipsum[65]

\lipsum[23]

\alist\lipsum[11]

\end{document}

The problem is how the list interacts with the surrounding document. In particular, whether or not there is a paragraph break between items for this pseudo list, I want consistent spacing in front of the list, between items in the list, and following the last item. I use glue (something I'm not all that familiar with) to try to achieve the desired effect. The above does a reasonable job, but I want to be able to better. (The point o the \aevbox was to help me see discrepencies.)

Another approach dispenses with glue altogether. Instead I change the definition of \par.

\documentclass{article}

\makeatletter

\newif\if@aelist
\newif\if@aedoublepar
\newcounter{aelistcnt}
\newcommand\alist{\ae@list}
\def\ae@list{%%
  \refstepcounter{aelistcnt}%%
  \ae@par@test
  \parshape 1 2em \dimexpr\columnwidth-4em\relax
  \noindent
  \makebox[0pt][r]{(\arabic{aelistcnt})\hspace{0.5em}}%%
}

\def\ae@par@test{%%
  \typeout{===>\theaelistcnt}%%
  \if@aelist
    \ae@@@par
    \let\par\ae@@par
    \typeout{\space\space\space\space:(TRUE):\space\space PREVIOUSLY LIST}%%
  \else
    \typeout{\space\space\space\space:(FALSE):\space NEW LIST}%%
    \vspace{2ex}%%
    \par
    \let\ae@par\par
    \let\par\ae@@par
  \fi
  \@aelisttrue
  }

\def\ae@@par{%%
  \typeout{\space\space\space\space:ae@@par:}%%
  \ae@par
  \vspace{2ex}%%
  \@aedoublepartrue
  \let\par\ae@@@@par
  }

\def\ae@@@par{%%
  \typeout{\space\space\space\space:ae[3@]par:}%%
  \if@aedoublepar
    \@aedoubleparfalse
  \else
    \vspace{2ex}%%
    \ae@par
  \fi
}

\def\ae@@@@par{%%
  \typeout{\space\space\space\space:ae[4@]par:BACK TO NORMAL PAR}%%
  \let\par\ae@par
  \@aelistfalse
  \@aedoubleparfalse
  \par
}

\makeatother

\usepackage{lipsum}
\begin{document}

\lipsum[13]

\alist a
\alist b
\alist c

\alist d
\alist \lipsum[11]
\alist \lipsum[39]
\alist \lipsum[65]

\lipsum[23]

\alist\lipsum[11]

\lipsum[23]

\end{document}

This seems to do a better job. But I'm still not entirely satisfied. There seems to be no nice way to clean up the definition of \par early and I worry that some other LaTeX code may come in and inadvertently create havoc with an only-partially reimplemented \par command. (One benefit of this exercise is I've seen how nice an environment can be for containing and cleaning up code before things get to out of whack.)

So what I'm interested in are suggestions for better ways of handling this without having to actually manually create the proper list environment.

  • A(n) (offtopic) note: you have \par saved in \endgraf, just in case you don't need to do so many \lets to save/restore. – Manuel Jul 19 '14 at 17:16
  • @Manuel Thank you. I hadn't considered that, but also I would like to maintain whatever definition of \par was current prior to changing it myself. – A.Ellett Jul 19 '14 at 17:24
2

What you want is, I believe, \addvspace. The problem with \par can be tackled with a group.

\documentclass{article}

\makeatletter

\newcounter{aelistcnt}
\newcommand\alist{\ae@list}
\def\ae@list{%%
  \refstepcounter{aelistcnt}%%
  \par
  \addvspace{2ex plus 0pt minus 2ex}%
  \begingroup
  \let\ae@@par\par
  \def\par{\ae@par}%
  \parshape 1 2em \dimexpr\columnwidth-4em\relax
  \noindent
  \makebox[0pt][r]{(\arabic{aelistcnt})\hspace{0.5em}}%%
}

\def\ae@par{%%
  \ae@@par\endgroup
  \addvspace{1ex plus 0pt minus 1ex}%
  }

\makeatother

\def\aevbox{%%
  \raisebox{0pt}[0pt][0pt]{\makebox[0pt]{\rule{1pt}{4ex}}}}

\usepackage{lipsum}

\begin{document}

\lipsum[13]

\alist \aevbox Pr
\alist b

\alist \lipsum[11]
\alist \aevbox\lipsum[39]
\alist \lipsum[65]

\lipsum[23]

\alist\lipsum[11]

\end{document}

enter image description here

  • So simple! But spot on. – A.Ellett Jul 19 '14 at 22:40
  • Is there a difference between \let\par\ae@par and \def\par{\ae@par} beyond the obvious one of expansion. – A.Ellett Jul 19 '14 at 22:54
  • @A.Ellett Personal preference? ;-) – egreg Jul 20 '14 at 10:03

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.