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?

quabbage
  • 133

1 Answers1

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.)

Circumscribe
  • 10,856
  • 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 Mar 29 '18 at 06:59
  • 1
    No problem. Your last sentence ended rather abruptly, what did you notice? – Circumscribe Mar 29 '18 at 07:17
  • Sorry for trailing off in that comment, I accidentally hit the return key. What I was going to say is that your first solution works better for me on more complicated documents. I just need to figure out how to get the numbering in the margin and I'm good to go (using \vspace in the definition of para seems to break line spacing). However if I can't get that to work, your solution is still workable for me so once again, thank you. – quabbage Mar 29 '18 at 08:06
  • I've modified my answer so that it puts the paragraph numbers in the margins. – Circumscribe Mar 29 '18 at 08:29
  • 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: https://tex.stackexchange.com/q/7453/156366 – Circumscribe Mar 29 '18 at 08:32
  • I can't thank you enough! Should I just add a % to every line in the macro definitions? And I feel really cheeky asking this but as I don't often have the chance to speak to an expert I will take this opportunity and ask: is there any way to increase the distance of the numbering in the margin from the text? I’ve tried setting marginparwidth but it doesn’t seem to have an impact…? Thank you so much for your time. – quabbage Mar 29 '18 at 09:20
  • 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. – Circumscribe Mar 29 '18 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{}). I've also added a (commented out) version that left-aligns single-digit numbers relative to multi-digit numbers. FYI: \makebox[0pt][]{} creates a box that is right/left aligned and takes up zero space – Circumscribe Mar 29 '18 at 10:26
  • Brilliant - you have made a massive difference to the project I am working on. All the best, Brian – quabbage Mar 29 '18 at 10:51