3

I am working on a LaTeX solution that needs to process plain text written by others in Markdown. I need to automatically number the paragraphs from the plain text (i.e. there will not be LaTeX code such as \paragraph or \item in the text).

To move this forward, I previously asked this question and received some pointers which helped me to introduce automatically numbered paragraphs in the processed documents by modifying \@afterheading (thank you again @NicolaTabot).

Unfortunately I have spotted a problem in that a bulleted list seems to break the solution.

My minimum working example is as follows:

\documentclass[11pt]{article}
\usepackage{titlesec}
\setcounter{secnumdepth}{3}

\setlength{\parindent}{0em} % indent subsequent paragraphs

\newcounter{para}
\newcommand*{\numberedparagraph}{%
\refstepcounter{para}
\textbf{\thepara.\space}
}

\let\oldep\everypar\newtoks\everypar  
\oldep{\the\everypar\everypar{\numberedparagraph}}

\makeatletter %
\renewcommand{\@afterheading}{%
  \@nobreaktrue
\everypar{%
\if@nobreak
  \@nobreakfalse
  \clubpenalty\@M
  \if@afterindent
  \else
{\setbox\z@\lastbox}%
  \fi
\else
  \clubpenalty\@clubpenalty
  \everypar{\numberedparagraph}% <- modification
\fi
\numberedparagraph% <- modification
  }%
}

\begin{document}

\everypar{\numberedparagraph}

\section{Section 1}

This is paragraph 1.

This is paragraph 2, and here are some bullets:

\begin{itemize}
    \item One.
    \item Two.
    \item Three.
\end{itemize}

And then this paragraph should be numbered 3 but it is not.

Numbering returns for this paragraph, but now the count is incorrect.

\end{document}

Here is a screenshot of the resulting document:

enter image description here

Can anyone help me with this please?

1 Answer 1

2

Below are two possible solutions. I wrote the bottom one first, and it is a simple extension of your original code that does the same thing for \itemize that you had already done for \section. I think the top one is probably more durable in the sense that it seems less likely to break (and easier to adapt), but things might've been set up as they were for some other reason that I'm not aware of.


New solution:

Here is a new solution, which I like better:

\documentclass[11pt]{article}

\usepackage{titlesec}
\setcounter{secnumdepth}{3}

\usepackage{etoolbox} %% for \apptocmd and \pretocmd

\setlength{\parindent}{0pt} % do not indent subsequent paragraphs

\newcounter{para}
\newcommand*{\numberedparagraph}{%
  \refstepcounter{para}%
  \makebox[0pt][r]{\textbf{\thepara.~}}% %% This puts the number in the margin
  %\makebox[0pt][r]{\makebox[0pt][l]{\textbf{\thepara.}}\hspace{2em}}% %% This also left-aligns multi-digit numbers
  %\textbf{\thepara.~}% %% And this indents the paragraph instead
}

\let\oldep\everypar
\newtoks\everypar
\oldep{\the\everypar\ifinhibitparnums\numberedparagraph\fi}

\newif\ifinhibitparnums
\inhibitparnumstrue

%% Inhibiting paragraph numbers in section/subsection/... titles
\makeatletter
% \pretocmd{\@sect}{\inhibitparnumsfalse}{}{}         %% <- this only works without titlesec
% \apptocmd{\@sect}{\inhibitparnumstrue}{}{}          %% <- this only works without titlesec
\pretocmd{\ttl@straight@ii}{\inhibitparnumsfalse}{}{} %% <- this only works with titlesec
\apptocmd{\ttl@straight@ii}{\inhibitparnumstrue}{}{}  %% <- this only works with titlesec
\makeatother

%% Inhibiting it in itemize
\pretocmd{\itemize}{\inhibitparnumsfalse}{}{}
%% N.B. \ifinhibitparnums is reset automatically when the environment ends

\begin{document}

\section{Section 1}

This is paragraph 1.

This is paragraph 2, and here are some bullets:

\begin{itemize}
    \item One.
    \item Two.
    \item Three.
\end{itemize}

And then this paragraph should be numbered 3, and it is! Also it is long enough to span two lines!

Numbering returns for this paragraph, and the count is still correct.

\end{document}

I defined a conditional, \ifinhibitparnums and number paragraphs only when it is set to false. I prevent section titles from being numbered by redefining \ttl@straight@ii, which produces section titles for titlesec, so that it first sets this conditional to true, then does its thing and finally sets \ifinhibitparnums back to false. (To be more precise, I use \pretocmd to prepend \inhibitparnumstrue to this macro and \apptocmd to append \inhibitparnumsfalse. These are from the etoolbox package.)

You can also try to for instance similarly patch the tabular environment using \pretocmd{\tabular}{\inhibitparnumstrue}{}{}. This can also be made to work for starred environments, as explained in this answer.

To temporarily inhibit paragraph numbers, you can also manually type \inhibitparnumstrue, and to resume numbering type \inhibitparnumsfalse.

Here is the output:

enter image description here


Original solution:

The value of \everypar is temporarily changed after the end of an environment, just like after \section. This is done by the internal macro \@doendpe, which is called by \end.

One possible solution would thus be to redefine \@doendpe in exactly the way as you had already modified \@afterheading:

\documentclass[11pt]{article}
\usepackage{titlesec}
\setcounter{secnumdepth}{3}

\setlength{\parindent}{0pt} % indent subsequent paragraphs

\newcounter{para}
\newcommand*{\numberedparagraph}{%
  \refstepcounter{para}%
  \makebox[0pt][r]{\textbf{\thepara.~}}% %% This puts the number in the margin
  %\makebox[0pt][r]{\makebox[0pt][l]{\textbf{\thepara.}}\hspace{2em}}% %% This also left-aligns multi-digit numbers
  %\textbf{\thepara.~}% %% And this indents the paragraph instead
}

\let\oldep\everypar\newtoks\everypar  
\oldep{\the\everypar\everypar{\numberedparagraph}}

\makeatletter

\renewcommand{\@afterheading}{%
  \@nobreaktrue
\everypar{%
\if@nobreak
  \@nobreakfalse
  \clubpenalty\@M
  \if@afterindent
  \else
{\setbox\z@\lastbox}%
  \fi
\else
  \clubpenalty\@clubpenalty
  \everypar{\numberedparagraph}% <- modification
\fi
\numberedparagraph% <- modification
  }%
}

\def\@doendpe{\@endpetrue
  \def\par{%
    \@restorepar\everypar{\numberedparagraph}% <- modification
    \par\@endpefalse
  }%
  \everypar{%
    {\setbox\z@\lastbox}\everypar{\numberedparagraph}% <- modification
    \numberedparagraph % <- modification
    \@endpefalse
  }%
}

\makeatother % <- you forgot this, it is good form to restore the catcode of @

\AtBeginDocument{\everypar{\numberedparagraph}}

\begin{document}

\section{Section 1}

This is paragraph 1.

This is paragraph 2, and here are some bullets:

\begin{itemize}
    \item One.
    \item Two.
    \item Three.
\end{itemize}

And then this paragraph should be numbered 3 but it is not.

Numbering returns for this paragraph, but now the count is incorrect.

\end{document}

It feels like there should be a better solution though (edit: see above). (One that doesn't break whenever LaTeX does anything with \everypar.)

9
  • Thank you so much. I had given up hope on this problem, but you have saved the day, and once again this community amazes me with its generosity!I have noticed that using
    – quabbage
    Commented Mar 29, 2018 at 6:59
  • 1
    No problem. Your last sentence ended rather abruptly, what did you notice? Commented Mar 29, 2018 at 7:17
  • 1
    Also: I hadn't thought to check your original \numberedparagraph before, assume it did what you wanted. A few lines were missing a % at the end which caused some (possibly) unwanted spaces to appear. See here: tex.stackexchange.com/q/7453/156366 Commented Mar 29, 2018 at 8:32
  • 1
    Compared to many of the people here I'm far from an expert. Newlines are interpreted as spaces by TeX, and ending a line with a % comments out this (possibly unwanted) space. You should end a line with a % whenever putting a space there would be bad (which is often true in text, and rarely the case in equations). If you don't know what you're doing it might be safer to put a % at the end of every line in a definition. See the answer I linked to for more information. Commented Mar 29, 2018 at 10:24
  • 1
    To change the amount of space between the number and the paragraph you can change the ~ to some other spacing macro (like \quad or \hspace{<len>}). I've also added a (commented out) version that left-aligns single-digit numbers relative to multi-digit numbers. FYI: \makebox[0pt][<r or l>]{<stuff>} creates a box that is right/left aligned and takes up zero space Commented Mar 29, 2018 at 10:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .