155 |
requires you to have `display-time' running. If you don't want to use |
requires you to have `display-time' running. If you don't want to use |
156 |
`display-time', but still want the modeline to show how much time is |
`display-time', but still want the modeline to show how much time is |
157 |
left, set this variable to nil. You will need to restart Emacs (or |
left, set this variable to nil. You will need to restart Emacs (or |
158 |
toggle the value of `timeclock-modeline-display') for the change to |
toggle the function `timeclock-modeline-display') for the change to |
159 |
take effect." |
take effect." |
160 |
:set (lambda (symbol value) |
:set (lambda (symbol value) |
161 |
(let ((currently-displaying |
(let ((currently-displaying |
204 |
|
|
205 |
(defcustom timeclock-day-over-hook nil |
(defcustom timeclock-day-over-hook nil |
206 |
"*A hook that is run when the workday has been completed. |
"*A hook that is run when the workday has been completed. |
207 |
This hook is only run if the current time remaining is being display |
This hook is only run if the current time remaining is being displayed |
208 |
in the modeline. See the variable `timeclock-modeline-display'." |
in the modeline. See the variable `timeclock-modeline-display'." |
209 |
:type 'hook |
:type 'hook |
210 |
:group 'timeclock) |
:group 'timeclock) |
301 |
(add-hook 'display-time-hook 'timeclock-update-modeline)) |
(add-hook 'display-time-hook 'timeclock-update-modeline)) |
302 |
(setq timeclock-update-timer |
(setq timeclock-update-timer |
303 |
(run-at-time nil 60 'timeclock-update-modeline)))) |
(run-at-time nil 60 'timeclock-update-modeline)))) |
304 |
(setq global-mode-string |
(setq global-mode-string |
305 |
(delq 'timeclock-mode-string global-mode-string)) |
(delq 'timeclock-mode-string global-mode-string)) |
306 |
(remove-hook 'timeclock-event-hook 'timeclock-update-modeline) |
(remove-hook 'timeclock-event-hook 'timeclock-update-modeline) |
307 |
(if (boundp 'display-time-hook) |
(if (boundp 'display-time-hook) |
311 |
(cancel-timer timeclock-update-timer) |
(cancel-timer timeclock-update-timer) |
312 |
(setq timeclock-update-timer nil))) |
(setq timeclock-update-timer nil))) |
313 |
(force-mode-line-update) |
(force-mode-line-update) |
314 |
on-p)) |
(setq timeclock-modeline-display on-p))) |
315 |
|
|
316 |
;; This has to be here so that the function definition of |
;; This has to be here so that the function definition of |
317 |
;; `timeclock-modeline-display' is known to the "set" function. |
;; `timeclock-modeline-display' is known to the "set" function. |
400 |
(if arg |
(if arg |
401 |
(run-hooks 'timeclock-done-hook)))) |
(run-hooks 'timeclock-done-hook)))) |
402 |
|
|
403 |
|
;; Should today-only be removed in favour of timeclock-relative? - gm |
404 |
(defsubst timeclock-workday-remaining (&optional today-only) |
(defsubst timeclock-workday-remaining (&optional today-only) |
405 |
"Return the number of seconds until the workday is complete. |
"Return the number of seconds until the workday is complete. |
406 |
The amount returned is relative to the value of `timeclock-workday'. |
The amount returned is relative to the value of `timeclock-workday'. |
407 |
If TODAY-ONLY is non-nil, the value returned will be relative only to |
If TODAY-ONLY is non-nil, the value returned will be relative only to |
408 |
the time worked today, and not to past time. This argument only makes |
the time worked today, and not to past time." |
|
a difference if `timeclock-relative' is non-nil." |
|
409 |
(let ((discrep (timeclock-find-discrep))) |
(let ((discrep (timeclock-find-discrep))) |
410 |
(if discrep |
(if discrep |
411 |
(if today-only |
(- (if today-only (cadr discrep) |
412 |
(- (cadr discrep)) |
(car discrep))) |
|
(- (car discrep))) |
|
413 |
0.0))) |
0.0))) |
414 |
|
|
415 |
;;;###autoload |
;;;###autoload |
416 |
(defun timeclock-status-string (&optional show-seconds today-only) |
(defun timeclock-status-string (&optional show-seconds today-only) |
417 |
"Report the overall timeclock status at the present moment." |
"Report the overall timeclock status at the present moment. |
418 |
|
If SHOW-SECONDS is non-nil, display second resolution. |
419 |
|
If TODAY-ONLY is non-nil, the display will be relative only to time |
420 |
|
worked today, ignoring the time worked on previous days." |
421 |
(interactive "P") |
(interactive "P") |
422 |
(let ((remainder (timeclock-workday-remaining)) |
(let ((remainder (timeclock-workday-remaining)) ; today-only? |
423 |
(last-in (equal (car timeclock-last-event) "i")) |
(last-in (equal (car timeclock-last-event) "i")) |
424 |
status) |
status) |
425 |
(setq status |
(setq status |
544 |
(floor (mod seconds 65536)) |
(floor (mod seconds 65536)) |
545 |
(floor (* (- seconds (ffloor seconds)) 1000000)))) |
(floor (* (- seconds (ffloor seconds)) 1000000)))) |
546 |
|
|
547 |
|
;; Should today-only be removed in favour of timeclock-relative? - gm |
548 |
(defsubst timeclock-when-to-leave (&optional today-only) |
(defsubst timeclock-when-to-leave (&optional today-only) |
549 |
"Return a time value representing at when the workday ends today. |
"Return a time value representing at when the workday ends today. |
550 |
If TODAY-ONLY is non-nil, the value returned will be relative only to |
If TODAY-ONLY is non-nil, the value returned will be relative only to |
551 |
the time worked today, and not to past time. This argument only makes |
the time worked today, and not to past time." |
|
a difference if `timeclock-relative' is non-nil." |
|
552 |
(timeclock-seconds-to-time |
(timeclock-seconds-to-time |
553 |
(- (timeclock-time-to-seconds (current-time)) |
(- (timeclock-time-to-seconds (current-time)) |
554 |
(let ((discrep (timeclock-find-discrep))) |
(let ((discrep (timeclock-find-discrep))) |
563 |
today-only) |
today-only) |
564 |
"Return a string representing at what time the workday ends today. |
"Return a string representing at what time the workday ends today. |
565 |
This string is relative to the value of `timeclock-workday'. If |
This string is relative to the value of `timeclock-workday'. If |
566 |
NO-MESSAGE is non-nil, no messages will be displayed in the |
SHOW-SECONDS is non-nil, the value printed/returned will include |
567 |
minibuffer. If SHOW-SECONDS is non-nil, the value printed/returned |
seconds. If TODAY-ONLY is non-nil, the value returned will be |
568 |
will include seconds. If TODAY-ONLY is non-nil, the value returned |
relative only to the time worked today, and not to past time." |
569 |
will be relative only to the time worked today, and not to past time. |
;; Should today-only be removed in favour of timeclock-relative? - gm |
|
This argument only makes a difference if `timeclock-relative' is |
|
|
non-nil." |
|
570 |
(interactive) |
(interactive) |
571 |
(let* ((then (timeclock-when-to-leave today-only)) |
(let* ((then (timeclock-when-to-leave today-only)) |
572 |
(string |
(string |
609 |
(mapcar 'list timeclock-reason-list))) |
(mapcar 'list timeclock-reason-list))) |
610 |
|
|
611 |
(defun timeclock-update-modeline () |
(defun timeclock-update-modeline () |
612 |
"Update the `timeclock-mode-string' displayed in the modeline." |
"Update the `timeclock-mode-string' displayed in the modeline. |
613 |
|
The value of `timeclock-relative' affects the display as described in |
614 |
|
that variable's documentation." |
615 |
(interactive) |
(interactive) |
616 |
(let ((remainder (timeclock-workday-remaining)) |
(let ((remainder (timeclock-workday-remaining (not timeclock-relative))) |
617 |
(last-in (equal (car timeclock-last-event) "i"))) |
(last-in (equal (car timeclock-last-event) "i"))) |
618 |
(when (and (< remainder 0) |
(when (and (< remainder 0) |
619 |
(not (and timeclock-day-over |
(not (and timeclock-day-over |
829 |
|
|
830 |
(defun timeclock-log-data (&optional recent-only filename) |
(defun timeclock-log-data (&optional recent-only filename) |
831 |
"Return the contents of the timelog file, in a useful format. |
"Return the contents of the timelog file, in a useful format. |
832 |
|
If the optional argument RECENT-ONLY is non-nil, only show the contents |
833 |
|
from the last point where the time debt (see below) was set. |
834 |
|
If the optional argument FILENAME is non-nil, it is used instead of |
835 |
|
the file specified by `timeclock-file.' |
836 |
|
|
837 |
A timelog contains data in the form of a single entry per line. |
A timelog contains data in the form of a single entry per line. |
838 |
Each entry has the form: |
Each entry has the form: |
839 |
|
|
1028 |
log-data))) |
log-data))) |
1029 |
|
|
1030 |
(defun timeclock-find-discrep () |
(defun timeclock-find-discrep () |
1031 |
"Find overall discrepancy from `timeclock-workday' (in seconds)." |
"Calculate time discrepancies, in seconds. |
1032 |
|
The result is a three element list, containing the total time |
1033 |
|
discrepancy, today's discrepancy, and the time worked today." |
1034 |
;; This is not implemented in terms of the functions above, because |
;; This is not implemented in terms of the functions above, because |
1035 |
;; it's a bit wasteful to read all of that data in, just to throw |
;; it's a bit wasteful to read all of that data in, just to throw |
1036 |
;; away more than 90% of the information afterwards. |
;; away more than 90% of the information afterwards. |
1131 |
(< (nth 1 t1) (nth 1 t2))))) |
(< (nth 1 t1) (nth 1 t2))))) |
1132 |
|
|
1133 |
(defun timeclock-day-base (&optional time) |
(defun timeclock-day-base (&optional time) |
1134 |
"Given a time within a day, return 0:0:0 within that day." |
"Given a time within a day, return 0:0:0 within that day. |
1135 |
|
If optional argument TIME is non-nil, use that instead of the current time." |
1136 |
(let ((decoded (decode-time (or time (current-time))))) |
(let ((decoded (decode-time (or time (current-time))))) |
1137 |
(setcar (nthcdr 0 decoded) 0) |
(setcar (nthcdr 0 decoded) 0) |
1138 |
(setcar (nthcdr 1 decoded) 0) |
(setcar (nthcdr 1 decoded) 0) |
1152 |
0))) |
0))) |
1153 |
|
|
1154 |
(defun timeclock-generate-report (&optional html-p) |
(defun timeclock-generate-report (&optional html-p) |
1155 |
"Generate a summary report based on the current timelog file." |
"Generate a summary report based on the current timelog file. |
1156 |
|
By default, the report is in plain text, but if the optional argument |
1157 |
|
HTML-P is non-nil html markup is added." |
1158 |
(interactive) |
(interactive) |
1159 |
(let ((log (timeclock-log-data)) |
(let ((log (timeclock-log-data)) |
1160 |
(today (timeclock-day-base))) |
(today (timeclock-day-base))) |
1346 |
;;; A helpful little function |
;;; A helpful little function |
1347 |
|
|
1348 |
(defun timeclock-visit-timelog () |
(defun timeclock-visit-timelog () |
1349 |
"Open up the .timelog file in another window." |
"Open the file named by `timeclock-file' in another window." |
1350 |
(interactive) |
(interactive) |
1351 |
(find-file-other-window timeclock-file)) |
(find-file-other-window timeclock-file)) |
1352 |
|
|