js-emacs / js2-refactor.el

A JavaScript refactoring library for emacs
GNU General Public License v3.0
373 stars 47 forks source link

does not work well with evil-mode #45

Open mikedmcfarland opened 9 years ago

mikedmcfarland commented 9 years ago

Currently js2 refactor doesn't work if you are using evil. This is because multiple cursors has issues with evil.

Though the underlying problem is with multiple cursors, when I encountered problems I wasn't even aware that js2-refactor used mutliple cursors, nor the incompatibility with evil. I don't use multiple cursors, and it was surprising

Here's a workaround ripped from the config files here. It disables evil while running in multiple cursors. This workaround enables the js2-refactor commands.

;; =============================================================
;; Multiple cursors evil compat (use emacs mode during mc)
;; =============================================================
(defvar mc-evil-compat/evil-prev-state nil)
(defvar mc-evil-compat/mark-was-active nil)

(defun user-utils/evil-visual-or-normal-p ()
  "True if evil mode is enabled, and we are in normal or visual mode."
  (and (bound-and-true-p evil-mode)
       (not (memq evil-state '(insert emacs)))))

(defun mc-evil-compat/switch-to-emacs-state ()
  (when (user-utils/evil-visual-or-normal-p)

    (setq mc-evil-compat/evil-prev-state evil-state)

    (when (region-active-p)
      (setq mc-evil-compat/mark-was-active t))

    (let ((mark-before (mark))
          (point-before (point)))

      (evil-emacs-state 1)

      (when (or mc-evil-compat/mark-was-active (region-active-p))
        (goto-char point-before)
        (set-mark mark-before)))))

(defun mc-evil-compat/back-to-previous-state ()
  (when mc-evil-compat/evil-prev-state
    (unwind-protect
        (case mc-evil-compat/evil-prev-state
          ((normal visual) (evil-force-normal-state))
          (t (message "Don't know how to handle previous state: %S"
                      mc-evil-compat/evil-prev-state)))
      (setq mc-evil-compat/evil-prev-state nil)
      (setq mc-evil-compat/mark-was-active nil))))

(add-hook 'multiple-cursors-mode-enabled-hook
          'mc-evil-compat/switch-to-emacs-state)
(add-hook 'multiple-cursors-mode-disabled-hook
          'mc-evil-compat/back-to-previous-state)

(defun mc-evil-compat/rectangular-switch-state ()
  (if rectangular-region-mode
      (mc-evil-compat/switch-to-emacs-state)
    (setq mc-evil-compat/evil-prev-state nil)))

;; When running edit-lines, point will return (position + 1) as a
;; result of how evil deals with regions
(defadvice mc/edit-lines (before change-point-by-1 activate)
  (when (user-utils/evil-visual-or-normal-p)
    (if (> (point) (mark))
        (goto-char (1- (point)))
      (push-mark (1- (mark))))))

(add-hook 'rectangular-region-mode-hook 'mc-evil-compat/rectangular-switch-state)

(defvar mc--default-cmds-to-run-once nil)
NicolasPetton commented 9 years ago

Can you create an issue in the Multiple-Cursors issue tracker instead?

mikedmcfarland commented 9 years ago

Multiple cursors already has an issue reported for this. Even though the underlying problem is definitely with multiple cursors, not js2-refactor, I still felt this should be reported. Understandably you guys may feel differently.

The fact that js2-refactor uses multiple cursors is an implementation detail. It wasn't obvious to me when I encountered problems with js2-refactor that multiple cursors was at fault, and it would've saved me loads of time to have seen a report like this.

Also the workaround is significantly more useful for js2-refactor then with plain old multiple cursors. Disabling Evil during multiple cursors makes it fairly difficult to use, since suddenly your normal text editing commands are gone. However this isn't an issue with js2-refactor since its making the changes.

NicolasPetton commented 8 years ago

@magnars clj-refactor is also using mc, right? Is the same issue affecting clj-refactor?

magnars commented 8 years ago

Yes, clj-refactor allows the user to opt out of multiple-cursors usage.

NicolasPetton commented 8 years ago

Magnar Sveen notifications@github.com writes:

Yes, clj-refactor allows the user to opt out of multiple-cursors usage.

Could this be easily backported to js2-refactor?

magnars commented 8 years ago

Not easily, no. clj-refactor tackles it for each individual refactoring.

NicolasPetton commented 8 years ago

Magnar Sveen notifications@github.com writes:

Not easily, no. clj-refactor tackles it for each individual refactoring.

BTW, what's the motivation for disabling mc?

magnars commented 8 years ago

The same as here. It doesn't play well with evil-mode.

dannyfreeman commented 6 years ago

Would it be possible to add support for evil-mc if evil-mode is installed?