Category Archives: org

On this page:

Org: Changing the task states

I find it useful to keep track of which tasks I’ve started. Adding the
following line to the start of my Org file adds STARTED to my to-do
status keywords.

#+SEQ_TODO: TODO(t) STARTED(s) WAITING(w) | DONE(d)

Here’s some code to make it easier to clock in and out of tasks:

(defun sacha/org-clock-in-if-starting ()
  "Clock in when the task is marked STARTED."
  (when (and (string= state "STARTED")
             (not (string= last-state state)))
    (org-clock-in)))
(add-hook 'org-after-todo-state-change-hook
	  'sacha/org-clock-in-if-starting)
(defadvice org-clock-in (after sacha activate)
  "Set this task's status to 'STARTED'."
  (org-todo "STARTED"))

On Technorati: ,

Random Emacs symbol: isearch-update-ring – Function: Add STRING to the beginning of the search ring.

Generating a table of projects and their actions

Here’s how I generated my list of 101 short-term goals.

First, I brainstormed the list of goals in an org-mode file. Each goal
is represented by a level-2 outline heading. Current projects are
tagged :PROJECT:. The goals are grouped under level-1 outline
headings, like this:

 * Reading, Writing, and Sharing
 ** 30. Write and publish a 350-page book about Emacs :PROJECT:

Then I went through all of the goals and added next actions to each of them.

 * Reading, Writing, and Sharing
 ** 30. Write and publish a 350-page book about Emacs :PROJECT:
 *** TODO 30min Write another blog post about Emacs.

This made it easy to keep track of my finished tasks. Whenever I
finished a next action, I’d mark a task as DONE and create another
task in the same project. (Hey, I can automate that bit…)

To generate the list of next actions for projects without including
the finished tasks, I used C-c C-v (org-show-todo-tree). I found that
command by typing M-x org-show- and letting icomplete-mode show me the
possible functions.

Then I exported the visible tree to a temporary buffer with C-c C-e v
SPC (org-export, visible, keep buffer). I used re-builder to test a
regular expression that combined the project headline with the task
headline. I then copied the regular expression into a short Lisp
program that replaced all the matching lines with the table row. I
then exported this with C-c C-e H (org-export, HTML to buffer) and
edited the page a little before saving it to a file.

This ability to quickly parse and massage the data into the form I
want is one of the things that I love about Emacs. =)

On Technorati: ,

Random Emacs symbol: debugger-setup-buffer – Function: Initialize the `*Backtrace*’ buffer for entry to the debugger.

Optimizing your action loop

If you want to be radically more effective at doing things, get better
at deciding what to do. Few things are more personal than figuring out
what you’re going to do with your life: at this moment, for this day,
for the next few years. Few decisions are made as frequently. If you
can improve the way you make that decision, you’ll reap the benefits
everywhere.

We’ve all developed some ways of coping. We all have our quirks.
One of mine is that I can’t settle on one way of planning my tasks.
Some days, I’m all strategic and top-down, connecting my life goals
with the tasks I plan to do that day. Other days, I just need to get a
crucial task out of my head so that I don’t forget it while hunting
for my keys. Some days, I block out time to work on my priority
projects. Other days, I have to work around other people’s schedules,
so it’s all about cramming whatever I can into whenever I’ve got.

Now think of all the other geeks out there, and you’ll understand how
to-do list programs might outnumber programmers. Despite the
collective efforts of companies like Microsoft and IBM, despite the
coolness of Web 2.0 services like Remember the Milk, despite the
renaissance of paper-based planners such as the Hipster PDA, I have
never found anything as powerful as a plain text file in terms of
personal productivity: a plain text file with shortcuts that are
form-fitted to the way I work.

Here’s what my workday looks like:

  • I do a _quick_ scan of e-mail to see if any tasks have come in. I copy those into my inbox. I resist the urge to reply right away, as that turns e-mail into a huge timesink.
  • 5-10 minutes are enough to schedule and prioritize my tasks for the day. I see both my calendar and my task list at the same time, and I can estimate my load. I leave plenty of space for things that come up. I feel better when I finish my scheduled tasks and then cross off a few more, than when I don’t finish everything I planned and I have to postpone tasks to the next day.
  • I work on my highest-priority task for the day.
  • _Then_ I respond to e-mail.
  • Then I work through everything else in roughly 45-minute chunks, with some downtime in between to recharge my brain and take care of routine tasks.
  • My computer is set up to encourage me to take 10-second breaks every 5 minutes and 2.5 minute breaks every hour. The numbers are arbitrary, but the result feels good. This works out even better when I work from home: 2.5 minutes is just enough time to clear the sink, or to empty the dishwasher, or to start some tea…

A plain text file keeps me all organized, thanks to the Org module for
the Emacs text editor. The text file shows me what’s on my horizon and
what’s on today’s schedule. The text file helps me deal with
interruptions because it keeps track of what I was working on and what
I need to do.

The text file even helps me learn more about myself and my skills
through detailed time-tracking. Every time I start a task, the clock
starts. Every time I mark a task as waiting or done, the clock stops,
and the elapsed time is stored in the task. This helps me tune my time
estimates and report time at the end of the week.

And it’s just amazing. I don’t feel that I waste a lot of time. I have
a sense of progress. I can see the big picture, and things almost
never fall through the cracks. (When they do, that’s because I hadn’t
gotten around to putting them in my text file yet.) Sure, this still
doesn’t give me enough time to do everything I want to do, but I don’t
feel stressed out about it because I’m working well. From now on, most
of the performance improvement will come from improving my skills and
learning more.

If I can do this much as a new hire with a pretty nifty task
management system, think about what you can do with all your
experience. What _could_ you do if you spent less time fighting with
your memory or with your TODO system, and more time making the
difference you want to make?

On Technorati: , , , , ,

Random Emacs symbol: edebug-stop – Command: Stop execution and do not continue.

Finding out if I’m overscheduled

If you’re anything like me, your task list is long and growing, but
the time you have is just as fixed. How do you manage that? I handle
that problem by looking at my calendar and my task list together when
I’m planning my day. I tend to be too optimistic about my tasks,
trying to schedule more into my day than I should. Fortunately, Emacs
can help me make sure I don’t overcommit. Here’s how it works.

When I create and schedule tasks, I try my best to add time estimates.
The numbers in the TODO headline represent minutes.

* TODO 15 Announce tea party
  SCHEDULED: <2007-12-08 Sat>
* DONE 30 Drop letters off at post office
  SCHEDULED: <2007-12-08 Sat>
* TODO 60 Write blog post about tasks
  SCHEDULED: <2007-12-08 Sat>
* TODO 60 Make book notes
  SCHEDULED: <2007-12-09 Sun>
* TODO 30 Start on my letter for 2007
  SCHEDULED: <2007-12-08 Sat>
* TODO 60 Follow up with DemoCamp contacts
  SCHEDULED: <2007-12-08 Sat>
  DEADLINE: <2007-12-09 Sun>
* TODO 60 Respond to mail
  SCHEDULED: <2007-12-08 Sat>

Then my custom agenda view looks like this:

Day-agenda:
Saturday   8 December 2007
  6:00......  --------------------
  8:00......  --------------------
 10:00......  --------------------
 12:00......  --------------------
 14:00......  --------------------
 14:00-17:15  Scheduled:  TODO Take another driving lesson - emergency stuff
 16:00......  --------------------
 18:00......  --------------------
 20:00......  --------------------
 22:00......  --------------------
              In   1 d.:  TODO 60 Follow up with DemoCamp contacts
              Scheduled:  TODO 15 Announce tea party
              Scheduled:  TODO 60 Write blog post about tasks
              Scheduled:  TODO 30 Start on my letter for 2007
              Scheduled:  TODO 60 Follow up with DemoCamp contacts
              Scheduled:  TODO 60 Respond to mail
              In 937 d.:  101 things in 1001 days
62.7% load: 225 minutes to be scheduled, 359 minutes free, 134 minutes gap

I’ll need to figure out over the next few weeks what kind of a load
threshold is good (you really don’t want to try for 100%), but at
least it’s visible!

(setq org-agenda-custom-commands
      '(("i" "My agenda"
         ((org-agenda-list nil nil 1)
          (sacha/org-load)))
        ;; ... other stuff goes here
      ))

(defun sacha/org-show-load ()
  "Show my unscheduled time and free time for the day."
  (interactive)
  (let ((time (sacha/org-calculate-free-time
               ;; today
               (calendar-gregorian-from-absolute (time-to-days (current-time)))
               ;; now
               (let* ((now (decode-time))
                      (cur-hour (nth 2 now))
                      (cur-min (nth 1 now)))
                 (+ (* cur-hour 60) cur-min))
               ;; until the last time in my time grid
               (let ((last (car (last (elt org-agenda-time-grid 2)))))
                 (+ (* (/ last 100) 60) (% last 100))))))
    (message "%.1f%% load: %d minutes to be scheduled, %d minutes free, %d minutes gap"
            (/ (car time) (* .01 (cdr time)))
            (car time)
            (cdr time)
            (- (cdr time) (car time)))))

(defun sacha/org-load (match)
  "Can be included in `org-agenda-custom-commands'."
  (let ((inhibit-read-only t)
        (time (sacha/org-calculate-free-time
               ;; today
               (calendar-gregorian-from-absolute org-starting-day)
               ;; now if today, else start of day
               (if (= org-starting-day
                      (time-to-days (current-time)))
                   (let* ((now (decode-time))
                          (cur-hour (nth 2 now))
                          (cur-min (nth 1 now)))
                     (+ (* cur-hour 60) cur-min))
                 (let ((start (car (elt org-agenda-time-grid 2))))
                   (+ (* (/ start 100) 60) (% start 100))))
                 ;; until the last time in my time grid
               (let ((last (car (last (elt org-agenda-time-grid 2)))))
                 (+ (* (/ last 100) 60) (% last 100))))))
    (goto-char (point-max))
    (insert (format
             "%.1f%% load: %d minutes to be scheduled, %d minutes free, %d minutes gap"
             (/ (car time) (* .01 (cdr time)))
             (car time)
             (cdr time)
             (- (cdr time) (car time))))))

(defun sacha/org-calculate-free-time (date start-time end-of-day)
  "Return a cons cell of the form (TASK-TIME . FREE-TIME) for DATE, given START-TIME and END-OF-DAY.
DATE is a list of the form (MONTH DAY YEAR).
START-TIME and END-OF-DAY are the number of minutes past midnight."
  (save-window-excursion
  (let ((files org-agenda-files)
        (total-unscheduled 0)
        (total-gap 0)
        file
        rtn
        rtnall
        entry
        (last-timestamp start-time)
        scheduled-entries)
    (while (setq file (car files))
      (catch 'nextfile
        (org-check-agenda-file file)
        (setq rtn (org-agenda-get-day-entries file date :scheduled :timestamp))
        (setq rtnall (append rtnall rtn)))
      (setq files (cdr files)))
    ;; For each item on the list
    (while (setq entry (car rtnall))
      (let ((time (get-text-property 1 'time entry)))
        (cond
         ((and time (string-match "\\([^-]+\\)-\\([^-]+\\)" time))
          (setq scheduled-entries (cons (cons
                                         (save-match-data (appt-convert-time (match-string 1 time)))
                                         (save-match-data (appt-convert-time (match-string 2 time))))
                                        scheduled-entries)))
         ((and time
               (string-match "\\([^-]+\\)\\.+" time)
               (string-match "^[A-Z]+ \\([0-9]+\\)" (get-text-property 1 'txt entry)))
          (setq scheduled-entries
                (let ((start (and (string-match "\\([^-]+\\)\\.+" time)
                                 (appt-convert-time (match-string 1 time)))))
                  (cons (cons start
                              (and (string-match "^[A-Z]+ \\([0-9]+\\)" (get-text-property 1 'txt entry))
                                   (+ start (string-to-number (match-string 1 (get-text-property 1 'txt entry))))))
                        scheduled-entries))))
         ((string-match "^[A-Z]+ \\([0-9]+\\)" (get-text-property 1 'txt entry))
          (setq total-unscheduled (+ (string-to-number
                                      (match-string 1 (get-text-property 1 'txt entry)))
                                     total-unscheduled)))))
      (setq rtnall (cdr rtnall)))
    ;; Sort the scheduled entries by time
    (setq scheduled-entries (sort scheduled-entries (lambda (a b) (< (car a) (car b)))))

    (while scheduled-entries
      (let ((start (car (car scheduled-entries)))
            (end (cdr (car scheduled-entries))))
      (cond
       ;; are we in the middle of this timeslot?
       ((and (>= last-timestamp start)
             (<= last-timestamp end))
        ;; move timestamp later, no change to time
        (setq last-timestamp end))
       ;; are we completely before this timeslot?
       ((< last-timestamp start)
        ;; add gap to total, skip to the end
        (setq total-gap (+ (- start last-timestamp) total-gap))
        (setq last-timestamp end)))
      (setq scheduled-entries (cdr scheduled-entries))))
    (if (< last-timestamp end-of-day)
        (setq total-gap (+ (- end-of-day last-timestamp) total-gap)))
    (cons total-unscheduled total-gap))))

On Technorati: , , ,

Random Emacs symbol: select-safe-coding-system-function – Variable: Function to call to select safe coding system for encoding a text.

A day in a life with Org

I spend most of my day working on or near a computer: writing,
replying to e-mail, making phone calls, and so on. I use Lotus Notes
for my calendar because people need to be able to check my
availability for meetings. I use Emacs to keep track of what I need to
do, because it makes planning my day so much easier.

The first thing I do each morning is quickly go through my e-mail
looking for action items. Instead of leaving them in my mail inbox, I
create tasks for each of the items in my Org to-do list. I add notes
so that I don’t have to find the e-mails again. I also add other tasks
that come to mind. I add time estimates whenever I can.

This step is also a good time to review my personal objectives and
proactively set myself some tasks so that I can move towards them. For
example, if I want to learn more about career growth, I can’t wait for
e-mail from someone else telling me what to do. I have to think of
something to do, and build time into my day in order to do it. I put
all those tasks into my task inbox, which is just a header at the
bottom of my task list, like this:

(remove the leading space)

 * Inbox
 ** TODO ....
 ** TODO ....

Now that I’ve captured all these tasks, I review my day. What are my
appointments? What items are due today? I double-check this against
my official calendar to make sure I haven’t missed any
appointments. After I make sure that the important tasks and
appointments are there, I start filling in gaps, scheduling some of my
important-but-not-urgent tasks onto today.

After I’ve decided what to do that day, I review the rest of the
week. Does my workload look reasonable? Are there upcoming deadlines?
I try to make sure that all of my inbox items have scheduled dates. I
also review my list of waiting tasks to see if I need to follow up
with anyone.

After I’ve gotten the tasks all down and scheduled, it’s easy to
organize them under the appropriate headings. Billable tasks are filed
under the projects they belong to, and unbilled tasks are categorized
by how I need to report them and how I organize them into personal
projects. Organizing tasks into categories AFTER I schedule them means
less jumping around looking for unscheduled tasks.

This process (e-mail scan and daily and weekly overview) takes me
around 15 minutes, and helps keep me sane.

I try to keep my mornings free for creative brainstorming and heavy
lifting. Once I’ve reviewed my plans for the day and the week, I pick
a task and work on it for an hour or so. When I mark the task as
STARTED (“t” or “C-u t” from the Org agenda view), the clock
automatically starts ticking. When I mark the task as WAITING or DONE,
the clock automatically stops. Org timeclocking makes it easier for me
to report my hours at the end of each week. I can also compare the
actual times against my estimates, helping me improve my accuracy.

This process is my morning ritual: putting tasks into my Org agenda,
organizing them, reviewing and planning from my calendar, and then
getting started by working on something useful _before_ I spend time
catching up with the blogosphere or responding to my mail. It’s
complemented by my afternoon ritual of reviewing my completed tasks
with the Org agenda logbook and possibly blogging about some lessons
learned.

Here’s how you can use Org to do the same, assuming that you’ve set it
up already.

Morning ritual:

*Read your e-mail and create tasks.* Open your Org file. If it’s not yet in your Org agenda list, add it with C-c [ (org-agenda-file-to-front).

You can jump to the end of the file using M-> (end-of-buffer) and
add tasks just by typing “** TODO ” and the task name. If you read
e-mail in Emacs (and there are plenty of good reasons to do so!), you
can set up Remember Mode to make it easy to create hyperlinked tasks
from mail and other sources. Use C-c C-d (org-deadline) to note
deadlines for the current task, and use C-c C-s (org-schedule) to note
when a task needs to be done on a certain date.

*Review your projects and create tasks.* Tag projects like this:

 ** Learn about career options within the company     :PROJECT:

Then you can use a custom agenda view to see your agenda for today, your projects, and other useful information.
Here’s something you can add to your ~/.emacs:

(global-set-key (kbd "C-c a") 'org-agenda)
(setq org-agenda-custom-commands
      '(("a" "My custom agenda"
	 ((org-agenda-list nil nil 1)
	  (tags "PROJECT-WAITING")
	  (tags-todo "WAITING")
	  (tags-todo "-MAYBE")))))

You can then use C-c a a (org-agenda, custom command) to get an overview of your day/week, your
current projects, your WAITING tasks, and your active tasks.

*Review your day.* Use C-c a a (org-agenda, custom command) to see
your appointments for the day, and open your Org file in another
buffer. Use C-c C-s (org-schedule) in your Org file to schedule some
of your inbox tasks for the day and some of your tasks for other days
in the week. You can use Shift-right and Shift-left to reschedule
tasks from the agenda view. Use “w” in the agenda to switch to a
weekly view, and “d” to switch to a daily view.

If you want to see how your time estimates fit into your workday with
a load estimate like this:

15.8% load: 90 minutes to be scheduled, 570 minutes free, 480 minutes gap

add estimated number of minutes to your tasks like this:

** TODO 60 Browse through a book
** TODO 15 Scan my RSS feeds

and use the following code in your ~/.emacs:

(defun sacha/org-show-load ()
  "Show my unscheduled time and free time for the day."
  (interactive)
  (let ((time (sacha/org-calculate-free-time
               ;; today
               (calendar-gregorian-from-absolute (time-to-days (current-time)))
               ;; now
               (let* ((now (decode-time))
                      (cur-hour (nth 2 now))
                      (cur-min (nth 1 now)))
                 (+ (* cur-hour 60) cur-min))
               ;; until the last time in my time grid
               (let ((last (car (last (elt org-agenda-time-grid 2)))))
                 (+ (* (/ last 100) 60) (% last 100))))))
    (message "%.1f%% load: %d minutes to be scheduled, %d minutes free, %d minutes gap\n"
            (/ (car time) (* .01 (cdr time)))
            (car time)
            (cdr time)
            (- (cdr time) (car time)))))

(defun sacha/org-agenda-load (match)
  "Can be included in `org-agenda-custom-commands'."
  (let ((inhibit-read-only t)
        (time (sacha/org-calculate-free-time
               ;; today
               (calendar-gregorian-from-absolute org-starting-day)
               ;; now if today, else start of day
               (if (= org-starting-day
                      (time-to-days (current-time)))
                   (let* ((now (decode-time))
                          (cur-hour (nth 2 now))
                          (cur-min (nth 1 now)))
                     (+ (* cur-hour 60) cur-min))
                 (let ((start (car (elt org-agenda-time-grid 2))))
                   (+ (* (/ start 100) 60) (% start 100))))
                 ;; until the last time in my time grid
               (let ((last (car (last (elt org-agenda-time-grid 2)))))
                 (+ (* (/ last 100) 60) (% last 100))))))
    (goto-char (point-max))
    (insert (format
             "%.1f%% load: %d minutes to be scheduled, %d minutes free, %d minutes gap\n"
             (/ (car time) (* .01 (cdr time)))
             (car time)
             (cdr time)
             (- (cdr time) (car time))))))

(defun sacha/org-calculate-free-time (date start-time end-of-day)
  "Return a cons cell of the form (TASK-TIME . FREE-TIME) for DATE, given START-TIME and END-OF-DAY.
DATE is a list of the form (MONTH DAY YEAR).
START-TIME and END-OF-DAY are the number of minutes past midnight."
  (save-window-excursion
  (let ((files org-agenda-files)
        (total-unscheduled 0)
        (total-gap 0)
        file
        rtn
        rtnall
        entry
        (last-timestamp start-time)
        scheduled-entries)
    (while (setq file (car files))
      (catch 'nextfile
        (org-check-agenda-file file)
        (setq rtn (org-agenda-get-day-entries file date :scheduled :timestamp))
        (setq rtnall (append rtnall rtn)))
      (setq files (cdr files)))
    ;; For each item on the list
    (while (setq entry (car rtnall))
      (let ((time (get-text-property 1 'time entry)))
        (cond
         ((and time (string-match "\\([^-]+\\)-\\([^-]+\\)" time))
          (setq scheduled-entries (cons (cons
                                         (save-match-data (appt-convert-time (match-string 1 time)))
                                         (save-match-data (appt-convert-time (match-string 2 time))))
                                        scheduled-entries)))
         ((and time
               (string-match "\\([^-]+\\)\\.+" time)
               (string-match "^[A-Z]+ \\(\\[#[A-Z]\\]\\)? \\([0-9]+\\)" (get-text-property 1 'txt entry)))
          (setq scheduled-entries
                (let ((start (and (string-match "\\([^-]+\\)\\.+" time)
                                 (appt-convert-time (match-string 1 time)))))
                  (cons (cons start
                              (and (string-match "^[A-Z]+ \\(\\[#[A-Z]\\]\\)? \\([0-9]+\\) " (get-text-property 1 'txt entry))
                                   (+ start (string-to-number (match-string 2 (get-text-property 1 'txt entry))))))
                        scheduled-entries))))
         ((string-match "^[A-Z]+ \\([0-9]+\\)" (get-text-property 1 'txt entry))
          (setq total-unscheduled (+ (string-to-number
                                      (match-string 1 (get-text-property 1 'txt entry)))
                                     total-unscheduled)))))
      (setq rtnall (cdr rtnall)))
    ;; Sort the scheduled entries by time
    (setq scheduled-entries (sort scheduled-entries (lambda (a b) (< (car a) (car b)))))

    (while scheduled-entries
      (let ((start (car (car scheduled-entries)))
            (end (cdr (car scheduled-entries))))
      (cond
       ;; are we in the middle of this timeslot?
       ((and (>= last-timestamp start)
             (< = last-timestamp end))
        ;; move timestamp later, no change to time
        (setq last-timestamp end))
       ;; are we completely before this timeslot?
       ((< last-timestamp start)
        ;; add gap to total, skip to the end
        (setq total-gap (+ (- start last-timestamp) total-gap))
        (setq last-timestamp end)))
      (setq scheduled-entries (cdr scheduled-entries))))
    (if (< last-timestamp end-of-day)
        (setq total-gap (+ (- end-of-day last-timestamp) total-gap)))
    (cons total-unscheduled total-gap))))

Then you can add it to your custom agenda by using this in your ~/.emacs:

;; Change your existing org-agenda-custom-commands
(setq org-agenda-custom-commands
      '(("a" "My custom agenda"
	 ((org-agenda-list nil nil 1)
          (sacha/org-agenda-load)    ; ADD THIS LINE
	  (tags "PROJECT-WAITING")
	  (tags-todo "WAITING")
	  (tags-todo "-MAYBE")))))

*Organize your inbox.* Now that you’ve scheduled your tasks, move them
under the appropriate headings. You can use TAB to collapse a task
into a single line, then C-k (kill-line) to cut it and C-y to paste it
elsewhere. I like using C-r (isearch-backward) to search for the right
place in the file.

*Get to work!* You may find it useful to have four states for a task: TODO, STARTED, WAITING, and DONE.
It’s also handy to type in a note when you mark a task as done. To set that up, just add the following to the beginning of your Org file:

#+STARTUP: lognotedone
#+SEQ_TODO: TODO STARTED WAITING DONE

Then you can use “t” (org-todo) from the Org agenda view or C-c C-t
(org-todo) from the Org file to mark a TODO task as STARTED, or to
move from one state to the other. To move to a specific state (DONE
from STARTED, for example), either edit it directly or use C-u before
the org-todo command.

Use the following code to automatically clock in when you start a
task, start a task when you clock in, and clock out of a task when you
mark it as waiting.

(defun sacha/org-clock-in-if-starting ()
  "Clock in when the task is marked STARTED."
  (when (and (string= state "STARTED")
             (not (string= last-state state)))
    (org-clock-in)))
(add-hook 'org-after-todo-state-change-hook
	  'sacha/org-clock-in-if-starting)
(defadvice org-clock-in (after sacha activate)
  "Set this task's status to 'STARTED'."
  (org-todo "STARTED"))

(defun sacha/org-clock-out-if-waiting ()
  "Clock in when the task is marked STARTED."
  (when (and (string= state "WAITING")
             (not (string= last-state state)))
    (org-clock-out)))
(add-hook 'org-after-todo-state-change-hook
	  'sacha/org-clock-out-if-waiting)

*Review your accomplishments at the end of the day.* You can use the
Org agenda logbook to see all your completed tasks. From an Org agenda
view such as the custom one you set up for C-c a a, type “l”
(lowercase L). You can then see your completed TODOs.

To review your time usage, you can use C-c C-x C-d (org-clock-display)
from an Org buffer to see time totals according to the tree, or you
can add a table to your custom agenda view. Add the following to your
~/.emacs:

(defun sacha/org-agenda-clock (match)
  ;; Find out when today is
  (let* ((inhibit-read-only t))
    (goto-char (point-max))
    (org-dblock-write:clocktable
     `(:scope agenda
       :maxlevel 4
       :tstart ,(format-time-string "%Y-%m-%d" (calendar-time-from-absolute (1+ org-starting-day) 0))
       :tend ,(format-time-string "%Y-%m-%d" (calendar-time-from-absolute (+ org-starting-day 2) 0))))))

and then add sacha/org-agenda-clock to your custom agenda in
org-agenda-custom-commands in your ~/.emacs file, like this:

;; Change your existing org-agenda-custom-commands
(setq org-agenda-custom-commands
      '(("a" "My custom agenda"
	 ((org-agenda-list nil nil 1)
          (sacha/org-agenda-load)
          (sacha/org-agenda-clock)    ; Add this line
	  (tags "PROJECT-WAITING")
	  (tags-todo "WAITING")
	  (tags-todo "-MAYBE")))))

You can then use C-c a a (org-agenda, custom command) to see a table summarizing your clocked-in time for that day.

END RESULT: You can add tasks, quickly get an overview of your day and
week, reschedule tasks until you’ve got a realistic load, keep track
of your progress, and review your accomplishments.

Org keeps me sane. =) The code above only looks like a lot of customization, but it’s well worth it.

Next, I’m going to figure out how to calculate my velocity, or estimated time divided by actual time taken… =)

(Thanks to Pete Bevin for catching a typo! =) )

On Technorati: , , , ,

Random Emacs symbol: floor – Function: Return the largest integer no greater than ARG.

Publishing my Org agenda to my blog

Some people like reading my task list.

No, I don’t know why, either. =)

But it’s up again, just in case you want to see it. This one is based
on Org-mode for Emacs, so it’s not the same task list that used to
show up on my Planner wiki.

Expect this to change a lot as I figure out how I want it to fit in.
The downside of using WordPress as my front-end is that it looks like
it’s going to be difficult to get the kind of day view I have with my
Planner version. How
do I get it to display future pages?

I may end up writing yet another layer on top of this… =(

Anyway, here’s my highly idiosyncratic config, just in case you want
to get started hacking this onto your system:

(defvar sacha/org-publish-agenda-directory "~/notebook/org/" "*Directory to save the published agenda to.")
(org-defkey org-agenda-mode-map  "p" 'sacha/org-publish-agenda)
(defun sacha/org-publish-agenda ()
  "Copy the agenda buffer to a file in `sacha/org-publish-agenda-directory'."
  (interactive)
  ;; Take the entire contents of the agenda and dump it into a text file labeled with the date.
  (let ((agenda (with-current-buffer org-agenda-buffer-name
                  (unless org-agenda-show-log (org-agenda-log-mode))
                  (buffer-string)))
        (filename (format-time-string "%Y-%m-%d.txt" (if org-starting-day (calendar-time-from-absolute (1+ org-starting-day) 0)
                                                       (current-time)))))
    (with-temp-buffer
      (insert agenda)
      (write-file (expand-file-name filename
                                    sacha/org-publish-agenda-directory)))))

(defun sacha/org-publish-agenda-today (interactive)
  "Publish today's agenda. Suitable for ~/.emacs, we hope."
  (let ((entry (assoc "a" org-agenda-custom-commands)))
    (if entry
        (org-run-agenda-series (nth 1 entry) (cddr entry))
      (call-interactively 'org-agenda-list))
  (sacha/org-publish-agenda)))

On Technorati: , ,

Random Emacs symbol: hack-local-variables – Function: Parse and put into effect this buffer’s local variables spec.