% \iffalse meta-comment
%
% File: xpunctuate.dtx
%
% Copyright (C) 2023 by Philip G. Ratcliffe <philip.ratcliffe@uninsubria.it>
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.
% The latest version of this license is in the file
%
%    http://www.latex-project.org/lppl.txt
%
% This file is part of the "xpunctuate package" (the Work in LPPL)
% and all files in that package must be distributed together.
%
% The released version of this package is available from CTAN.
%
% This package has the LPPL maintenance status "maintained".
%
% The current maintainer of this package is Philip G. Ratcliffe.
%
% This work consists of the files xpunctuate.dtx and xpunctuate.ins
% and the derived file xpunctuate.sty.
%
% \fi
%
% \iffalse
%
%<package>\NeedsTeXFormat{LaTeX2e}[2020/10/01]
%<package>\ProvidesPackage{xpunctuate}
%<package>  [2023/08/13 v2.0 punctuation after command names (PGR)]
%
%<*driver>
\documentclass[british]{ltxdoc}
\usepackage{xpunctuate}
%
\NewDocElement[macrolike=false]{Generic}{generic}
\renewcommand\thefootnote{\color{red}{\emph{\alph{footnote}}}}
\newenvironment{codelist}
  {\begin{list}{}{\setlength\leftmargin{3em}}\item[]}{\end{list}}
\newcommand\eg{\xperiodafter{\emph{e}.\emph{g}}}
\newcommand\ie{\xperiodafter{\emph{i}.\emph{e}}}
%
\CodelineIndex
\EnableCrossrefs
\RecordChanges
\DoNotIndex{\def,\let,\futurelet}
\DoNotIndex{\if,\else,\fi,\ifx,\fi,\iftrue,\fi,\iffalse,\fi}
\DoNotIndex{\the,\csname,\endcsname,\expandafter,\noexpand,\protect}
%
\begin{document}
  \DocInput{xpunctuate.dtx}
\end{document}
%</driver>
% \fi
%
% \CheckSum{154}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \changes{v1.0}{2012/05/21}{first public release}
% \changes{v2.0}{2023/08/13}{general upgrade}
%
% \GetFileInfo{xpunctuate.sty}
%
% \DoNotIndex{\CodelineIndex,\EnableCrossrefs,\RecordChanges}
%
% \title{The \texttt{xpunctuate} package for \LaTeX2e
% \\[1ex] \small (\fileversion, last revision \filedate)}
%
% \author{Philip G. Ratcliffe
% \\[1ex] \small \textsf{philip.ratcliffe@uninsubria.it}
% \\[2ex] \small Dipartimento di Scienza e Alta Tecnologia
% \\ \small Universit\`a degli Studi dell'Insubria---Como
% \\ \small and
% \\ \small Istituto Nazionale di Fisica Nucleare
% \\ \small Sezione di Milano Bicocca}
%
% \date{}
%
% \maketitle
%
% \begin{abstract}
% The |xpunctuate| package provides package writers and ordinary users with
% automatic post-macro punctuation insertion, \ie beyond (but similar to) that
% of the |xspace| package, which is required here. Three new macros are
% defined: |\xperiod|, |\xcomma| and |\xperiodcomma|, designed to insert the
% required punctuation marks \emph{if and only if} necessary, following a
% similar procedure to the |xspace| package. A further four macros
% (|\xspaceafter|, |\xperiodafter|, |\xcommaafter| and |\xperiodcommaafter|)
% are constructed to avoid the small superfluous space after possible font
% changes (such as |\emph|) that involve the correction |\/|, which would
% otherwise be hidden.
% \end{abstract}
%
% \section{Introduction}
%
% The present package is mainly intended for package writers, but may also
% serve the ordinary user; it provides additional post-macro punctuation
% insertion, similar to that of the |xspace| package. Three new macros are
% defined: |\xperiod|, |\xcomma| and |\xperiodcomma|, which, in an analogous
% fashion to the standard |\xspace| macro, insert any relevant punctuation
% where necessary. Four additional macros, of the form |\x|\dots|after|, avoid
% the small superfluous space due to the following period or comma being
% isolated from a preceding~|\/|.
%
% \section{Package call}
%
% \DescribeGeneric{package call}
% The package is loaded via a standard call:
% \begin{codelist}
% |\usepackage{xpunctuate}|
% \end{codelist}
%
% \subsection{User options}
%
% \DescribeGeneric{user options}
% There are at present \emph{no} user options.
%
% \subsection{User macros}
%
% Three user macros are defined, each having a pre-punctuation space-correcting
% variant, plus a similar extension of the |\xspace| macro.
%
% \DescribeMacro{\xperiod}
% The purpose of this macro is to insert a period if not found as the
% successive \LaTeX\ input token. Typical use will be in defining
% abbreviations, where there may or may not be a following \emph{accidental}
% sentence-terminating full stop. If \emph{no} explicit period follows, one is
% inserted, the occurrence is assumed to be mid-sentence and therefore normal
% inter-word spacing is applied. However, if it \emph{is} followed by a period,
% then this is considered to be a sentence terminator, it is left as is with no
% further insertions and the appropriate trailing space will then naturally
% ensue.
%
% After defining |\newcommand{\gb}{G.B\xperiod}|, the command |\gb| will
% determine when to insert a period after itself and when not, with also the
% correct mid-sentence or end-of-sentence spacing as required. Thus, the input
% \newcommand{\gb}{G.B\@\xperiod}
% \begin{codelist}
% |\gb is a very nice place to live.\\|\\
% |I live in \gb. It is a small island off the coast of France|\\
% |\gb\footnote{The small island off the coast of France.}|\\
% |is a very nice place to live.|
% \end{codelist}
% results in the output
% \begin{codelist}
% \gb is a very nice place to live.\\
% I live in \gb. It is a small island off the coast of France.\\
% \gb\footnote{The small island off the coast of France.}
% is a very nice place to live.
% \end{codelist}
%
% \DescribeMacro{\xcomma}
% This macro similarly inserts a comma if not found as the next token. A
% typical application might be following an abbreviation such as `eg' (\ie when
% used \emph{without} periods), which according to different standard style
% manuals should or should not be followed by a comma. It has no special
% spacing behaviour.
%
% \DescribeMacro{\xperiodcomma}
% This macro inserts a period \emph{and} a comma if not found as the next input
% tokens. Typical use will be, as above, for abbreviations such as `e.g.'\ (\ie
% \emph{with} periods) when they should be followed by a comma, but may also
% occur fortuitously immediately preceding an explicit sentence-closing period
% or indeed an explicit comma, the correct trailing space of which would then
% ensue. Note that this action \emph{cannot} be reproduced via successive use
% of the single macros, \ie the combination |\xperiod\xcomma|.
%
% \DescribeMacro{\xspaceafter}
% \DescribeMacro{\xperiodafter}
% \DescribeMacro{\xcommaafter}
% \DescribeMacro{\xperiodcommaafter}
% The variants |\x|\dots|after| are similar to the above except that they take
% the object word or phrase to be spaced or punctuated as an argument; the
% slight incorrect spacing adjustment between the word and following period or
% comma is thus avoided when, for example, the word is |\emph|'asised. Other
% punctuation marks do \emph{not} suffer from this problem.
%
% Note that although the action of |\xperiodcommaafter| may also be obtained
% via suitable nesting of |\xperiodafter| and |\xcommaafter|, this combination
% has not been thoroughly tested; the compound macro is thus included for both
% safety and backwards compatibility.
%
% In the case of the macros that guarantee a trailing period (\emph{with} or
% \emph{without} a comma), if the final letter of the word or phrase is a
% capital (\eg `Ph.D.'), to guarantee the correct end-of-sentence trailing
% spacing, it should be immediately followed by an explicit |\@|. That is, the
% definition should be of the form
% \begin{codelist}
% |\newcommand\PhD{Ph.D\@\xperiod}|\\[-0.67ex]
% \hspace*{-\leftmargin}\, or\\[-0.67ex]
% |\newcommand\PhD{\xperiodafter{Ph.D\@}}|
% \end{codelist}
% N.B. If the ending capital letter or letters are \eg |\emph|'asised, the |\@|
% should be placed \emph{inside} the |\emph|'asis:\footnote{It is for this
% reason that it \emph{cannot} be incorporated directly into the |xpunctuate|
% macros.}
% \begin{codelist}
% |\newcommand\PhD{\emph{Ph}.\emph{D\@}\xperiod}|\\[-0.67ex]
% \hspace*{-\leftmargin}\, or\\[-0.67ex]
% |\newcommand\PhD{\xperiodafter{\emph{Ph}.\emph{D\@}}}|
% \end{codelist}
%
% The following are various other examples of possible usage:
% \begin{codelist}
% |\newcommand\etc{etc\xperiod}|\\
% |\newcommand\eg{i.e\xperiodcomma}|\\
% |\newcommand\etal{\xperiodafter{\emph{et al}}}|\\
% |\newcommand\ie{\xperiodcommaafter{\emph{e}.\emph{g}}}|
% \end{codelist}
% Note how the closing period in the above is \emph{not} explicitly present,
% being inserted by the relevant macro as and when necessary, with too the 
% correct spacing.
%
% \subsection{Caveats}
%
% \begin{generic}{caveats}
% No specific care should be necessary when employing the macros defined here;
% in particular, they are all \emph{robust}. However, trailing punctuation
% hidden inside or by other macro definitions may not always be correctly
% interpreted. Moreover, the known limitations of |\xspace| remain.
% \end{generic}
%
% \subsection{External package requirements}
%
% \begin{generic}{xspace}
% The |xspace| package is required and is loaded automatically. Note that, in
% the \emph{absence} of |\xspace|, the necessary presence of explicit trailing
% backslashes for correct spacing following command strings, would frustrate
% the functionality of all the macros defined here.\footnote{Users who shun the
% use of |xspace| will probably not appreciate the present package either.}
% \end{generic}
%
% \subsection{Package conflicts}
%
% \begin{generic}{conflicts}
% There are no known conflicts with any standard \LaTeX2e\ packages.
% \end{generic}
%
% \StopEventually{\PrintChanges\PrintIndex}
%
% \section{Implementation}
%
% \subsection{External packages}
% \begin{generic}{packages}
% First, load the |xspace| package, for automatic trailing-space insertion:
%    \begin{macrocode}
\RequirePackage{xspace}
%    \end{macrocode}
% \changes{v2.0}{2023/08/13}{useful \texttt{xspace} exceptions added}
% \begin{generic}{exceptions}
% and add some useful extra |xspace| exceptions relevant to the present
% package.
%    \begin{macrocode}
\xspaceaddexceptions{\xcomma\xperiod\xperiodcomma}
%    \end{macrocode}
% \end{generic}
% \end{generic}
%
% \subsection{User commands}
%
% \changes{v2.0}{2023/08/13}{revamped all macros}
% \begin{macro}{\xspaceafter}
% \changes{v2.0}{2023/08/13}{macro added}
% This macro takes one argument, which it prints as is. It then inserts
% |\xspace| immediately after, but nothing if followed by a comma or period.
%    \begin{macrocode}
\NewDocumentCommand\xspaceafter{}{\xpnct@aux\xspace@aux}
%    \end{macrocode}
% The correct spacing between the argument and any following comma or period is
% thus maintained in the case of, say, an |\emph|'asised argument. The
% necessity arises as the presence of |\xspace| `hides' any following
% punctuation from a possible |\/| spacing-correction command.
% \end{macro}
%
% \begin{macro}{\xperiod}
% The following macro inserts a period if this is not found to be the next
% character.
%    \begin{macrocode}
\NewDocumentCommand\xperiod{}{\xpnct@aux\xperiod@aux{}}
%    \end{macrocode}
% It may thus be used to construct common abbreviations (such as `etc.').
% \end{macro}
%
% \begin{macro}{\xperiodafter}
% This macro takes one argument and inserts a period after it if this is not
% found to be the next character.
%    \begin{macrocode}
\NewDocumentCommand\xperiodafter{}{\xpnct@aux\xperiod@aux}
%    \end{macrocode}
% The correct spacing between the argument and period is again thus maintained
% in the case of, say, |\emph|, as in often \emph{italicised} abbreviations
% (such as `\emph{etc}.').
% \end{macro}
%
% \begin{macro}{\xcomma}
% The following macro inserts a comma if this is not found to be the next
% character.
%    \begin{macrocode}
\NewDocumentCommand\xcomma{}{\xpnct@aux\xcomma@aux{}}
%    \end{macrocode}
% It may thus be used to construct those common abbreviations (without periods)
% that might normally be followed by a comma, such as `eg' or `ie' according to
% standard American-English usage.
% \end{macro}
%
% \begin{macro}{\xcommaafter}
% The following macro takes one argument and inserts a comma after it if this
% is not found to be the next character.
%    \begin{macrocode}
\NewDocumentCommand\xcommaafter{}{\xpnct@aux\xcomma@aux}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\xperiodcomma}
% The following macro first adds a period and then a comma if these are not
% found to be the next characters.
%    \begin{macrocode}
\NewDocumentCommand\xperiodcomma{}{\xpnct@aux\xperiodcomma@aux{}}
%    \end{macrocode}
% It may thus be used to construct those common abbreviations that might
% normally be followed by a comma (such as `e.g.,'), the comma being inserted
% \emph{if and only if} there is no following explicit sentence-ending period.
% Here, there is of course no problem of spacing either preceding or following
% the period. If only a period is found, it is treated as an end-of-sentence
% and the correct spacing will ensue accordingly. A following period--comma
% combination, if found, will be left as is.
% \end{macro}
%
% \begin{macro}{\xperiodcommaafter}
% This macro takes one argument and inserts a period and/or a comma after it if
% these are not found to be the next characters.
%    \begin{macrocode}
\NewDocumentCommand\xperiodcommaafter{}{\xpnct@aux\xperiodcomma@aux}
%    \end{macrocode}
% It may thus be used to construct those common \emph{italicised} abbreviations
% that should normally be followed by a comma (such as `\eg,').
% \end{macro}
%
% \subsection{Internal macros}
%
% \begin{macro}{\xpnct@tok}
% A token register is defined to store a possible object word or phrase:
%    \begin{macrocode}
\newtoks\xpnct@tok
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\xpnct@aux}
% The general setup and call to the final output macros for the above user
% commands is handled by the following auxiliary macro:
%    \begin{macrocode}
\def\xpnct@aux#1#2{%
  \xpnct@tok{#2}%
  \futurelet\xpnct@nxt#1}
%    \end{macrocode}
% \end{macro}
% Note that all the user commands defined earlier terminate by inserting an
% |\xspace| \emph{if} and \emph{only if} the required punctuation has actually
% been inserted by the macro.
%
% \begin{macro}{\xspace@aux}
% Testing and output for |\xspaceafter| are performed by the following macro:
%    \begin{macrocode}
\def\xspace@aux{%
  \ifx\xpnct@nxt,\else
  \ifx\xpnct@nxt.\else
    \xpnct@tok\expandafter{\the\xpnct@tok\xspace}%
  \fi\fi
  \the\xpnct@tok}
%    \end{macrocode}
% Only periods and commas need be excluded, as the spacing is correct for all
% other punctuation marks.
% \end{macro}
%
% \begin{macro}{\xperiod@aux}
% Testing and output for |\xperiod| and |\xperiodafter| are performed by this
% macro:
%    \begin{macrocode}
\def\xperiod@aux{%
  \ifx\xpnct@nxt.\else
    \xpnct@tok\expandafter{\the\xpnct@tok.\@\xspace}%
  \fi
  \the\xpnct@tok}
%    \end{macrocode}
% The approach adopted is to treat an explicit following period as an
% end-of-sentence full stop; the trailing space is then handled accordingly.
% However, when an explicit period is \emph{not} found), the placement of |\@|
% immediately after the inserted period thus avoids standard end-of-sentence
% spacing, assuming such an occurrence to be mid-sentence (as for
% abbreviations). If, in contrast, an explicit period \emph{is} found, it is
% retained as is and will thus generate the correct end-of-sentence spacing.
% \end{macro}
%
% \begin{macro}{\xcomma@aux}
% Testing and output for |\xcomma| and |\xcommaafter| are performed by the
% following macro (shamelessly copied from an \emph{old} |xspace.sty| and
% suitably hacked):
%    \begin{macrocode}
\def\xcomma@aux{%
  \ifx\xpnct@nxt.\else
  \ifx\xpnct@nxt,\else
  \ifx\xpnct@nxt:\else
  \ifx\xpnct@nxt;\else
  \ifx\xpnct@nxt!\else
  \ifx\xpnct@nxt?\else
  \ifx\xpnct@nxt/\else
  \ifx\xpnct@nxt-\else
  \ifx\xpnct@nxt'\else
  \ifx\xpnct@nxt)\else
  \ifx\xpnct@nxt]\else
  \ifx\xpnct@nxt\}\else
  \ifx\xpnct@nxt\egroup\else
  \ifx\xpnct@nxt\/\else
    \xpnct@tok\expandafter{\the\xpnct@tok,\xspace}%
  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
  \the\xpnct@tok}
%    \end{macrocode}
% Note that certain of the default exceptions set by the |xspace| package are
% missing here, for obvious reasons.
% \end{macro}
%
% \begin{macro}{\xperiodcomma@aux}
% Testing and output for |\xperiodcomma| and |\xperiodcommaafter| are performed
% by the following:
%    \begin{macrocode}
\def\xperiodcomma@aux{%
  \ifx\xpnct@nxt.\else
    \xpnct@tok\expandafter{\the\xpnct@tok.\@\xcomma}%
  \fi
  \the\xpnct@tok}
%    \end{macrocode}
% The presence or absence of an explicit following period is again taken to
% imply an end-of- or mid-sentence respectively, unless followed by an explicit
% comma, other closing punctuation or brackets say, when it will be assumed
% mid-sentence. Note, moreover, that |\@| is \emph{still} necessary here as the
% period may not necessarily be immediately followed by a comma, \eg if it is
% followed by a closing bracket or quotation marks.
% \end{macro}
%
% \begin{macro}{\endinput}
% Finally, explicitly terminate the package input here.
%    \begin{macrocode}
\endinput
%    \end{macrocode}
% \end{macro}
%
% \Finale
%
\endinput
%%
%% End of file `xpunctuate.dtx'.