modeller
modeller

Reputation: 3850

How to fold html tag in Emacs?

I am using hs-minor-mode and fold-dwim mode.

I added below regex to match html tags by setting the variable hs-special-modes-alist:

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

But there is no effect when I use it (using command fold-dwim-toggle.) inside html file.


Here is the relevant section in my .emacs file:

;; 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
    )))

Upvotes: 3

Views: 1791

Answers (2)

theadorabledev
theadorabledev

Reputation: 23

I answered the question here: Does emacs offer hide show for html mode, but here it is again.

I wrote this for mhtml-mode and it works pretty well, it can fold HTML by tag as well as the embedded CSS and JS. Simply add it to your emacs config file and you'll be set to go.

;; 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))

Regex Breakdown:

  • "{\\|<[^/>]+?": Match either { or any opening HTML tags. It matches up to but doesn't include the closing > in the opening tag. That allows the <script> and <style> tags to be treated as HTML tags instead of JS or CSS.

  • "}\\|</[^/>]*[^/]>": Match either } or a closing tag.

Upvotes: 0

Drew
Drew

Reputation: 30701

I'm not familiar with hs-special-modes-alist. But looking at the source code briefly, I see nothing that suggests that the END pattern can refer to the BEGIN pattern's subgroups, which is, I assume, what you are trying to do by using "</\1>". I'm guessing that you want \1 to be substituted by whatever was matched by the first subgroup of the BEGIN pattern.

None of the examples of hs-special-modes-alist in the code make use of a subgroup match number (such as \1). And the doc says that END needs to be, itself, a regexp. Presumably it matches the end independently from START matching the beginning.

The doc does mention that START can itself "be a list of the form (COMPLEX-START MDATA-SELECTOR), where COMPLEX-START is a regexp w/ multiple parts and MDATA-SELECTOR an integer that specifies which sub-match is the proper place to adjust point, before calling hs-forward-sexp-func.

I don't think that corresponds immediately to what you want, but at least it indicates a use of subgroup matching. Perhaps you can use that to match both beginning and ending tags. I haven't looked further at the code, e.g. to see where and how hs-forward-sexp-func is used.

For another thing, you generally need to double backslashes in Lisp strings. So if you want \1 you might need to use "</\\1>". Likewise, for \( - use \\( etc.

Maybe this will get you a little further toward what you want.

(Note, BTW, that regexps are a lousy way to try to parse things like HTML code.)

Upvotes: 3

Related Questions