3

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
    )))
modeller
  • 3,770
  • 3
  • 25
  • 49
  • What would be a typical example of code that you use, please, where the beginning regexp is always matched with `<\([A-Za-z][A-Za-z0-9]*\)[^>]*>.*?`, and the ending regexp is always matched with `\1>` – lawlist Apr 06 '15 at 01:19
  • 1
    @lawlist for example, I want to fold the block of div: `
    Something
    `, or another block: `some conent `. THe current code won't even work for the first simple case.
    – modeller Apr 06 '15 at 01:22
  • I tried pasting your proposed code in a `*Scratch*` buffer -- i.e., `
    Something
    ` and `some conent `, and then I typed `M-x re-builder`. In between the double quotes in the `*RE-Builder*` buffer, I tried your proposed beginning regexp -- `<\([A-Za-z][A-Za-z0-9]*\)[^>]*>.*?` -- and then I tried using your proposed ending regexp -- `\1>`. In both cases, nothing got highlighted in the `*Scratch*` buffer. This would appear to indicate that the proposed beginning regexp and proposed ending regexp are incorrect.
    – lawlist Apr 06 '15 at 01:25
  • Would you try to combine the beginning and ending regexp into one and do the search again? I suspect that the separated strings makes the ending regexp's group matching fail. – modeller Apr 06 '15 at 01:29
  • Ah . . . Emacs likes double backslashes on open and close parentheses . . . `<\\([A-Za-z][A-Za-z0-9]*\\)[^>]*>.*?` I'm still working on the ending regexp. – lawlist Apr 06 '15 at 01:31

2 Answers2

3

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

Drew
  • 29,895
  • 7
  • 74
  • 104
  • thanks. Also appreciate if any advice on alternative folding solution. – modeller Apr 06 '15 at 01:43
  • Perhaps someone else will have a suggestion about an alternative folding solution; I don't. You might try looking around to see how others have used `hs-special-modes-alist` or other things in `hideshow.el`, before giving up on it. If you don't get a useful suggestion here, try (a) grepping the Emacs source code and (b) googling for `hs-special-modes-alist` and `hideshow` (plus `emacs`, of course). – Drew Apr 06 '15 at 01:48
0

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.

  • For the block start regex, should it be "+?" (not "*?") ? Otherwise, it will also match the closing tag. (which seems to cause problems for hs-hide-level ) – sgu Aug 19 '21 at 02:20
  • @sgu Thanks! I'd been trying to track that bug down for a while, I'd thought it was in mhtml-forward somewhere. – theadorabledev Sep 08 '21 at 14:30