0

I'm trying to write a command that behaves like evil's O unless I'm on a line that is an org-mode heading, in which case I want the command to insert a new heading and enter insert mode with the cursor positioned on the same line as that new heading (after the leading * characters and space).

Previously I used evil-org-eol-call, but it seems that's been deprecated in favour of evil-org-define-eol-command, so I'm trying to use that:

(defun my/org-open-above ()
    (interactive)
    (evil-open-above 1)
    (org-insert-heading))

(defun my/either-O-or-org-open-above ()
    (interactive)
    (if (not (org-at-heading-p))
        (call-interactively #'evil-open-above)
        (apply (evil-org-define-eol-command #'my/org-open-above))))

When I evaluate the second defun above, I get:

Wrong type argument: symbolp, (function my/org-open-above)

and yet, evaluating in *scratch* I get:

(symbolp #'my/org-open-above)
t

What am I doing wrong? Here's the definition of evil-org-define-eol-command:

(defmacro evil-org-define-eol-command (cmd)
"Return a function that executes CMD at eol and then enters insert state.
eol stands for end of line.
For many org functions such as `org-insert-heading', this creates a heading below the current line."
(let ((newcmd (intern (concat "evil-org-" (symbol-name cmd) "-below"))))
    `(progn
    (defun ,newcmd ()
        ,(concat "Call `" (symbol-name cmd) "' at end of line and go to insert mode.")
        (interactive)
        (end-of-visible-line)
        (call-interactively #',cmd)
        (evil-insert nil))
    #',newcmd)))
  • Please highlight the question and remove the details that are not relevant to the question. – Dan Oct 1 '17 at 13:10
  • 1
    Your apply usage is wrong, read its docstring and explain what exactly you intend to do there. – wasamasa Oct 1 '17 at 13:44
  • That aside, you cannot apply macros or funcall them as they're code expansions, not callable functions. – wasamasa Oct 1 '17 at 13:45
  • @wasamasa apply: oops, thanks. I now see that the problem I ask about here is caused by not needing the #' because evil-org-define-eol-command is a macro. However, if I understand correctly, though evil-org-define-eol-command is itself a macro, its expansion is a function, not a macro, so that was not the problem. – Croad Langshan Oct 1 '17 at 16:56
  • Having removed the #', I got a warning about reference to free variable ‘me/org-open-above’, which I think is the reason I inserted the incorrect #'. I added (eval-when-compile (require 'evil-org)) to avoid that. – Croad Langshan Oct 1 '17 at 17:08
0

There are two problems:

  1. Since evil-org-define-eol-command is a macro not a function, the function passed to it should not be quoted with #'.

  2. apply's final argument is a list of arguments, so the appropriate function to use here is funcall, not apply

(Thanks to wasamasa's push in the right direction)

Here's a corrected version:

(defun me/org-open-above ()
    (interactive)
    (evil-open-above 1)
    (org-insert-heading))

(eval-when-compile
    (require 'evil-org))

(defun me/either-O-or-org-open-above ()
    (interactive)
    (if (not (org-at-heading-p))
        (call-interactively #'evil-open-above)
        (funcall (evil-org-define-eol-command me/org-open-above))))

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.