Category Archives: org

Rediscovering Emacs features, or what to do after you get carried away installing packages

A kid in a candy store – that’s me with M-x list-packages, EmacsWiki pages, Planet Emacsen, and other sources of Emacs goodness. Because Emacs has so much functionality and people keep adding stuff to it, it’s easy to forget about the cool goodies in configuration files and the Emacs codeverse. It’s important to practise and review, though, because there are all sorts of great keyboard shortcuts and commands that could make Emacs even better if I could just drill them into my brain.

Spaced repetition is a great technique for prioritizing and learning things. Emacs Org has an org-drill module that implements flashcards for Org headings that are tagged with :drill:. I’ve been using this to prepare for the Canadian citizenship exam, and that’s been working out well. So I started creating an emacs-drill.org file with headings for the things I’m interested in learning, such as multiple-cursor-mode and ace-jump-mode…

… And then I remembered, hey, my Emacs configuration is one big Org file (thanks to the joys of literate programming) so why don’t I just stick the :drill: tag onto the relevant snippets and run M-x org-drill there?

This might actually work out. =)

I was thinking of doing some kind of idle-timer hook, but I actually don’t mind manually triggering it. Besides, I’m experimenting with John Wiegley’s org-agenda display paired with winner-mode to save my window configuration.

Come to think of it, it might be good to add a random Emacs keybinding to the org-agenda display. I’ve installed keywiz, so I can reuse some of the code from that:

(use-package keywiz)
(defun sacha/load-keybindings ()
  "Since we don't want to have to pass through a keywiz game each time..."
  (setq keywiz-cached-commands nil)
  (do-all-symbols (sym)
    (when (and (commandp sym)
               (not (memq sym '(self-insert-command
                                digit-argument undefined))))
      (let ((keys (apply 'nconc (mapcar
                                 (lambda (key)
                                   (when (keywiz-key-press-event-p key)
                                     (list key)))
                                 (where-is-internal sym)))))
        ;;  Politically incorrect, but clearer version of the above:
        ;;    (let ((keys (delete-if-not 'keywiz-key-press-event-p
        ;;                               (where-is-internal sym))))
        (and keys
             (push (list sym keys) keywiz-cached-commands)))))))
  (sacha/load-keybindings)
  ;; Might be good to use this in org-agenda...
  (defun sacha/random-keybinding ()
    "Describe a random keybinding."
    (let* ((command (keywiz-random keywiz-cached-commands))
         (doc (and command (documentation (car command)))))
      (if command
          (concat (symbol-name (car command)) " "
                  "(" (mapconcat 'key-description (cadr command) ", ") ")"
                  (if doc
                      (concat ": " (substring doc 0 (string-match "\n" doc)))
                    ""))
"")))

… and a minor adjustment to org-agenda-custom-commands…

(defun sacha/org-agenda-with-tip (arg) (org-agenda-list arg) (let ((inhibit-read-only t)) (insert (sacha/random-keybinding) “\n”))) (setq org-agenda-custom-commands `((“a” “Agenda” sacha/org-agenda-with-tip) (“T” todo-tree “TODO”)
;; more here; see my config file
)))

… and now I see a random Emacs keybinding every time I review my to-do list.

agenda-tip

If you find yourself forgetting to revisit the nifty Emacs snippets you’ve added to your configuration, add reminders for yourself. Make yourself some flashcards with org-drill.el or flashcard.el and give that a try, or integrate reminders into your workflow. Have fun!

Emacs Org: Task-related keyboard shortcuts for the agenda

I really love the way you can tweak Emacs’ keyboard shortcuts and functionality to fit the way you want to work. Here are three keyboard shortcuts I’ve added to my Org agenda to make it even easier to work with tasks.

x: Mark the current task as done. Same as typing t x, but somehow it feels like it has more oomph as a single-character shortcut.

X: Mark the current task as done and create a new task at the same level, taking advantage of the task template I’d previously created in org-capture-templates.

N: Create a new note or task at the current position.

Make it easy to mark a task as done

(defun sacha/org-agenda-done (&optional arg)
  "Mark current TODO as done.
This changes the line at point, all other lines in the agenda referring to
the same tree node, and the headline of the tree node in the Org-mode file."
  (interactive "P")
  (org-agenda-todo "DONE"))
;; Override the key definition for org-exit
(define-key org-agenda-mode-map "x" 'sacha/org-agenda-done)

Make it easy to mark a task as done and create a follow-up task

  (defun sacha/org-agenda-mark-done-and-add-followup ()
    "Mark the current TODO as done and add another task after it.
Creates it at the same level as the previous task, so it's better to use
this with to-do items than with projects or headings."
    (interactive)
    (org-agenda-todo "DONE")
    (org-agenda-switch-to)
    (org-capture 0 "t"))
;; Override the key definition
(define-key org-agenda-mode-map "X" 'sacha/org-agenda-mark-done-and-add-followup)

Capture something based on the agenda position

(defun sacha/org-agenda-new ()
  "Create a new note or task at the current agenda item.
Creates it at the same level as the previous task, so it's better to use
this with to-do items than with projects or headings."
  (interactive)
  (org-agenda-switch-to)
  (org-capture 0))
;; New key assignment
(define-key org-agenda-mode-map "N" 'sacha/org-agenda-new)

Check out my Emacs configuration for other ideas.

Emacs Org: Display a subset of tasks by context

I wanted to get a quick preview of my top three tasks by context. Since org-tags-view didn’t seem to have a built-in way to limit the
number of displayed items, I used defadvice to add my own. Here’s the relevant code from my Emacs configuration:

(defvar sacha/org-agenda-limit-items nil "Number of items to show in agenda to-do views; nil if unlimited.")
(defadvice org-agenda-finalize-entries (around sacha activate)
  (if sacha/org-agenda-limit-items
      (progn
        (setq list (mapcar 'org-agenda-highlight-todo list))
        (if nosort
          (setq ad-return-value
            (subseq list 0 sacha/org-agenda-limit-items))
          (when org-agenda-before-sorting-filter-function
            (setq list (delq nil (mapcar org-agenda-before-sorting-filter-function list))))
          (setq ad-return-value
                (mapconcat 'identity
                           (subseq
                            (sort list 'org-entries-lessp)
                            0
                            sacha/org-agenda-limit-items)
                           "\n"))))
    ad-do-it))

and the snippet from my org-agenda-custom-commands:

(setq org-agenda-custom-commands
  '(
    ;; ... other commands go here
    ("0" "Block agenda"
         ((tags-todo "+@phone")
          (tags-todo "+@work")
          (tags-todo "+@drawing")
          (tags-todo "+@coding")
          (tags-todo "+@writing")
          (tags-todo "+@computer")
          (tags-todo "+@home"))
         ((org-agenda-sorting-strategy '(priority-up effort-down))
          (sacha/org-agenda-limit-items 3)))
        (")" "Block agenda"
         ((tags-todo "+@phone")
          (tags-todo "+@work")
          (tags-todo "+@drawing")
          (tags-todo "+@coding")
          (tags-todo "+@writing")
          (tags-todo "+@computer")
          (tags-todo "+@home"))
         ((org-agenda-sorting-strategy '(priority-down effort-down))
          (sacha/org-agenda-limit-items nil)))
        ("9" "Unscheduled by context"
         ((tags-todo "+@phone")
          (tags-todo "+@work")
          (tags-todo "+@drawing")
          (tags-todo "+@coding")
          (tags-todo "+@writing")
          (tags-todo "+@computer")
          (tags-todo "+@home"))
         ((org-agenda-skip-function
           (lambda nil
             (org-agenda-skip-entry-if (quote scheduled) (quote deadline)
                                       (quote regexp) "\n]+>")))
          (org-agenda-sorting-strategy '(priority-down effort-down))
          (sacha/org-agenda-limit-items 3)))
    ;; ... more after this
))

This way, I can see all of my common contexts on one screen, and I can decide what I want to work on first.

Emacs: Strike through headlines for DONE tasks in Org

I wanted a quick way to visually distinguish DONE tasks from tasks I still need to do. This handy snippet from the Emacs Org-mode mailing list does the trick by striking through the headlines for DONE tasks.

image

Here’s the code:

(setq org-fontify-done-headline t)
(custom-set-faces
 '(org-done ((t (:foreground "PaleGreen"   
                 :weight normal
                 :strike-through t))))
 '(org-headline-done 
            ((((class color) (min-colors 16) (background dark)) 
               (:foreground "LightSalmon" :strike-through t)))))

View my Emacs configuration

Transcript: Emacs chat with John Wiegley

This post is long, so if you’re reading this on the main page, go to http://sachachua.com/blog/2012/07/transcript-emacs-chat-john-wiegley/ to view the full transcript!

[Read more →]

Using Emacs Org for grocery lists and batch cooking

We like preparing our meals in bulk. Buying groceries and cooking up a storm on the weekends means that we can grab quick and healthy lunches from the fridge or freezer, enjoy a variety of dinners during the week, and focus on other things that we want to do in the evenings.

I was looking for a menu planner and grocery list maker to help us plan and execute these batch cooking sessions more efficiently. In particular, I wanted something that could sort the ingredients for preparation, too. I like preparing ingredients for all the different recipes before I start cooking. If several recipes call for garlic, I might as well chop a lot of garlic in one session instead of breaking out the chopping board for each recipe.

I tried several menu planning and grocery list apps, but I wasn’t happy with any of the ones I came across. I like using Emacs for as much as possible, so I figured that I should give it a try. Here’s what I did and how it worked out.

I created an Org file for my recipes. In this plain-text outline, I created sections for my plan, shopping list, preparation tasks, and recipes. Under recipes, I created TODO items and scheduled them. Here’s an example entry:

** TODO Colorful bulgur salad
   SCHEDULED: <2012-06-19 Tue>

http://allrecipes.com/recipe/colorful-bulgur-salad/

| 1/2 cup        | bulgur wheat     |                    | [[Colorful bulgur salad]] |
| 1/2 cup        | chicken broth    |                    | [[Colorful bulgur salad]] |
| 1 small        | cucumber         | seeded and chopped | [[Colorful bulgur salad]] |
| 1              | tomato           | chopped            | [[Colorful bulgur salad]] |
| 1              | carrot           | shredded           | [[Colorful bulgur salad]] |
| 3              | green onions     | thinly sliced      | [[Colorful bulgur salad]] |
| 3 tablespoons  | fresh lime juice |                    | [[Colorful bulgur salad]] |
| 3/4 tablespoon | chili powder     |                    | [[Colorful bulgur salad]] |
| 1 pinch        | garlic powder    |                    | [[Colorful bulgur salad]] |

I reformatted each recipe to fit this format, with columns for quantity, type, preparation, and recipe link. After I chose several recipes, I copied the ingredient lists into my preparation section and my shopping section. In the shopping section, I deleted the lines for ingredients I already had or could skip. I used org-table-sort-lines to sort the table by the second column, which gave me this list:

| 1 bag              | chicken legs and thighs |                                                        | [[Arroz caldo]] |
| 2 small or 1 large | cucumber                | chopped                                                | [[Gazpacho]] |
| 1 small            | cucumber                | seeded and chopped                                     | [[Colorful bulgur salad]] |
| 3                  | green onions            | thinly sliced                                          | [[Colorful bulgur salad]] |
| 1                  | red onion               | cut into 1" pieces                                     | [[Shrimp kebabs]] |
| 1 pound            | shrimp                  | peeled and deveined                                    | [[Shrimp kebabs]] |
| 6 - 8              | tomatoes                | chopped (Roma or plum are best; Don't lose the juice!) | [[Gazpacho]] |
| 1                  | zucchini                | seeded and cut into 1" pieces                          | [[Shrimp kebabs]] |

It wasn’t sorted by aisle, but that was easy to do when I copied the list onto a recycled envelope. If I find myself using this a lot, I might write an Emacs Lisp function to gather the tables and sort the rows by aisle.

Anyway, shopping list in hand, we picked up our groceries in about ten minutes last Saturday. The next day, I looked at my prep list:

|                    | basil                                  | chopped                                                | [[Gazpacho]]              |
| 1/2 cup            | bulgur wheat                           |                                                        | [[Colorful bulgur salad]] |
| 1 tbsp             | butter                                 |                                                        | [[Bubble and squeak]]     |
| 2 tbsp             | canola or peanut oil                   |                                                        | [[Teriyaki tofu]]         |
| 1                  | carrot                                 | shredded                                               | [[Colorful bulgur salad]] |
| 1/2 cup            | chicken broth                          |                                                        | [[Colorful bulgur salad]] |
| 1 bag              | chicken legs and thighs                | separated                                              | [[Arroz caldo]]           |
| 3/4 tablespoon     | chili powder                           |                                                        | [[Colorful bulgur salad]] |
| 1/4 cup            | cider vinegar                          |                                                        | [[Teriyaki tofu]]         |
| 1 can              | corned beef                            |                                                        | [[Bubble and squeak]]     |
| 3 tbsp             | cornstarch                             |                                                        | [[Teriyaki tofu]]         |
| 1 tbsp             | cornstarch                             |                                                        | [[Teriyaki tofu]]         |
| 1 small            | cucumber                               | seeded and chopped                                     | [[Colorful bulgur salad]] |
| 2 small or 1 large | cucumber                               | chopped                                                | [[Gazpacho]]              |
| 1 lb               | firm tofu                              | drained                                                | [[Teriyaki tofu]]         |
|                    | fresh ground black pepper              |                                                        | [[Gazpacho]]              |
| 3 tablespoons      | fresh lime juice                       |                                                        | [[Colorful bulgur salad]] |
| 3 cloves           | garlic                                 | chopped                                                | [[Arroz caldo]]           |
| 1 clove            | garlic                                 | minced                                                 | [[Teriyaki tofu]]         |
| 2 cloves           | garlic                                 | diced                                                  | [[Gazpacho]]              |
| 1 tablespoon       | garlic                                 | minced                                                 | [[Shrimp kebabs]]         |
| 1 pinch            | garlic powder                          |                                                        | [[Colorful bulgur salad]] |
|                    | glutinous rice                         |                                                        | [[Arroz caldo]]           |
| 1 tsp ginger       | grated or minced                       |                                                        | [[Teriyaki tofu]]         |
|                    | green onions                           | chopped                                                | [[Arroz caldo]]           |
| 3                  | green onions                           | thinly sliced                                          | [[Colorful bulgur salad]] |
|                    | leftover vegetables (cabbage, carrots) |                                                        | [[Bubble and squeak]]     |
| 1                  | lemon                                  | juice of                                               | [[Gazpacho]]              |
| 2 teaspoons        | lemon juice                            |                                                        | [[Shrimp kebabs]]         |
| 1/4 cup            | olive oil                              |                                                        | [[Shrimp kebabs]]         |
| 1                  | onion                                  | thinly sliced                                          | [[Bubble and squeak]]     |
| 1/2 large          | onion                                  | chopped finely       (red is a nice alternative)       | [[Gazpacho]]              |
| 1/2 large          | onion                                  | chopped in 1/4 inch chunks                             | [[Gazpacho]]              |
| pinch              | parsley                                | finely chopped                                         | [[Shrimp kebabs]]         |
| 1/4 tsp            | pepper                                 |                                                        | [[Teriyaki tofu]]         |
| 1/4 teaspoon       | pepper                                 |                                                        | [[Shrimp kebabs]]         |
| 3 cups             | potatoes                               | mashed                                                 | [[Bubble and squeak]]     |
| 1                  | red onion                              | cut into 1" pieces                                     | [[Shrimp kebabs]]         |
|                    | salt (preferably sea salt)             |                                                        | [[Gazpacho]]              |
| 1 tsp              | sesame oil                             |                                                        | [[Teriyaki tofu]]         |
| 1 pound            | shrimp                                 | peeled and deveined                                    | [[Shrimp kebabs]]         |
|                    | soy sauce                              |                                                        | [[Arroz caldo]]           |
| 1/2 cup            | soy sauce                              |                                                        | [[Teriyaki tofu]]         |
| 1                  | tomato                                 | chopped                                                | [[Colorful bulgur salad]] |
| 6 - 8              | tomatoes                               | chopped (Roma or plum are best; Don't lose the juice!) | [[Gazpacho]]              |
|                    | virgin olive oil                       |                                                        | [[Gazpacho]]              |
| 1/2 cup            | white sugar                            |                                                        | [[Teriyaki tofu]]         |
| 1                  | zucchini                               | seeded and cut into 1" pieces                          | [[Shrimp kebabs]]         |

Sorting the list by ingredient made it easy to go through the groups of ingredients and prepare them all, and the links to the recipes made it easy to look up next steps. I planned the order of doing them. First, I prepared the bulgur wheat because that needed an hour to soak. I saved the chicken legs for the end because they were messy, and I saved the onions for later as well because they always make me cry. I cut and chopped and food-processed my way through stacks of vegetables, covering the kitchen table with bowls.

With all the ingredients prepared, I washed the utensils and put things away. That freed up counter space for cooking. I reordered the recipes so that it was easy to see what to work on next, and I started cooking.

The entire cooking sprint took me 5 hours and 42 minutes, which was a lot of cooking but well worth it. With that and the meals we’d prepared over the past few weeks, our freezer’s stuffed to capacity. Four tidy stacks of identical food containers, then odds and ends crammed into the spaces! By golly.

I really liked planning this batch cooking session in Emacs. Org tables made things easy to sort, and the hyperlinks let me look up recipes and notes quickly.

I could probably make this even better by:

  • rigging up my foot pedal to scroll up and down through food.org
  • copying in the recipe steps so that I can take advantage of that scrolling
  • figuring out how to use Org Babel to automatically compile the ingredient tables for the named recipes

Now if only someone would write M-x wash-dishes