4

I'd like to automatically add a final period if the argument of \paragraph does not end with either ., ?, or !.

A solution has been provided in Add a period after each paragraph title but this requires the last letter not being an upper case. How to address the general case?

\documentclass{article}

\usepackage{xparse} \usepackage{amsthm} % for @addpunct

\makeatletter \let\latexparagraph\paragraph \RenewDocumentCommand{\paragraph}{som}{% \IfBooleanTF{#1} {\latexparagraph*{#3}} {\IfNoValueTF{#2} {\latexparagraph{\maybe@addperiod{#3}}} {\latexparagraph[#2]{\maybe@addperiod{#3}}}% }% } \newcommand{\maybe@addperiod}[1]{% #1@addpunct{.}% } \makeatother

\begin{document}

\paragraph{This is the title} And some text follows.

\paragraph{This is the title.} And some text follows.

\paragraph{Is this is a title?} And some text follows.

\paragraph{This is the title X} And some text follows.

\paragraph{This is the title X.} And some text follows.

\paragraph{Is this is a title X?} And some text follows.

\end{document}

enter image description here

Mico
  • 506,678
user94293
  • 4,254
  • 1
    A capital letter should be marked with \@ if you expect punctuation to follow and it's not an abbreviation. – egreg May 14 '23 at 12:27
  • Please advise if you might ever use \paragraph with an optional argument, e.g., \paragraph[Title]{This is the title}. – Mico May 14 '23 at 12:50

2 Answers2

8

Here's a LuaLaTeX-based solution. It works by examining the argument of \paragraph and making use of Lua's powerful find, gsub, and sub string functions. If no punctuation mark is present at the end of the string, a period is inserted. As a (likely minor) bonus, this solution works with both \paragraph and \paragraph* directives.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}

\usepackage{luacode} % for 'luacode' environment \begin{luacode}

function doit ( u , v ) -- aux. function that does most of the work
  v = v:sub ( 1, -2 )        -- strip off closing curly brace
  v = v:gsub ( "%s+$" , "" ) -- strip off any trailing whitespace
  w = v:sub ( -1 )           -- retrieve last char in 'v' string
  if ( w=="." or w=="?" or w=="!" ) then
  else
    v = v.."." -- add period to end of 'v' string
  end
  return u .. v .. "}" -- add back the closing curly brace
end
function maybeaddperiod ( s )      -- the main function
  if s:find ( "\\paragraph" ) then -- we need to do something...
    return s:gsub ( "(\\paragraph%*?)%s*(%b{})" , doit )
  end
end
\end{luacode*}
% Add the Lua function to LuaTeX's "process_input_buffer" callback:
\AtBeginDocument{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , maybeaddperiod, "maybeaddperiod" )}}

\begin{document} 
%% Insert period at end of arg of "\paragraph"
\paragraph{This is the title } And some text follows.
\paragraph{This is the title X} And some text follows.
\paragraph*{This is the title } And some text follows.

\bigskip
%% Don't insert period
\paragraph{This is the title. } And some text follows.
\paragraph{Is this the title?} And some text follows.
\paragraph{This is the title! } And some text follows. 
\end{document}
Mico
  • 506,678
6

You can use regular expressions. Here I check whether the argument ends with ‘!’, ‘?’ or ‘.’ and, if not, a period is added.

\documentclass{article}

\NewCommandCopy\latexparagraph\paragraph \RenewDocumentCommand{\paragraph}{sO{#3}m}{% \IfBooleanTF{#1} {\latexparagraph*{\maybeaddperiod{#3}}} {\latexparagraph[#2]{\maybeaddperiod{#3}}}% }

\ExplSyntaxOn \NewDocumentCommand{\maybeaddperiod}{m} { \userninefourtwoninethree_maybeaddperiod:n { #1 } }

\cs_new_protected:Nn \userninefourtwoninethree_maybeaddperiod:n { \regex_match:nnTF { .*[!?.] \Z } { #1 } { #1 } { #1. } } \ExplSyntaxOff

\begin{document}

\paragraph{This is the title} And some text follows.

\paragraph{This is the title.} And some text follows.

\paragraph{Is this is a title?} And some text follows.

\paragraph{This is the title X} And some text follows.

\paragraph{This is the title X.} And some text follows.

\paragraph{Is this is a title X?} And some text follows.

\end{document}

enter image description here

Anyway, the previous solution works if you take the habit of adding \@ after any trailing uppercase letter that's not an abbreviation.

egreg
  • 1,121,712
  • 1
    +1. You may also want to strip off any trailing whitespace in the argument of \paragraph, to deal with cases such as \paragraph{This is the title }. – Mico May 14 '23 at 12:45
  • 1
    @Mico No, that's something nobody should have in their document. – egreg May 14 '23 at 12:53
  • 1
    @egreg Thank you. Also added the case of the ":"; \regex_match:nnTF { .*[\!\?\.\:] \Z } { #1 } { #1 } { #1. } – user94293 May 15 '23 at 04:47