我正在尝试编写一个脚本(在emacs lisp
)来转换TeX
显示数学样式,例如,
$$
x + y = z
$$
进入LaTeX
\begin{equation*}
x + y = z
\end{equation*}
为了达到我的目的我设想了这个算法:
在扫描文件中的
"$$"
字符串时,我会一次又一次地临时替换字符串,"$$"
如下"$$\TESTIFDISPLAYMATH"
所示\TESTIFDISPLAYMATH
:\newcommand{\TESTIFDISPLAYMATH}{\mathchoice{\wlog{DISPLAY MATH OK}}{}{}{}}
(这是必要的,以避免出现“$x,$$y,$”之类的误报)
此时,我将编译我的
.tex
文件以生成.log
文件并扫描它以查找我的目标字符串。删除
"\TESTIFDISPLAYMATH"
字符串后,如果“DISPLAY MATH OK”,我将执行替换。
我的问题是:
我能否以更快的方式完成任务?我的意思是,例如,无需
.tex
为每个实例完全编译我的文件"$$"
。有没有可以做到这一点的工具?
我愿意接受任何建议。
答案1
我确实不知道最好的方法是什么,但这里有几个建议。
由于您使用的是 Emacs,因此您可以尝试以下正则表达式替换:
\$\$\([^$]+\)\$\$ → \\begin{equation}\1\\end{equation}
这将匹配任何形式的
$$…$$
,其中…
可以是任何不包含 的字符序列(包括换行符)$
。它不会因您提到的误报而失败($x,$$y,$
),但会因类似 的内容而失败$x,$$y,$$z,$
。为了安全起见,您可能希望先
\\
用一些独特的东西替换,然后再用\$
一些独特的东西替换(两者都不是正则表达式),然后撤消这些替换。第一次替换是为了防止替换\$
in\\$
,第二次替换是为了防止替换\$$
when\$
是文字 $ 符号,第二次替换开始或结束一个等式。如果你想知道所有显示数学环境的行号,你可以添加
\everydisplay\expandafter{\the\everydisplay\GenericWarning{\relax}{DISPLAY MATH}}
到你的序言。这将打印
DISPLAY MATH on input line <line>
每个显示方程。( 的内容
\everydisplay
插入到每个显示环境的开始处。您可以使用 向其中添加一些内容\everydisplay\expandafter{\the\everydisplay<addition>}
。 )您的
\TESTIFDISPLAYMATH
算法实际上不起作用,因为 的每个分支\mathchoice
始终都会执行(尽管只打印一个)。因此,DISPLAY MATH OK
无论是否从显示环境中调用此宏, 都会打印。如果你想走这条路,你可能想尝试类似
\let\TESTIFDISPLAYMATH\empty %% <- does nothing \makeatletter %% <- make @ usable in command names \everydisplay\expandafter{\the\everydisplay \@ifnextchar\TESTIFDISPLAYMATH{\wlog{DISPLAY MATH OK}}{}} \makeatother %% <- revert @
你应该添加这个在最后你的序言(特别是在加载之后
amsmath
,或者甚至可能在加载之后\begin{document}
(为了安全起见)。DISPLAY MATH OK
只要等式中出现的第一件事是,它就会打印\TESTIFDISPLAYMATH
。它可能与某些包不兼容(如果它们\everydisplay
在运行时发生变化,但我不知道有任何变化)。或者你可以尝试
\let\TESTIFDISPLAYMATH\empty %% <- does nothing \everydisplay\expandafter{\the\everydisplay \renewcommand\TESTIFDISPLAYMATH{\wlog{DISPLAY MATH OK}}}
这种方式
\TESTIFDISPLAYMATH
通常不执行任何操作,但它被重新定义为DISPLAY MATH OK
在显示数学环境中使用时写入日志文件。不过,在这样的环境中使用时也会触发\text{…}
,因此它仍然不完美。
答案2
虽然没有经过严格测试,但 Lisp 函数看起来可能像这样。它$$
用环境替换所有出现在一行中的equation*
。如果使用 调用C-u M-x,它还会查找 inline$$
并替换它们。
(defun GN/fix-math ()
"Search and replace TeX's $$ with LaTeX's \"equation*\" environment.
Replaces only $$ in single lines. If invoked with `C-u', then
also looks after $$ which are inline. User is asked for
confirmation then."
(interactive)
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(let ((kill-whole-line nil))
(while (and (re-search-forward (concat "^[ \t]*" (regexp-quote "$$") "[ \t]*$") nil t)
(texmathp))
(beginning-of-line)
(kill-line)
(insert "\\begin{equation*}")
(re-search-forward (concat "^[ \t]*" (regexp-quote "$$") "[ \t]*$") nil t)
(beginning-of-line)
(kill-line)
(LaTeX-close-environment)
(forward-line -1)
(LaTeX-fill-environment nil)))))
(when current-prefix-arg
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(while (re-search-forward (regexp-quote "$$") nil t)
(when (yes-or-no-p "Replace $$? ")
(delete-char -2)
(newline)
(save-excursion
(end-of-line -1)
(delete-horizontal-space))
(insert "\\begin{equation*}")
(newline)
(indent-according-to-mode)
(re-search-forward (regexp-quote "$$") nil t)
(delete-char -2)
(LaTeX-close-environment)
(forward-line -1)
(LaTeX-fill-environment nil)))))))