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

2
  • 1
    A capital letter should be marked with \@ if you expect punctuation to follow and it's not an abbreviation.
    – egreg
    May 14, 2023 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, 2023 at 12:50

2 Answers 2

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.

3
  • 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, 2023 at 12:45
  • 1
    @Mico No, that's something nobody should have in their document.
    – egreg
    May 14, 2023 at 12:53
  • 1
    @egreg Thank you. Also added the case of the ":"; \regex_match:nnTF { .*[\!\?\.\:] \Z } { #1 } { #1 } { #1. }
    – user94293
    May 15, 2023 at 4:47
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}

You must log in to answer this question.

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