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

Already on GitHub? Sign in to your account

After 0 kbd iterations: Buffer is read-only: #<buffer ...> #788

Open
Alexander-Shukaev opened this Issue Mar 7, 2017 · 4 comments

Comments

Projects
None yet
2 participants

Alexander-Shukaev commented Mar 7, 2017 edited

Run:

emacs -Q --eval '(add-to-list '"'"'load-path (concat user-emacs-directory "elpa/evil-YYYYMMDD.ABC"))' --eval '(require '"'"'evil)' --eval '(evil-mode)' --eval '(define-key evil-visual-state-map "i" '"'"'evil-insert)'

then

:e <read-only-file>

where <read-only-file> is e.g. /etc/fstab, then C-v to go to the block-visual state, then select multiple lines (at least two), then i to perform multi-line insertion, then type something. Notice the

Buffer is read-only: #<buffer ...>

errors as you type. That's fine, but now press ESC and you will get

After 0 kbd iterations: Buffer is read-only: #<buffer ...>

If you now inspect the contents of the evil-state variable, it will be nil. Evil is now in the broken state. Of course pressing ESC one more time will get you to the normal state and everything should be fine. Nevertheless, why this error with After 0 kbd iterations is happening exactly in case of multi-line C-v? That is if you now try other variants (v, V, single-line C-v) and the same scenario, you will see that After 0 kbd iterations never occurs, the very first ESC will already bring you to the normal state, and Evil is never in the broken state. Something fundamental is wrong here.

Member

wasamasa commented Mar 7, 2017 edited

Thanks, I can reproduce this behavior and will try investigating later. For the record, you can reproduce this in an easier way by running make emacs from a git checkout of Evil, and evaluating (define-key evil-visual-state-map "i" 'evil-insert). Also, the mapping isn't necessary, you can just use "I" to insert at the beginning of the rectangular selection.

edit: Fun, turns out "I" is bound to evil-insert, so that's why it works.

Member

wasamasa commented Mar 7, 2017

I've figured out two things meanwhile, but no complete solution:

  • The After 0 kbd iterations: ... error is thrown by the command loop whenever an error prevents it from completing, like a hook
  • The error is thrown from evil-insert-state-exit-hook because evil-cleanup-insert-state is called from it and fails executing its last part where it repeats the insertion action (which explains why you only get it for more than one block line, only stuff after the first line gets the repeat treatment)

I suspect that due to this error, Evil fails changing the state properly, but debugging this is a bit hard because of the heavy macro use in evil-states.el

Some good analysis out there! If you have spare time, would you mind to share how you debugged this? I mean, I've spent like a couple of hours and still could not catch the proper place. I tried debug-on-entry, debug-on-error, debug-on-message, and edebug-defun. None of those brought me a proper backtrace.

Member

wasamasa commented Mar 8, 2017 edited

For the first one, I grepped the Emacs sources. For the second, I copied definitions from evil-states.el, tried using edebug on them, macroexpanded them, instrumented them with edebug, noticed they behaved differently in edebug (repeated insert failed completely), then did some good old printf-debugging to find out in which order modes where enabled and ran their hooks. I figured out this way that the error originates from evil-cleanup-insert-state (which could be instrumented, unlike the macros running it) and it is run from evil-insert-state-hook.

https://lists.gnu.org/archive/html/emacs-devel/2010-07/msg01410.html describes a better approach that might work for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment