智能 \footnotemark 宏:如果在标点符号前插入则交换

智能 \footnotemark 宏:如果在标点符号前插入则交换

出于显而易见的原因,放置脚注标记是一种很好的做法(实际上也是正确的做法)标点符号,这是:

  • 错误:
    • 这是声明1
    • 这是语句2,这是另一个语句。
    • 这是问题3吗?
  • 正确的:
    • 这是一个声明。1
    • 这是一个声明,2这是另一个声明。
    • 这是一个问题吗?3

现在,我很健忘,所以我通常做错事。也就是说,我经常写成This is a statement\footnotemark.而不是This is a statement.\footnotemark。此外,我很懒,所以我宁愿让计算机帮我纠正我(和其他人)的错误,或者至少提醒我。因此,我制作了以下宏:

\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}% 
}

这是一个 MWE,在实际实现中,有多个\@ifnextchar嵌套,涵盖逗号、分号、句号、问号和感叹号。我的具体问题是:

  1. 我怎样才能抑制下一个字符(宏后面的字符)以便脚注标记和标点符号交换位置?请考虑这也必须与\footnote已经接受参数的参数一起工作。
  2. 有没有更优雅的方式来处理这个其他棕褐色嵌套\@ifnextchar

我几乎确信这无法在 LaTeX 中完成,但在放弃之前,我宁愿咨询专家。

提前致谢。

注意:请不要提出建议sed或任何其他基于 bash 的方法。我知道我可以在 Makefile 中添加一些行来修复 latex 代码,但这不是重点(已经实现)。

答案1

我正在使用完全不同的方法添加第二个答案。而我的另一个答案用于listofitems搜索标点符号列表,它只能处理后面跟着\footnotemark单个标点符号的情况。

\footnotemark例如,如果 后面跟着 、...."甚至".,那么它将不起作用''。为了在这里处理这个问题,在不使用包的情况\futurelet下,我使用了一种模仿cite包中使用的方法,检查连续的字符以查看它们是否与 中找到的字符匹配\marklist

这里,我仅介绍了 的方法\footnotemark,但没有理由不能为 提供类似的方法\footnote。请注意,这里不提供对可选参数的支持。

\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}

在此处输入图片描述

如果真的想采用这种方法(没有可选参数)\footnote,那么可以简单地定义

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

调用上述版本的\footnotemark

答案2

这可能就足够了,但是正如 MWE 中所描述的,在某些情况下可能会中断。

\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}

在此处输入图片描述

答案3

到目前为止,我已经让这个解决方案奏效了。它并不强大,因此欢迎提出意见和改进。

\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%
    }%
}

相关内容