comparison lisp/calendar/timeclock.el @ 51861:91e4e5fd11de

(timeclock-use-display-time, timeclock-day-over-hook) (timeclock-workday-remaining, timeclock-status-string) (timeclock-when-to-leave, timeclock-when-to-leave-string) (timeclock-log-data, timeclock-find-discrep, timeclock-day-base) (timeclock-generate-report, timeclock-visit-timelog): Doc fix. (timeclock-modeline-display): Set the variable `timeclock-modeline-display'. (timeclock-update-modeline): Doc fix. Respect value of `timeclock-relative'.
author Glenn Morris <rgm@gnu.org>
date Thu, 10 Jul 2003 01:02:11 +0000
parents 48facdb1558e
children 0c6d39d0f49d
comparison
equal deleted inserted replaced
51860:f9ae39b1c1e6 51861:91e4e5fd11de
153 The advantage to this is that it means one less timer has to be set 153 The advantage to this is that it means one less timer has to be set
154 running amok in Emacs' process space. The disadvantage is that it 154 running amok in Emacs' process space. The disadvantage is that it
155 requires you to have `display-time' running. If you don't want to use 155 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 156 `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 157 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 158 toggle the function `timeclock-modeline-display') for the change to
159 take effect." 159 take effect."
160 :set (lambda (symbol value) 160 :set (lambda (symbol value)
161 (let ((currently-displaying 161 (let ((currently-displaying
162 (and (boundp 'timeclock-modeline-display) 162 (and (boundp 'timeclock-modeline-display)
163 timeclock-modeline-display))) 163 timeclock-modeline-display)))
202 :type 'hook 202 :type 'hook
203 :group 'timeclock) 203 :group 'timeclock)
204 204
205 (defcustom timeclock-day-over-hook nil 205 (defcustom timeclock-day-over-hook nil
206 "*A hook that is run when the workday has been completed. 206 "*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 207 This hook is only run if the current time remaining is being displayed
208 in the modeline. See the variable `timeclock-modeline-display'." 208 in the modeline. See the variable `timeclock-modeline-display'."
209 :type 'hook 209 :type 'hook
210 :group 'timeclock) 210 :group 'timeclock)
211 211
212 (defcustom timeclock-out-hook nil 212 (defcustom timeclock-out-hook nil
299 ;; on calling this function. 299 ;; on calling this function.
300 (if display-time-mode (timeclock-update-modeline)) 300 (if display-time-mode (timeclock-update-modeline))
301 (add-hook 'display-time-hook 'timeclock-update-modeline)) 301 (add-hook 'display-time-hook 'timeclock-update-modeline))
302 (setq timeclock-update-timer 302 (setq timeclock-update-timer
303 (run-at-time nil 60 'timeclock-update-modeline)))) 303 (run-at-time nil 60 'timeclock-update-modeline))))
304 (setq global-mode-string 304 (setq global-mode-string
305 (delq 'timeclock-mode-string global-mode-string)) 305 (delq 'timeclock-mode-string global-mode-string))
306 (remove-hook 'timeclock-event-hook 'timeclock-update-modeline) 306 (remove-hook 'timeclock-event-hook 'timeclock-update-modeline)
307 (if (boundp 'display-time-hook) 307 (if (boundp 'display-time-hook)
308 (remove-hook 'display-time-hook 308 (remove-hook 'display-time-hook
309 'timeclock-update-modeline)) 309 'timeclock-update-modeline))
310 (when timeclock-update-timer 310 (when timeclock-update-timer
311 (cancel-timer timeclock-update-timer) 311 (cancel-timer timeclock-update-timer)
312 (setq timeclock-update-timer nil))) 312 (setq timeclock-update-timer nil)))
313 (force-mode-line-update) 313 (force-mode-line-update)
314 on-p)) 314 (setq timeclock-modeline-display on-p)))
315 315
316 ;; This has to be here so that the function definition of 316 ;; This has to be here so that the function definition of
317 ;; `timeclock-modeline-display' is known to the "set" function. 317 ;; `timeclock-modeline-display' is known to the "set" function.
318 (defcustom timeclock-modeline-display nil 318 (defcustom timeclock-modeline-display nil
319 "Toggle modeline display of time remaining. 319 "Toggle modeline display of time remaining.
398 (funcall timeclock-get-reason-function)))) 398 (funcall timeclock-get-reason-function))))
399 (run-hooks 'timeclock-out-hook) 399 (run-hooks 'timeclock-out-hook)
400 (if arg 400 (if arg
401 (run-hooks 'timeclock-done-hook)))) 401 (run-hooks 'timeclock-done-hook))))
402 402
403 ;; Should today-only be removed in favour of timeclock-relative? - gm
403 (defsubst timeclock-workday-remaining (&optional today-only) 404 (defsubst timeclock-workday-remaining (&optional today-only)
404 "Return the number of seconds until the workday is complete. 405 "Return the number of seconds until the workday is complete.
405 The amount returned is relative to the value of `timeclock-workday'. 406 The amount returned is relative to the value of `timeclock-workday'.
406 If TODAY-ONLY is non-nil, the value returned will be relative only to 407 If TODAY-ONLY is non-nil, the value returned will be relative only to
407 the time worked today, and not to past time. This argument only makes 408 the time worked today, and not to past time."
408 a difference if `timeclock-relative' is non-nil."
409 (let ((discrep (timeclock-find-discrep))) 409 (let ((discrep (timeclock-find-discrep)))
410 (if discrep 410 (if discrep
411 (if today-only 411 (- (if today-only (cadr discrep)
412 (- (cadr discrep)) 412 (car discrep)))
413 (- (car discrep)))
414 0.0))) 413 0.0)))
415 414
416 ;;;###autoload 415 ;;;###autoload
417 (defun timeclock-status-string (&optional show-seconds today-only) 416 (defun timeclock-status-string (&optional show-seconds today-only)
418 "Report the overall timeclock status at the present moment." 417 "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."
419 (interactive "P") 421 (interactive "P")
420 (let ((remainder (timeclock-workday-remaining)) 422 (let ((remainder (timeclock-workday-remaining)) ; today-only?
421 (last-in (equal (car timeclock-last-event) "i")) 423 (last-in (equal (car timeclock-last-event) "i"))
422 status) 424 status)
423 (setq status 425 (setq status
424 (format "Currently %s since %s (%s), %s %s, leave at %s" 426 (format "Currently %s since %s (%s), %s %s, leave at %s"
425 (if last-in "IN" "OUT") 427 (if last-in "IN" "OUT")
540 "Convert SECONDS (a floating point number) to an Emacs time structure." 542 "Convert SECONDS (a floating point number) to an Emacs time structure."
541 (list (floor seconds 65536) 543 (list (floor seconds 65536)
542 (floor (mod seconds 65536)) 544 (floor (mod seconds 65536))
543 (floor (* (- seconds (ffloor seconds)) 1000000)))) 545 (floor (* (- seconds (ffloor seconds)) 1000000))))
544 546
547 ;; Should today-only be removed in favour of timeclock-relative? - gm
545 (defsubst timeclock-when-to-leave (&optional today-only) 548 (defsubst timeclock-when-to-leave (&optional today-only)
546 "Return a time value representing at when the workday ends today. 549 "Return a time value representing at when the workday ends today.
547 If TODAY-ONLY is non-nil, the value returned will be relative only to 550 If TODAY-ONLY is non-nil, the value returned will be relative only to
548 the time worked today, and not to past time. This argument only makes 551 the time worked today, and not to past time."
549 a difference if `timeclock-relative' is non-nil."
550 (timeclock-seconds-to-time 552 (timeclock-seconds-to-time
551 (- (timeclock-time-to-seconds (current-time)) 553 (- (timeclock-time-to-seconds (current-time))
552 (let ((discrep (timeclock-find-discrep))) 554 (let ((discrep (timeclock-find-discrep)))
553 (if discrep 555 (if discrep
554 (if today-only 556 (if today-only
559 ;;;###autoload 561 ;;;###autoload
560 (defun timeclock-when-to-leave-string (&optional show-seconds 562 (defun timeclock-when-to-leave-string (&optional show-seconds
561 today-only) 563 today-only)
562 "Return a string representing at what time the workday ends today. 564 "Return a string representing at what time the workday ends today.
563 This string is relative to the value of `timeclock-workday'. If 565 This string is relative to the value of `timeclock-workday'. If
564 NO-MESSAGE is non-nil, no messages will be displayed in the 566 SHOW-SECONDS is non-nil, the value printed/returned will include
565 minibuffer. If SHOW-SECONDS is non-nil, the value printed/returned 567 seconds. If TODAY-ONLY is non-nil, the value returned will be
566 will include seconds. If TODAY-ONLY is non-nil, the value returned 568 relative only to the time worked today, and not to past time."
567 will be relative only to the time worked today, and not to past time. 569 ;; Should today-only be removed in favour of timeclock-relative? - gm
568 This argument only makes a difference if `timeclock-relative' is
569 non-nil."
570 (interactive) 570 (interactive)
571 (let* ((then (timeclock-when-to-leave today-only)) 571 (let* ((then (timeclock-when-to-leave today-only))
572 (string 572 (string
573 (if show-seconds 573 (if show-seconds
574 (format-time-string "%-I:%M:%S %p" then) 574 (format-time-string "%-I:%M:%S %p" then)
607 "Ask the user for the reason they are clocking out." 607 "Ask the user for the reason they are clocking out."
608 (timeclock-completing-read "Reason for clocking out: " 608 (timeclock-completing-read "Reason for clocking out: "
609 (mapcar 'list timeclock-reason-list))) 609 (mapcar 'list timeclock-reason-list)))
610 610
611 (defun timeclock-update-modeline () 611 (defun timeclock-update-modeline ()
612 "Update the `timeclock-mode-string' displayed in the modeline." 612 "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."
613 (interactive) 615 (interactive)
614 (let ((remainder (timeclock-workday-remaining)) 616 (let ((remainder (timeclock-workday-remaining (not timeclock-relative)))
615 (last-in (equal (car timeclock-last-event) "i"))) 617 (last-in (equal (car timeclock-last-event) "i")))
616 (when (and (< remainder 0) 618 (when (and (< remainder 0)
617 (not (and timeclock-day-over 619 (not (and timeclock-day-over
618 (equal timeclock-day-over 620 (equal timeclock-day-over
619 (timeclock-time-to-date 621 (timeclock-time-to-date
825 (nth 2 (or log-data (timeclock-log-data)))) 827 (nth 2 (or log-data (timeclock-log-data))))
826 828
827 829
828 (defun timeclock-log-data (&optional recent-only filename) 830 (defun timeclock-log-data (&optional recent-only filename)
829 "Return the contents of the timelog file, in a useful format. 831 "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
830 A timelog contains data in the form of a single entry per line. 837 A timelog contains data in the form of a single entry per line.
831 Each entry has the form: 838 Each entry has the form:
832 839
833 CODE YYYY/MM/DD HH:MM:SS [COMMENT] 840 CODE YYYY/MM/DD HH:MM:SS [COMMENT]
834 841
1019 (cons (cons last-date day) 1026 (cons (cons last-date day)
1020 (cadr log-data)))) 1027 (cadr log-data))))
1021 log-data))) 1028 log-data)))
1022 1029
1023 (defun timeclock-find-discrep () 1030 (defun timeclock-find-discrep ()
1024 "Find overall discrepancy from `timeclock-workday' (in seconds)." 1031 "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."
1025 ;; This is not implemented in terms of the functions above, because 1034 ;; This is not implemented in terms of the functions above, because
1026 ;; it's a bit wasteful to read all of that data in, just to throw 1035 ;; it's a bit wasteful to read all of that data in, just to throw
1027 ;; away more than 90% of the information afterwards. 1036 ;; away more than 90% of the information afterwards.
1028 ;; 1037 ;;
1029 ;; If it were implemented using those functions, it would look 1038 ;; If it were implemented using those functions, it would look
1120 (or (< (car t1) (car t2)) 1129 (or (< (car t1) (car t2))
1121 (and (= (car t1) (car t2)) 1130 (and (= (car t1) (car t2))
1122 (< (nth 1 t1) (nth 1 t2))))) 1131 (< (nth 1 t1) (nth 1 t2)))))
1123 1132
1124 (defun timeclock-day-base (&optional time) 1133 (defun timeclock-day-base (&optional time)
1125 "Given a time within a day, return 0:0:0 within that day." 1134 "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."
1126 (let ((decoded (decode-time (or time (current-time))))) 1136 (let ((decoded (decode-time (or time (current-time)))))
1127 (setcar (nthcdr 0 decoded) 0) 1137 (setcar (nthcdr 0 decoded) 0)
1128 (setcar (nthcdr 1 decoded) 0) 1138 (setcar (nthcdr 1 decoded) 0)
1129 (setcar (nthcdr 2 decoded) 0) 1139 (setcar (nthcdr 2 decoded) 0)
1130 (apply 'encode-time decoded))) 1140 (apply 'encode-time decoded)))
1140 (if (> count 0) 1150 (if (> count 0)
1141 (/ total count) 1151 (/ total count)
1142 0))) 1152 0)))
1143 1153
1144 (defun timeclock-generate-report (&optional html-p) 1154 (defun timeclock-generate-report (&optional html-p)
1145 "Generate a summary report based on the current timelog file." 1155 "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."
1146 (interactive) 1158 (interactive)
1147 (let ((log (timeclock-log-data)) 1159 (let ((log (timeclock-log-data))
1148 (today (timeclock-day-base))) 1160 (today (timeclock-day-base)))
1149 (if html-p (insert "<p>")) 1161 (if html-p (insert "<p>"))
1150 (insert "Currently ") 1162 (insert "Currently ")
1332 </td></table>"))))) 1344 </td></table>")))))
1333 1345
1334 ;;; A helpful little function 1346 ;;; A helpful little function
1335 1347
1336 (defun timeclock-visit-timelog () 1348 (defun timeclock-visit-timelog ()
1337 "Open up the .timelog file in another window." 1349 "Open the file named by `timeclock-file' in another window."
1338 (interactive) 1350 (interactive)
1339 (find-file-other-window timeclock-file)) 1351 (find-file-other-window timeclock-file))
1340 1352
1341 (provide 'timeclock) 1353 (provide 'timeclock)
1342 1354