From mboxrd@z Thu Jan 1 00:00:00 1970 From: Toby Cubitt Subject: Re: [PATCH] Separate clocksum format for durations >= 1 day Date: Tue, 13 Nov 2012 14:03:04 +0100 Message-ID: <20121113130304.GA13301@c3po> References: <87mwyrjj7x.fsf@gmail.com> Reply-To: Toby Cubitt Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="x+6KMIRAuhnl3hBn" Return-path: Received: from eggs.gnu.org ([208.118.235.92]:47924) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TYG8j-0005W9-Ek for emacs-orgmode@gnu.org; Tue, 13 Nov 2012 08:02:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TYG8g-0005g8-Ch for emacs-orgmode@gnu.org; Tue, 13 Nov 2012 08:02:53 -0500 Received: from sanddollar.geekisp.com ([216.168.135.167]:49048) by eggs.gnu.org with smtp (Exim 4.71) (envelope-from ) id 1TYG8g-0005fv-56 for emacs-orgmode@gnu.org; Tue, 13 Nov 2012 08:02:50 -0500 Content-Disposition: inline In-Reply-To: <87mwyrjj7x.fsf@gmail.com> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org --x+6KMIRAuhnl3hBn Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Attached is a new two-patch series implementing finer-grained control over the format of clocksum durations (only in overlays and the mode-line; the format of the CLOCK entries stored in org files remains unchanged and hard-coded, as before). The first patch: - defines a new org-minutes-to-clocksum-string function (replacing org-minutes-to-hh:mm-string) for formatting time durations according to customization options; - unifies the formatting of clocksum durations throughout org-colview.el and org-clock.el by always calling org-minutes-to-clocksum-string to do the formatting; - extends the org-time-clocksum-format defcustom, allowing it to either be a single format string (as before), or a list of between 1 and 3 format strings for the minutes, hours and days components of a time duration; - retains the org-time-clocksum-use-fractional and org-time-clocksum-fractional-format defcustoms, whose meaning is unchanged. The second patch: - further extends org-time-clocksum-format to allow separate month and year components (where a month is taken to be 30 days, a year to be 365 days). Both patches maintain backwards-compatibility with any existing customizations users may have made to these variables. They just add an additional type for org-time-clocksum-format. The reason for retaining separate org-time-clocksum-format and org-time-clocksum-fractional-format's is that (i) it doesn't make much sense to have a list of formats for separate components when using the fractional format (see Nicolas' examples earlier in this discussion thread); (ii) it maintains backwards-compatibility; (iii) it side-steps the issue of making users customize the format whenever they modify org-time-clocksum-use-fractional. I'm not wedded to new customization type I've used in org-time-clocksum-format. If you prefer a plist, or a different ordering of the format strings in the list, or a different customization ui, that's fine by me. Toby -- Dr T. S. Cubitt Mathematics and Quantum Information group Department of Mathematics Complutense University Madrid, Spain email: tsc25@cantab.net web: www.dr-qubit.org --x+6KMIRAuhnl3hBn Content-Type: text/x-patch; charset=us-ascii Content-Disposition: attachment; filename="0001-Allow-more-flexible-customization-of-clocksum-format.patch" >From 812b6704191d96a8fc255e9c282eeef8deb091cf Mon Sep 17 00:00:00 2001 From: "Toby S. Cubitt" Date: Sun, 11 Nov 2012 22:20:24 +0000 Subject: [PATCH 1/2] Allow more flexible customization of clocksum format * lisp/org.el (org-time-clocksum-format): as well as a single format string, can now be a list of up to three format strings which determine how the minutes, hours and days compontents of a clocksum duraction should be formated. * lisp/org.el (org-minutes-to-clocksum-string): function replacing org-minutes-to-hh:mm-string, which converts a number of minutes to a string according to the customization options. * lisp/org-colview.el (org-columns-number-to-string): use new org-minutes-to-clocksum-string function to format clocksum durations. * lisp/org-clock.el: instead of calling org-minutes-to-hh:mm-string or passing org-time-clocksum-format directly to format in order to format a clock duration as a string, always call the new org-minutes-to-clocksum-string function to do this. --- lisp/org-clock.el | 51 +++++++++++++------------------------ lisp/org-colview.el | 3 +- lisp/org.el | 69 +++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 81 insertions(+), 42 deletions(-) diff --git a/lisp/org-clock.el b/lisp/org-clock.el index 84eb2fd..c768491 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -556,28 +556,23 @@ pointing to it." If an effort estimate was defined for the current item, use 01:30/01:50 format (clocked/estimated). If not, show simply the clocked time like 01:50." - (let* ((clocked-time (org-clock-get-clocked-time)) - (h (floor clocked-time 60)) - (m (- clocked-time (* 60 h)))) + (let ((clocked-time (org-clock-get-clocked-time))) (if org-clock-effort (let* ((effort-in-minutes (org-duration-string-to-minutes org-clock-effort)) - (effort-h (floor effort-in-minutes 60)) - (effort-m (- effort-in-minutes (* effort-h 60))) (work-done-str (org-propertize - (format org-time-clocksum-format h m) + (org-minutes-to-clocksum-string clocked-time) 'face (if (and org-clock-task-overrun (not org-clock-task-overrun-text)) 'org-mode-line-clock-overrun 'org-mode-line-clock))) - (effort-str (format org-time-clocksum-format effort-h effort-m)) + (effort-str (org-minutes-to-clocksum-string effort-in-minutes)) (clockstr (org-propertize (concat " [%s/" effort-str "] (" (replace-regexp-in-string "%" "%%" org-clock-heading) ")") 'face 'org-mode-line-clock))) (format clockstr work-done-str)) - (org-propertize (format - (concat "[" org-time-clocksum-format " (%s)]") - h m org-clock-heading) + (org-propertize (concat "[" (org-minutes-to-clocksum-string clocked-time) + (format " (%s)" org-clock-heading) "]") 'face 'org-mode-line-clock)))) (defun org-clock-get-last-clock-out-time () @@ -650,7 +645,7 @@ the mode line." (setq value (- current value)) (if (equal ?+ sign) (setq value (+ current value))))) (setq value (max 0 value) - org-clock-effort (org-minutes-to-hh:mm-string value)) + org-clock-effort (org-minutes-to-clocksum-string value)) (org-entry-put org-clock-marker "Effort" org-clock-effort) (org-clock-update-mode-line) (message "Effort is now %s" org-clock-effort)) @@ -1528,8 +1523,9 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." "\\>")))) (org-todo org-clock-out-switch-to-state)))))) (force-mode-line-update) - (message (concat "Clock stopped at %s after HH:MM = " org-time-clocksum-format "%s") te h m - (if remove " => LINE REMOVED" "")) + (message (concat "Clock stopped at %s after " + (org-minutes-to-clocksum-string (+ (* 60 h) m)) "%s") + te (if remove " => LINE REMOVED" "")) (run-hooks 'org-clock-out-hook) (unless (org-clocking-p) (org-clock-delete-current))))))) @@ -1797,12 +1793,9 @@ Use \\[org-clock-remove-overlays] to remove the subtree times." (when org-remove-highlights-with-change (org-add-hook 'before-change-functions 'org-clock-remove-overlays nil 'local)))) - (if org-time-clocksum-use-fractional - (message (concat "Total file time: " org-time-clocksum-fractional-format - " (%d hours and %d minutes)") - (/ (+ (* h 60.0) m) 60.0) h m) - (message (concat "Total file time: " org-time-clocksum-format - " (%d hours and %d minutes)") h m h m)))) + (message (concat "Total file time: " + (org-minutes-to-clocksum-string org-clock-file-total-minutes) + " (%d hours and %d minutes)") h m))) (defvar org-clock-overlays nil) (make-variable-buffer-local 'org-clock-overlays) @@ -1814,9 +1807,6 @@ This creates a new overlay and stores it in `org-clock-overlays', so that it will be easy to remove." (let* ((c 60) (h (floor (/ time 60))) (m (- time (* 60 h))) (l (if level (org-get-valid-level level 0) 0)) - (fmt (concat "%s " (if org-time-clocksum-use-fractional - org-time-clocksum-fractional-format - org-time-clocksum-format) "%s")) (off 0) ov tx) (org-move-to-column c) @@ -1825,14 +1815,9 @@ will be easy to remove." (setq ov (make-overlay (point-at-bol) (point-at-eol)) tx (concat (buffer-substring (point-at-bol) (point)) (make-string (+ off (max 0 (- c (current-column)))) ?.) - (org-add-props (if org-time-clocksum-use-fractional - (format fmt - (make-string l ?*) - (/ (+ (* h 60.0) m) 60.0) - (make-string (- 16 l) ?\ )) - (format fmt - (make-string l ?*) h m - (make-string (- 16 l) ?\ ))) + (org-add-props (concat (format "%s " (make-string l ?*)) + (org-minutes-to-clocksum-string time) + (format "%s" (make-string (- 16 l) ?\ ))) (list 'face 'org-clock-overlay)) "")) (if (not (featurep 'xemacs)) @@ -2392,7 +2377,7 @@ from the dynamic block definition." (if properties (make-string (length properties) ?|) "") ; properties columns, maybe (concat (format org-clock-total-time-cell-format (nth 7 lwords)) "| ") ; instead of a headline (format org-clock-total-time-cell-format - (org-minutes-to-hh:mm-string (or total-time 0))) ; the time + (org-minutes-to-clocksum-string (or total-time 0))) ; the time "|\n") ; close line ;; Now iterate over the tables and insert the data @@ -2416,7 +2401,7 @@ from the dynamic block definition." (if level-p "| " "") ; level column, maybe (if timestamp "| " "") ; timestamp column, maybe (if properties (make-string (length properties) ?|) "") ;properties columns, maybe - (org-minutes-to-hh:mm-string (nth 1 tbl))))) ; the time + (org-minutes-to-clocksum-string (nth 1 tbl))))) ; the time ;; Get the list of node entries and iterate over it (setq entries (nth 2 tbl)) @@ -2449,7 +2434,7 @@ from the dynamic block definition." hlc headline hlc "|" ; headline (make-string (min (1- ntcol) (or (- level 1))) ?|) ; empty fields for higher levels - hlc (org-minutes-to-hh:mm-string (nth 3 entry)) hlc ; time + hlc (org-minutes-to-clocksum-string (nth 3 entry)) hlc ; time "|\n" ; close line ))))) ;; When exporting subtrees or regions the region might be diff --git a/lisp/org-colview.el b/lisp/org-colview.el index 9d58b5f..d9afbd1 100644 --- a/lisp/org-colview.el +++ b/lisp/org-colview.el @@ -1058,8 +1058,7 @@ Don't set this, this is meant for dynamic scoping.") ((memq fmt '(estimate)) (org-estimate-print n printf)) ((not (numberp n)) "") ((memq fmt '(add_times max_times min_times mean_times)) - (let* ((h (floor n)) (m (floor (+ 0.5 (* 60 (- n h)))))) - (format org-time-clocksum-format h m))) + (org-hours-to-clocksum-string n)) ((eq fmt 'checkbox) (cond ((= n (floor n)) "[X]") ((> n 1.) "[-]") diff --git a/lisp/org.el b/lisp/org.el index 080b527..3ae1892 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -2714,11 +2714,37 @@ commands, if custom time display is turned on at the time of export." (concat "[" (substring f 1 -1) "]") f))) -(defcustom org-time-clocksum-format "%d:%02d" +(defcustom org-time-clocksum-format '(":%02d" "%d" "%dd ") ;"%d:%02d" "The format string used when creating CLOCKSUM lines. -This is also used when org-mode generates a time duration." +This is also used when org-mode generates a time duration. + +The value can be a single format string containing two +%-sequences, which will be filled with the number of hours and +minutes in that order. + +Alternatively, the value can be a list of up to three format +strings. In this case, the first format string in the list is +used for the number of minutes, the second for the number of +hours, and the third for the number of days if the duration is +longer than 1 day. The complete formatted duration is obtained by +concatenating these in the order: days, minutes, hours. + +If the list contains fewer than three format strings, it +restricts the largest time unit in the formatted duration to be +the largest one in the list. A two-element list means the +duration will always be expressed in hours and minutes, a +one-element list means the duration will always be expressed in +minutes." :group 'org-time - :type 'string) + :type '(choice (string :tag "single format") + (group :tag "mins" (string :tag "minutes format")) + (group :tag "mins,hrs" + (string :tag "minutes format") + (string :tag "hours format")) + (group :tag "mins,hrs,days" + (string :tag "minutes format") + (string :tag "hours format") + (string :tag "days format")))) (defcustom org-time-clocksum-use-fractional nil "If non-nil, \\[org-clock-display] uses fractional times. @@ -16667,11 +16693,40 @@ If there is already a time stamp at the cursor position, update it." (org-insert-time-stamp (encode-time 0 0 0 (nth 1 cal-date) (car cal-date) (nth 2 cal-date)))))) -(defun org-minutes-to-hh:mm-string (m) +(defun org-minutes-to-clocksum-string (m) "Compute H:MM from a number of minutes." - (let ((h (/ m 60))) - (setq m (- m (* 60 h))) - (format org-time-clocksum-format h m))) + (let* ((d (/ m 1400)) (h (/ (- m (* 1400 d)) 60))) + (setq m (- m (* 1400 d) (* 60 h))) + (if org-time-clocksum-use-fractional + (format org-time-clocksum-fractional-format + (/ (+ (* 60.0 (+ (* 1400 d) h)) m) 60.0)) + (cond + ((stringp org-time-clocksum-format) + (format org-time-clocksum-format (+ (* 1400 d) h) m)) + ((> d 0) + (if (>= (length org-time-clocksum-format) 3) + (concat (format (nth 2 org-time-clocksum-format) d) + (format (nth 1 org-time-clocksum-format) h) + (format (nth 0 org-time-clocksum-format) m)) + (if (>= (length org-time-clocksum-format) 2) + (concat (format (nth 1 org-time-clocksum-format) + (+ (* 1400 d) h) m) + (format (nth 0 org-time-clocksum-format) m)) + (format (nth 0 org-time-clocksum-format) + (+ (* 60 (+ (* 1400 d) h)) m))))) + (t (if (>= (length org-time-clocksum-format) 2) + (concat (format (nth 1 org-time-clocksum-format) + (+ (* 1400 d) h) m) + (format (nth 0 org-time-clocksum-format) m)) + (format (nth 0 org-time-clocksum-format) + (+ (* 60 (+ (* 1400 d) h)) m)))))))) + +(defalias 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string) +(make-obsolete 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string + "org-mode version 7.9.3") + +(defun org-hours-to-clocksum-string (n) + (org-minutes-to-clocksum-string (* n 60))) (defun org-hh:mm-string-to-minutes (s) "Convert a string H:MM to a number of minutes. -- 1.7.8.6 --x+6KMIRAuhnl3hBn Content-Type: text/x-patch; charset=us-ascii Content-Disposition: attachment; filename="0002-Optionally-allow-months-and-years-to-be-used-in-cloc.patch" >From 3a6a227158507d2f6500488f1f87eac8a6d47463 Mon Sep 17 00:00:00 2001 From: "Toby S. Cubitt" Date: Mon, 12 Nov 2012 11:45:47 +0000 Subject: [PATCH 2/2] Optionally allow months and years to be used in clocksum format --- lisp/org.el | 98 ++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 57 insertions(+), 41 deletions(-) diff --git a/lisp/org.el b/lisp/org.el index 3ae1892..fd05104 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -2722,29 +2722,25 @@ The value can be a single format string containing two %-sequences, which will be filled with the number of hours and minutes in that order. -Alternatively, the value can be a list of up to three format +Alternatively, the value can be a list of up to five format strings. In this case, the first format string in the list is used for the number of minutes, the second for the number of -hours, and the third for the number of days if the duration is -longer than 1 day. The complete formatted duration is obtained by -concatenating these in the order: days, minutes, hours. - -If the list contains fewer than three format strings, it -restricts the largest time unit in the formatted duration to be -the largest one in the list. A two-element list means the -duration will always be expressed in hours and minutes, a -one-element list means the duration will always be expressed in -minutes." +hours, the third for the number of days if the duration is longer +than 1 day, the fourth for the number of months if the duration +is longer than 1 month (a month is taken to be 30 days here), the +fifth for the number of years if the duration is longer than 1 +year (a year is taken to be 365 days here). The complete +formatted duration is obtained by concatenating these in the +order: years, months, days, hours, minutes. + +If the list contains fewer than five elements, the largest time +unit in the formatted duration is restricted to the largest time +unit in the list. E.g. a two-element list means the duration will +always be expressed in hours and minutes, a one-element list +means the duration will always be expressed in minutes." :group 'org-time - :type '(choice (string :tag "single format") - (group :tag "mins" (string :tag "minutes format")) - (group :tag "mins,hrs" - (string :tag "minutes format") - (string :tag "hours format")) - (group :tag "mins,hrs,days" - (string :tag "minutes format") - (string :tag "hours format") - (string :tag "days format")))) + :type '(choice (string :tag "format string") + (repeat :tag "list" (string :tag "format string")))) (defcustom org-time-clocksum-use-fractional nil "If non-nil, \\[org-clock-display] uses fractional times. @@ -16695,31 +16691,51 @@ If there is already a time stamp at the cursor position, update it." (defun org-minutes-to-clocksum-string (m) "Compute H:MM from a number of minutes." - (let* ((d (/ m 1400)) (h (/ (- m (* 1400 d)) 60))) - (setq m (- m (* 1400 d) (* 60 h))) + (let ((h (/ m 60)) d M Y) + (setq m (- m (* 60 h))) (if org-time-clocksum-use-fractional (format org-time-clocksum-fractional-format - (/ (+ (* 60.0 (+ (* 1400 d) h)) m) 60.0)) + (/ (+ (* 60.0 h) m) 60.0)) (cond + ;; single hh:mm format ((stringp org-time-clocksum-format) - (format org-time-clocksum-format (+ (* 1400 d) h) m)) - ((> d 0) - (if (>= (length org-time-clocksum-format) 3) - (concat (format (nth 2 org-time-clocksum-format) d) - (format (nth 1 org-time-clocksum-format) h) - (format (nth 0 org-time-clocksum-format) m)) - (if (>= (length org-time-clocksum-format) 2) - (concat (format (nth 1 org-time-clocksum-format) - (+ (* 1400 d) h) m) - (format (nth 0 org-time-clocksum-format) m)) - (format (nth 0 org-time-clocksum-format) - (+ (* 60 (+ (* 1400 d) h)) m))))) - (t (if (>= (length org-time-clocksum-format) 2) - (concat (format (nth 1 org-time-clocksum-format) - (+ (* 1400 d) h) m) - (format (nth 0 org-time-clocksum-format) m)) - (format (nth 0 org-time-clocksum-format) - (+ (* 60 (+ (* 1400 d) h)) m)))))))) + (format org-time-clocksum-format h m)) + ;; years + ((and (>= (length org-time-clocksum-format) 5) + (> (/ h 8760) 0)) + (setq Y (/ h 8760) h (- h (* 8760 Y)) + M (/ h 720) h (- h (* 720 M)) + d (/ h 24) h (- h (* 24 d))) + (concat (format (nth 4 org-time-clocksum-format) Y) + (format (nth 3 org-time-clocksum-format) M) + (format (nth 2 org-time-clocksum-format) d) + (format (nth 1 org-time-clocksum-format) h) + (format (nth 0 org-time-clocksum-format) m))) + ;; months + ((and (>= (length org-time-clocksum-format) 4) + (> (/ h 720) 0)) + (setq M (/ h 720) h (- h (* 720 M)) + d (/ h 24) h (- h (* 24 d))) + (concat (format (nth 3 org-time-clocksum-format) M) + (format (nth 2 org-time-clocksum-format) d) + (format (nth 1 org-time-clocksum-format) h) + (format (nth 0 org-time-clocksum-format) m))) + ;; days + ((and (>= (length org-time-clocksum-format) 3) + (> (/ h 24) 0)) + (setq d (/ h 24) h (- h (* 24 d))) + (concat (format (nth 2 org-time-clocksum-format) d) + (format (nth 1 org-time-clocksum-format) h) + (format (nth 0 org-time-clocksum-format) m))) + ;; hours + ((>= (length org-time-clocksum-format) 2) + (concat (format (nth 1 org-time-clocksum-format) h) + (format (nth 0 org-time-clocksum-format) m))) + ;; minutes + ((>= (length org-time-clocksum-format) 1) + (setq m (+ m (* 60 h))) + (format (nth 0 org-time-clocksum-format) m)) + (t ""))))) (defalias 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string) (make-obsolete 'org-minutes-to-hh:mm-string 'org-minutes-to-clocksum-string -- 1.7.8.6 --x+6KMIRAuhnl3hBn--