summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Guerry <bzg@altern.org>2012-07-12 14:04:54 +0200
committerBastien Guerry <bzg@altern.org>2012-07-12 14:04:54 +0200
commit3528fc6b423c43b9e42e2622936dacad9914dfd7 (patch)
treea0176fb2bfaab6b45d9713ade5cfd10119b5d71a
parent9fb530dc480308fcd3a04ced8600845cc3e7e4ef (diff)
downloadorg-mode-3528fc6b423c43b9e42e2622936dacad9914dfd7.tar.gz
Implement continuous clocking. Small other improvements. Update documentation.
* org.el (org-mode-map): Add `C-c C-x C-I' as a keybinding for `org-clock-in-last'. * org-clock.el (org-clock-continuously): New option. (org-clock-in): Three universal prefix arguments set `org-clock-continuously' to `t' temporarily. (org-clock-in-last): Fix call to `org-clock-select-task' and support continuous clocking. (org-clock-out-time): New variable. (org-clock-out): set `org-clock-out-time' when clocking out. Small docstring rewriting. (org-clock-remove-empty-clock-drawer): Fix "invalid search bound" bug when trying to delete empty logbook drawer. (org-clock-cancel): If the clock log is gone, send a warning instead of deleting the region that is supposed to contain it. * org.texi (Clocking commands): New cindex. (Clocking commands): Update documentation for `org-clock-in'. Document `org-clock-in-last'. Mention `org-clock-out' and `org-clock-in-last' as commands that can be globally bound. (Resolving idle time): Document continuous clocking.
-rw-r--r--doc/org.texi34
-rw-r--r--lisp/org-clock.el59
-rw-r--r--lisp/org.el1
3 files changed, 74 insertions, 20 deletions
diff --git a/doc/org.texi b/doc/org.texi
index e7da6e5..90844d8 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -6012,6 +6012,7 @@ what to do with it.
@table @kbd
@orgcmd{C-c C-x C-i,org-clock-in}
@vindex org-clock-into-drawer
+@vindex org-clock-continuously
@cindex property, LOG_INTO_DRAWER
Start the clock on the current item (clock-in). This inserts the CLOCK
keyword together with a timestamp. If this is not the first clocking of
@@ -6022,9 +6023,10 @@ the setting of this variable for a subtree by setting a
@code{CLOCK_INTO_DRAWER} or @code{LOG_INTO_DRAWER} property.
When called with a @kbd{C-u} prefix argument,
select the task from a list of recently clocked tasks. With two @kbd{C-u
-C-u} prefixes, clock into the task at point and mark it as the default task.
-The default task will always be available when selecting a clocking task,
-with letter @kbd{d}.@*
+C-u} prefixes, clock into the task at point and mark it as the default task;
+the default task will then always be available with letter @kbd{d} when
+selecting a clocking task. With three @kbd{C-u C-u C-u} prefixes, force
+continuous clocking by starting the clock when the last clock stopped.@*
@cindex property: CLOCK_MODELINE_TOTAL
@cindex property: LAST_REPEAT
@vindex org-clock-modeline-total
@@ -6054,6 +6056,12 @@ HH:MM}. See the variable @code{org-log-note-clock-out} for the
possibility to record an additional note together with the clock-out
timestamp@footnote{The corresponding in-buffer setting is:
@code{#+STARTUP: lognoteclock-out}}.
+@orgcmd{C-c C-x C-I,org-clock-in-last}
+@vindex org-clock-continuously
+Reclock the last clocked task. With one @kbd{C-u} prefix argument,
+select the task from the clock history. With two @kbd{C-u} prefixes,
+force continuous clocking by starting the clock when the last clock
+stopped.
@orgcmd{C-c C-x C-e,org-clock-modify-effort-estimate}
Update the effort estimate for the current clock task.
@kindex C-c C-y
@@ -6088,6 +6096,10 @@ The @kbd{l} key may be used in the timeline (@pxref{Timeline}) and in
the agenda (@pxref{Weekly/daily agenda}) to show which tasks have been
worked on or closed during a day.
+@strong{Important:} note that both @code{org-clock-out} and
+@code{org-clock-in-last} can have a global keybinding and will not
+modify the window disposition.
+
@node The clock table, Resolving idle time, Clocking commands, Clocking work time
@subsection The clock table
@cindex clocktable, dynamic block
@@ -6225,7 +6237,9 @@ would be
@end example
@node Resolving idle time, , The clock table, Clocking work time
-@subsection Resolving idle time
+@subsection Resolving idle time and continuous clocking
+
+@subsubheading Resolving idle time
@cindex resolve idle time
@cindex idle, resolve, dangling
@@ -6292,6 +6306,18 @@ to a recovery event rather than a set amount of idle time.
You can also check all the files visited by your Org agenda for dangling
clocks at any time using @kbd{M-x org-resolve-clocks}.
+@subsubheading Continuous clocking
+@cindex continuous clocking
+@vindex org-clock-continuously
+
+You may want to start clocking from the time when you clocked out the
+previous task. To enable this systematically, set @code{org-clock-continuously}
+to @code{t}. Each time you clock in, Org retrieves the clock-out time of the
+last clocked entry for this session, and start the new clock from there.
+
+If you only want this from time to time, use three universal prefix arguments
+with @code{org-clock-in} and two @kbd{C-u C-u} with @code{org-clock-in-last}.
+
@node Effort estimates, Relative timer, Clocking work time, Dates and Times
@section Effort estimates
@cindex effort estimates
diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 34a4dcc..6e7bf5b 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -325,6 +325,12 @@ play with them."
:version "24.1"
:type 'boolean)
+(defcustom org-clock-continuously nil
+ "Non-nil means to start clocking from the last clock-out time, if any."
+ :type 'boolean
+ :version "24.1"
+ :group 'org-clock)
+
(defcustom org-clock-total-time-cell-format "*%s*"
"Format string for the total time cells."
:group 'org-clock
@@ -1054,7 +1060,10 @@ recently clocked tasks to
clock into. When SELECT is \\[universal-argument] \\[universal-argument], \
clock into the current task and mark
it as the default task, a special task that will always be offered in
-the clocking selection, associated with the letter `d'."
+the clocking selection, associated with the letter `d'.
+When SELECT is \\[universal-argument] \\[universal-argument] \\[universal-argument], \
+clock in by using the last clock-out time as the start time
+\(see `org-clock-continuously' to make this the default behavior.)"
(interactive "P")
(setq org-clock-notification-was-shown nil)
(catch 'abort
@@ -1073,6 +1082,11 @@ the clocking selection, associated with the letter `d'."
(let ((org-clock-clocking-in t))
(org-resolve-clocks))) ; check if any clocks are dangling
+ (when (equal select '(64))
+ ;; Set start-time to `org-clock-out-time'
+ (let ((org-clock-continuously t))
+ (org-clock-in nil org-clock-out-time)))
+
(when (equal select '(4))
(setq selected-task (org-clock-select-task "Clock-in on task: "))
(if selected-task
@@ -1191,7 +1205,8 @@ the clocking selection, associated with the letter `d'."
(setq org-clock-total-time (org-clock-sum-current-item
(org-clock-get-sum-start)))
(setq org-clock-start-time
- (or (and leftover
+ (or (and org-clock-continuously org-clock-out-time)
+ (and leftover
(y-or-n-p
(format
"You stopped another clock %d mins ago; start this one from then? "
@@ -1238,13 +1253,20 @@ the clocking selection, associated with the letter `d'."
;;;###autoload
(defun org-clock-in-last (&optional arg)
"Clock in the last closed clocked item.
-When already clocking in, send an warning."
+When already clocking in, send an warning.
+With a universal prefix argument, select the task you want to
+clock in from the last clocked in tasks.
+With two universal prefix arguments, start clocking using the
+last clock-out time, if any."
(interactive "P")
- (if arg (org-clock-select-task)
- (org-clock-clock-in (cons (car org-clock-history) (current-time)))
- (message "Now clocking in: %s (in %s)"
- org-clock-current-task
- (buffer-name (marker-buffer org-clock-marker)))))
+ (if (equal arg '(4)) (org-clock-in (org-clock-select-task))
+ (let ((start-time (if (or org-clock-continuously (equal arg '(16)))
+ (or org-clock-out-time (current-time))
+ (current-time))))
+ (org-clock-clock-in (list (car org-clock-history)) nil start-time)
+ (message "Now clocking in: %s (in %s)"
+ org-clock-current-task
+ (buffer-name (marker-buffer org-clock-marker))))))
(defun org-clock-mark-default-task ()
"Mark current task as default task."
@@ -1377,9 +1399,10 @@ line and position cursor in that line."
(and (re-search-forward org-property-end-re nil t)
(goto-char (match-beginning 0))))))))
+(defvar org-clock-out-time nil) ; store the time of the last clock-out
(defun org-clock-out (&optional fail-quietly at-time)
"Stop the currently running clock.
-If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
+Throw an error if there is no running clock and FAIL-QUIETLY is nil."
(interactive)
(catch 'exit
(when (not (org-clocking-p))
@@ -1388,7 +1411,8 @@ If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
(setq frame-title-format org-frame-title-format-backup)
(force-mode-line-update)
(if fail-quietly (throw 'exit t) (error "No active clock")))
- (let (ts te s h m remove)
+ (let ((now (current-time)) ts te s h m remove)
+ (setq org-clock-out-time now)
(save-excursion ; Do not replace this with `with-current-buffer'.
(org-no-warnings (set-buffer (org-clocking-buffer)))
(save-restriction
@@ -1402,8 +1426,7 @@ If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
(goto-char (match-end 0))
(delete-region (point) (point-at-eol))
(insert "--")
- (setq te (org-insert-time-stamp (or at-time (current-time))
- 'with-hm 'inactive))
+ (setq te (org-insert-time-stamp (or at-time now) 'with-hm 'inactive))
(setq s (- (org-float-time (apply 'encode-time (org-parse-time-string te)))
(org-float-time (apply 'encode-time (org-parse-time-string ts))))
h (floor (/ s 3600))
@@ -1465,7 +1488,8 @@ If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
(when clock-drawer
(save-excursion
(org-back-to-heading t)
- (while (search-forward clock-drawer end t)
+ (while (and (< (point) end)
+ (search-forward clock-drawer end t))
(goto-char (match-beginning 0))
(org-remove-empty-drawer-at clock-drawer (point))
(forward-line 1))))))
@@ -1536,9 +1560,12 @@ UPDOWN tells whether to change 'up or 'down."
(save-excursion ; Do not replace this with `with-current-buffer'.
(org-no-warnings (set-buffer (org-clocking-buffer)))
(goto-char org-clock-marker)
- (delete-region (1- (point-at-bol)) (point-at-eol))
- ;; Just in case, remove any empty LOGBOOK left over
- (org-remove-empty-drawer-at "LOGBOOK" (point)))
+ (if (save-excursion (move-beginning-of-line 1)
+ (looking-at (concat "^[ \t]*" org-clock-string)))
+ (progn (delete-region (1- (point-at-bol)) (point-at-eol))
+ (org-remove-empty-drawer-at "LOGBOOK" (point)))
+ (message "Clock gone, cancel the timer anyway")
+ (sit-for 2)))
(move-marker org-clock-marker nil)
(move-marker org-clock-hd-marker nil)
(setq global-mode-string
diff --git a/lisp/org.el b/lisp/org.el
index 40e723e..7d664c9 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -17793,6 +17793,7 @@ BEG and END default to the buffer boundaries."
(org-defkey org-mode-map "\C-c\C-x\C-t" 'org-toggle-time-stamp-overlays)
(org-defkey org-mode-map "\C-c\C-x\C-i" 'org-clock-in)
+(org-defkey org-mode-map "\C-c\C-x\C-I" 'org-clock-in-last)
(org-defkey org-mode-map "\C-c\C-x\C-o" 'org-clock-out)
(org-defkey org-mode-map "\C-c\C-x\C-j" 'org-clock-goto)
(org-defkey org-mode-map "\C-c\C-x\C-x" 'org-clock-cancel)