mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-11-26 07:33:39 +00:00
Implement a basic history system for recently clocked tasks.
Recently clocked tasks are now remembered as well as a default task and an interrupted task. There is no automatic clock-in yet. Also, a number of bug fixes have sneaked into this patch, sorry for the mess.
This commit is contained in:
parent
2c2d172e10
commit
add34418c8
@ -8,6 +8,21 @@
|
||||
#+LINK_UP: index.html
|
||||
#+LINK_HOME: http://orgmode.org
|
||||
|
||||
* Version 6.02a
|
||||
** Details
|
||||
*** Clock task history
|
||||
Org now remembers the last 5 tasks that you clocked into, to
|
||||
make it easier to clock back into a task after interrupting
|
||||
it for another task.
|
||||
- `C-u C-u C-c C-x C-i' (or `C-u C-u I' from the agenda) wil
|
||||
clock into that task and mark it as current default task.
|
||||
- `C-u C-c C-x C-i' (or `C-u I' from the agenda) will offer a
|
||||
list of recently clocked tasks, including the default task,
|
||||
for selection. `d' selects the default task, `i' selects
|
||||
the task that was interrupted by the task that is currently
|
||||
being clocked. `1',... selects a recent task. When you
|
||||
select a task, you will be clocked into it.
|
||||
|
||||
* Version 6.02
|
||||
|
||||
** Overview
|
||||
|
11
doc/org.texi
11
doc/org.texi
@ -4493,7 +4493,11 @@ 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
|
||||
this item, the multiple CLOCK lines will be wrapped into a
|
||||
@code{:CLOCK:} drawer (see also the variable
|
||||
@code{org-clock-into-drawer}).
|
||||
@code{org-clock-into-drawer}). 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}.
|
||||
@kindex C-c C-x C-o
|
||||
@item C-c C-x C-o
|
||||
Stop the clock (clock-out). The inserts another timestamp at the same
|
||||
@ -4518,8 +4522,9 @@ Cancel the current clock. This is useful if a clock was started by
|
||||
mistake, or if you ended up working on something else.
|
||||
@kindex C-c C-x C-j
|
||||
@item C-c C-x C-j
|
||||
Jump to the entry that contains the currently running clock, an another
|
||||
window.
|
||||
Jump to the entry that contains the currently running clock. With a
|
||||
@kbd{C-u} prefix arg, select the target task from a list of recently clocked
|
||||
tasks.
|
||||
@kindex C-c C-x C-d
|
||||
@item C-c C-x C-d
|
||||
Display time summaries for each subtree in the current buffer. This
|
||||
|
@ -93,6 +93,82 @@ The function is called with point at the beginning of the headline."
|
||||
(defvar org-clock-heading "")
|
||||
(defvar org-clock-start-time "")
|
||||
|
||||
(defvar org-clock-history
|
||||
(list (make-marker) (make-marker) (make-marker) (make-marker) (make-marker))
|
||||
"Marker pointing to the previous task teking clock time.
|
||||
This is used to find back to the previous task after interrupting work.
|
||||
When clocking into a task and the clock is currently running, this marker
|
||||
is moved to the position of the currently running task and continues
|
||||
to point there even after the task is clocked out.")
|
||||
|
||||
(defun org-clock-history-push (&optional pos buffer)
|
||||
(let ((m (org-last org-clock-history)))
|
||||
(move-marker m (or pos (point)) buffer)
|
||||
(setq org-clock-history
|
||||
(reverse (cdr (reverse org-clock-history))))
|
||||
(while (member m org-clock-history)
|
||||
(move-marker (car (member m org-clock-history)) nil))
|
||||
(setq org-clock-history (cons m org-clock-history))))
|
||||
|
||||
(defun org-clock-select-task (&optional prompt)
|
||||
"Select a task that recently was associated with clocking."
|
||||
(interactive)
|
||||
(let (sel-list rpl file task (i 0))
|
||||
(save-window-excursion
|
||||
(org-switch-to-buffer-other-window
|
||||
(get-buffer-create "*Clock Task Select*"))
|
||||
(erase-buffer)
|
||||
(when (marker-buffer org-clock-default-task)
|
||||
(insert (org-add-props "Default Task\n" nil 'face 'bold))
|
||||
(setq s (org-clock-insert-selection-line ?d org-clock-default-task))
|
||||
(push s sel-list))
|
||||
(when (marker-buffer org-clock-interrupted-task)
|
||||
(insert (org-add-props "Interrupted Task\n" nil 'face 'bold))
|
||||
(setq s (org-clock-insert-selection-line ?i org-clock-interrupted-task))
|
||||
(push s sel-list))
|
||||
(insert (org-add-props "Recent Tasks\n" nil 'face 'bold))
|
||||
(mapc
|
||||
(lambda (m)
|
||||
(when (marker-buffer m)
|
||||
(setq i (1+ i)
|
||||
s (org-clock-insert-selection-line
|
||||
(string-to-char (number-to-string i)) m))
|
||||
(push s sel-list)))
|
||||
org-clock-history)
|
||||
(shrink-window-if-larger-than-buffer)
|
||||
(message (or prompt "Select task for clocking:"))
|
||||
(setq rpl (read-char-exclusive))
|
||||
(cond
|
||||
((eq rpl ?q) nil)
|
||||
((eq rpl ?x) nil)
|
||||
((assoc rpl sel-list) (cdr (assoc rpl sel-list)))
|
||||
(t (error "Invalid task choice %c" rpl))))))
|
||||
|
||||
(defun org-clock-insert-selection-line (i marker)
|
||||
(when (marker-buffer marker)
|
||||
(let (file cat task)
|
||||
(with-current-buffer (marker-buffer marker)
|
||||
(save-excursion
|
||||
(goto-char marker)
|
||||
(setq file (buffer-file-name (marker-buffer marker))
|
||||
cat (or (org-get-category)
|
||||
(progn (org-refresh-category-properties)
|
||||
(org-get-category)))
|
||||
task (org-get-heading 'notags))))
|
||||
(when (and cat task)
|
||||
(insert (format "[%c] %-15s %s\n" i cat task))
|
||||
(cons i marker)))))
|
||||
|
||||
(defvar org-clock-default-task (make-marker)
|
||||
"Marker pointing to the default task that should clock time.
|
||||
The clock can be made to switch to this task after clocking out
|
||||
of a different task.")
|
||||
|
||||
(defvar org-clock-interrupted-task (make-marker)
|
||||
"Marker pointing to the default task that should clock time.
|
||||
The clock can be made to switch to this task after clocking out
|
||||
of a different task.")
|
||||
|
||||
(defun org-update-mode-line ()
|
||||
(let* ((delta (- (time-to-seconds (current-time))
|
||||
(time-to-seconds org-clock-start-time)))
|
||||
@ -106,14 +182,39 @@ The function is called with point at the beginning of the headline."
|
||||
(defvar org-clock-mode-line-entry nil
|
||||
"Information for the modeline about the running clock.")
|
||||
|
||||
(defun org-clock-in ()
|
||||
(defun org-clock-in (&optional select)
|
||||
"Start the clock on the current item.
|
||||
If necessary, clock-out of the currently active clock."
|
||||
(interactive)
|
||||
(org-clock-out t)
|
||||
(let (ts)
|
||||
If necessary, clock-out of the currently active clock.
|
||||
With prefix arg SELECT, offer a list of recently clocked tasks to
|
||||
clock into. When SELECT is `C-u C-u', clock into the current task and mark
|
||||
is as the default task, a special task that will always be offered in
|
||||
the clocking selection, associated with the letter `d'."
|
||||
(interactive "P")
|
||||
(let (ts selected-task)
|
||||
;; Are we interrupting the clocking of a differnt task?
|
||||
(if (marker-buffer org-clock-marker)
|
||||
(progn
|
||||
(move-marker org-clock-interrupted-task
|
||||
(marker-position org-clock-marker)
|
||||
(marker-buffer org-clock-marker))
|
||||
(let ((org-clock-inhibit-clock-restart t))
|
||||
(org-clock-out t)))
|
||||
(move-marker org-clock-interrupted-task nil))
|
||||
|
||||
(cond
|
||||
((equal select '(16))
|
||||
(save-excursion
|
||||
(org-back-to-heading t)
|
||||
(move-marker org-clock-default-task (point))))
|
||||
((equal select '(4))
|
||||
(setq selected-task (org-clock-select-task "Clock-in on task: "))))
|
||||
|
||||
(save-excursion
|
||||
(org-back-to-heading t)
|
||||
(when (and selected-task (marker-buffer selected-task))
|
||||
(set-buffer (marker-buffer selected-task))
|
||||
(goto-char selected-task))
|
||||
(org-clock-history-push)
|
||||
(when (and org-clock-in-switch-to-state
|
||||
(not (looking-at (concat outline-regexp "[ \t]*"
|
||||
org-clock-in-switch-to-state
|
||||
@ -127,7 +228,7 @@ If necessary, clock-out of the currently active clock."
|
||||
(setq org-clock-heading "???")))
|
||||
(setq org-clock-heading (propertize org-clock-heading 'face nil))
|
||||
(org-clock-find-position)
|
||||
|
||||
|
||||
(insert "\n") (backward-char 1)
|
||||
(indent-relative)
|
||||
(insert org-clock-string " ")
|
||||
@ -258,19 +359,23 @@ If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
|
||||
(force-mode-line-update)
|
||||
(message "Clock canceled"))
|
||||
|
||||
(defun org-clock-goto (&optional delete-windows)
|
||||
"Go to the currently clocked-in entry."
|
||||
(defun org-clock-goto (&optional select)
|
||||
"Go to the currently clocked-in entry.
|
||||
With prefix arg SELECT, offer recently clocked tasks."
|
||||
(interactive "P")
|
||||
(if (not (marker-buffer org-clock-marker))
|
||||
(error "No active clock"))
|
||||
(switch-to-buffer-other-window
|
||||
(marker-buffer org-clock-marker))
|
||||
(if delete-windows (delete-other-windows))
|
||||
(goto-char org-clock-marker)
|
||||
(org-show-entry)
|
||||
(org-back-to-heading)
|
||||
(org-cycle-hide-drawers 'children)
|
||||
(recenter))
|
||||
(let ((m (if select
|
||||
(org-clock-select-task "Select task to go to: ")
|
||||
org-clock-marker)))
|
||||
(if (not (marker-buffer m))
|
||||
(if select
|
||||
(error "No task selected")
|
||||
(error "No active clock")))
|
||||
(switch-to-buffer (marker-buffer m))
|
||||
(goto-char m)
|
||||
(org-show-entry)
|
||||
(org-back-to-heading)
|
||||
(org-cycle-hide-drawers 'children)
|
||||
(recenter)))
|
||||
|
||||
(defvar org-clock-file-total-minutes nil
|
||||
"Holds the file total time in minutes, after a call to `org-clock-sum'.")
|
||||
@ -666,9 +771,9 @@ the currently selected interval size."
|
||||
(scope 'agenda)
|
||||
(p1 (copy-sequence params))
|
||||
file)
|
||||
(plist-put p1 :tostring t)
|
||||
(plist-put p1 :multifile t)
|
||||
(plist-put p1 :scope 'file)
|
||||
(setq p1 (plist-put p1 :tostring t))
|
||||
(setq p1 (plist-put p1 :multifile t))
|
||||
(setq p1 (plist-put p1 :scope 'file))
|
||||
(org-prepare-agenda-buffers files)
|
||||
(while (setq file (pop files))
|
||||
(with-current-buffer (find-buffer-visiting file)
|
||||
@ -767,17 +872,17 @@ the currently selected interval size."
|
||||
(apply 'encode-time (org-parse-time-string ts)))))
|
||||
(if te (setq te (time-to-seconds
|
||||
(apply 'encode-time (org-parse-time-string te)))))
|
||||
(plist-put p1 :header "")
|
||||
(plist-put p1 :step nil)
|
||||
(plist-put p1 :block nil)
|
||||
(setq p1 (plist-put p1 :header ""))
|
||||
(setq p1 (plist-put p1 :step nil))
|
||||
(setq p1 (plist-put p1 :block nil))
|
||||
(while (< ts te)
|
||||
(or (bolp) (insert "\n"))
|
||||
(plist-put p1 :tstart (format-time-string
|
||||
(car org-time-stamp-formats)
|
||||
(seconds-to-time ts)))
|
||||
(plist-put p1 :tend (format-time-string
|
||||
(car org-time-stamp-formats)
|
||||
(seconds-to-time (setq ts (+ ts step)))))
|
||||
(setq p1 (plist-put p1 :tstart (format-time-string
|
||||
(car org-time-stamp-formats)
|
||||
(seconds-to-time ts))))
|
||||
(setq p1 (plist-put p1 :tend (format-time-string
|
||||
(car org-time-stamp-formats)
|
||||
(seconds-to-time (setq ts (+ ts step))))))
|
||||
(insert "\n" (if (eq step0 'day) "Daily report: " "Weekly report starting on: ")
|
||||
(plist-get p1 :tstart) "\n")
|
||||
(org-dblock-write:clocktable p1)
|
||||
|
Loading…
Reference in New Issue
Block a user