Build a chart from Org-mode clocks

Org-mode is a great todo and agenda application. It's possible to use it to clock how much time you spend on a task. I've been clocking my work for a few months using org-mode. I love that I can get a summary of how much time I have spent on each stuff I do. However, it's difficult to see how much time you spend daily. You have to look at each clock entry and sum the durations. Not very friendly. My idea was to chart the hours spent per day. You put the cursor on any task and you get a bar chart showing you how much time was spent per day.

It's turning this:

*** project1
**** task1
     CLOCK: [2010-11-20 Sun 19:42]--[2010-11-20 Sun 20:14] =>  0:32
     CLOCK: [2010-11-20 Sun 18:54]--[2010-11-20 Sun 19:24] =>  0:30
     CLOCK: [2010-11-20 Sun 17:25]--[2010-11-20 Sun 17:40] =>  0:15
     CLOCK: [2010-11-20 Sun 15:07]--[2010-11-20 Sun 15:45] =>  0:38
     CLOCK: [2010-11-20 Sun 10:06]--[2010-11-20 Sun 12:37] =>  2:31
     CLOCK: [2010-11-19 Sat 17:21]--[2010-11-19 Sat 19:33] =>  2:12
     CLOCK: [2010-11-19 Sat 14:52]--[2010-11-19 Sat 16:53] =>  2:01
     CLOCK: [2010-11-18 Fri 17:45]--[2010-11-18 Fri 18:27] =>  0:42
     CLOCK: [2010-11-18 Fri 11:17]--[2010-11-18 Fri 15:20] =>  4:03
**** task2
    :LOGBOOK:
    CLOCK: [2010-11-19 Sat 12:51]--[2010-11-19 Sat 14:52] =>  2:01
    CLOCK: [2010-11-18 Fri 17:08]--[2010-11-18 Fri 17:45] =>  0:37
    CLOCK: [2010-11-18 Fri 11:17]--[2010-11-18 Fri 11:17] =>  0:00
    CLOCK: [2010-11-17 Thu 12:40]--[2010-11-17 Thu 13:05] =>  0:25
    CLOCK: [2010-11-17 Thu 10:16]--[2010-11-17 Thu 11:58] =>  1:42
    CLOCK: [2010-11-16 Wed 19:32]--[2010-11-16 Wed 20:29] =>  0:57
    CLOCK: [2010-11-16 Wed 14:06]--[2010-11-16 Wed 16:04] =>  1:58
    CLOCK: [2010-11-16 Wed 11:55]--[2010-11-16 Wed 13:00] =>  1:05
    CLOCK: [2010-11-15 Tue 16:32]--[2010-11-15 Tue 17:59] =>  1:27
    CLOCK: [2010-11-15 Tue 10:55]--[2010-11-15 Tue 12:27] =>  1:32
    CLOCK: [2010-11-14 Mon 18:05]--[2010-11-14 Mon 19:52] =>  1:47
    CLOCK: [2010-11-14 Mon 16:10]--[2010-11-14 Mon 17:46] =>  1:36
    CLOCK: [2010-11-14 Mon 14:40]--[2010-11-14 Mon 15:24] =>  0:44
    CLOCK: [2010-11-14 Mon 09:50]--[2010-11-14 Mon 11:34] =>  1:44
    CLOCK: [2010-11-13 Sun 22:22]--[2010-11-13 Sun 23:17] =>  0:55
    CLOCK: [2010-11-13 Sun 15:23]--[2010-11-13 Sun 18:56] =>  3:33
    CLOCK: [2010-11-12 Sat 14:25]--[2010-11-12 Sat 17:08] =>  2:43
    CLOCK: [2010-11-11 Fri 19:25]--[2010-11-11 Fri 19:52] =>  0:27
    CLOCK: [2010-11-11 Fri 15:30]--[2010-11-11 Fri 18:15] =>  2:45
    CLOCK: [2010-11-11 Fri 10:26]--[2010-11-11 Fri 12:26] =>  2:00
    CLOCK: [2010-11-10 Thu 15:12]--[2010-11-10 Thu 18:49] =>  3:37
    CLOCK: [2010-11-10 Thu 10:08]--[2010-11-10 Thu 12:42] =>  2:34
    CLOCK: [2010-11-09 Wed 22:18]--[2010-11-10 Thu 00:13] =>  1:55
    CLOCK: [2010-11-09 Wed 15:09]--[2010-11-09 Wed 15:59] =>  0:50
    CLOCK: [2010-11-09 Wed 14:05]--[2010-11-09 Wed 14:50] =>  0:45
    :END:

Into this:

chart?chxl=1:|09|10|11|12|13|14|15|16|17|18|19|20|21&chxr=0%2c0%2c8|1%2c0%2c105&chxt=y%2cx&chbh=15&chs=600x400&cht=bvg&chco=80C65A&chds=0%2c8&chd=t:3.283333333333333%2c6.4%2c5.2%2c2.716666666666667%2c4.466666666666667%2c5.85%2c2.9833333333333334%2c4.0%2c2.1166666666666667%2c5.366666666666666%2c6.233333333333333%2c4.433333333333334%2c0.0&chg=0%2c25%2c0%2c0&chma=|5%2c10&chtt=Clocked+Activity+%2812+days%2c+53+hours%29&chm=h%2cFF0000%2c0%2c0.552604%2c1

Behind the scene, I've used Google chart api, and a few lines of emacs lisp. If you like that, copy the code below in your .emacs and bind a key to org-chart-clocks-current-item (define-key org-mode-map [f4] 'org-chart-clocks-current-item).

(defun org-time-delta-seconds (time-string seconds)
  (format-time-string
   "%Y-%m-%d"
   (seconds-to-time
    (+ (org-float-time (apply 'encode-time
     (org-parse-time-string time-string)))
       seconds))))

(defun org-list-clocks-current-item ()
  "Extract clocked hours per day of current item"
  (save-excursion
    (save-restriction
      (org-narrow-to-subtree)
      (goto-char (point-max))
      (let ((re (concat "^[ \t]*" org-clock-string
"[ \t]*\\(?:\\[\\([0-9-]+\\).*?\\]-+\\(\\[.*?\\]\\)\\|=>[ \t]+\\([0-9]+\\):\\([0-9]+\\)\\)"))
   (one-day (* 3600 24)))
(re-search-backward re nil t)
(setq match (match-string 2)
     ts (substring match 1 11)
     te (org-time-delta-seconds match one-day)
     res '()
     dates '())
(while (< (org-float-time
  (apply 'encode-time(org-parse-time-string ts)))
 (org-float-time (current-time)))
 (org-clock-sum ts te)
 (setq res (cons (/ org-clock-file-total-minutes 60.0) res)
dates (cons (substring ts 8 10) dates))
 (setq ts te
te (org-time-delta-seconds ts one-day)))
(list dates res)))))

(defun org-chart-clocks-current-item ()
  "Request a Google Chart with the clocked time of the current item."
  (interactive)
  (let* ((x (org-list-clocks-current-item))
(dates (reverse (car x)))
(res (reverse (cadr x)))
(active-days (length (remove-if (lambda (x) (= x 0)) res)))
(sum-hours (reduce (lambda (a b) (+ a b)) res)))
    (browse-url (format "http://chart.apis.google.com/chart?chxl=1:|%s&chxr=0,0,8|1,0,105&chxt=y,x&chbh=15&chs=600x400&cht=bvg&chco=80C65A&chds=0,8&chd=t:%s&chg=0,25,0,0&chma=|5,10&chtt=Clocked+Activity+(%d+days,+%d+hours)&chm=h,FF0000,0,%f,1"
     (mapconcat (lambda (x) x) dates "|")
     (mapconcat (lambda (x) (format "%s" x)) res  ",")
     active-days
     sum-hours
     (/ sum-hours active-days 8)))))

If you change the code, I'll love to hear about your hacks. So, let me know. The most recent version of this code lives somewhere in this file: http://code.google.com/p/marcshacks/source/browse/elisp/personal/marcshacks.el

Lisp interpreter in javascript with jQuery

I started using lisp a few years ago when I wanted to configure the hell out of emacs. After understanding lisp better thanks to some great videos,I built my own lisp interpreter. After two days of work, I had a somewhat working system. The interpreter is not complete however it runs some basic expressions. I guess the code is interesting for CS students trying to understand lisp better. There aren't much comments in the source code but the logic is split into small functions. It shouldn't be too difficult to read. First the lisp string is turned into a list that is passed to the eval-apply cycle and voila.

You can get the source code and add issues on the Google Code page.

Examples of what you can evaluate

Factorial

(defun fact (x) (if (<= x 1) 1 (* x (fact (- x 1)))))
(fact 5)

Reverse a list

(defun reverse- (x r)
(if (not (car x)) r (reverse- (cdr x) (cons (car x) r))))
(defun reverse (x) (reverse- x (list)))
(reverse (list 1 2 3 4))

Map a list

(defun mapcar (x f)
(if (not (car x)) (list) (cons (f (car x)) (mapcar (cdr x) f))))
(mapcar (list 1 2 3) (lambda (x) (* x x)))

Here's what you can use

car cdr cons
not and or
>= > <= < = eq
+ - * /
nil list setq if lambda defun

There's also a js function. It's to call any javascript function. Try ((js Math.abs) -23)

More javascript lisp interpreters

Some people have written this kind of program before. I have tried them but I couldn't evaluate expressions the way I wanted. You can take a look at the work of Paul M. ParksJoe Ganley or Brian Morearty.

 

Firefox Ubiquity Commands

I have built a bunch of Ubiquity commands.

  • Purify Page gets rid of all the images and flash contents of the current page. Turns the page black and white.
  • Ubiquity Gmail Messages shows up to 9 of your most recent unread messages. Press ALT+number to open a message in gmail.
  • Holiday Calendar shows you the current and the next month plus all the localized holidays. The current day is highlighted.
  • Multi Search is a specific sites search with preview using Bing. Here are the commands you can use: python, django, php, javascript, w3.org, jquery. Press ALT+number to open a result in a new tab.

Google code page

Non blocking copy in emacs dired-mode


Dired-mode is my only file manager and every once in a while I copy large files. It causes emacs to freeze for a few minutes. The copying is done by copy-file. It's the low level function blocking emacs. I first tried to replace it with dired-do-async-shell-command. I told my script to use the shell's cp command asynchronously. It worked well when copying 1 file but with 2+ files, I got a prompt asking me if I want to kill the running shell. I decided to go with a simpler solution:

- select some files
- press !
- type cp * /path-to-dest/ &