Emacs 用于清除乳胶代码的Elisp宏

Emacs 用于清除乳胶代码的Elisp宏,emacs,latex,elisp,auctex,Emacs,Latex,Elisp,Auctex,有人知道一些用于清理LaTeX代码的好的elisp宏吗 我对其他人的源代码进行了大量编辑,我想扩展我的清理工具集,因为并不是每个人都以我喜欢的方式组织他们的代码;-) 其中一个特别有趣的是,在缓冲区上运行函数X,并使所有LaTeX环境(\begin{…}和\end{…}对)位于它们自己的行上,这有助于代码的可读性 我可以自己尝试一下,但是我想听听关于编程这样一个函数的最佳实践的建议,例如,它当然不应该引入自己的空行 建议 编辑:对于归档文件,以下是基于给定答案的当前版本(假设使用auctex)。

有人知道一些用于清理LaTeX代码的好的elisp宏吗

我对其他人的源代码进行了大量编辑,我想扩展我的清理工具集,因为并不是每个人都以我喜欢的方式组织他们的代码;-)

其中一个特别有趣的是,在缓冲区上运行函数X,并使所有LaTeX环境(\begin{…}和\end{…}对)位于它们自己的行上,这有助于代码的可读性

我可以自己尝试一下,但是我想听听关于编程这样一个函数的最佳实践的建议,例如,它当然不应该引入自己的空行

建议

编辑:对于归档文件,以下是基于给定答案的当前版本(假设使用auctex)。这或多或少符合我目前的需要。我添加了y-or-n测试,只是为了能够检测到我没有想到的角落案例

(defun enviro-split ()
  "Find begin and end macros, and put them on their own line."
  (interactive)
  (save-excursion
(beginning-of-buffer)

;; loop over document looking for begin and end macros
(while (re-search-forward "\\\\\\(begin\\|end\\)" nil t)
  (catch 'continue 

    ; if the line is a pure comment, then goto next
    (if (TeX-in-commented-line)
    (throw 'continue nil)
      )
    ;; when you find one, back up to the beginning of the macro
    (search-backward "\\")

    ;; If it's not at the beginning of the line, add a newline
    (when (not (looking-back "^[ \t]*"))
      (if (y-or-n-p "newline?")
      (insert "\n")
    )
      )

    ;; move over the arguments, one or two pairs of matching braces
    (search-forward "{")        ; start of the argument
    (forward-char -1)
    (forward-sexp)          ; move over the argument
    (if (looking-at "[ \t]*{")  ; is there a second argument?
    (forward-sexp)
      )             ; move over it if so
    (if (looking-at "[ \t]*\\[")    ; is there a second argument?
    (forward-sexp)
      )             ; move over it if so
    (when (looking-at (concat "[ \t]*" (regexp-quote TeX-esc) "label"))
      (goto-char (match-end 0))
      (forward-sexp)
      )

    (if (looking-at (concat "[ \t]*%" ))
    (throw 'continue nil)
      ) 

    ;; If there is anything other than whitespace following the macro,
    ;; insert a newline
    (if (not (looking-at "\\s *$"))
    ;;(insert "\n")
    (if (y-or-n-p "newline (a)?")
        (insert "\n")
      )
      )
    ) ; end catch 'continue
  )
(LaTeX-fill-buffer 'left)
)
  )

您可能需要编写一个regexp,并为此执行一个regexp替换。然而,我发现这些操作的逻辑变得非常复杂,特别是当你想考虑各种边缘情况时。在您的示例中,您需要处理一些使用一个参数的环境,而其他环境使用两个参数。我认为将一系列简单的regexp与基本的文本编辑命令结合起来更容易:

(defun enviro-split ()
  "Find begin and end macros, and put them on their own line."
  (interactive)
  (save-excursion
    (beginning-of-buffer)

    ;; loop over document looking for begin and end macros
    (while (re-search-forward "\\\\\\(begin\\|end\\)" nil t)

      ;; when you find one, back up to the beginning of the macro
      (search-backward "\\")

      ;; If it's not at the beginning of the line, add a newline
      (when (not (looking-at "^"))
        (insert "\n"))

      ;; move over the arguments, one or two pairs of matching braces
      (search-forward "{")              ; start of the argument
      (forward-char -1)
      (forward-sexp)                    ; move over the argument
      (if (looking-at "\\s *{")         ; is there a second argument?
          (forward-sexp))               ; move over it if so

      ;; If there is anything other than whitespace following the macro,
      ;; insert a newline
      (if (not (looking-at "\\s *$"))
          (insert "\n")))))

这种方法的优点是使用Emacs的内置函数来移动sexps,这比使用自己的regexp来处理大括号内的多个可能嵌套的表达式要容易得多。

使用可选参数,它会变得更加复杂。谢谢我有一个类似的宏,它可以在自己的行上设置“\\”,很高兴看到我的方法没有完全错误。当然,从长远来看,还需要考虑注释数据。嗯,这不是我所需要的。查看say\begin前面的测试应该测试它是否只是空白,如果不是,则是换行符。