Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

keeping track of time spent per file?

1 view
Skip to first unread message

rodrigo vanegas

unread,
Jun 4, 1995, 3:00:00 AM6/4/95
to
In article <MUCIT.95J...@vein.cs.rochester.edu> mu...@cs.rochester.edu (Bulent Murtezaoglu) writes:

> Is there a package that keeps track of how much time is spent typing
> to/using a buffer? (w/ idle time thresholds etc.) Or else how can I
> catch each input event? A cursory look at apropos output and the
> elisp manual failed to yield a useful hook. I need this for a pet
> project to keep track of how much time I'm really spending on what
> (papers, programming, mail, news etc.). Thanks.

Here's some code. Let me know what you think.


(defvar log-major-mode major-mode
"Major mode of current buffer at end of last command")
(defvar log-last-command-time (current-time)
"Time at which last command took place")
(defvar log-current-time-block 0
"Accumulated unlogged unidle time")
(defvar log-unidle nil
"Is user at terminal?")

(defvar log-stat-file "~/emacs.stats"
"File in which major-mode usage statistics are maintained")

(defvar log-stats
(if (file-exists-p log-stat-file)
(progn
(find-file log-stat-file)
(prog1
(car (read-from-string (buffer-string)))
(kill-buffer nil)))
())
"Association list of major mode -> time spent")

(defun time-difference (a b)
(let ((hi (- (car a) (car b)))
(lo (- (car (cdr a)) (car (cdr b)))))
(+ (lsh hi 16) lo)))


(defun log-stamp-time ()
(let* ((ct (current-time))
(d (time-difference ct log-last-command-time)))
(if (setq log-unidle (< d 180))
(setq log-current-time-block (+ d log-current-time-block)))
(setq log-last-command-time ct)))

;; Record major mode and time entered, if new
(defun log-hook ()
(log-stamp-time)
(if (not (and log-unidle (eq major-mode log-major-mode)))
(log-record))
(setq log-major-mode major-mode))

(defun log-record ()
;; Switching out of log-major-mode -- do bookkeeping for it
(let ((entry (assoc log-major-mode log-stats)))
(if (not entry)
(setq log-stats (cons (setq entry (cons log-major-mode 0))
log-stats)))
(setcdr entry
(+ (cdr entry) log-current-time-block))
(setq log-current-time-block 0)))

(defun log-write ()
(log-stamp-time)
(log-record)
(find-file log-stat-file)
(erase-buffer)
(insert "(")
(let ((comp (function (lambda (a b) (> (cdr a) (cdr b))))))
(insert (mapconcat (function (lambda (x) (format "%s" x)))
(sort log-stats comp)
"\n")))
(insert ")\n")
(save-buffer))

(add-hook 'post-command-hook 'log-hook)
(add-hook 'kill-emacs-hook 'log-write)


--
rodrigo vanegas
r...@cs.brown.edu

Bulent Murtezaoglu

unread,
Jun 4, 1995, 3:00:00 AM6/4/95
to

Is there a package that keeps track of how much time is spent typing to/using
a buffer? (w/ idle time thresholds etc.) Or else how can I catch each input
event? A cursory look at apropos output and the elisp manual failed to
yield a useful hook. I need this for a pet project to keep track of
how much time I'm really spending on what (papers, programming, mail, news
etc.). Thanks.

cheers,

BM

Ron Forrester

unread,
Jun 4, 1995, 3:00:00 AM6/4/95
to

I am not sure (I am a bit new to Emacs myself), but I think
post-command-hook is what you want:

C-h v post-command-hook:

post-command-hook's value is nil

Documentation:
Normal hook run after each command is executed.
While the hook is run, its value is temporarily set to nil
to avoid an unbreakable infinite loop if a hook function gets an error.
As a result, a hook function cannot straightforwardly alter the value of
`post-command-hook'. See the Emacs Lisp manual for a way of
implementing hook functions that alter the set of hook functions.


rjf
--
| "I don't like being bluffed -- makes me doubt | r...@aurora.pcg.com |
| my perception of reality..." | 71722,3175 |
| Chris in the morning on KBHR | |
+---------------------------------------------------+-----------------------+

mu...@cs.rochester.edu

unread,
Jun 4, 1995, 3:00:00 AM6/4/95
to
>>>>> "Ron" == Ron Forrester <r...@aurora.pcg.com> writes:
Ron> I am not sure (I am a bit new to Emacs myself), but I think
Ron> post-command-hook is what you want:

Ron> C-h v post-command-hook:

Works fine. Thank you very much. (I got a little counter running in the
mini-buffer right now using it)

cheers,

-M

Bulent Murtezaoglu

unread,
Jun 5, 1995, 3:00:00 AM6/5/95
to
>>>>> "rv" == rodrigo vanegas <rv@tahoe> writes:
[about logging time spent playing with various things in emacs}
rv> Here's some code. Let me know what you think.

I think it is very good. I modified it a bit to keep track of
buffer names as opposed to modes and have it read the log file
before quitting emacs. The latter might be necessary for efficiency
as the log file (and the assoc. list) is likely to get huge for a
heavy emacs user. I also added code to save the # of minutes instead of
seconds into the log file. Lots of other things (like not logging the time
spent in certain buffers and making the log variables buffer-local etc.)
can be added but I think it does what I want as is.

Here's the modified code:

(defvar log-buffer-name (buffer-name)
"Name of current buffer at end of last command")


(defvar log-last-command-time (current-time)
"Time at which last command took place")
(defvar log-current-time-block 0
"Accumulated unlogged unidle time")
(defvar log-unidle nil
"Is user at terminal?")

(defvar log-idle-threshold 180
"in seconds")

(defvar log-stat-file "~/emacs.stats"
"File in which usage statistics are maintained")

(defvar log-stats nil
"association list (buffername . time-spent)")

(defun time-difference (a b)
(let ((hi (- (car a) (car b)))
(lo (- (car (cdr a)) (car (cdr b)))))
(+ (lsh hi 16) lo)))


(defun log-stamp-time ()
(let* ((ct (current-time))
(d (time-difference ct log-last-command-time)))

(if (setq log-unidle (< d log-idle-threshold))


(setq log-current-time-block (+ d log-current-time-block)))
(setq log-last-command-time ct)))

;; Record buffer name and time entered, if new
(defun log-hook ()
(log-stamp-time)
(if (not (and log-unidle (eql (buffer-name) log-buffer-name)))
(log-record))
(setq log-buffer-name (buffer-name)))

(defun log-record ()
;; Switching out of log-buffer -- do bookkeeping for it
(let ((entry (assoc log-buffer-name log-stats)))
(if (not entry)
(setq log-stats (cons (setq entry (cons log-buffer-name 0))


log-stats)))
(setcdr entry
(+ (cdr entry) log-current-time-block))
(setq log-current-time-block 0)))


(defun log-write ()
(log-stamp-time)
(log-record)
(find-file log-stat-file)

(let ((old-log (and (> (buffer-size) 0)
(car (read-from-string (buffer-string))))))
(erase-buffer)
(insert (format "(\n%s \n)"
(mapconcat
(function (lambda (x) (format "%S" x)))
(sort
(log-merge-logs old-log log-stats)


(function (lambda (a b) (> (cdr a) (cdr b)))))

"\n")))
(save-buffer)))

(defun log-merge-logs (old-list new-list)
(mapcar (function (lambda (new-rec)
(and (> (cdr new-rec) 60)
(setcdr new-rec (/ (cdr new-rec) 60))
(let ((old-rec (assoc (car new-rec) old-list)))
(if old-rec
(setcdr old-rec (+ (cdr old-rec)
(cdr new-rec)))
(setq old-list (cons new-rec old-list)))))))
new-list)
old-list)

0 new messages