Issue #232 wontfix

evil-execute-in-normal-state doesn't work well

Exthen Lv
created an issue

I add this settings to my init.el file (define-key evil-emacs-state-map (kbd "C-o") 'evil-execute-in-normal-state)

In emacs-mode, I use "C-o o" to insert a line below, it did insert a line below,but the buffer stays in normal-mode, I supposed it would back into emacs-mode like most other commands with C-o (such C-o 3dd) in emacs-mode.("C-o O" also doesn't work well)

Comments (9)

  1. Michael Markert

    Can't reproduce with the current evil version and Gnu Emacs 24.3-snapshot.

    Which versions do you use?

    Can you reproduce from evil's repository version and make emacs?

  2. Frank Fischer repo owner

    I do not really know what you want to achieve (if you're in Emacs state, inserting something should not really be a problem), but using evil-execute-in-normal-state in Emacs state is definitely not what it has been written for. So whatever you're trying to achieve is completely unsupported and hardly a bug.

    But maybe I can give you hint for your problem. First you need to modify evil-execute-in-normal-state so that it does not switch back to emacs state when the executed command started insert state. Instead, in this situation it should ensure that the previous state of insert state is set to whatever was the previous state of normal state escaping from insert state should return to that state.

    (defun evil-execute-in-normal-state ()
      "Execute the next command in Normal state."
      (interactive)
      (evil-delay '(not (memq this-command
                              '(evil-execute-in-normal-state
                                evil-use-register
                                digit-argument
                                negative-argument
                                universal-argument
                                universal-argument-minus
                                universal-argument-more
                                universal-argument-other-key)))
          `(progn
             (if (evil-insert-state-p)
                 (setq evil-previous-state
                       (or (cdr-safe (assoc 'normal evil-previous-state-alist))
                           evil-previous-state))
               (evil-change-to-previous-state)
               (evil-normal-state-p)
               (setq evil-move-cursor-back ',evil-move-cursor-back)))
        'post-command-hook)
      (setq evil-move-cursor-back nil)
      (evil-normal-state)
      (evil-echo "Switched to Normal state for the next command ..."))
    

    Next you must ensure that pressing escape in insert state does not switch back to normal-state but to whatever was the previous state. You can do this by

    (define-key evil-insert-state-map [escape] 'evil-change-to-previous-state)
    

    But I make no guarantees that this works and does not break something else.

  3. Exthen Lv reporter

    Emacs 24.2 Evil 0.1(M-x: evil-version ; recently download at Evil-Home) Windows 8

    First, I'll describe my way to use evil, and why I love it so much! Then, I'll describe the best "C-o o" for me. (I am learning elisp now, but could not do it myself this time)

    Evil is written for users who want to use vim key-bindings in Emacs, and reminds the Emacs benefits, so they use vim-mode most of the time. I love evil, because I can use the vim key-bindings to enhance emacs key-bindings with "C-o", and I use emace-mode most of the time. For example, if I want to copy a line, I have to use "C-a C-SPC C-e M-w", but with evil, "C-o yy" copys a line too, and copied better (a line with \n in the end); if I want delete contents in two brackets such as "(global-set-key (kbd "C-=") 'er/expand-region)", I have to select them first and then delete, but with evil, "C-o dib" do it faster and more fluency! More like this->(C-4 C-S-backspace & C-o 4dd) (C-x r space register & C-o m register) (C-x r j register & C-o 'register) (M-< & C-o gg)etc. With settings bellow:

    (define-key evil-emacs-state-map (kbd "C-o") 'evil-execute-in-normal-state) (define-key evil-normal-state-map "t" 'evil-use-register)

    (C-x r s/i register & C-o t register 3yy/p/P) (C-s e & C-o 5f e) etc. I love evil so much!

    I can rebind Emacs keys to make it more suitable for me, but I think I can never do it better than evil.

    "C-o o" descriptions (and"C-o O")

    If the cursor is at the middle of a line, then I want to start a new line to start coding: <1>. (in vim-normal-mode) "o" gets it done, leave me to vim-insert-mode <2>. (in emacs-mode) "C-e RET" gets it done, leave me to emac-mode <3>. (in emacs-mode) I want "C-o o" gets it done, but not works well, without your codes at the comment, "C-o o" will start a new-line and leave me to vim-normal-mode, with your codes at the comment, "C-o o" will start a new-line and leave me to vim-insert-mode, I want "C-o o" start a new line and leave me to emacs-mode.

    I love evil very much, and thanks for your great jobs! (I am not a native English speaker, but I'll keep learning it!)

  4. Exthen Lv reporter

    (add-hook 'evil-insert-state-entry-hook 'evil-emacs-state) doesn't work well.

    <1>. create a new buffer, then "C-o o" insert a line below and leave to emacs-mode, but the cursor changed into a | not a block, and I can never back into vim-normal-mode to navigation with "C-z".

    <2>. create a new buffer, then "C-z" to normal-mode, then "i", but I got into emacs-mode, and I can never back into vim-normal-mode to navigation with "C-z", too.

    The keys like "C-o i/o/s/a/A" (the buffer is in emacs-mode) will bring me to vim-insert-mode (as "i/o/s/a/A" did in vim-normal-mode), not leave me at emacs-mode.

    Still thanks!

  5. Frank Fischer repo owner
    (defun evil-execute-in-normal-state ()
      "Execute the next command in Normal state."
      (interactive)
      (evil-delay '(not (memq this-command
                              '(evil-execute-in-normal-state
                                evil-use-register
                                digit-argument
                                negative-argument
                                universal-argument
                                universal-argument-minus
                                universal-argument-more
                                universal-argument-other-key)))
          `(progn
             (if (evil-insert-state-p)
                 (progn
                   (evil-emacs-state)
                   (setq evil-previous-state 'normal)) ; otherwise C-z will switch back to insert
               (evil-change-to-previous-state))
             (setq evil-move-cursor-back ',evil-move-cursor-back))
        'post-command-hook)
      (setq evil-move-cursor-back nil)
      (evil-normal-state)
      (evil-echo "Switched to Normal state for the next command ..."))
    
  6. Exthen Lv reporter

    Thanks very much! It works well except for a little bug: If the buffer is in indert-mode, and I use "C-o o" to insert a line bellow, the buffer goes into emacs-mode, not back into the previous insert-mode.

    I seldom use "C-o o" in insert-mode, so it's not a problem for me, but I think I should send it to you. Thanks, everything is OK now!

  7. Frank Fischer repo owner

    You can try the following, but note that this is completely untested, unsupported and unknown to work together well with other parts of evil.

    (defun evil-execute-in-normal-state ()
      "Execute the next command in Normal state."
      (interactive)
      (evil-delay '(not (memq this-command
                              '(evil-execute-in-normal-state
                                evil-use-register
                                digit-argument
                                negative-argument
                                universal-argument
                                universal-argument-minus
                                universal-argument-more
                                universal-argument-other-key)))
          `(progn
             (if (evil-insert-state-p)
                 (let ((prev-state (cdr-safe (assoc 'normal evil-previous-state-alist))))
                   (evil-change-state prev-state)
                   (setq evil-previous-state 'normal))
               (evil-change-to-previous-state))
             (setq evil-move-cursor-back ',evil-move-cursor-back))
        'post-command-hook)
      (setq evil-move-cursor-back nil)
      (evil-normal-state)
      (evil-echo "Switched to Normal state for the next command ..."))
    
  8. Log in to comment