Hippocamplus My Second Memory

Org mode

I’m giving Org mode a try. This page will contain my configuration and the small subset of commands that I want to learn.

Org file

  • Start with MY PROJECTS -*- mode: org; -*-

Configuration

In .emacs file:

(require 'org)
;; Change M-TAB completion to C-TAB
(define-key org-mode-map (kbd "C-<tab>") 'pcomplete)
(setq org-todo-keywords
      '((sequence "TODO" "ONGOING" "CLOCKING" "|" "DONE")))
(global-set-key (kbd "C-c a") 'org-agenda)
(setq org-startup-truncated nil) ;; wrap lines
(setq org-startup-indented 1) ;; heading indentation
(setq org-return-follows-link 1) ;; RET to follow links
(setq org-agenda-start-on-weekday nil) ;; start agenda on current day
(setq calendar-week-start-day 1) ;; but calendar starts on Monday (not Sunday!)
(setq org-catch-invisible-edits nil) ;; block (confusing) invisible edits ("...")
(setq org-enforce-todo-dependencies t) ;; Switch TODO dependencies on
(setq org-agenda-dim-blocked-tasks 'invisible) ;; Hide tasked blocked by dependencies
;; path to org files
(setq org-directory "~/Documents/orgmode")
(setq org-agenda-files (list org-directory))
;; capture
(setq org-default-notes-file (concat org-directory "/notes.org"))
(global-set-key (kbd "C-c c") 'org-capture)

Syntax

  • *bold*, /italic/, _underlined_, +strike-through+.
  • =verbatim=, ~code~.
: simple text, e.g. code source
: respecting line breaks

Keybindings

From anywhere

  • Capture a note: bound to C-c c
  • Open agenda views: bound to C-c a.

Edit mode

  • Reveal context around a point: C-c C-r
  • Completion: changed to C-tab.
  • Move to next/previous heading: C-c C-n/C-c C-p.
  • Move to next/previous same-level heading: C-c C-f/C-c C-b.
  • Move up to higher heading: C-c C-u.
  • Insert a new heading at the end of the current subtree: C-RET.
  • Promote/demote heading: M-LEFT/M-RIGHT.
  • Promote/demote subtree: M-S-LEFT/M-S-RIGHT.
  • Move subtree up/down: M-UP/M-DOWN.
  • Cycle through TODO states: S-RIGHT/S-LEFT.
  • Toggle the sparse tree view: C-c /.
  • Open link: C-c C-o.
  • New/edit link: C-c C-l.
  • Add property field: C-c C-x p.
  • Narrow/widen to subtree: C-x n s/C-x n w.
  • Switch a list to checklist: C-u C-c C-c

Timestamps

  • Insert/edit date: C-c .
  • Insert/edit schedule: C-c C-s.
  • Insert/edit deadline: C-c C-d.
  • Navigate with S-ARROW.
  • Jump to today with ..
  • 10:00+1 means from 10am to 11am.

Repeating events

For example regular meetings

  • Possible to write a timestamp like <2020-03-18 Wed 12:30 +1w>

After using this for some time, I agree with Karl Voit that it’s more practical to duplicate the events instead (helps dealing with exceptional changes, taking notes, keeping a trace once the event stops).

  • C-c C-x c clone an event/task (specify how many times and the time shift)

Agenda views

  • Highlight in file: SPC.
  • Jump to file: TAB.
  • Jump to file and close agenda: RET.
  • Change TODO states with t.
  • Previous/next day/week/month: b/f
  • Jump to a specific date: j.

Capture

  • Finish capture and go back to current buffer: C-c C-c.

TODO entry

*** TODO Do this before the deadline
    SCHEDULED: <2004-02-22 Sun>
    DEADLINE: <2004-02-29 Sun>

Tables

  • C-c C-c format the table. If on a TBLFM: line, recompute the formula.
  • "| " TAB make a new row.
  • "|-" TAB make a line separation.
  • M-RIGHT/M-LEFT move column.
  • M-UP/M-DOWN move row.
  • S-M-RIGHT/S-M-DOWN add new column/row.
  • S-M-LEFT/S-M-UP remove current column/row.
  • C-c } show rows/columns labels.
  • C-c ^ sort rows based on the current column.

An example with a right-aligned column, a field formula and a column formula.

|  <r> |      |      |
| ColA | ColB | ColC |
|------+------+------|
|  tes |   13 |   12 |
|  asd |    3 |    2 |
|    a |   16 |   15 |
|------+------+------|
| mean | 10.7 |  9.7 |
#+TBLFM: $3=$2-1::@>$2=vmean(@3..@-I);p3
  • Start a formula in a cell by typing :=FORMULA and C-c C-c (=FORMULA for column formulas).

  • @> means the last row

  • I to define range relative to the target field, e.g. @-I=row above.

  • A plot line could look like: #+PLOT: title:"graph title" ind:1 deps:(2 3) set:"xlabel 'ColA'"

  • C-c " g to make a plot (requires gnuplot and gnuplot to be installed)

Code block

Can be triggered by C-c C-, s (potentially surrounding a selected region).

A simple code block:

#+NAME: <name>
#+BEGIN_SRC <language>
  <body>
#+END_SRC

See the list of available languages. To switch on syntax highlighting, add to .emacs:

(setq org-src-fontify-natively t)

To enable the evaluation of a language, e.g. R:

(require 'ob-R)
(org-babel-do-load-languages
  'org-babel-load-languages
  '((R . t)))

If it looks like it’s not working, remove all *.elc files in ~/.emacs.d/elpa/org-plus-contrib-*/ and restart.

  • C-c C-c to evaluate a source block

Example of a R block that uses a named org-table as input:

#+tblname: tbl1
|   x |  y | group |
|-----+----+-------|
|   0 | 47 | A     |
| 111 | 50 | A     |
| 180 | 56 | A     |
|   0 | 46 | B     |
| 109 | 58 | B     |
| 167 | 60 | B     |

#+begin_src R :exports both :results output graphics :var tbl1=tbl1 :file tbl1-r.pdf :width 7 :height 5 :file-ext pdf
library(ggplot2)
ggplot(tbl1, aes(x=x, y=y, colour=group)) + geom_point()
#+end_src

Property drawer

No empty lines between header/scheduled/deadline and property chunk.

* John Doe
:PROPERTIES: 
:EMAIL:    [[mailto:john.doe@gmail.com][john.doe@gmail.com]]
:BIRTHDAY: 1982-01-14
:END:
  • To define which columns to show in the columns view, add at the beginning of the file: #+COLUMNS: %25ITEM %BIRTHDAY.
  • Toggle columns view on current item or whole file: C-c C-x C-c.
    • c to toggle compact table.
    • g to refresh.

Habits entry

** TODO Go for a run
SCHEDULED: <2019-07-16 Tue .+2d/7d>
:PROPERTIES: 
:STYLE:    habit
:LAST_REPEAT: [2019-07-14 Sun 14:13]
:END:
- State "DONE"       from "WAITING"    [2019-07-14 Sun 14:13] 

For a view of the habit and how well they are followed, I added to my .emacs:

(add-to-list 'org-modules 'org-habit)
(require 'org-habit)
;; (setq org-habit-show-all-today t
;;       org-habit-show-habits-only-for-today t
;;       org-habit-show-done-always-green t
;;       org-habit-graph-column 40
;;       org-habit-preceding-days 28
;;       org-habit-following-days 7)

Tags

  • Set/edit tag: C-c C-q

Clocking time

  • C-c C-x ; starts a timer/pomodoro.
  • C-c C-x C-i starts clocking, or I in agenda view.
  • C-c C-x C-o stops clocking (also stops when the task is DONE).
  • C-c C-x C-d shows a summary of the file.
  • C-c C-x C-r inserts a report table.

To force saving the clock items in a LOGBOOK drawer I added in my ~/.emacs:

(setq org-clock-into-drawer t)
(setq org-pretty-entities t)
(setq org-clock-in-switch-to-state "CLOCKING")

Custom agenda views

I either want to know the tasks and events for the day, or just the events for the upcoming week/year.

    1. Today’s agenda and un-scheduled tasks.
    1. Events for the upcoming week.
    1. Events for the upcoming year (recurrent events and birthdays excluded).
(setq org-agenda-custom-commands
      '(("c" "Today's agenda"
         ((agenda "" ((org-agenda-span 1)
                      (org-agenda-block-separator nil)
                      (org-agenda-skip-function
                       '(org-agenda-skip-subtree-if 'regexp ":habit:")
                       )
                      ))
          (alltodo ""
                   ((org-agenda-skip-function
                     (lambda nil
                       (org-agenda-skip-entry-if (quote scheduled)
                                                 (quote deadline))))
                    (org-agenda-overriding-header "Un-scheduled tasks:")
                    (org-agenda-block-separator nil)
                    ))
         (agenda ""
                  (
                   (org-agenda-span 'day)
                   (org-agenda-block-separator nil)
                   (org-agenda-format-date "")
                   (org-agenda-use-time-grid nil)
                   (org-agenda-skip-function
                    '(org-agenda-skip-subtree-if 'notregexp ":habit:")
                    )
                   (org-agenda-overriding-header "Habits:")
                   ))
          )
         )
        ("w" "Week's events"
         ((agenda "" ((org-agenda-span 7)
                      (org-agenda-skip-function
                       '(or (org-agenda-skip-entry-if 'todo '("TODO" "ONGOING" "DONE"))
                            )
                       )
                      (org-agenda-show-all-dates nil)
                      (org-agenda-overriding-header "Week's events:")
                      )))
         ((org-agenda-compact-blocks t))
         )
        ("y" "Year's events (no recurrents)"
         ((agenda "" ((org-agenda-span 365)
                      (org-agenda-skip-function
                       '(or (org-agenda-skip-entry-if 'todo '("TODO" "ONGOING" "DONE"))
                            (org-agenda-skip-subtree-if 'regexp ":recurrent:")
                            (org-agenda-skip-subtree-if 'regexp ":birthday:")
                            )
                       )
                      (org-agenda-show-all-dates nil)
                      (org-agenda-overriding-header "Year's events (no recurrents):")
                      )))
         ((org-agenda-compact-blocks t))
         )
        )
      )

I also changed the way tasks are displayed in the agenda view. Instead of showing the filename where the task resides, I show the first characters of the parent heading. That way I can use short and generic task names and still understand it in the agenda. No need to repeat the context in the task name anymore. I added in my .emacs:

;; Prefix tasks with parent heading
(defun getlasthead ()
  (let ((x (nth 0 (last (org-get-outline-path)))))
    (if x
	(if (> (string-width x) 12)
	    (concat "[" (org-format-outline-path (list (substring x 0 12))) "]")
	  (concat "[" (org-format-outline-path (list x)) "]"))
      "")))
(setq org-agenda-prefix-format " %i %-15(getlasthead)%?-12t% s ")

Shift timestamps by X hours when traveling to a different time zone

There is apparently no way to handle time zones easily. It makes it a bit annoying when traveling to a different time zone. This is the best I could find:

  1. In agenda view, mark the events to modify for bulk change using m
  2. Use a bulk change with a custom function. E.g. to add 3h: C-u 3 B h

I defined the custom function linked to the bulk command h in my .emacs:

(setq org-agenda-bulk-custom-functions
      `((?h (lambda () (call-interactively 'org-agenda-date-later-hours)))
        ,@org-agenda-bulk-custom-functions))

This is easy enough because I really just want to change the times of upcoming meetings, not everything. I don’t really care if the scheduled tasks I set for myself are not in the proper time zone, they tend to be re-scheduled anyway. And I travel for a couple of weeks maximum, so it’s quick to launch a week agenda view (C-c a w) and mark/shift the few upcoming meetings.

Reverse the order of headers

For example, when realizing half-way through that I prefer anti-chronological order (better have the latest/in-progress header at the top and not have to scroll down to the bottom).

From the higher-level header: M-x org-sort RET F point RET RET