5

The great org-mode has a fast way to jump between headings in an org file; M-x org-goto or C-c C-j. This doesn't work with evil mode that well.

If I am on evil normal mode in an org file, C-c C-j gets me the org-goto interface alright but I stay in normal mode. The same happens if I'm in insert mode. Even when I'm in Emacs state.

It is after the invocation of C-c C-j when I have to manually intervene and jump into Emacs state by myself in order to have the functionality work as intended. When I'm finished there, I stay in Emacs state, which I do not desire.

I had these two obvious tries with the machinery but evil ignores both methods. I'm in normal mode, no matter what.

;; No go
(defun progo-org-goto ()
  (interactive)
  (call-interactively 'evil-emacs-state)
  (call-interactively 'org-goto))

;; no go; but the advice did run.
;; also tried "after"
(defadvice org-goto (before goto-advice activate)
  (message "adviced goto")
  (call-interactively 'evil-emacs-state))

So what kind of magic do I have to perform to have evil change to Emacs state during the org-goto and then return to normal mode afterwards?

  • "So what kind of magic do I have to perform to have evil...?" As Arthur C. Clarke would say, "Sufficiently advanced technology". – Nathan Basanese Jun 10 '15 at 7:43
5

Your instincts were right on advising org-goto, but you want around advice rather than before advice. The following advice should do what you want:

(defadvice org-goto (around make-it-evil activate)
  (let ((orig-state evil-state)
        (evil-emacs-state-modes (cons 'org-mode evil-emacs-state-modes)))
    ad-do-it
    (evil-change-state orig-state)))

It saves your current state in the let-bound orig-state, temporarily adds org-mode to evil-emacs-state-modes so that *org-goto* (whose major mode is org-mode) will be opened in emacs-state, runs the regular org-goto function via ad-do-it, and then restores your original state.

  • That's what I'd missed when trying to find the answer, was trying to set the state rather than default to evil-emacs-state for org-mode temporarily. Should also be more future-proof in case the buffer name were to be changed somewhere. – Jonathan Leech-Pepin Oct 8 '14 at 15:06
  • Glad to help. Quick note: fixed a silly bug in the code: the push changed the list in place and left org-mode in the evil-emacs-state-modes list after finishing the function call. Swapping append in for push allows us to clean up after ourselves properly. – Dan Oct 8 '14 at 15:12
  • Sigh. Or, if we'd like it to be cleaner and easier on the eyes, use cons in place of append. The code now reflects this. – Dan Oct 8 '14 at 15:26
  • Indeed, this is slightly less hacky so better promote this. – souser12345 Oct 8 '14 at 16:20
4

org-goto creates a new buffer named *org-goto* when you use it. Therefore, you can check for this name with a hook, using something like:

(add-hook 'org-mode-hook (lambda ()
                           (if (string= "*org-goto*" (buffer-name))
                               (evil-emacs-state))))
  • Fantastic! thanks so much. I had this question on SU for months, nothing. Moved it here and took 15 mins :) – souser12345 Oct 8 '14 at 14:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.