felipeochoa / rjsx-mode

A JSX major mode for Emacs
https://github.com/felipeochoa/rjsx-mode
MIT License
641 stars 32 forks source link

enable some sgml dom-specific feature #64

Open earthIsAPrisonIfYouNotAwareItCanNotOut opened 6 years ago

earthIsAPrisonIfYouNotAwareItCanNotOut commented 6 years ago

Expect to add some dom feature related to sgml-mode

<div>|</div>

<div>                        ;; when press enter
  |
</div>
wyuenho commented 6 years ago

Are you sure this is an sgml-mode feature? I don't have it on Emacs 25.3

valignatev commented 6 years ago

sgml-mode does this for me in Emacs 26. web-mode does this as well

felipeochoa commented 6 years ago

I don't have this in sgml-mode on Emacs 26 -- is it possible it's one of your minor modes?

valignatev commented 6 years ago

Yes, you're right. I did an experiment with emacs -q, and it turned that this indentation is made by electric-pair-mode. So sgml-mode plus electric-pair-mode do the trick together.

But for some reason it doesn't work with rjsx-mode and electric-pair-mode.

felipeochoa commented 6 years ago

Great -- I was able to find how this works in sgml mode. The key difference is that the sgml syntax table sets < and > to be matching parens. Unfortunately we can't use the 'syntax-table property to force this, and can't set it up buffer-wide because of the other uses of < and > in javascript.

I looked at how web-mode handles this, and they're using their own post-command handler. I think it would be a great addition to rjsx if someone wanted to add something like that.

The relevant bit from web mode (slightly edited) is below in case anyone wants to adapt this for use in rjsx. We'd have to add text properties to the < and > tokens ('rjsx-class is already used for self-closing slashes), but otherwise this could be easily adapted I think.

(cond
 ((and web-mode-enable-auto-opening
       (member this-command '(newline electric-newline-and-maybe-indent newline-and-indent))
       (and (not (eobp))
            (eq (char-after) ?\<)
            (eq (get-text-property (point) 'tag-type) 'end)
            (looking-back ">\n[ \t]*" (point-min))
            (setq n (length (match-string-no-properties 0)))
            (eq (get-text-property (- (point) n) 'tag-type) 'start)
            (string= (get-text-property (- (point) n) 'tag-name)
                     (get-text-property (point) 'tag-name))))
  (newline-and-indent)
  (forward-line -1)
  (indent-according-to-mode)))
wyuenho commented 6 years ago

IMHO, all these paren matching/filling/point positioning facilities are best done using smartparens. Smartparens is best-in-class in its ability to navigate and manipulate mixed "parens". Instead of reinventing some of these bit by bit, might as well look into how best to leverage the other library.

felipeochoa commented 6 years ago

Can smartparens handle this electric indent behavior? I've been thinking about adding a section to the README about "suggested other modes" or similar