1

I'm using the org-pomodoro, and I have added a function to the org-pomodoro-started-hook that prompts the user for a reminder for what they should do during the break. However, I don't want to call read-from-minibuffer directly from the hook, since that would block other hooks added to org-pomodoro-started-hook from running until the user entered a prompt. What is the best way to prompt the user for input in a non-blocking manner? I'm envisioning a function that returns immediately after creating the minibuffer with the prompt but invokes a callback after the user input has been received.

telotortium
  • 233
  • 1
  • 7

1 Answers1

1

The solution I've come up with is to run the function prompting for user input in a timer using run-at-time:

(defun my-org-pomodoro-started-break-reminder-prompt (prompt)
  "Create Google Calendar event for break reminder after ‘org-pomodoro' session."
  (interactive "MBreak start reminder (leave empty for none): ")
  (let ((remove? (or (null prompt) (string-empty-p prompt))))
    (setq my-org-pomodoro-started-break-reminder-prompt
          (if remove? nil prompt))
    (unless (and remove? (null my-org-pomodoro-break-reminder-event-id))
         (my-org-pomodoro--create-alarm-event
          my-org-pomodoro-alarm-gcal-calendar-id
          my-org-pomodoro-break-reminder-event-id
          'my-org-pomodoro-break-reminder-event-id
          (if remove? "break start" prompt)
          org-pomodoro-end-time
          remove?))))
(defun my-org-pomodoro-started-break-reminder-prompt-hook ()
  "Adapt ‘my-org-pomodoro-started-break-reminder-prompt’ for hooks."
  (run-at-time 0.1 nil
               (lambda ()
                 (condition-case-unless-debug err
                     (progn
                       (call-interactively #'my-org-pomodoro-started-break-reminder-prompt)
                       (my-org-pomodoro-start-tick))
                   (t . (message "my-org-pomodoro-started-break-reminder-hook: error: %S" err))))))
(add-hook 'org-pomodoro-started-hook #'my-org-pomodoro-started-break-reminder-prompt-hook)

The hook is my-org-pomodoro-started-break-reminder-prompt-hook, while my prompting function is my-org-pomodoro-started-break-reminder-prompt (implicitly prompts using interactive). I decided that, in order to remind myself to complete the break reminder prompt, I would not start my ticking sounds (by calling my-org-pomodoro-start-tick) until after I've answered the prompt. This is easily done by just calling my-org-pomodoro-start-tick after my-org-pomodoro-started-break-reminder-prompt in a progn block in the function run by run-at-time.

edebug-trace confirms that the other hook functions are immediately run after my-org-pomodoro-started-break-reminder-prompt-hook, whereas the functions called by the timer only return after the other hooks run (in actuality, I didn't answer the prompt for 15 seconds or so).

======================================================================
1 -> (my-org-pomodoro-pomodoro-light-on)
1 <- my-org-pomodoro-pomodoro-light-on: #<process *pomodoro-light-on*>
======================================================================
1 -> (my-org-pomodoro-started-punch-in)
1 <- my-org-pomodoro-started-punch-in: t
======================================================================
1 -> (my-org-pomodoro-started-break-reminder-prompt-hook)
1 <- my-org-pomodoro-started-break-reminder-prompt-hook: [nil 25138 10149 773846 nil (closure (t) nil (condition-case err (progn (call-interactively #'my-org-pomodoro-started-break-reminder-prompt) (my-org-pomodoro-start-tick)) ((debug t) message "my-org-pomodoro-started-break-reminder-hook: error: %S" err))) nil nil 0 nil]
======================================================================
1 -> (my-org-pomodoro-started-create-log-event)
1 <- my-org-pomodoro-started-create-log-event: nil
======================================================================
1 -> (my-org-pomodoro-clear-break-end-alarm-id)
1 <- my-org-pomodoro-clear-break-end-alarm-id: nil
======================================================================
1 -> (my-org-pomodoro-pomodoro-light-on)
1 <- my-org-pomodoro-pomodoro-light-on: #<process *pomodoro-light-on*>
======================================================================
1 -> (my-org-pomodoro-started-punch-in)
1 <- my-org-pomodoro-started-punch-in: t
======================================================================
1 -> (my-org-pomodoro-started-break-reminder-prompt-hook)
1 <- my-org-pomodoro-started-break-reminder-prompt-hook: [nil 25138 10354 121408 nil (closure (t) nil (condition-case err (progn (call-interactively #'my-org-pomodoro-started-break-reminder-prompt) (my-org-pomodoro-start-tick)) ((debug t) message "my-org-pomodoro-started-break-reminder-hook: error: %S" err))) nil nil 0 nil]
======================================================================
1 -> (my-org-pomodoro-started-create-log-event)
1 <- my-org-pomodoro-started-create-log-event: nil
======================================================================
1 -> (my-org-pomodoro-clear-break-end-alarm-id)
1 <- my-org-pomodoro-clear-break-end-alarm-id: nil
======================================================================
1 -> (my-org-pomodoro-started-break-reminder-prompt "")
1 <- my-org-pomodoro-started-break-reminder-prompt: nil
======================================================================
1 -> (my-org-pomodoro-start-tick)
1 <- my-org-pomodoro-start-tick: #<process *org-pomodoro-ticking-process*>
telotortium
  • 233
  • 1
  • 7