您甚至不需要编写自己的函数 - sgml-mode(一个 gnu emacs 核心模块)有一个名为 (sgml-pretty-print ...) 的内置漂亮打印函数,它接受区域开始和结束参数。
如果您正在剪切和粘贴 xml,并且您发现您的终端在任意位置剪切线条,您可以使用此 pretty printer,它首先修复断线。
如果您只需要漂亮的缩进而不引入任何新的换行符,您可以使用以下击键将 indent-region
命令应用于整个缓冲区:
C-x h
C-M-\
如果您还需要引入换行符,以便开始和结束标记在不同的行上,您可以使用以下由 Benjamin Ferrari 编写的非常好的 elisp 函数。我在他的博客上找到了它,希望我可以在这里复制它:
(defun bf-pretty-print-xml-region (begin end)
"Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this. The function inserts linebreaks to separate tags that have
nothing but whitespace between them. It then indents the markup
by using nxml's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
(goto-char begin)
(while (search-forward-regexp "\>[ \\t]*\<" nil t)
(backward-char) (insert "\n") (setq end (1+ end)))
(indent-region begin end))
(message "Ah, much better!"))
这不依赖于像 Tidy 这样的外部工具。
Emacs 可以使用 M-| 运行任意命令。如果您安装了 xmllint:
"M-| xmllint --format -" 将格式化所选区域
"Cu M-| xmllint --format -" 将做同样的事情,用输出替换区域
当我想格式化和缩进 XML 或 HTML 时,我使用 nXML mode 进行编辑和 Tidy。还有an Emacs interface to Tidy.
wrong type argument: stringp, nil
的 Emacs 24 上运行
用于引入换行符,然后进行漂亮的打印
M-x sgml-mode
M-x sgml-pretty-print
感谢上面的 Tim Helmstedt,我做了这样的 st:
(defun nxml-pretty-format ()
(interactive)
(save-excursion
(shell-command-on-region (point-min) (point-max) "xmllint --format -" (buffer-name) t)
(nxml-mode)
(indent-region begin end)))
快速简单。非常感谢。
(indent-region 0 (count-lines (point-min) (point-max)))
这是我对 Benjamin Ferrari 的版本进行的一些调整:
search-forward-regexp 没有指定结束,因此它将对从区域开始到缓冲区结束(而不是区域结束)的内容进行操作
正如 Cheeso 所指出的,现在增量正确结束。
它会在
仍然有“不依赖外部整洁”等。但是,它确实需要 incf
宏的 cl
。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; pretty print xml region
(defun pretty-print-xml-region (begin end)
"Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this. The function inserts linebreaks to separate tags that have
nothing but whitespace between them. It then indents the markup
by using nxml's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
(goto-char begin)
;; split <foo><foo> or </foo><foo>, but not <foo></foo>
(while (search-forward-regexp ">[ \t]*<[^/]" end t)
(backward-char 2) (insert "\n") (incf end))
;; split <foo/></foo> and </foo></foo>
(goto-char begin)
(while (search-forward-regexp "<.*?/.*?>[ \t]*<" end t)
(backward-char) (insert "\n") (incf end))
(indent-region begin end nil)
(normal-mode))
(message "All indented!"))
一种方法是如果您有以下格式的内容
<abc> <abc><abc> <abc></abc> </abc></abc> </abc>
在 Emacs 中,尝试
M-x nxml-mode
M-x replace-regexp RET > *< RET >C-q C-j< RET
C-M-\ to indent
这会将上面的 xml 示例缩进到下面
<abc>
<abc>
<abc>
<abc>
</abc>
</abc>
</abc>
</abc>
在 VIM 中,您可以通过
:set ft=xml
:%s/>\s*</>\r</g
ggVG=
希望这可以帮助。
Emacs nxml-mode 可以处理呈现的格式,但您必须拆分行。对于根本不值得的较长文件。对较长的文件运行此样式表(最好使用 Saxon,恕我直言,行缩进正确)以获得漂亮的打印效果。对于要保留空格的任何元素,请在“programlisting”旁边添加它们的名称,如“programlisting yourElementName”
高温高压
我采用 Jason Viers' version 并添加了将 xmlns 声明放在自己的行中的逻辑。这假设您有 xmlns= 和 xmlns: 没有中间空格。
(defun cheeso-pretty-print-xml-region (begin end)
"Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this. The function inserts linebreaks to separate tags that have
nothing but whitespace between them. It then indents the markup
by using nxml's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
;; split <foo><bar> or </foo><bar>, but not <foo></foo>
(goto-char begin)
(while (search-forward-regexp ">[ \t]*<[^/]" end t)
(backward-char 2) (insert "\n") (incf end))
;; split <foo/></foo> and </foo></foo>
(goto-char begin)
(while (search-forward-regexp "<.*?/.*?>[ \t]*<" end t)
(backward-char) (insert "\n") (incf end))
;; put xml namespace decls on newline
(goto-char begin)
(while (search-forward-regexp "\\(<\\([a-zA-Z][-:A-Za-z0-9]*\\)\\|['\"]\\) \\(xmlns[=:]\\)" end t)
(goto-char (match-end 0))
(backward-char 6) (insert "\n") (incf end))
(indent-region begin end nil)
(normal-mode))
(message "All indented!"))
整洁看起来是一个不错的模式。必须看看它。如果我真的需要它提供的所有功能,我会使用它。
无论如何,这个问题困扰了我大约一个星期,我没有正确搜索。发布后,我开始搜索,发现一个带有 elisp function 的网站做得很好。作者还建议使用 Tidy。
感谢马塞尔的回答(太糟糕了,我没有足够的积分来升级你)。
很快就会在我的博客上发布。 这是一个post about it(带有指向 Marcel 网站的链接)。
我使用 xml-parse.el 中的 xml-reformat-tags
。通常,在运行此命令时,您会希望该点位于文件的开头。
有趣的是,该文件被合并到 Emacspeak 中。当我每天使用 Emacspeak 时,我认为 xml-reformat-tags
是 Emacs 内置的。有一天我把它弄丢了,不得不在网上搜索它,然后就进入了上面提到的维基页面。
我还附上了我的代码以启动 xml-parse。不确定这是否是最好的 Emacs 代码,但似乎对我有用。
(if (file-exists-p "~/.emacs.d/packages/xml-parse.el")
(let ((load-path load-path))
(add-to-list 'load-path "~/.emacs.d/packages")
(require 'xml-parse))
)
自 2017 年起,emacs 已默认提供此功能,但您必须将这个小功能写入 ~/.emacs.d/init.el
:
(require 'sgml-mode)
(defun reformat-xml ()
(interactive)
(save-excursion
(sgml-pretty-print (point-min) (point-max))
(indent-region (point-min) (point-max))))
然后只需调用 M-x reformat-xml
来源:https://davidcapello.com/blog/emacs/reformat-xml-on-emacs/
恐怕我更喜欢本杰明法拉利版本。内部漂亮的打印总是将结束标签放在值之后的新行中,在标签值中插入不需要的 CR。
不定期副业成功案例分享
sgml-mode
随着时间的推移会发生怎样的变化。今天,我调用了C-x C-f foo.xml
、M-x sgml-mode
,然后是M-x sgml-pretty-print
,我的 xml 文件打印得很漂亮。 (好吧,emacs 在完成之前挂了 20 秒或更长时间。在漂亮的打印之前它是一个单行文件,之后是 720 行。)C-x g
才能选择整个缓冲区作为一个区域。C-x h
,然后选择M-x sgml-pretty-print
。 xml 现在将非常格式化