Issues Integrating Other Modes With Evil-Mode

Tad Ashlock tad.ashlock at
Sun Aug 24 16:29:40 CEST 2014

I'm attempting to integrate org-mode with evil-mode.  I'm aware of the
existing evil-org-mode, but what I'm attempting is much deeper.  Rather
than just adding some evil keybindings to some org functions, I want
 the basic evil operations to work on org files.  That is, evil-mode
operators, commands, and motions are org-aware.

I see that when evil-mode is in the normal state:

* the user presses 'x', which is bound to evil-delete-char
* evil-delete-char calls evil-delete
* evil-delete calls Emacs's delete-region to perform the deletion

When my new evil-org-mode (a minor mode) is active, I need evil-delete-char
to call org-delete-char to perform the deletion.  Not directly, of course.
The following seems to work.

(defun evil-org-delete-region (beg end)
  (let ((N (- end beg)))
      (goto-char beg)
      (org-delete-char N))))

(evil-define-operator evil-org-delete-char (beg end type register)
  "Delete next character."
  :motion evil-forward-char
  (interactive "<R><x>")
  (cl-letf (((symbol-function 'delete-region) #'(lambda (beg end)
(evil-org-delete-region beg end))))
    (evil-delete beg end type register)))

(define-key evil-org-mode-map [remap evil-delete-char]

Essentially, I remap evil-delete-char to evil-org-delete-char.  This new
function temporarily redefines delete-region to be evil-org-delete-region,
which, in turn, calls org-delete-char.  Then the subsequent cal
l to evil-delete will call org-delete-char with no changes to the evil-mode
source code.  Great!  But...

(1) This approach gets more complicated for other evil-mode functions.

    * For example, evil-org-delete-backward-char-and-join requires more
indirection in order to restore the function-cell value of
delete-backward-char, because that's what the org-mode function needs to

    * Remapping a remapped binding doesn't chain.  And it appears that
remapping a binding in my minor mode doesn't override the remapped binding
that evil-mode does.  For example, if I remap delete-backward-cha
r in evil-org-mode, the evil-mode (insert state) binding
(evil-delete-backward-char-and-join) still gets called.

    * I can't figure out how to intercept operators like "dd" (delete whole
line), in order to override their low-level Emacs calls.

(2) This approach isn't composable.  That is, another minor mode could not
integrate with evil-mode while evil-org-mode is active.


(1) Is there a good, clean, composable, way of doing what I'm trying to do?

(2) If not, is there an acceptable change that could be made to evil-mode
to support what I'm trying to do?  A change that improves the ability to
integrate with evil-mode in general, not just for my purpose?

If the answer to question (1) is 'no', I'm thinking the answer to question
(2) might be something along the lines of replacing evil-mode's calls to
fundamental Emacs text manipulation commands (like delete-regio
n) with (abnormal) hooks.  Each hook would default to being the command
currently being called directly, but could be made buffer local and
modified by another mode to support awareness of the buffer's contents.
  This would also allow, in theory, multiple modes to hook into the
actions.  Although I can't quite picture how this would work cleanly in

Thank you,
-------------- next part --------------
An HTML attachment was scrubbed...

More information about the implementations-list mailing list