【问题标题】:How to fold html tag in Emacs?如何在 Emacs 中折叠 html 标签?
【发布时间】:2015-04-05 23:59:25
【问题描述】:

我正在使用 hs-minor-mode 和 fold-dwim 模式。

我通过设置变量 hs-special-modes-alist 在下面添加了正则表达式以匹配 html 标签:

(html-mode "<\([A-Za-z][A-Za-z0-9]*\)[^>]*>.*?" "</\1>" "-->" nil nil)
;; Format: (MODE START END COMMENT-START FORWARD-SEXP-FUNC ADJUST-BEG-FUNC)

但是当我在 html 文件中使用它(使用命令 fold-dwim-toggle.)时没有效果。


这是我的 .emacs 文件中的相关部分:

;; hideshow
(setq hs-special-modes-alist
  (mapcar 'purecopy
  '((c-mode "{" "}" "/[*/]" nil nil)
    (c++-mode "{" "}" "/[*/]" nil nil)
    (bibtex-mode ("@\\S(*\\(\\s(\\)" 1))
    (java-mode "{" "}" "/[*/]" nil nil)
    (js-mode "{" "}" "/[*/]" nil)
    ;; (html-mode "<!-- {{{ " "<!-- }}} -->" " -->" nil t)
    (html-mode "<\([A-Za-z][A-Za-z0-9]*\)[^>]*>.*?"  "</\1>" "-->" nil nil) ;gw: self edited, see blw ref:
    ;; http://www.regular-expressions.info/examples.html
    )))

【问题讨论】:

  • 请问您使用的典型代码示例是什么,开头的正则表达式始终与&lt;\([A-Za-z][A-Za-z0-9]*\)[^&gt;]*&gt;.*?匹配,而结尾的正则表达式始终与&lt;/\1&gt;匹配
  • @lawlist 例如,我想折叠 div 的块:&lt;div&gt;Something&lt;/div&gt;,或者另一个块:&lt;span class="someclass"&gt;some conent &lt;/span&gt;。当前的代码甚至不适用于第一个简单的案例。
  • 我尝试将您建议的代码粘贴到*Scratch* 缓冲区中——即&lt;div&gt;Something&lt;/div&gt;&lt;span class="someclass"&gt;some conent &lt;/span&gt;,然后我输入了M-x re-builder。在*RE-Builder* 缓冲区中的双引号之间,我尝试了您建议的开始正则表达式——&lt;\([A-Za-z][A-Za-z0-9]*\)[^&gt;]*&gt;.*?——然后我尝试使用你建议的结束正则表达式——&lt;/\1&gt;。在这两种情况下,*Scratch* 缓冲区中都没有突出显示。这似乎表明建议的开始正则表达式和建议的结束正则表达式不正确。
  • 您是否尝试将开始和结束的正则表达式合并为一个并再次进行搜索?我怀疑分隔的字符串会使结束正则表达式的组匹配失败。
  • 啊。 . . Emacs 喜欢在左括号和右括号上使用双反斜杠。 . . &lt;\\([A-Za-z][A-Za-z0-9]*\\)[^&gt;]*&gt;.*? 我还在处理结尾正则表达式。

标签: html regex emacs elisp


【解决方案1】:

我不熟悉hs-special-modes-alist。但是简单地看一下源代码,我没有看到任何迹象表明END 模式可以引用BEGIN 模式的子组,我假设这就是您尝试使用"&lt;/\1&gt;" 所做的事情。我猜您希望 \1BEGIN 模式的第一个子组匹配的任何内容替换。

代码中hs-special-modes-alist 的示例都没有使用子组匹配号(例如\1)。文档说END 本身需要是一个正则表达式。大概它独立于匹配开头的START匹配结尾。

文档确实提到START 本身可以“(COMPLEX-START MDATA-SELECTOR) 形式的列表,其中COMPLEX-START 是一个带有多个部分的正则表达式,并且 MDATA-SELECTOR 一个整数,指定哪个子匹配是正确的 调整点的位置,在调用hs-forward-sexp-func之前。

我不认为这与您想要的直接对应,但至少它表明使用子组匹配。也许您可以使用它来匹配开始和结束标签。我没有进一步查看代码,例如查看hs-forward-sexp-func 的使用位置和方式。

另一方面,您通常需要在 Lisp 字符串中使用双反斜杠。所以如果你想要\1,你可能需要使用"&lt;/\\1&gt;"。同样,对于 \( - 使用 \\( 等。

也许这会让你更接近你想要的。

(注意,顺便说一句,正则表达式是尝试解析 HTML 代码等内容的糟糕方法。)

【讨论】:

  • 谢谢。如果对替代折叠解决方案有任何建议,也将不胜感激。
  • 也许其他人会有关于替代折叠解决方案的建议;我不。在放弃之前,您可以尝试四处看看其他人如何使用hs-special-modes-alisthideshow.el 中的其他内容。如果您在这里没有得到有用的建议,请尝试 (a) 搜索 Emacs 源代码和 (b) 搜索 hs-special-modes-alisthideshow(当然还有 emacs)。
【解决方案2】:

我在这里回答了这个问题:Does emacs offer hide show for html mode,但又来了。

我为 mhtml-mode 编写了这个,它工作得很好,它可以按标签折叠 HTML 以及嵌入的 CSS 和 JS。只需将其添加到您的 emacs 配置文件中,您就可以开始使用了。

;; When called this automatically detects the submode at the current location.
;; It will then either forward to end of tag(HTML) or end of code block(JS/CSS).
;; This will be passed to hs-minor-mode to properly navigate and fold the code.
(defun mhtml-forward (arg)
  (interactive "P")
  (pcase (get-text-property (point) 'mhtml-submode)
    ('nil (sgml-skip-tag-forward 1))
    (submode (forward-sexp))))

;; Adds the tag and curly-brace detection to hs-minor-mode for mhtml.
(add-to-list 'hs-special-modes-alist
             '(mhtml-mode
               "{\\|<[^/>]+?"
               "}\\|</[^/>]*[^/]>"
               "<!--"
               mhtml-forward
               nil))

正则表达式分解:

  • "{\\|&lt;[^/&gt;]+?":匹配{ 或任何打开的HTML 标记。它匹配到但不包括在开始标记中的结束 &gt;。这允许将 &lt;script&gt;&lt;style&gt; 标签视为 HTML 标签,而不是 JS 或 CSS。

  • "}\\|&lt;/[^/&gt;]*[^/]&gt;":匹配} 或结束标记。

【讨论】:

  • 对于块启动正则表达式,它应该是“+”吗? (不是 ”*?”) ?否则,它也会匹配结束标签。 (这似乎会导致 hs-hide-level 出现问题)
  • @sgu 谢谢!我一直在尝试追踪该错误一段时间,我认为它在 mhtml-forward 某处。
猜你喜欢
  • 2011-09-21
  • 2013-02-24
  • 2014-02-25
  • 2011-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多