使用 Emacs+Auctex 删除 tex 文件中的注释

使用 Emacs+Auctex 删除 tex 文件中的注释

我正在处理其他人的 LaTeX 文件,有时它们看起来很乱。我正在寻找一种不更改代码即可删除所有注释的方法。问题是我想保留所有空格并排除百分号\%。我自己做这件事感觉有点不安全,而且我是 Emacs 新手。也许已经写好了一些东西?但是如果没有,也许您可​​以通过指出我应该包含在 elisp 代码中的危险情况来帮助我。

PS 另外,如果能提供任何关于如何让其他人的代码更易读的建议,我将非常感激:)。

答案1

如果你不需要担心逐字或动词的使用,那么

(query-replace-regexp "\\(^\\| *[^\\\\]\\)%.*" "" nil nil)

可能是安全的(并且它确实进行查询替换,因此无论如何您都可以说“是”或“否”)。

请注意,如果注释位于行首,则此操作将删除整行(因为留下一个空白行会形成一个段落)。但是,如果注释不是整行,则不会删除行尾,这意味着它可能会引入空格,因此它在文档上可能是安全的,但在宏代码中则不安全。

那是

blah blah
%not this line
blah blah

变成

blah blah
blah blah

abc% a comment here
xyz

变成

abc
xyz

更正确的翻译(相对容易做到)应该是

abcxyz

但这会使整个文件变成一行长行,所以您必须注意在命令名称后留出空格。


LaTeX 不是常规语言,因此如果使用正则表达式解析它,那么它会弄乱一些构造。这就是为什么它们被称为正则表达式。另一种方法是做一个完整的 latex 解析器,但这很难。考虑一下xii.tex这个网站上有一些这样的例子。试图在其中找到注释会很棘手(没有,但 emacs 不知道)。

如果您愿意,在删除百分比时删除前面的换行符会相对容易。对于动词和逐字,我可能会先将 % 更改为 [[[PERCENTWASHERE]],然后在删除 % 后再将其改回

也许与此不同(定义一个交互式命令,M-x xxx在定义被评估后您可以运行它)它会处理5并且verbatim如果\verb| ... % |您使用其他字符作为\verb分隔符,则需要进行一些修改。

(defun xxx ()
(interactive)

(goto-char (point-min))
(while (re-search-forward "\\\\begin{verbatim}" nil 1)
  (progn
   (replace-regexp "%" "@@@@@PERCENT@@@@@" nil (point)
           (save-excursion
             (progn (re-search-forward "\\\\end{verbatim}" nil 1) (point))))))

(goto-char (point-min))
(while (re-search-forward "\\\\verb|" nil 1)
  (progn
   (replace-regexp "%" "@@@@@PERCENT@@@@@" nil (point)
           (save-excursion
             (progn (re-search-forward "|" nil 1) (point))))))

(goto-char (point-min))
(query-replace-regexp  "%.*\\(\n\\|$\\)" "" nil nil)

(goto-char (point-min))
 (replace-regexp  "@@@@@PERCENT@@@@@" "%"  nil nil)
)

答案2

有一些用例需要使用正则表达式查询

(query-replace-regexp "\\(^\\| *[^\\\\]\\)%.*" "" nil nil)

提议者大卫·卡莱尔对我不起作用。

注意:下面我写的“斜杠”是指“反斜杠”。

首要问题

正则表达式匹配非斜杠后跟百分号,因此:

123%foo
456

变成:

12
456

第二期

引入%评论可能会被忽略,因此它不是评论,但转义也可能被转义,因此这是注释。简而言之,我们需要确保注释前面有零个或偶数个斜杠。这似乎很复杂,但请考虑一下:

\\% <- Don't forget the newline 

正则表达式跳过了此注释,因为百分比被视为转义,但实际上并非如此。在 LaTeX 中,长斜杠序列并不罕见,因此我们需要管理奇偶校验。

第三期

注释会吃掉尾随换行符。此功能通常是故意使用的,例如在宏中,您需要换行符以提高可读性,但您不希望在替换宏时使用它。因此,对于全行注释,最好删除带有尾随(或前导)换行符的注释,即

123
%foo
456

应该

123
456

对于内联注释,最好移动注释文本,同时保留新行,即

123%foo

应该

123%

为了克服这些问题,我建议使用以下宏。

(defun no-coms ()
  (interactive)
  (while (search-forward-regexp "\\(\n?\\)\\(.*?\\)\\(\\\\*\\)\\(%.*\\)" nil t)
    (when (cl-evenp (length (match-string 3))) ; bslahes should be even
      ;; Are we at bol?
      (if (and (string-empty-p (match-string 2)) (string-empty-p (match-string 3)))
      (replace-match "" nil nil nil 0)    ; if so remove whole match
    (replace-match "%" nil nil nil 4))))) ; else just remove comment text

评估宏,可能将其添加到您的初始化文件中,然后将光标放在您希望宏开始工作的位置后,键入
ALT+ Xno-coms

注意,我还没有彻底测试过这个宏。
以下是一些解释,供好奇的人参考。

删除 ELisp 转义后,正则表达式简化为:

(\n?)(.*?)(\\*)(%.*)

因此它匹配为子组:可选的换行符、非贪婪的任意字符、零个或多个斜杠、百分号后跟任意字符。

(while (search-forward-regexp ...继续向前搜索,直到正则表达式找到匹配项。

(when (cl-evenp (length ...提取第三个子组匹配(斜线)并且仅当返回的匹配数为偶数时才继续。

(if (string-empty-p (match-string 2))...检查可选换行符和百分比之间是否有字符,即第二和第三个子组是否都为空,在这种情况下百分比位于行首,并且我们有整行注释。

(replace-match "" nil nil nil 0)if肯定的情况。我们有一个整行注释,并且我们替换整个匹配(子组零),其中包括初始换行符。

(replace-match "%" nil nil nil 4)是另一种情况。此处第四个匹配项(%后面是注释文本)仅被替换为百分号。

相关内容