0

I use org-mode and log time into a drawer ((setq org-clock-into-drawer t)). I often clock in and out in succession and have to go into the LOGBOOK drawer to see how much time I spent.

How can I display that time in the mini-buffer after clocking out?

1

There is an org-clock-out-hook that you can attach a function to:

(defun my-org-clock-out ()
    (message org-clock-duration-last-clock))

(add-hook 'org-clock-out-hook #'my-org-clock-out)

Unfortunately, there is no variable like org-clock-duration-last-clock so the above won't work. After having a quick look, I found no plausible candidate for such a variable, nor an easy way to calculate it. So I modified org-clock.el :-) Here's the diff, if you decide to go this way, but as usual, having your own modifications is fraught with peril:

diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index a6eb49e1c..d1a2a4962 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -1185,6 +1185,7 @@ so long."

 (defvar org-clock-current-task nil "Task currently clocked in.")
 (defvar org-clock-out-time nil) ; store the time of the last clock-out
+(defvar org-clock-duration-last-clock nil) ; store the duration of the last clock
 (defvar org--msg-extra)

 ;;;###autoload
@@ -1600,7 +1601,8 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
            (org-time-string-to-time ts)))
        h (floor s 3600)
        m (floor (mod s 3600) 60))
-     (insert " => " (format "%2d:%02d" h m))
+     (setq org-clock-duration-last-clock (format "%2d:%02d" h m))
+     (insert " => "  org-clock-duration-last-clock)
      (move-marker org-clock-marker nil)
      (move-marker org-clock-hd-marker nil)
      ;; Possibly remove zero time clocks.  However, do not add

It adds a global variable org-clock-duration-last-clock and sets it to the string "HH:MM" that is inserted in the CLOCK line in the drawer. That can then be used by the hook function as described above.

I don't know if there is demand for this feature, but you might want to suggest it as an enhancement on the Org mode mailing list. Who knows? Somebody there (or perhaps here) might have a better way of doing it, without having to make modifications to Org mode.

5
  • I tried these changes in my source at /Applications/Emacs.app/Contents/Resources/lisp/org/org-clock.el.gz and got an error in the mini-buffer Symbol's value as variable is void: org-clock-duration-last-clock. I also tried to find the variable: C-h v org-clock-duration-last-clock and got [No match]. – miguelmorin Sep 24 '19 at 13:41
  • Thanks for the suggestion of the mailing list, but the last time I joined one by GNU I got spammed on my email, so I'd rather avoid it. If there's enough interest and you're in it, could you suggest this enhancement? And maybe also this minor bug that I found in the source code of org-clock.el: in line 1587, instead of s (- s (* 60 s))), it should be s (- s (* 60 m))). – miguelmorin Sep 24 '19 at 14:33
  • 1
    Re: the first comment. You probably did not reload the modified org-clock,el file (or or did not compile it and reload org-clock.elc). Re: the third comment - that's fine, but that's where Org mode development discussions, bug reports etc. happen. Re: the last part of the third comment, we probably have different versions - I found the ref you provided but on line 2949, so things have changed although the calculation is still wrong: I'll report it. With your answer, I don't think that the enhancement I suggested is needed: org-last-inserted-timestamp is probably enough. – NickD Sep 24 '19 at 16:17
  • Good to know about source code, I'll try that next time that I can't find a work-around. Yes, I liked the solution with org-last-inserted-timestamp and I don't think we need to request an enhancement. On different source code, I probably installed org-mode manually with MELPA, though I can't remember how. This page mentions running the development version of org-mode. How do you keep up to date with the latest stable version? – miguelmorin Sep 24 '19 at 20:49
  • 1
    I run pretty close to the bleeding edge: the master branch from the git repo, currently Org mode version 9.2.6 (release_9.2.6-539-g1fd07c ). The stable version from MELPA (or the maint branch on the git repo) is 9.2.6-1-g97c14ca8c. – NickD Sep 25 '19 at 0:11
1

Org mode saves a variable org-last-inserted-timestamp. I save this value into another variable after clocking in, which I subtract from the new value of org-last-inserted-timestamp after clocking out. Then I make calculations similar to the source code (in lines 1580-1588 of org-clock.el, except that I used let* and local variables instead of setq, and avoided reassigning the same variable s) to compute the elapsed time, and display it, and display it as a message.

Add this in your Emacs initialization file, e.g. ~/.emacs:

(defun org-compute-timestamp-difference (later-timestamp earlier-timestamp)
  "Computes the difference in string timestamps as a float."
  (-
   (float-time (apply #'encode-time (org-parse-time-string later-timestamp)))
   (float-time (apply #'encode-time (org-parse-time-string earlier-timestamp)))))

(defun org-float-time-diff-to-hours-minutes (diff)
  "Returns a float time difference in hh:mm format."
  (let* ((hours (floor (/ diff 3600)))
     (diff_minus_hours (- diff (* 3600 hours)))
     (minutes (floor (/ diff_minus_hours 60))))
    (format "%2d:%02d" hours minutes)))

(defun org-save-clock-in-timestamp ()
  (setq org-last-clock-in-timestamp org-last-inserted-timestamp))

(defun org-show-last-clock-duration ()
  (let ((diff (org-compute-timestamp-difference org-last-inserted-timestamp org-last-clock-in-timestamp)))
    (message (concat "Last clocked duration: " (org-float-time-diff-to-hours-minutes diff)))))

(add-hook 'org-clock-in-hook #'org-save-clock-in-timestamp)
(add-hook 'org-clock-out-hook #'org-show-last-clock-duration)

If you don't see the result in the mini-buffer, you may have other functions in the hook that overwrite the message, such as save-buffer. In this case, either silence the output from those functions, e.g. (setq save-silently t) for save-buffer, add the above function to the hook before all the others (the first function added to the hook is the last to run), or wrap all functions to be called by the hook in a single function (my preferred solution, as it's more robust to moving lines of code):

(defun org-clock-out-functions ()
  (save-buffer)
  (org-show-last-clock-duration))
(add-hook 'org-clock-out-hook #'org-clock-out-functions)

Thank you to @NickD, whose answer pointed me to this solution.

1
  • Very nice! TIL about org-last-inserted-timestamp. – NickD Sep 24 '19 at 16:02

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.