3

For obvious reasons, it is a good practice (actually the correct way to do it) to place footnote markers after the punctuation marks, this is:

  • Incorrect:
    • This is a statement1.
    • This is a statement2, and this is another statement.
    • Is this a question3?
  • Correct:
    • This is a statement.1
    • This is a statement,2 and this is another statement.
    • Is this a question?3

Now, I'm quite forgetful, so I normally do it in a wrong way. This is, I often write This is a statement\footnotemark. instead of This is a statement.\footnotemark. Besides, I'm lazy so I'd rather have the computer fixing my (and others') mistakes for me, or at least remind me. Therefore, I made the following macro:

\let\oldfootnotemark\footnotemark
\renewcommand{\footnotemark}{%
    \@ifnextchar.{%
        % I neet to change this line so the dot and the mark switch places
        \oldfootnotemark\textcolor{red}{\bfseries Fix me!}
    }{\oldfootnotemark\xspace}% 
}

That's a MWE, in the real implementation there are several \@ifnextchar nested to cover coma, semicolon, period, and question and exclamation marks. My questions in concrete are:

  1. How can I suppress the next character (the one following the macro) so the footnote mark and the punctuation character switch places? Please consider that this must also work with \footnote which already takes a parameter.
  2. Is it there a more elegant way to approach this other tan nesting \@ifnextchar?

I'm almost sure this can't be done in LaTeX but before giving up, I rather ask the experts.

Thanks in advance.

Note: Please abstain from suggesting sed or any other bash-based approaches. I know I can add some lines in Makefile to fix the latex code, but that's not the point (already implemented).

2
  • See the fnpct package: ctan.org/pkg/fnpct Commented Mar 27, 2019 at 21:30
  • Thanks a lot for the hint! This package looks quite useful. However after reading the documentation, you must get used to set the footnote BEFORE the punctuation mark. The solution I'm looking for aims at a forgetful person that will use both interchangeably, so not the precise answer I'm looking for. However, I might well sed footnotes and integrate this package once the draft moves to a definitive version.
    – Kyordhel
    Commented Mar 28, 2019 at 12:29

3 Answers 3

2

I am adding a 2nd answer using a completely different approach. Whereas my other answer uses listofitems to search for list of punctuation, it can only handle cases where the \footnotemark is followed by a single punctuation character.

It will not work when the \footnotemark is followed by, for example, ..., .", "., or even ''. To handle that here, without the use of packages, I use a \futurelet approach modeled after the one used in the cite package, to check successive characters to see if they match those found in a \marklist.

Here, I only present the approach for \footnotemark, but there is no reason a comparable method can't also be done for \footnote. Note that support for optional arguments is not provided here.

\documentclass{article}
\let\oldfootnotemark\footnotemark
\def\marklist{.,:;!?'"}% LIST OF SEARCHED-FOR PUNCTUATION
\def\foundmarks{}%
\def\foundmark#1{\footnotemark}% EATS THE RESIDUAL MARK AND LOOKS AGAIN
\def\nomarksfound{%
  \foundmarks
  \gdef\foundmarks{}%
  \oldfootnotemark{}}% PRINTS OUT FOUND MARKS FOLLOWED BY ORIG. \footnotemark
% \foundmarks ARE SAVED AND PRINTED TOGETHER FOR KERNING REASONS, e.g. ''

\def\footnotemark{%
  \let\fnmcloseout\nomarksfound% ASSUME NO PUNCTUATION FOLLOWS \footnotemark
  \futurelet\tmpA\testformarks}

\def\testformarks{%
  \expandafter\marktest\expandafter\tmpA\marklist\delimiter\fnmcloseout}

\makeatletter
\def\marktest#1#2#3\delimiter{%
  \ifx#1#2%
    \g@addto@macro\foundmarks{#2}% SAVED, NOT PRINTED, FOR KERNING REASONS
    \let\fnmcloseout\foundmark% SET UP CLOSEOUT TO DO IT AGAIN
  \fi
  \ifx\relax#3\relax\else
    \marktest#1#3\delimiter% AGAIN, UNTIL MARK LIST EXHAUSTED
  \fi}
\makeatother
\begin{document}
Word\footnotemark next

Word\footnotemark{} next

Word\footnotemark: Next

Word\footnotemark. Next

Word\footnotemark... Next

``Word\footnotemark.'' Next
\end{document}

enter image description here

If one really wanted to adopt this (no optional argument) approach for \footnote, as well, one could simply define

\renewcommand\footnote[1]{%
  \stepcounter{footnote}%
  \footnotetext{#1}%
  \addtocounter{footnote}{-1}%
  \footnotemark%
}

calling upon the above version of \footnotemark.

2

This may suffice, but can, as described in the MWE, break under certain circumstances.

\documentclass{article}
\usepackage{listofitems}
\let\oldfootnotemark\footnotemark
\renewcommand\footnotemark[1]{%
  \setsepchar{.||,||;||:||"||?||!}%
  \readlist\nextchar{ #1}%
  \ifnum\listlen\nextchar[]>1\relax #1\oldfootnotemark\else
    \oldfootnotemark\expandafter#1\fi%
}
\let\oldfootnote\footnote
\renewcommand\footnote[2]{%
  \setsepchar{.||,||;||:||"||?||!}%
  \readlist\nextchar{ #2}%
  \ifnum\listlen\nextchar[]>1\relax #2\oldfootnote{#1}\else
    \oldfootnote{#1} \expandafter#2\fi%
}
\begin{document}
xyz\footnotemark

xyz\footnotemark{} text

xyz\footnotemark.

xyz\footnotemark,

xyz\footnotemark!

``xyz\footnotemark"

\footnotemark\begin{tabular}{|c|}\hline x\\\hline\end{tabular} can occur right
  before an environment.\bigskip

Footnote\footnote{My fn}, changed separately.

Footnote\footnote{My fn} was changed separately.

Footnote\footnote{My fn}\begin{tabular}{|c|}\hline x\\\hline\end{tabular} can occur 
  before environment, but a space is injected.\bigskip

BAD CASE:

Footnote\footnote{My fn}-mid-word has wrong spacing.
\end{document}

enter image description here

4
  • Amazing! Thanks a lot. I don't think there is a bad case there, tho. One never adds footnotes in the middle of a [composite] word. Quotes are not an issue because I'm using csquotes, but for the rest it works like a charm. I need to give a try to xyz\footnotemark text (without the {} after \footnotemark) since I'm more used to \footnotemark~ and that will be a habit extremely hard to break.
    – Kyordhel
    Commented Mar 28, 2019 at 12:32
  • 1
    @Kyordhel With my approach, xyz\footnotemark~text looks the same as xyz\footnotemark{} text, except that the former prohibits a line break. One would not use xyz\footnotemark text in any case, because the space would always be supressed. Commented Mar 28, 2019 at 12:36
  • Okay, thanks for the hint, today I learned something new. So the good practice is \macro{}. What if at the very end of the \renewcommand I add \xspace? I can give it a try, but perhaps it has pernicious effects on the code and I must stop being that lazy.
    – Kyordhel
    Commented Mar 28, 2019 at 12:43
  • 1
    @Kyordhel I do not use xspace and it is not even recommended by its author: tex.stackexchange.com/questions/86565/drawbacks-of-xspace/…, LOL. I prefer the best-practice approach of \macro{}. However, there are times where ~ does make sense, for example between the word Fig. and its associated number, where you would like to prohibit a linebreak. Commented Mar 28, 2019 at 12:51
0

Si far I got this solution working. It is not robust, so comments and improvements are welcome.

\let\oldfootnote\footnote
\let\oldfootnotemark\footnotemark
\renewcommand{\footnote}[2]{%
    \IfSubStr{.,;?!}{#2}{%
        #2\oldfootnote{#1}\xspace%
    }{%
        \oldfootnote{#1}\xspace#2%
    }%
}
\renewcommand{\footnotemark}[1]{%
    \IfSubStr{.,;?!}{#1}{%
        #1\oldfootnotemark\xspace%
    }{%
        \oldfootnotemark\xspace#1%
    }%
}

You must log in to answer this question.

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