Emacs能为我重新缩进一大块HTML吗?

78

在emacs中编辑HTML时,是否有一种自动美化标记的方法,可以将类似于以下这样的代码块自动转化为格式良好的形式:

  <table>
  <tr>
<td>blah</td></tr></table>

...变成这样:

<table>
 <tr>
  <td>
   blah
  </td>
 </tr>
</table>

1
这在较新版本的emacs中要容易得多。这是一个向下滚动的情况。 - Russia Must Remove Putin
10个回答

123

如果您处于html-mode或nxml-mode模式下,可以在同一区域/缓冲区上执行sgml-pretty-printindent-for-tab操作。

sgml-pretty-print将在适当的位置添加新行,而indent-for-tab则添加漂亮的缩进。两者结合起来可以得到格式正确的html/xml。


5
好的回答。只需记得暂时切换到sgml-mode以运行sgml-pretty-print,然后回到nxml-mode。 - cayhorstmann
6
感谢您!sgml-pretty-print对我在不切换模式的情况下从HTML文档中起到了作用。 - Ev Dolzhenko
2
唯一真正有效的答案。我的意思是,即使在无效的 XML(即仅为 HTML 文件的一部分)上也可以工作。 - Misha Tavkhelidze

31
默认情况下,当你在Emacs(22或23版本)中访问一个.html文件时,它会将你放入html-mode。这可能不是你想要的。你可能想用nxml-mode,它非常高级。nxml-mode似乎只有在Emacs 23中才附带,尽管你可以从nXML网站下载它以适用于更早的emacs版本。还有一个名为nxml-mode的Debian和Ubuntu软件包。你可以使用以下命令进入nxml-mode:
M-x nxml-mode

你可以通过以下方式查看nxml模式文档:
C-h i g (nxml-mode) RET

话虽如此,你可能需要使用类似 Tidy 的东西来重新格式化你的xhtml示例。 nxml-mode 可以帮你实现这个目标。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head></head>
<body>
<table>
  <tr>
<td>blah</td></tr></table>
</body>

to

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head></head>
  <body>
    <table>
      <tr>
    <td>blah</td></tr></table>
</body>
</html>

但是我没有看到一个更通用的设施来对特定的XML标记进行换行,就像你想要的那样。请注意,C-j将插入具有适当缩进的新行,因此您可以快速录制宏或编写defun来处理表格。


12
我进入nxml-mode后,使用C-x h来选择整个区域,然后输入M-x 'indent-region'。这样你将会得到正确缩进的HTML代码。感谢nxml-mode! - zhanxw
2
nxml-mode对于HTML片段的缩进不正确,可能是因为它们没有文档类型。一旦按照@nevcx的建议插入换行符,html-mode就可以正常工作了。 - boatcoder

14

http://www.delorie.com/gnu/docs/emacs/emacs_277.html

选择要修复的区域后(要选择整个缓冲区,请使用C-x h)。

C-M-q

重新缩进一个括号组中的所有行(indent-sexp)。

C-M-\

重新缩进区域中的所有行(indent-region)。


4
对我来说这样行不通——在上面的例子中,按C-M-q没有任何效果,而按C-M-\则会导致完全不正确的缩进。 - raldi
在nxml模式下对我也不起作用。index-sexp和indent-region将缩进已经有换行符的代码,而这个例子缺少了一些。 - Justin Tanner
1
C-X h <ESC> x 缩进区域 - Richard Gomes

10
我自己编写了一个函数来处理XML,这在nxml-mode中效果很好。对于HTML应该也能很好地工作:
(defun jta-reformat-xml ()
  "Reformats xml to make it readable (respects current selection)."
  (interactive)
  (save-excursion
    (let ((beg (point-min))
          (end (point-max)))
      (if (and mark-active transient-mark-mode)
          (progn
            (setq beg (min (point) (mark)))
            (setq end (max (point) (mark))))
        (widen))
      (setq end (copy-marker end t))
      (goto-char beg)
      (while (re-search-forward ">\\s-*<" end t)
        (replace-match ">\n<" t t))
      (goto-char beg)
      (indent-region beg end nil))))

谢谢。我多年来一直想要这个! - Christian Madsen
这实际上是最简单和最好的解决方案。我会经常使用它!谢谢!!! - BenjaminBallard
对我来说可行。感觉也是最简单的解决方案。非常感谢。 - cammil

10
在我目前正在编译的emacs 25中,假设您在HTML模式下,请使用
Ctrl-x
h来选择全部内容,然后按下Tab

9
这个问题很老,但我对各种答案并不满意。如果您正在运行相对较新的emacs(我正在运行24.4.1),则重新缩进HTML文件的简单方法是:
  • 用emacs打开文件
  • 使用C-x h标记整个文件(注意:如果要查看正在标记的内容,请将(setq transient-mark-mode t)添加到您的.emacs文件中)
  • 执行M-x indent-region
这种方法的好处在于它不需要任何插件(Conway的建议),也不需要替换正则表达式(nevcx的建议),也不需要切换模式(jfm3的建议)。Jay的建议是正确的方向-一般来说,执行C-M-q将根据模式的规则进行缩进-例如,在我的经验中,C-M-q适用于js-mode和几种其他模式。但是,html-modenxml-mode似乎都没有实现C-M-q

1
很棒的答案。两行。完美地完成了所有工作! - Tony
跟进问题,您的解决方案不会在HTML中缩进JavaScript。您有任何简单快捷的解决方案吗?谢谢。 - Tony
1
如果换行符已经放置在正确的位置,这将起作用。sgml-pretty-print有助于解决这个问题(但在我看来,仍然没有做出最好的选择)。 - pnj

8
你可以使用正则表达式进行替换。
 M-x replace-regexp

 \(</[^>]+>\)

 \1C-q-j

整理整个缓冲区

 C-x h
 M-x indent-region

6

Tidy可以实现你想要的功能,但似乎只能针对整个缓冲区进行操作(并且结果是XHTML格式)。

M-x tidy-buffer

4

如果你安装了xmllint,你可以使用以下命令将一个区域(pipe a region)传递给它:

M-|
Shell command on region: xmllint --format -

结果将会在一个新的缓冲区中显示。 我用XML实现了这个功能,虽然我相信xmllint需要其他一些选项才能处理HTML或其他不完美的XML。nxml-mode会告诉你是否有一个格式良好的文档。

使用前缀参数,shell-command-on-region 将用 shell 命令的输出替换原始区域。例如:C-u M-| - phils
谢谢,phils,我知道那个功能在那里,但是不记得如何调用它了! - Geoff

2

最简单的方法是通过命令行完成。

  • 确保您已安装Tidy
  • 输入tidy -i -m <<file_name>>

请注意,-m选项将新整理的文件替换为旧文件。如果您不想这样做,可以输入tidy -i -o <<tidied_file_name>> <<untidied_file_name>>

-i用于缩进。或者,您可以创建一个包含设置的.tidyrc文件。

indent: auto
indent-spaces: 2
wrap: 72
markup: yes
output-xml: no
input-xml: no
show-warnings: yes
numeric-entities: yes
quote-marks: yes
quote-nbsp: yes
quote-ampersand: no
break-before-br: no
uppercase-tags: no
uppercase-attributes: no

这样,您只需键入 tidy -o <<tidied_file_name>> <<untidied_file_name>>

要了解更多信息,请在命令行上键入man tidy


1
据我所知,这是从Shell调用的。我认为他想在Emacs中找到解决方案。 - Nikana Reklawyks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接