Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Not a bug] How could I get rjsx-mode to newline and indent when I'm in between tags? #108

Open
mch1992 opened this issue Jun 22, 2019 · 4 comments

Comments

@mch1992
Copy link

mch1992 commented Jun 22, 2019

When you press RET between {} it does the following (where | is the cursor):

{|}
{
   [indent-level] |
}

How can I get rjsx-mode to do the same with html/react component tags

<component>|</component>

RET

<component>
   [indent-level] |
</component>
@sooqua
Copy link

sooqua commented Sep 6, 2019

Seems like I managed to bring this functionality from web-mode in a very hackish way.
And I'm using Doom Emacs, but this shouldn't be too hard to modify for vanilla emacs:

(when (featurep! :lang javascript)
  (setq-default js-indent-level 2)
  (when (featurep! :lang web)
    ;; Web mode tag expansion in rjsx
    (after! rjsx-mode
      (defun ~+javascript-rjsx-mode-h ()
        (require 'web-mode)
        (setq web-mode-markup-indent-offset 2)
        (add-hook 'after-change-functions 'web-mode-on-after-change nil t)
        (add-hook 'post-command-hook      'web-mode-on-post-command nil t))
      (setq ~+javascript-rjsx-do-web-mode-indent nil)
      (defun ~+javascript-rjsx-newline-and-indent-a ()
        (when (derived-mode-p 'rjsx-mode)
          (setq ~+javascript-rjsx-do-web-mode-indent t)))
      (defun ~+javascript-rjsx-indent-line-a ()
        (when (and (derived-mode-p 'rjsx-mode)
                   ~+javascript-rjsx-do-web-mode-indent)
          (web-mode-indent-line)
          (setq ~+javascript-rjsx-do-web-mode-indent nil)))
      (advice-add 'newline-and-indent :before #'~+javascript-rjsx-newline-and-indent-a)
      (advice-add 'rjsx-indent-line :before #'~+javascript-rjsx-indent-line-a)
      (add-hook 'rjsx-mode-hook #'~+javascript-rjsx-mode-h))))

@felipeochoa
Copy link
Owner

Seems like a very heavyweight solution. Here's what electric-pair does in case you want to adapt. (Check out electric-pair-post-self-insert-function)

  1. Use post-self-insert-hook and check for newline (eq last-command-event ?\n)
  2. Check if we are in a region of whitespace between two matchings "pairs". This would be the rjsx-specific bit. You could do a quick regex/syntax check for > preceding and </ following followed by confirmation via the AST
  3. (save-excursion (newline 1 t))
(when (and (if (functionp electric-pair-open-newline-between-pairs)
                      (funcall electric-pair-open-newline-between-pairs)
                    electric-pair-open-newline-between-pairs)
                  (eq last-command-event ?\n)
                  (< (1+ (point-min)) (point) (point-max))
                  (eq (save-excursion
                        (skip-chars-backward "\t\s")
                        (char-before (1- (point))))
                      (matching-paren (char-after))))
         (save-excursion (newline 1 t)))

@sooqua
Copy link

sooqua commented Sep 14, 2019

For some reason this doesn't work at all. Even (matching-paren (char-after)) is failing right before the <. It only works for (){}.
And I've now mapped a lot of refactoring functions from web-mode so I think I'll stick to it for now.
Thanks for the idea though.

@Maxxen
Copy link

Maxxen commented Jun 26, 2020

For those that want a quick fix that just works similarly to web-mode

(defun tag-expand ()
  (interactive)
  (if (and
       (looking-at "[ \t]*<")
       (looking-back ">[ \t]*"))
      (progn (newline-and-indent)
             (save-excursion (newline-and-indent))
             (indent-according-to-mode))
    (newline-and-indent)))

(add-hook 'rjsx-mode-hook (lambda () (local-set-key (kbd "RET") 'tag-expand)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants