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?

1
  • "So what kind of magic do I have to perform to have evil...?" As Arthur C. Clarke would say, "Sufficiently advanced technology". Jun 10, 2015 at 7:43

2 Answers 2

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.

4
  • 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. Oct 8, 2014 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, 2014 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, 2014 at 15:26
  • Indeed, this is slightly less hacky so better promote this.
    – mike3996
    Oct 8, 2014 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))))
1
  • Fantastic! thanks so much. I had this question on SU for months, nothing. Moved it here and took 15 mins :)
    – mike3996
    Oct 8, 2014 at 14:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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