From 0d2e773d9d3c5691ec8ee612402bbac4e117169b Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Mon, 1 Jan 2018 15:35:34 +0100 Subject: [PATCH 01/13] [Org] Function stub for merging clock lines into existing file unfinished. --- site-lisp/db-org.el | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 3b12428..eec45d1 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1088,6 +1088,25 @@ ending at 23:61. When not given, FILES defaults to (concat date " 23:61") files)) +(defun db/org-add-clock-line-to-file (id start end) + "Add clock line with START and END time to task identified by ID." + (warn "This function is untested, don’t use it for anything serious.") + ;; First insert clock line at task + (let ((location (org-id-find id))) + (when (null location) + (user-error "ID %s cannot be found" id)) + (org-with-point-at location + (db/org-add-clocking-time start end))) + ;; Now find other clocklines and update them: change starting and ending time + ;; accordingly, and if the time is completely within the given bounds, delete + ;; it. + (let ((start-sec (org-time-string-to-seconds start)) + (end-sec (org-time-string-to-seconds end))) + (db/org-map-clock-lines-and-entries + (lambda (line-start line-end) + (error "Not yet implemented.")) + (lambda ())))) + ;;; End From b81a152d424f10647e34be7a9f818534d7b58396 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 12:49:43 +0100 Subject: [PATCH 02/13] [Org] Keep point and mark when iterating over clock lines and headlines --- site-lisp/db-org.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index eec45d1..a9ba952 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -957,10 +957,12 @@ end of the file upwards." (cond ((match-end 2) ;; Two time stamps. - (funcall clockline-fn (match-string 2) (match-string 3))) + (save-mark-and-excursion + (funcall clockline-fn (match-string 2) (match-string 3)))) (t ;; A headline - (funcall headline-fn)))))))) + (save-mark-and-excursion + (funcall headline-fn))))))))) (defun db/org-clocking-time-in-range (tstart tend) "Return list of all tasks in the current buffer together with From fab318d5dca6694fefbbd74e2019880ebc303e94 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 12:50:50 +0100 Subject: [PATCH 03/13] [Org] Rearrange code for manually inserting new clock lines --- site-lisp/db-org.el | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index a9ba952..507b0ea 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -513,27 +513,6 @@ are equal return nil." (org-use-tag-inheritance nil) (org-agenda-prefix-format '((tags . " "))))))) -(defun db/org-add-clocking-time (starting-time ending-time) - "Add \"CLOCK:\" line to the task under point in the current org-mode file." - (interactive - (list (starting-time (org-read-date 4 'totime nil - "Start:" (current-time) nil t)) - (ending-time (org-read-date 4 'totime nil - "End:" (current-time) nil t)))) - (if (not (eq major-mode 'org-mode)) - (user-error "Must be in org mode") - (save-mark-and-excursion - (org-clock-find-position nil) - (open-line 1) - (indent-according-to-mode) - (insert "CLOCK: ") - (org-insert-time-stamp starting-time t t) - (insert "--") - (org-insert-time-stamp ending-time t t) - (org-clock-update-time-maybe)))) - -(bind-key "C-c C-x C-a" #'db/org-add-clocking-time org-mode-map) - ;; A Hydra for changing agenda appearance ;; http://oremacs.com/2016/04/04/hydra-doc-syntax/ @@ -1090,6 +1069,27 @@ ending at 23:61. When not given, FILES defaults to (concat date " 23:61") files)) +(defun db/org-add-clocking-time (starting-time ending-time) + "Add \"CLOCK:\" line to the task under point in the current org-mode file." + (interactive + (list (starting-time (org-read-date 4 'totime nil + "Start:" (current-time) nil t)) + (ending-time (org-read-date 4 'totime nil + "End:" (current-time) nil t)))) + (if (not (eq major-mode 'org-mode)) + (user-error "Must be in org mode") + (save-mark-and-excursion + (org-clock-find-position nil) + (open-line 1) + (indent-according-to-mode) + (insert "CLOCK: ") + (org-insert-time-stamp starting-time t t) + (insert "--") + (org-insert-time-stamp ending-time t t) + (org-clock-update-time-maybe)))) + +(bind-key "C-c C-x C-a" #'db/org-add-clocking-time org-mode-map) + (defun db/org-add-clock-line-to-file (id start end) "Add clock line with START and END time to task identified by ID." (warn "This function is untested, don’t use it for anything serious.") From 0fa88c141fce44962c8e3c9c7283ebf1acf2c2be Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 12:51:08 +0100 Subject: [PATCH 04/13] [Org] First working version of clock line inserter --- site-lisp/db-org.el | 84 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 507b0ea..e559f5b 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1091,23 +1091,79 @@ ending at 23:61. When not given, FILES defaults to (bind-key "C-c C-x C-a" #'db/org-add-clocking-time org-mode-map) (defun db/org-add-clock-line-to-file (id start end) - "Add clock line with START and END time to task identified by ID." - (warn "This function is untested, don’t use it for anything serious.") - ;; First insert clock line at task - (let ((location (org-id-find id))) + "Add clock line with START and END time to task identified by ID. +TODO: specify time format" + (let ((location (org-id-find id t))) (when (null location) (user-error "ID %s cannot be found" id)) + ;; Update existing clock lines + (let ((new-start (org-time-string-to-seconds start)) + (new-end (org-time-string-to-seconds end)) + (timestamp-format (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]"))) + (org-with-point-at location + (db/org-map-clock-lines-and-entries + (lambda (timestamp-1 timestamp-2) + (let ((current-start (float-time + (apply #'encode-time + (org-parse-time-string timestamp-1)))) + (current-end (float-time + (apply #'encode-time + (org-parse-time-string timestamp-2))))) + (cond + ;; if the current clock line is completely contained within the + ;; given period, delete it + ((and (<= new-start current-start current-end new-end)) + (kill-whole-line)) + ;; if the current clock line completely contains the given one, + ;; split it + ((and (<= current-start new-start) + (<= new-end current-end)) + (beginning-of-line) + (let ((kill-whole-line nil)) + (kill-line)) + (indent-according-to-mode) + (insert "CLOCK: ") + (insert (format-time-string timestamp-format current-start)) + (insert "--") + (insert (format-time-string timestamp-format new-start)) + (org-clock-update-time-maybe) + (beginning-of-line) + (open-line 1) + (indent-according-to-mode) + (insert "CLOCK: ") + (insert (format-time-string timestamp-format new-end)) + (insert "--") + (insert (format-time-string timestamp-format current-end)) + (org-clock-update-time-maybe)) + ;; New interval overlaps beginning of current line + ((<= new-start current-start new-end current-end) + (beginning-of-line) + (let ((kill-whole-line nil)) + (kill-line)) + (indent-according-to-mode) + (insert "CLOCK: ") + (insert (format-time-string timestamp-format new-end)) + (insert "--") + (insert (format-time-string timestamp-format current-end)) + (org-clock-update-time-maybe)) + ;; New interval overlaps at end of current line + ((<= current-start new-start current-end new-end) + (beginning-of-line) + (let ((kill-whole-line nil)) + (kill-line)) + (indent-according-to-mode) + (insert "CLOCK: ") + (insert (format-time-string timestamp-format current-start)) + (insert "--") + (insert (format-time-string timestamp-format new-start)) + (org-clock-update-time-maybe))))) + (lambda () + ;; keep headline as they are, i.e., do nothing + )))) + ;; Finally add the new clock line (org-with-point-at location - (db/org-add-clocking-time start end))) - ;; Now find other clocklines and update them: change starting and ending time - ;; accordingly, and if the time is completely within the given bounds, delete - ;; it. - (let ((start-sec (org-time-string-to-seconds start)) - (end-sec (org-time-string-to-seconds end))) - (db/org-map-clock-lines-and-entries - (lambda (line-start line-end) - (error "Not yet implemented.")) - (lambda ())))) + (db/org-add-clocking-time (apply #'encode-time (org-parse-time-string start)) + (apply #'encode-time (org-parse-time-string end)))))) ;;; End From 2fcc4c468585ac801fdc5492346aeeb9e409a7ee Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 13:06:31 +0100 Subject: [PATCH 05/13] [Org] Cleaing up code on manipulating clock lines --- site-lisp/db-org.el | 81 ++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 46 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index e559f5b..613b007 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1069,6 +1069,22 @@ ending at 23:61. When not given, FILES defaults to (concat date " 23:61") files)) + +;;; Manipulating Clock Lines + +(defun db/org-insert-clockline (time-1 time-2) + "Insert new clock line from TIME-1 to TIME-2 at the beginning + of the current line. TIME-1 and TIME-2 must be given in a + format understandable by `format-time-string’, which see." + (let ((timestamp-format (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]"))) + (beginning-of-line) + (indent-according-to-mode) + (insert "CLOCK: ") + (insert (format-time-string timestamp-format time-1)) + (insert "--") + (insert (format-time-string timestamp-format time-2)) + (org-clock-update-time-maybe))) + (defun db/org-add-clocking-time (starting-time ending-time) "Add \"CLOCK:\" line to the task under point in the current org-mode file." (interactive @@ -1081,26 +1097,20 @@ ending at 23:61. When not given, FILES defaults to (save-mark-and-excursion (org-clock-find-position nil) (open-line 1) - (indent-according-to-mode) - (insert "CLOCK: ") - (org-insert-time-stamp starting-time t t) - (insert "--") - (org-insert-time-stamp ending-time t t) - (org-clock-update-time-maybe)))) + (db/org-insert-clockline starting-time ending-time)))) (bind-key "C-c C-x C-a" #'db/org-add-clocking-time org-mode-map) (defun db/org-add-clock-line-to-file (id start end) "Add clock line with START and END time to task identified by ID. -TODO: specify time format" +START and END must be given as org-mode timestamp strings." (let ((location (org-id-find id t))) (when (null location) (user-error "ID %s cannot be found" id)) ;; Update existing clock lines (let ((new-start (org-time-string-to-seconds start)) - (new-end (org-time-string-to-seconds end)) - (timestamp-format (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]"))) - (org-with-point-at location + (new-end (org-time-string-to-seconds end))) + (with-current-buffer (marker-buffer location) (db/org-map-clock-lines-and-entries (lambda (timestamp-1 timestamp-2) (let ((current-start (float-time @@ -1108,7 +1118,9 @@ TODO: specify time format" (org-parse-time-string timestamp-1)))) (current-end (float-time (apply #'encode-time - (org-parse-time-string timestamp-2))))) + (org-parse-time-string timestamp-2)))) + (kill-whole-line nil) ; don’t delete newlines if not asked to + ) (cond ;; if the current clock line is completely contained within the ;; given period, delete it @@ -1116,50 +1128,27 @@ TODO: specify time format" (kill-whole-line)) ;; if the current clock line completely contains the given one, ;; split it - ((and (<= current-start new-start) - (<= new-end current-end)) + ((and (<= current-start new-start new-end current-end)) (beginning-of-line) - (let ((kill-whole-line nil)) - (kill-line)) - (indent-according-to-mode) - (insert "CLOCK: ") - (insert (format-time-string timestamp-format current-start)) - (insert "--") - (insert (format-time-string timestamp-format new-start)) - (org-clock-update-time-maybe) + (kill-line) + (db/org-insert-clockline current-start new-start) (beginning-of-line) (open-line 1) - (indent-according-to-mode) - (insert "CLOCK: ") - (insert (format-time-string timestamp-format new-end)) - (insert "--") - (insert (format-time-string timestamp-format current-end)) - (org-clock-update-time-maybe)) + (db/org-insert-clockline new-end current-end)) ;; New interval overlaps beginning of current line ((<= new-start current-start new-end current-end) (beginning-of-line) - (let ((kill-whole-line nil)) - (kill-line)) - (indent-according-to-mode) - (insert "CLOCK: ") - (insert (format-time-string timestamp-format new-end)) - (insert "--") - (insert (format-time-string timestamp-format current-end)) - (org-clock-update-time-maybe)) + (kill-line) + (db/org-insert-clockline new-end current-end)) ;; New interval overlaps at end of current line ((<= current-start new-start current-end new-end) (beginning-of-line) - (let ((kill-whole-line nil)) - (kill-line)) - (indent-according-to-mode) - (insert "CLOCK: ") - (insert (format-time-string timestamp-format current-start)) - (insert "--") - (insert (format-time-string timestamp-format new-start)) - (org-clock-update-time-maybe))))) - (lambda () - ;; keep headline as they are, i.e., do nothing - )))) + (kill-line) + (db/org-insert-clockline current-start new-start))))) + + ;; keep headline as they are, i.e., do nothing + (lambda ())))) + ;; Finally add the new clock line (org-with-point-at location (db/org-add-clocking-time (apply #'encode-time (org-parse-time-string start)) From 2c8d8ddaf197874b598f642710630475ea0f525a Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 14:06:51 +0100 Subject: [PATCH 06/13] [Org] Save point and mark when inserting new clock lines --- site-lisp/db-org.el | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 613b007..c0adb67 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1075,15 +1075,17 @@ ending at 23:61. When not given, FILES defaults to (defun db/org-insert-clockline (time-1 time-2) "Insert new clock line from TIME-1 to TIME-2 at the beginning of the current line. TIME-1 and TIME-2 must be given in a - format understandable by `format-time-string’, which see." + format understandable by `format-time-string’, which see. + Saves mark and point." (let ((timestamp-format (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]"))) - (beginning-of-line) - (indent-according-to-mode) - (insert "CLOCK: ") - (insert (format-time-string timestamp-format time-1)) - (insert "--") - (insert (format-time-string timestamp-format time-2)) - (org-clock-update-time-maybe))) + (save-mark-and-excursion + (beginning-of-line) + (indent-according-to-mode) + (insert "CLOCK: ") + (insert (format-time-string timestamp-format time-1)) + (insert "--") + (insert (format-time-string timestamp-format time-2)) + (org-clock-update-time-maybe)))) (defun db/org-add-clocking-time (starting-time ending-time) "Add \"CLOCK:\" line to the task under point in the current org-mode file." @@ -1132,7 +1134,6 @@ START and END must be given as org-mode timestamp strings." (beginning-of-line) (kill-line) (db/org-insert-clockline current-start new-start) - (beginning-of-line) (open-line 1) (db/org-insert-clockline new-end current-end)) ;; New interval overlaps beginning of current line From 2a6c40d44680129485180b5753639d82a885dd78 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 14:07:13 +0100 Subject: [PATCH 07/13] [Org] Minor formatting --- site-lisp/db-org.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index c0adb67..1e04003 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1147,8 +1147,8 @@ START and END must be given as org-mode timestamp strings." (kill-line) (db/org-insert-clockline current-start new-start))))) - ;; keep headline as they are, i.e., do nothing - (lambda ())))) + ;; Keep headline as they are, i.e., do nothing + (lambda ()))) ;; Finally add the new clock line (org-with-point-at location From 375e39dd3543f46ee4127d5286f4851ccce0d8fb Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 14:07:20 +0100 Subject: [PATCH 08/13] [Org] Simplification --- site-lisp/db-org.el | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 1e04003..41d3983 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1150,10 +1150,9 @@ START and END must be given as org-mode timestamp strings." ;; Keep headline as they are, i.e., do nothing (lambda ()))) - ;; Finally add the new clock line - (org-with-point-at location - (db/org-add-clocking-time (apply #'encode-time (org-parse-time-string start)) - (apply #'encode-time (org-parse-time-string end)))))) + ;; Finally add the new clock line + (org-with-point-at location + (db/org-add-clocking-time new-start new-end))))) ;;; End From 766b12e4e3e66fc3cee7f294e73a68ad412db1cd Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 18:29:13 +0100 Subject: [PATCH 09/13] [Org] Updating documentation for clock line mapping function --- site-lisp/db-org.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 41d3983..e198bfe 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -925,7 +925,8 @@ For each clockline, call CLOCKLINE-FN with the starting and ending time as arguments and point on the beginning of the line. For each headline, call HEADLINE-FN with no arguments and point on the start of the headline. Traversal will be done from the -end of the file upwards." +end of the file upwards. If the buffer is narrowed, only this +region will be traversed." (when (eq major-mode 'org-mode) (let* ((re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*" org-clock-string From 0bbaf4b62bc5a6e6c813d9ebded1b9f35481f4f9 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 18:29:37 +0100 Subject: [PATCH 10/13] =?UTF-8?q?[Org]=20Change=20time=20representation=20?= =?UTF-8?q?for=20=E2=80=98db/org-add-clock-line-to-file=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site-lisp/db-org.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index e198bfe..0cd49d3 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1106,13 +1106,15 @@ ending at 23:61. When not given, FILES defaults to (defun db/org-add-clock-line-to-file (id start end) "Add clock line with START and END time to task identified by ID. -START and END must be given as org-mode timestamp strings." +START and END must be given as time objects as returned by +`encode-time’, or as an integer or float denoting seconds since +1970-01-01." (let ((location (org-id-find id t))) (when (null location) (user-error "ID %s cannot be found" id)) ;; Update existing clock lines - (let ((new-start (org-time-string-to-seconds start)) - (new-end (org-time-string-to-seconds end))) + (let ((new-start (float-time start)) + (new-end (float-time end))) (with-current-buffer (marker-buffer location) (db/org-map-clock-lines-and-entries (lambda (timestamp-1 timestamp-2) From fa0fb98291e3ad867d2c28bc42edadf11155f35f Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 13 Jan 2018 18:29:56 +0100 Subject: [PATCH 11/13] [Org] Cosmetics --- site-lisp/db-utils.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-lisp/db-utils.el b/site-lisp/db-utils.el index b66932d..930ab9e 100644 --- a/site-lisp/db-utils.el +++ b/site-lisp/db-utils.el @@ -368,7 +368,7 @@ path." (org-clock-update-time-maybe))))) -;;; +;;; End (provide 'db-utils) From 74a26b4d5a84b6e78573ae37e409ee06bb9d85c7 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sun, 21 Jan 2018 16:09:27 +0100 Subject: [PATCH 12/13] [Org] Change API of function to add clock lines to task Instead of resolving an ID, this function now gets a marker designating the task where the provided clock line should go to. --- site-lisp/db-org.el | 95 ++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 0cd49d3..c986ec1 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1104,58 +1104,57 @@ ending at 23:61. When not given, FILES defaults to (bind-key "C-c C-x C-a" #'db/org-add-clocking-time org-mode-map) -(defun db/org-add-clock-line-to-file (id start end) - "Add clock line with START and END time to task identified by ID. +(defun db/org-add-clock-line-to-marker (target-marker start end) + "Add clock line with START and END time to task identified by TARGET-MARKER. START and END must be given as time objects as returned by `encode-time’, or as an integer or float denoting seconds since -1970-01-01." - (let ((location (org-id-find id t))) - (when (null location) - (user-error "ID %s cannot be found" id)) - ;; Update existing clock lines - (let ((new-start (float-time start)) - (new-end (float-time end))) - (with-current-buffer (marker-buffer location) - (db/org-map-clock-lines-and-entries - (lambda (timestamp-1 timestamp-2) - (let ((current-start (float-time - (apply #'encode-time - (org-parse-time-string timestamp-1)))) - (current-end (float-time - (apply #'encode-time - (org-parse-time-string timestamp-2)))) - (kill-whole-line nil) ; don’t delete newlines if not asked to - ) - (cond - ;; if the current clock line is completely contained within the - ;; given period, delete it - ((and (<= new-start current-start current-end new-end)) - (kill-whole-line)) - ;; if the current clock line completely contains the given one, - ;; split it - ((and (<= current-start new-start new-end current-end)) - (beginning-of-line) - (kill-line) - (db/org-insert-clockline current-start new-start) - (open-line 1) - (db/org-insert-clockline new-end current-end)) - ;; New interval overlaps beginning of current line - ((<= new-start current-start new-end current-end) - (beginning-of-line) - (kill-line) - (db/org-insert-clockline new-end current-end)) - ;; New interval overlaps at end of current line - ((<= current-start new-start current-end new-end) - (beginning-of-line) - (kill-line) - (db/org-insert-clockline current-start new-start))))) +1970-01-01. TARGET-MARKER must be positioned on the task where +the clock line is to be added to." + (when (not (markerp target-marker)) + (user-error "Marker not valid.")) + (let ((new-start (float-time start)) + (new-end (float-time end))) + (with-current-buffer (marker-buffer target-marker) + (db/org-map-clock-lines-and-entries + (lambda (timestamp-1 timestamp-2) + (let ((current-start (float-time + (apply #'encode-time + (org-parse-time-string timestamp-1)))) + (current-end (float-time + (apply #'encode-time + (org-parse-time-string timestamp-2)))) + (kill-whole-line nil) ; don’t delete newlines if not asked to + ) + (cond + ;; if the current clock line is completely contained within the + ;; given period, delete it + ((and (<= new-start current-start current-end new-end)) + (kill-whole-line)) + ;; if the current clock line completely contains the given one, + ;; split it + ((and (<= current-start new-start new-end current-end)) + (beginning-of-line) + (kill-line) + (db/org-insert-clockline current-start new-start) + (open-line 1) + (db/org-insert-clockline new-end current-end)) + ;; New interval overlaps beginning of current line + ((<= new-start current-start new-end current-end) + (beginning-of-line) + (kill-line) + (db/org-insert-clockline new-end current-end)) + ;; New interval overlaps at end of current line + ((<= current-start new-start current-end new-end) + (beginning-of-line) + (kill-line) + (db/org-insert-clockline current-start new-start))))) - ;; Keep headline as they are, i.e., do nothing - (lambda ()))) + ;; Keep headline as they are, i.e., do nothing + (lambda ()))) - ;; Finally add the new clock line - (org-with-point-at location - (db/org-add-clocking-time new-start new-end))))) + ;; Finally add the new clock line + (org-with-point-at target-marker + (db/org-add-clocking-time new-start new-end)))) ;;; End From b790d989774ff75a182402ad71f2448df1712b99 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sun, 21 Jan 2018 16:10:21 +0100 Subject: [PATCH 13/13] [Org] Functions to copy clock lines from one task to another --- site-lisp/db-org.el | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index c986ec1..5352ef9 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -1156,6 +1156,49 @@ the clock line is to be added to." (org-with-point-at target-marker (db/org-add-clocking-time new-start new-end)))) +(defun db/org-clock-lines-of-task (marker) + "Return list of all clock lines of task under MARKER. +Each clock line is represented as a cons cell (START . END), +where both START and END are the starting and ending times of the +corresponding clock lines, encoded as a float denoting the +seconds since the epoch. Includes clock lines of all subtrees as +well. The order of the entries in the resulting list will be +reversed of what it is in the subtree of MARKER." + (when (not (markerp marker)) + (user-error "Marker not valid.")) + (let ((clock-lines nil)) + (save-mark-and-excursion + (org-with-point-at marker + (org-narrow-to-subtree) + (db/org-map-clock-lines-and-entries + (lambda (start end) + (push (cons (org-time-string-to-seconds start) + (org-time-string-to-seconds end)) + clock-lines)) + (lambda ())))) + clock-lines)) + +(defun db/org-copy-clock-lines (source-id target-id) + "Copy clock lines from one task to another, adapting clock + lines in the file of TARGET-ID accordingly. + +Both SOURCE-ID and TARGET-ID must designate known org-mode +tasks. Copies all clock lines attached to SOURCE-ID or to one of +its subtree." + (let ((source-marker (org-id-find source-id :get-marker)) + (target-marker (org-id-find target-id :get-marker))) + (cl-assert (markerp source-marker) + "Source task %s not found" source-id) + (cl-assert (markerp target-marker) + "Target task %s not found" target-id) + + ;; We first fetch the relevant clock-lines into memory, and then add them to + ;; the target task one by one, adjusting the other clock lines in between; + ;; this is rather inefficient, but we will fix this only when we need it. + (dolist (clock-line (db/org-clock-lines-of-task source-marker)) + (db/org-add-clock-line-to-marker target-marker + (car clock-line) (cdr clock-line))))) + ;;; End