[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: post-command-hook to slow?
From: |
Thorsten Jolitz |
Subject: |
Re: post-command-hook to slow? |
Date: |
Fri, 06 Jun 2014 19:37:51 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) |
"Pascal J. Bourguignon" <pjb@informatimago.com> writes:
> Thorsten Jolitz <tjolitz@gmail.com> writes:
>
>> Its a bit hard to explain, in fact I don't want to run a
>> post-command-hook, I just want to call an Org function in a temporary
>> buffer - but that function runs a post-command hook, and I have to deal
>> with that (it is somehow run too late, when the temp buffer is already
>> closed).
>>
>> An MWE is difficult unless you are an Org user, but anyway:
>>
>> Evaluate this in an emacs-lisp-mode buffer (without the
>> surrounding #+begin_ and #+end_ delimiters):
>>
>> #+begin_src emacs-lisp
>> (setq org-todo-keywords
>> (quote
>> ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!/!)")
>> (sequence
>> "WAITING(w@/!)" "HOLD(h@/!)" "|"
>> "CANCELLED(c@/!)" "PHONE"))))
>>
>> (with-temp-buffer
>> (org-mode)
>> (insert "* Level 1\nSome Text\n")
>> (org-todo)
>> (message "%s" (buffer-substring-no-properties
>> (point-min) (point-max))))
>> #+end_src
>>
>> you should be prompted for a state, choose TODO first (t) and it should
>> work.
>>
>> Then evaluate 'with-temp-buffer again, this time chosing a state with an
>> @ in its definition:
>>
>> "WAITING" or "HOLD" or "CANCELLED
>>
>> because thats triggers taking a log note (and calling a
>> post-command-hook function).
>>
>> You should get the error:
>>
>> ,-----------------------------------------------
>> | Error in post-command-hook (org-add-log-note):
>> | (error "Marker does not point anywhere")
>> `-----------------------------------------------
>>
>> When you insert a message statement at the very beginning of
>> `org-add-log-note' that print current-buffer an major-mode, you will see
>> that its called in the emacs-lisp buffer and not in the temp buffer.
>
> Ok. So you see how things go. This is a general technique in emacs
> applications, since we start from an editing event loop.
Thank you very much for your detailled and very informative reply!
> org-todo opens a menu buffer with a list of choices. In this case, it
> reads the user choice modaly, with org-icompleting-read: you cannot do
> anything else than select a menu item.
>
> But then, in some cases, it needs to let the user edit a note.
> To do that,
> org-todo adds org-add-log-note to post-command-hook, and
> org-add-log-note removes itself from it. This chains the org-todo and
> org-add-log-note commands in the main editing event loop.
>
> org-add-log-note sets up a *Org Note* buffer, and similarly, returns, to
> let the user edit it in the main editing event loop. When the user
> types C-c C-c, the org-ctrl-c-ctrl-c command is called which store the
> note. In the mean time a lot of commands can be given by the user. He
> may switch to other buffers and come back to the note a long time later.
>
> Since the org application doesn't expect to do anything else once the
> note is stored, org-store-log-note doesn't have any final hook. We
> would have to advice it, to add one. On the other hand,
> org-store-log-note is called from the org-finish-function hook, set up
> by org-add-log-note, so we could set this hook to call
> org-store-log-note, and our own function.
I had to write it down like this to get a clear picture:
,----------------------------------------------------------------------
| * Program Flow
|
| 1. user calls (outshine-use-outorg 'org-todo)
|
| - calls outorg-edit-as-org, which sets up a *outorg-edit-buffer*
| in org-mode and makes it current buffer
|
| - calls org-todo
|
| + adds org-add-log-note to post-command-hook
|
| + org-add-log-note is called SOMETIMES
|
| * removes itself from post-command-hook
|
| * sets up a *Org Note* buffer
|
| * sets up org-finish-function hook
|
| * returns control to main editing event loop
|
| - calls outorg-copy-edits-and-exit => TOO EARLY
|
| [2. user eventually types C-c C-c to store note]
|
| [- org-finish-function hook calls org-store-log-note]
`----------------------------------------------------------------------
> In any case, we have two architectures, either:
>
> - we may use the same modeless model as the org application (and any
> other emacs application), therefore not using with-temp-buffer, but
> creating a temporary buffer, and by way of hooks, chain the activities
> we need. or:
This is the way to go for me, since this is the way outorg works. I
figured out how to do it more or less like this:
#+begin_src emacs-lisp
(defun outshine-use-outorg-finish-store-log-note ()
"Finish store-log-note and exit recursive edit"
(org-store-log-note)
(outorg-copy-edits-and-exit))
#+end_src
[these are just relevant excerpts, not a complete working function]
#+begin_src emacs-lisp
(outorg-edit-as-org)
(call-interactively fun))
(when (marker-buffer org-log-note-marker)
(org-add-log-note)
(org-set-local
'org-finish-function
'outshine-use-outorg-finish-store-log-note))
#+end_src
This works fine in cases when org-add-log-note is actually called, but
for state changes to e.g. TODO when no log is taken, the finish
function and thus outorg-copy-edits-and-exit is never called, thus the
*outorg-edit-buffer* stays around.
To solve the problem completely I would need need something like
#+begin_src emacs-lisp
(if (not (marker-buffer org-log-note-marker))
(outorg-copy-edits-and-exit)
(org-add-log-note)
(org-set-local
'org-finish-function
'outshine-use-outorg-finish-store-log-note)))))
#+end_src
but this does not work ...
> - we can still use with-temp-buffer, but we have to call
> (recursive-edit) to insert an editing event loop to let the user gain
> control until we (OR the user!) choose to exit or abort the recursive
> edit.
>
> Here is how you would implement this later case:
>
> (defun pjb-finish-store-log-note-and-exit-recursive-edit ()
> (org-store-log-note)
> (exit-recursive-edit))
>
> (with-temp-buffer
> (org-mode)
> (insert "* Level 1\nSome Text\n")
> (org-todo)
> (message "BEFORE: %s" (buffer-substring-no-properties
> (point-min) (point-max)))
> (when (marker-buffer org-log-note-marker)
> (org-add-log-note)
> (org-set-local 'org-finish-function
> 'pjb-finish-store-log-note-and-exit-recursive-edit)
> (recursive-edit))
> (message "AFTER: %s" (buffer-substring-no-properties
> (point-min) (point-max))))
This works like a charm, and might even be better, but I want to reuse
existing code.
> Notice that in this problem post-command-hook is only incidental, even
> if the error message reporte mentionned it. It's used to chain the
> commands, but the problem is not related to commands and
> post-command-hook at all.
Thanks again, not only for helping solve the problem, but for giving
valuable insight into Emacs patterns.
--
cheers,
Thorsten