From eeefe2b193edffb6a5e7df916dfec017bdd984ba Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Thu, 19 Dec 2019 11:01:05 +0100 Subject: [PATCH] Restructure repository notes Remove Snapshot of Bernt Hansen's org-mode file, and move remaining emacs-notes.org to toplevel. --- doc/bernt-hansen_org-mode.org | 6680 ------------------------ doc/emacs-notes.org => emacs-notes.org | 0 2 files changed, 6680 deletions(-) delete mode 100644 doc/bernt-hansen_org-mode.org rename doc/emacs-notes.org => emacs-notes.org (100%) diff --git a/doc/bernt-hansen_org-mode.org b/doc/bernt-hansen_org-mode.org deleted file mode 100644 index 0f9f91e..0000000 --- a/doc/bernt-hansen_org-mode.org +++ /dev/null @@ -1,6680 +0,0 @@ -#+TITLE: Org Mode - Organize Your Life In Plain Text! -#+LANGUAGE: en -#+AUTHOR: Bernt Hansen (IRC: BerntH on freenode) -#+EMAIL: bernt@norang.ca -#+OPTIONS: H:3 num:t toc:3 \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:nil -#+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:t pri:nil tags:not-in-toc -#+OPTIONS: author:t creator:t timestamp:t email:t -#+DESCRIPTION: A description of how I currently use org-mode -#+KEYWORDS: org-mode Emacs organization GTD getting-things-done git -#+SEQ_TODO: FIXME FIXED -#+INFOJS_OPT: view:nil toc:t ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js -#+EXPORT_SELECT_TAGS: export -#+EXPORT_EXCLUDE_TAGS: noexport - -Org-mode is a fabulous organizational tool originally built by Carsten -Dominik that operates on plain text files. Org-mode is part of Emacs. - -* How To Use This Document -:PROPERTIES: -:CUSTOM_ID: HowToUseThisDocument -:END: -[2012-11-24 Sat 23:28] - -This document assumes you've had some exposure to org-mode already so -concepts like the agenda, capture mode, etc. won't be completely -foreign to you. More information about org-mode can be found in the -[[http://orgmode.org/index.html#sec-4.1][Org-Mode Manual]] and on the [[http://orgmode.org/worg/][Worg Site]]. - -I have been using org-mode as my personal information manager for -years now. I started small with just the default =TODO= and =DONE= -keywords. I added small changes to my workflow and over time it -evolved into what is described by this document. - -I still change my workflow and try new things regularly. This -document describes mature workflows in my current org-mode setup. I -tend to document changes to my workflow 30 days after implementing -them (assuming they are still around at that point) so that the new -workflow has a chance to mature. - -Some of the customized Emacs settings described in this document are -set at their default values. This explicitly shows the setting for -important org-mode variables used in my workflow and to keep my -workflow behaviour stable in the event that the default value changes -in the future. - -This document is available as an [[http://doc.norang.ca/org-mode.org][org file]] which you can load in Emacs -and tangle with =C-c C-v C-t= which will create org-mode.el in the -same directory as the org-mode.org file. This will extract all of the -elisp examples in this document into a file you can include in your -.emacs file. -* License -:PROPERTIES: -:CUSTOM_ID: License -:END: -[2011-11-19 Sat 21:53] - -#+begin_example -Copyright (C) 2013 Bernt Hansen. -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 -or any later version published by the Free Software Foundation; -with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. - -Code in this document is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public -License as published by the Free Software Foundation, either -version 3 of the License, or (at your option) any later version. - -This code is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -#+end_example - -This document http://doc.norang.ca/org-mode.html (either in its -[[http://doc.norang.ca/org-mode.html][HTML format]] or in its [[http://doc.norang.ca/org-mode.org][Org format]]) is licensed under the GNU Free -Documentation License version 1.3 or later -(http://www.gnu.org/copyleft/fdl.html). - -The code examples and CSS stylesheets are licensed under the GNU -General Public License v3 or later -(http://www.gnu.org/licenses/gpl.html). -* Change History - What's new -:PROPERTIES: -:CUSTOM_ID: ChangeHistory -:END: - -#+name: org-mode-doc-version -#+begin_src sh :exports none -#!/bin/sh -git describe --abbrev=4 -#+end_src - -#+name: org-mode-version -#+begin_src sh :exports none -cd ~/git/org-mode && git describe HEAD -#+end_src - -This is version call_org-mode-doc-version() of this document. This -document is created using the publishing features of =org-mode= git -version call_org-mode-version(). - -The source for this document can be found as a [[http://doc.norang.ca/org-mode.org][plain text org file]]. I -try to update this document about once a month. - -The change history for this document can be found at -[[http://git.norang.ca/?p%3Dorg-mode-doc.git%3Ba%3Dsummary][git://git.norang.ca/org-mode-doc.git]]. -* Getting Started -:PROPERTIES: -:CUSTOM_ID: GettingStarted -:END: - -Getting started with =org-mode= is really easy. You only need a few lines in your -emacs startup to use the latest version of org-mode from the =git= repository. -** Getting org-mode with Git -:PROPERTIES: -:CUSTOM_ID: GettingOrgModeWithGit -:END: -[2012-06-24 Sun 11:21] - -I keep a copy of the org-mode =git= repository in =~/git/org-mode/=. This clone -was created with -#+begin_src sh -cd ~/git -git clone git://orgmode.org/org-mode.git -#+end_src - -To update and get new commits from the org-mode developers you can use -#+begin_src sh -cd ~/git/org-mode -git pull -make uncompiled -#+end_src - -I run uncompiled source files in my setup so the uncompiled =make= target is all you need. - -I normally track the =master= branch in the org-mode repository. -** Org-Mode Setup -:PROPERTIES: -:CUSTOM_ID: Setup -:END: - -The following setup in my .emacs enables =org-mode= for most buffers. -=org-mode= is the default mode for =.org=, =.org_archive=, and =.txt= -files. - -#+header: :tangle no -#+begin_src emacs-lisp -;;; -;;; Org Mode -;;; -(add-to-list 'load-path (expand-file-name "~/git/org-mode/lisp")) -(add-to-list 'auto-mode-alist '("\\.\\(org\\|org_archive\\|txt\\)$" . org-mode)) -(require 'org) -;; -;; Standard key bindings -(global-set-key "\C-cl" 'org-store-link) -(global-set-key "\C-ca" 'org-agenda) -(global-set-key "\C-cb" 'org-iswitchb) -#+end_src - -#+header: :tangle yes -#+begin_src emacs-lisp :exports none -;; The following setting is different from the document so that you -;; can override the document path by setting your path in the variable -;; org-mode-user-lisp-path -;; -(if (boundp 'org-mode-user-lisp-path) - (add-to-list 'load-path org-mode-user-lisp-path) - (add-to-list 'load-path (expand-file-name "~/git/org-mode/lisp"))) - -(add-to-list 'auto-mode-alist '("\\.\\(org\\|org_archive\\|txt\\)$" . org-mode)) -(require 'org) -;; -;; Standard key bindings -(global-set-key "\C-cl" 'org-store-link) -(global-set-key "\C-ca" 'org-agenda) -(global-set-key "\C-cb" 'org-iswitchb) -#+end_src - -That's all you need to get started using headlines and lists in org-mode. - -The rest of this document describes customizations I use in my setup, -how I structure org-mode files, and other changes to fit the way I -want org-mode to work. -** Organizing Your Life Into Org Files -:PROPERTIES: -:CUSTOM_ID: OrgFiles -:END: - -Tasks are separated into logical groupings or projects. -Use separate org files for large task groupings and -subdirectories for collections of files for multiple -projects that belong together. - -Here are sample files that I use. - -The following org files collect non-work related tasks: - -| Filename | Description | -|--------------+--------------------------------------------| -| todo.org | Personal tasks and things to keep track of | -| gsoc2009.org | Google Summer of Code stuff for 2009 | -| farm.org | Farm related tasks | -| mark.org | Tasks related to my son Mark | -| org.org | Org-mode related tasks | -| git.org | Git related tasks | - -The following org-file collects org capture notes and tasks: - -| Filename | Description | -|------------+---------------------| -| refile.org | Capture task bucket | - -The following work-related org-files keep my business notes (using -fictitious client names) - -| Filename | Description | -|-------------+-----------------------------------------| -| norang.org | Norang tasks and notes | -| XYZ.org | XYZ Corp tasks and notes | -| ABC.org | ABC Ltd tasks | -| ABC-DEF.org | ABC Ltd tasks for their client DEF Corp | -| ABC-KKK.org | ABC Ltd tasks for their client KKK Inc | -| YYY.org | YYY Inc tasks | - -Org-mode is great for dealing with multiple clients and client -projects. An org file becomes the collection of projects, notes, -etc. for a single client or client-project. - -Client ABC Ltd. has multiple customer systems that I work on. -Separating the tasks for each client-customer into separate org files -helps keep things logically grouped and since clients come and go this -allows entire org files to be added or dropped from my agenda to keep -only what is important visible in agenda views. - -Other org files are used for publishing only and do not contribute to the agenda. -See [[#Publishing][Publishing and Exporting]] for more details. -** Agenda Setup -:PROPERTIES: -:CUSTOM_ID: AgendaSetup -:END: - -Here is my current =org-agenda-files= setup. -#+header: :tangle no -#+begin_src emacs-lisp -(setq org-agenda-files (quote ("~/git/org" - "~/git/org/client1" - "~/git/client2"))) -#+end_src - -#+header: :tangle yes -#+begin_src emacs-lisp :exports none -;; The following setting is different from the document so that you -;; can override the document org-agenda-files by setting your -;; org-agenda-files in the variable org-user-agenda-files -;; -(if (boundp 'org-user-agenda-files) - (setq org-agenda-files org-user-agenda-files) - (setq org-agenda-files (quote ("~/git/org" - "~/git/org/client1" - "~/git/client2")))) -#+end_src - -=org-mode= manages the =org-agenda-files= variable automatically using -=C-c [= and =C-c ]= to add and remove files respectively. However, -this replaces my directory list with a list of explicit filenames -instead and is not what I want. If this occurs then adding a new org -file to any of the above directories will not contribute to my agenda -and I will probably miss something important. - -I have disabled the =C-c [= and =C-c ]= keys in =org-mode-hook= to -prevent messing up my list of directories in the =org-agenda-files= -variable. I just add and remove directories manually in my =.emacs= -file. Changing the list of directories in =org-agenda-files= happens -very rarely since new files in existing directories are automatically -picked up. - -I also disable the comment function =C-c ;= since I never use those. -I kept accidentally hitting this key sequence when doing =C-c -singlequote= for editing source blocks. - -In the example above I have =~/git/client2= in a separate git -repository from ~/git/org. This gives me the flexibility of leaving -confidential information at the client site and having all of my -personal information available everywhere I use org-mode. I -synchronize my personal repositories on multiple machines and skip the -confidential info on the non-client laptop I travel with. -=org-agenda-files= on this laptop does not include the =~/git/client2= -directory. -** Org File Structure -:PROPERTIES: -:CUSTOM_ID: OrgFileStructure -:END: - -Most of my org files are set up with level 1 headings as main -categories only. Tasks and projects normally start as level 2. - -Here are some examples of my level 1 headings in - -=todo.org=: - -- Special Dates - - Includes level 2 headings for - - - Birthdays - - Anniversaries - - Holidays - -- Finances -- Health and Recreation -- House Maintenance -- Lawn and Garden Maintenance -- Notes -- Tasks -- Vehicle Maintenance -- Passwords - - -=norang.org=: - -- System Maintenance -- Payroll -- Accounting -- Finances -- Hardware Maintenance -- Tasks -- Research and Development -- Notes -- Purchase Order Tracking -- Passwords - -Each of these level 1 tasks normally has a =property drawer= -specifying the category for any tasks in that tree. Level 1 headings -are set up like this: - -#+begin_src org :exports src -,* Health and Recreation - :PROPERTIES: - :CATEGORY: Health - :END: - ... -,* House Maintenance - :PROPERTIES: - :CATEGORY: House - :END: -#+end_src -** Key bindings -:PROPERTIES: -:CUSTOM_ID: KeyBindings -:END: - -I live in the agenda. To make getting to the agenda faster I mapped -=F12= to the sequence =C-c a= since I'm using it hundreds of times a -day. - -I have the following custom key bindings set up for my emacs (sorted by frequency). - -| Key | For | Used | -|---------+-------------------------------------------------+------------| -| F12 | Agenda (1 key less than C-c a) | Very Often | -| C-c b | Switch to org file | Very Often | -| F11 | Goto currently clocked item | Very Often | -| C-c c | Capture a task | Very Often | -| C-F11 | Clock in a task (show menu with prefix) | Often | -| f9 g | Gnus - I check mail regularly | Often | -| f5 | Show todo items for this subtree | Often | -| S-f5 | Widen | Often | -| f9 b | Quick access to bbdb data | Often | -| f9 c | Calendar access | Often | -| C-S-f12 | Save buffers and publish current project | Often | -| C-c l | Store a link for retrieval with C-c C-l | Often | -| f8 | Go to next org file in org-agenda-files | Sometimes | -| f9 r | Boxquote selected region | Sometimes | -| f9 t | Insert inactive timestamp | Sometimes | -| f9 v | Toggle visible mode (for showing/editing links) | Sometimes | -| C-f9 | Previous buffer | Sometimes | -| C-f10 | Next buffer | Sometimes | -| C-x n r | Narrow to region | Sometimes | -| f9 f | Boxquote insert a file | Sometimes | -| f9 i | Info manual | Sometimes | -| f9 I | Punch Clock In | Sometimes | -| f9 O | Punch Clock Out | Sometimes | -| f9 o | Switch to org scratch buffer | Sometimes | -| f9 s | Switch to scratch buffer | Sometimes | -| f9 h | Hide other tasks | Rare | -| f7 | Toggle line truncation/wrap | Rare | -| f9 T | Toggle insert inactive timestamp | Rare | -| C-c a | Enter Agenda (minimal emacs testing) | Rare | - -Here is the keybinding setup in lisp: -#+header: :tangle yes -#+begin_src emacs-lisp -;; Custom Key Bindings -(global-set-key (kbd "") 'org-agenda) -(global-set-key (kbd "") 'bh/org-todo) -(global-set-key (kbd "") 'bh/widen) -(global-set-key (kbd "") 'bh/set-truncate-lines) -(global-set-key (kbd "") 'org-cycle-agenda-files) -(global-set-key (kbd " ") 'bh/show-org-agenda) -(global-set-key (kbd " b") 'bbdb) -(global-set-key (kbd " c") 'calendar) -(global-set-key (kbd " f") 'boxquote-insert-file) -(global-set-key (kbd " g") 'gnus) -(global-set-key (kbd " h") 'bh/hide-other) -(global-set-key (kbd " n") 'bh/toggle-next-task-display) -(global-set-key (kbd " w") 'widen) - -(global-set-key (kbd " I") 'bh/punch-in) -(global-set-key (kbd " O") 'bh/punch-out) - -(global-set-key (kbd " o") 'bh/make-org-scratch) - -(global-set-key (kbd " r") 'boxquote-region) -(global-set-key (kbd " s") 'bh/switch-to-scratch) - -(global-set-key (kbd " t") 'bh/insert-inactive-timestamp) -(global-set-key (kbd " T") 'bh/toggle-insert-inactive-timestamp) - -(global-set-key (kbd " v") 'visible-mode) -(global-set-key (kbd " l") 'org-toggle-link-display) -(global-set-key (kbd " SPC") 'bh/clock-in-last-task) -(global-set-key (kbd "C-") 'previous-buffer) -(global-set-key (kbd "M-") 'org-toggle-inline-images) -(global-set-key (kbd "C-x n r") 'narrow-to-region) -(global-set-key (kbd "C-") 'next-buffer) -(global-set-key (kbd "") 'org-clock-goto) -(global-set-key (kbd "C-") 'org-clock-in) -(global-set-key (kbd "C-s-") 'bh/save-then-publish) -(global-set-key (kbd "C-c c") 'org-capture) - -(defun bh/hide-other () - (interactive) - (save-excursion - (org-back-to-heading 'invisible-ok) - (hide-other) - (org-cycle) - (org-cycle) - (org-cycle))) - -(defun bh/set-truncate-lines () - "Toggle value of truncate-lines and refresh window display." - (interactive) - (setq truncate-lines (not truncate-lines)) - ;; now refresh window display (an idiom from simple.el): - (save-excursion - (set-window-start (selected-window) - (window-start (selected-window))))) - -(defun bh/make-org-scratch () - (interactive) - (find-file "/tmp/publish/scratch.org") - (gnus-make-directory "/tmp/publish")) - -(defun bh/switch-to-scratch () - (interactive) - (switch-to-buffer "*scratch*")) -#+end_src - -The main reason I have special key bindings (like =F11=, and =F12=) is -so that the keys work in any mode. If I'm in the Gnus summary buffer -then =C-u C-c C-x C-i= doesn't work, but the =C-F11= key combination -does and this saves me time since I don't have to visit an org-mode -buffer first just to clock in a recent task. -* Tasks and States -:PROPERTIES: -:CUSTOM_ID: TasksAndStates -:END: - -I use one set of TODO keywords for all of my org files. Org-mode lets -you define TODO keywords per file but I find it's easier to have a -standard set of TODO keywords globally so I can use the same setup in -any org file I'm working with. - -The only exception to this is this document :) since I don't want -=org-mode= hiding the =TODO= keyword when it appears in headlines. -I've set up a dummy =#+SEQ_TODO: FIXME FIXED= entry at the top of this -file just to leave my =TODO= keyword untouched in this document. -** TODO keywords -:PROPERTIES: -:CUSTOM_ID: TodoKeywords -:END: - -I use a light colour theme in emacs. I find this easier to read on bright sunny days. - -Here are my =TODO= state keywords and colour settings: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-todo-keywords - (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") - (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING")))) - -(setq org-todo-keyword-faces - (quote (("TODO" :foreground "red" :weight bold) - ("NEXT" :foreground "blue" :weight bold) - ("DONE" :foreground "forest green" :weight bold) - ("WAITING" :foreground "orange" :weight bold) - ("HOLD" :foreground "magenta" :weight bold) - ("CANCELLED" :foreground "forest green" :weight bold) - ("MEETING" :foreground "forest green" :weight bold) - ("PHONE" :foreground "forest green" :weight bold)))) -#+end_src -*** Task States -:PROPERTIES: -:CUSTOM_ID: TodoKeywordTaskStates -:END: - -Tasks go through the sequence =TODO= -> =DONE=. - -The following diagram shows the possible state transitions for a task. - -#+begin_src plantuml :file normal_task_states.png :cache yes -title Task States -[*] -> TODO -TODO -> NEXT -TODO -> DONE -NEXT -> DONE -DONE -> [*] -TODO --> WAITING -WAITING --> TODO -NEXT --> WAITING -WAITING --> NEXT -HOLD --> CANCELLED -WAITING --> CANCELLED -CANCELLED --> [*] -TODO --> HOLD -HOLD --> TODO -TODO --> CANCELLED -TODO: t -NEXT: n -DONE: d -WAITING:w -note right of WAITING: Note records\nwhat it is waiting for -HOLD:h -note right of CANCELLED: Note records\nwhy it was cancelled -CANCELLED:c -WAITING --> DONE -#+end_src - -#+results[c0362b66d6337f3ae0ac7ab2d715687debfa6652]: -[[file:normal_task_states.png]] - -*** Project Task States -:PROPERTIES: -:CUSTOM_ID: TodoKeywordProjectTaskStates -:END: - -I use a lazy project definition. I don't like to bother with manually -stating 'this is a project' and 'that is not a project'. For me a project -definition is really simple. If a task has subtasks with a todo keyword -then it's a project. That's it. - -Projects can be defined at any level - just create a task with a todo -state keyword that has at least one subtask also with a todo state -keyword and you have a project. Projects use the same todo keywords -as regular tasks. One subtask of a project needs to be marked =NEXT= -so the project is not on the stuck projects list. -*** Phone Calls -:PROPERTIES: -:CUSTOM_ID: TodoKeywordPhoneCalls -:END: - -Telephone calls are special. They are created in a done state by a capture task. -The time of the call is recorded for as long as the capture task is active. If I need -to look up other details and want to close the capture task early I can just -=C-c C-c= to close the capture task (stopping the clock) and then =f9 SPC= to resume -the clock in the phone call while I do other things. -#+begin_src plantuml :file phone_states.png :cache yes -title Phone Call Task State -[*] -> PHONE -PHONE -> [*] -#+end_src - -#+results[7fcae03150f58bbcc260379916083e99a91983c4]: -[[file:phone_states.png]] - -*** Meetings -:PROPERTIES: -:CUSTOM_ID: TodoKeywordMeetings -:END: - -Meetings are special. They are created in a done state by a capture -task. I use the MEETING capture template when someone interrupts what -I'm doing with a question or discussion. This is handled similarly to -phone calls where I clock the amount of time spent with whomever it is -and record some notes of what was discussed (either during or after -the meeting) depending on content, length, and complexity of the -discussion. - -The time of the meeting is recorded for as long as the capture task is -active. If I need to look up other details and want to close the -capture task early I can just =C-c C-c= to close the capture task -(stopping the clock) and then =f9 SPC= to resume the clock in the -meeting task while I do other things. -#+begin_src plantuml :file meeting_states.png :cache yes -title Meeting Task State -[*] -> MEETING -MEETING -> [*] -#+end_src - -#+results[27cce0a2a2c020d46bb1801a287cca4327a13dff]: -[[file:meeting_states.png]] - -** Fast Todo Selection -:PROPERTIES: -:CUSTOM_ID: FastTodoSelection -:END: - -Fast todo selection allows changing from any task todo state to any -other state directly by selecting the appropriate key from the fast -todo selection key menu. This is a great feature! - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-use-fast-todo-selection t) -#+end_src - -Changing a task state is done with =C-c C-t KEY= - -where =KEY= is the appropriate fast todo state selection key as defined in =org-todo-keywords=. - -The setting -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-treat-S-cursor-todo-selection-as-state-change nil) -#+end_src -allows changing todo states with S-left and S-right skipping all of -the normal processing when entering or leaving a todo state. This -cycles through the todo states but skips setting timestamps and -entering notes which is very convenient when all you want to do is fix -up the status of an entry. -** TODO state triggers -:PROPERTIES: -:CUSTOM_ID: ToDoStateTriggers -:END: - -I have a few triggers that automatically assign tags to tasks based on -state changes. If a task moves to =CANCELLED= state then it gets a -=CANCELLED= tag. Moving a =CANCELLED= task back to =TODO= removes the -=CANCELLED= tag. These are used for filtering tasks in agenda views -which I'll talk about later. - -The triggers break down to the following rules: - -- Moving a task to =CANCELLED= adds a =CANCELLED= tag -- Moving a task to =WAITING= adds a =WAITING= tag -- Moving a task to =HOLD= adds =WAITING= and =HOLD= tags -- Moving a task to a done state removes =WAITING= and =HOLD= tags -- Moving a task to =TODO= removes =WAITING=, =CANCELLED=, and =HOLD= tags -- Moving a task to =NEXT= removes =WAITING=, =CANCELLED=, and =HOLD= tags -- Moving a task to =DONE= removes =WAITING=, =CANCELLED=, and =HOLD= tags - -The tags are used to filter tasks in the agenda views conveniently. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-todo-state-tags-triggers - (quote (("CANCELLED" ("CANCELLED" . t)) - ("WAITING" ("WAITING" . t)) - ("HOLD" ("WAITING") ("HOLD" . t)) - (done ("WAITING") ("HOLD")) - ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) - ("NEXT" ("WAITING") ("CANCELLED") ("HOLD")) - ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) -#+end_src -* Adding New Tasks Quickly with Org Capture -:PROPERTIES: -:CUSTOM_ID: Capture -:END: - -Org Capture mode replaces remember mode for capturing tasks and notes. - -To add new tasks efficiently I use a minimal number of capture -templates. I used to have lots of capture templates, one for each -org-file. I'd start org-capture with =C-c c= and then pick a template -that filed the task under =* Tasks= in the appropriate file. - -I found I still needed to refile these capture tasks again to the -correct location within the org-file so all of these different capture -templates weren't really helping at all. Since then I've changed my -workflow to use a minimal number of capture templates -- I create the -new task quickly and refile it once. This also saves me from -maintaining my org-capture templates when I add a new org file. -** Capture Templates -:PROPERTIES: -:CUSTOM_ID: CaptureTemplates -:END: - -When a new task needs to be added I categorize it into one of a few -things: - -- A phone call (p) -- A meeting (m) -- An email I need to respond to (r) -- A new task (t) -- A new note (n) -- An interruption (j) -- A new habit (h) - -and pick the appropriate capture task. - -Here is my setup for org-capture - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-directory "~/git/org") -(setq org-default-notes-file "~/git/org/refile.org") - -;; I use C-c c to start capture mode -(global-set-key (kbd "C-c c") 'org-capture) - -;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol -(setq org-capture-templates - (quote (("t" "todo" entry (file "~/git/org/refile.org") - "* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t) - ("r" "respond" entry (file "~/git/org/refile.org") - "* NEXT Respond to %:from on %:subject\nSCHEDULED: %t\n%U\n%a\n" :clock-in t :clock-resume t :immediate-finish t) - ("n" "note" entry (file "~/git/org/refile.org") - "* %? :NOTE:\n%U\n%a\n" :clock-in t :clock-resume t) - ("j" "Journal" entry (file+datetree "~/git/org/diary.org") - "* %?\n%U\n" :clock-in t :clock-resume t) - ("w" "org-protocol" entry (file "~/git/org/refile.org") - "* TODO Review %c\n%U\n" :immediate-finish t) - ("m" "Meeting" entry (file "~/git/org/refile.org") - "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t) - ("p" "Phone call" entry (file "~/git/org/refile.org") - "* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t) - ("h" "Habit" entry (file "~/git/org/refile.org") - "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"<%Y-%m-%d %a .+1d/3d>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n")))) -#+end_src - -Capture mode now handles automatically clocking in and out of a -capture task. This all works out of the box now without special hooks. -When I start a capture mode task the task is clocked in as specified -by =:clock-in t= and when the task is filed with =C-c C-c= the clock -resumes on the original clocking task. - -The quick clocking in and out of capture mode tasks (often it takes -less than a minute to capture some new task details) can leave -empty clock drawers in my tasks which aren't really useful. Since I -remove clocking lines with 0:00 length I end up with a clock drawer -like this: - -#+begin_src org :exports src -,* TODO New Capture Task - :LOGBOOK: - :END: - [2010-05-08 Sat 13:53] -#+end_src -I have the following setup to remove these empty =LOGBOOK= drawers if -they occur. - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Remove empty LOGBOOK drawers on clock out -(defun bh/remove-empty-drawer-on-clock-out () - (interactive) - (save-excursion - (beginning-of-line 0) - (org-remove-empty-drawer-at (point)))) - -(add-hook 'org-clock-out-hook 'bh/remove-empty-drawer-on-clock-out 'append) -#+end_src -** Separate file for Capture Tasks -:PROPERTIES: -:CUSTOM_ID: CaptureRefileOrg -:END: - -I have a single org file which is the target for my capture templates. - -I store notes, tasks, phone calls, and org-protocol tasks in -=refile.org=. I used to use multiple files but found that didn't -really have any advantage over a single file. - -Normally this file is empty except for a single line at the top which -creates a =REFILE= tag for anything in the file. - -The file has a single permanent line at the top like this -#+begin_src org :exports src -,#+FILETAGS: REFILE -#+end_src -** Capture Tasks is all about being FAST -:PROPERTIES: -:CUSTOM_ID: CaptureTasksAreFast -:END: - -Okay I'm in the middle of something and oh yeah - I have to remember -to do that. I don't stop what I'm doing. I'm probably clocking a -project I'm working on and I don't want to lose my focus on that but I -can't afford to forget this little thing that just came up. - -So what do I do? Hit =C-c c= to start capture mode and select =t= -since it's a new task and I get a buffer like this: - -#+begin_src org :exports src -,* TODO - [2010-08-05 Thu 21:06] - - [[file:~/git/org-mode-doc/org-mode.org::*Capture%20Tasks%20is%20all%20about%20being%20FAST][Capture Tasks is all about being FAST]] -#+end_src - -Enter the details of the TODO item and =C-c C-c= to file it away in -refile.org and go right back to what I'm really working on secure in -the knowledge that that item isn't going to get lost and I don't have -to think about it anymore at all now. - -The amount of time I spend entering the captured note is clocked. The -capture templates are set to automatically clock in and out of the -capture task. This is great for interruptions and telephone calls -too. -* Refiling Tasks -:PROPERTIES: -:CUSTOM_ID: Refiling -:END: - -Refiling tasks is easy. After collecting a bunch of new tasks in my -refile.org file using capture mode I need to move these to the -correct org file and topic. All of my active org-files are in my -=org-agenda-files= variable and contribute to the agenda. - -I collect capture tasks in refile.org for up to a week. These now -stand out daily on my block agenda and I usually refile them during -the day. I like to keep my refile task list empty. -** Refile Setup -:PROPERTIES: -:CUSTOM_ID: RefileSetup -:END: - -To refile tasks in org you need to tell it where you want to refile things. - -In my setup I let any file in =org-agenda-files= and the current file -contribute to the list of valid refile targets. - -I've recently moved to using IDO to complete targets directly. I find -this to be faster than my previous complete in steps setup. At first -I didn't like IDO but after reviewing the documentation again and -learning about =C-SPC= to limit target searches I find it is much -better than my previous complete-in-steps setup. Now when I want to -refile something I do =C-c C-w= to start the refile process, then type -something to get some matching targets, then =C-SPC= to restrict the -matches to the current list, then continue searching with some other -text to find the target I need. =C-j= also selects the current -completion as the final target. I like this a lot. I show full -outline paths in the targets so I can have the same heading in -multiple subtrees or projects and still tell them apart while -refiling. - -I now exclude =DONE= state tasks as valid refile targets. This helps to keep the -refile target list to a reasonable size. - -Here is my refile configuration: -#+header: :tangle yes -#+begin_src emacs-lisp -; Targets include this file and any file contributing to the agenda - up to 9 levels deep -(setq org-refile-targets (quote ((nil :maxlevel . 9) - (org-agenda-files :maxlevel . 9)))) - -; Use full outline paths for refile targets - we file directly with IDO -(setq org-refile-use-outline-path t) - -; Targets complete directly with IDO -(setq org-outline-path-complete-in-steps nil) - -; Allow refile to create parent tasks with confirmation -(setq org-refile-allow-creating-parent-nodes (quote confirm)) - -; Use IDO for both buffer and file completion and ido-everywhere to t -(setq org-completion-use-ido t) -(setq ido-everywhere t) -(setq ido-max-directory-size 100000) -(ido-mode (quote both)) -; Use the current window when visiting files and buffers with ido -(setq ido-default-file-method 'selected-window) -(setq ido-default-buffer-method 'selected-window) -; Use the current window for indirect buffer display -(setq org-indirect-buffer-display 'current-window) - -;;;; Refile settings -; Exclude DONE state tasks from refile targets -(defun bh/verify-refile-target () - "Exclude todo keywords with a done state from refile targets" - (not (member (nth 2 (org-heading-components)) org-done-keywords))) - -(setq org-refile-target-verify-function 'bh/verify-refile-target) -#+end_src - -To refile a task to my =norang.org= file under =System Maintenance= I -just put the cursor on the task and hit =C-c C-w= and enter =nor C-SPC -sys RET= and it's done. IDO completion makes locating targets a snap. -** Refiling Tasks -:PROPERTIES: -:CUSTOM_ID: RefilingTasks -:END: - -Tasks to refile are in their own section of the block agenda. To find -tasks to refile I run my agenda view with =F12 SPC= and scroll down to -second section of the block agenda: =Tasks to Refile=. This view -shows all tasks (even ones marked in a =done= state). - -Bulk refiling in the agenda works very well for multiple tasks going -to the same place. Just mark the tasks with =m= and then =B r= to -refile all of them to a new location. Occasionally I'll also refile -tasks as subtasks of the current clocking task using =C-2 C-c C-w= -from the =refile.org= file. - -Refiling all of my tasks tends to take less than a minute so I -normally do this a couple of times a day. -** Refiling Notes -:PROPERTIES: -:CUSTOM_ID: RefilingNotes -:END: - -I keep a =* Notes= headline in most of my org-mode files. Notes have -a =NOTE= tag which is created by the capture template for notes. This -allows finding notes across multiple files easily using the agenda -search functions. - -Notes created by capture tasks go first to =refile.org= and are later -refiled to the appropriate project file. Some notes that are project -related get filed to the appropriate project instead of under the -catchall =* NOTES= task. Generally these types of notes are specific -to the project and not generally useful -- so removing them from the -notes list when the project is archived makes sense. -** Refiling Phone Calls and Meetings -:PROPERTIES: -:CUSTOM_ID: RefilingPhoneCalls -:END: - -Phone calls and meetings are handled using capture mode. I time my -calls and meetings using the capture mode template settings to clock -in and out the capture task while the phone call or meeting is in -progress. - -Phone call and meeting tasks collect in =refile.org= and are later -refiled to the appropriate location. Some phone calls are billable -and we want these tracked in the appropriate category. I refile my -phone call and meeting tasks under the appropriate project so time -tracking and reports are as accurate as possible. -* Custom agenda views -:PROPERTIES: -:CUSTOM_ID: CustomAgendaViews -:END: - -I now have one block agenda view that has everything on it. I also -keep separate single view agenda commands for use on my slower Eee -PC - since it takes prohibitively long to generate my block agenda on -that slow machine. I'm striving to simplify my layout with everything -at my fingertips in a single agenda on my workstation which is where I -spend the bulk of my time. - -Most of my old custom agenda views were rendered obsolete when -filtering functionality was added to the agenda in newer versions of -=org-mode= and now with block agenda functionality I can combine -everything into a single view. - -Custom agenda views are used for: -- Single block agenda shows the following - - overview of today - - Finding tasks to be refiled - - Finding stuck projects - - Finding NEXT tasks to work on - - Show all related tasks - - Reviewing projects - - Finding tasks waiting on something - - Findings tasks to be archived -- Finding notes -- Viewing habits - -If I want just today's calendar view then =F12 a= is still faster than -generating the block agenda - especially if I want to view a week or -month's worth of information, or check my clocking data. In that case -the extra detail on the block agenda view is never really needed and I -don't want to spend time waiting for it to be generated. -** Setup -:PROPERTIES: -:CUSTOM_ID: CustomAgendaViewSetup -:END: - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Do not dim blocked tasks -(setq org-agenda-dim-blocked-tasks nil) - -;; Compact the block agenda view -(setq org-agenda-compact-blocks t) - -;; Custom agenda command definitions -(setq org-agenda-custom-commands - (quote (("N" "Notes" tags "NOTE" - ((org-agenda-overriding-header "Notes") - (org-tags-match-list-sublevels t))) - ("h" "Habits" tags-todo "STYLE=\"habit\"" - ((org-agenda-overriding-header "Habits") - (org-agenda-sorting-strategy - '(todo-state-down effort-up category-keep)))) - (" " "Agenda" - ((agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header "Tasks to Refile") - (org-tags-match-list-sublevels nil))) - (tags-todo "-CANCELLED/!" - ((org-agenda-overriding-header "Stuck Projects") - (org-agenda-skip-function 'bh/skip-non-stuck-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-HOLD-CANCELLED/!" - ((org-agenda-overriding-header "Projects") - (org-agenda-skip-function 'bh/skip-non-projects) - (org-tags-match-list-sublevels 'indented) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-CANCELLED/!NEXT" - ((org-agenda-overriding-header (concat "Project Next Tasks" - (if bh/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'bh/skip-projects-and-habits-and-single-tasks) - (org-tags-match-list-sublevels t) - (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-sorting-strategy - '(todo-state-down effort-up category-keep)))) - (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header (concat "Project Subtasks" - (if bh/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'bh/skip-non-project-tasks) - (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header (concat "Standalone Tasks" - (if bh/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'bh/skip-project-tasks) - (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-CANCELLED+WAITING|HOLD/!" - ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks" - (if bh/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'bh/skip-non-tasks) - (org-tags-match-list-sublevels nil) - (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks))) - (tags "-REFILE/" - ((org-agenda-overriding-header "Tasks to Archive") - (org-agenda-skip-function 'bh/skip-non-archivable-tasks) - (org-tags-match-list-sublevels nil)))) - nil)))) -#+end_src - -My block agenda view looks like this when not narrowed to a project. -This shows top-level projects and =NEXT= tasks but hides the project details since -we are not focused on any particular project. - -[[file:block-agenda-nonproject.png]] - -After selecting a project (with =P= on any task in the agenda) the block agenda changes to show the project and -any subprojects in the Projects section. Tasks show project-related tasks that are hidden when not -narrowed to a project. - -This makes it easy to focus on the task at hand. - -[[file:block-agenda-project.png]] - -I generally work top-down on the agenda. Things with deadlines and -scheduled dates (planned to work on today or earlier) show up in the -agenda at the top. - -My day goes generally like this: - -- Punch in (this starts the clock on the default task) -- Look at the agenda and make a mental note of anything important to deal with today -- Read email and news - - create notes, and tasks for things that need responses with org-capture -- Check refile tasks and respond to emails -- Look at my agenda and work on important tasks for today - - Clock it in - - Work on it until it is =DONE= or it gets interrupted -- Work on tasks -- Make journal entries (=C-c c j=) for interruptions -- Punch out for lunch and punch back in after lunch -- work on more tasks -- Refile tasks to empty the list - - Tag tasks to be refiled with =m= collecting all tasks for the same target - - Bulk refile the tasks to the target location with =B r= - - Repeat (or refile individually with =C-c C-w=) until all refile tasks are gone -- Mark habits done today as DONE -- Punch out at the end of the work day -** What do I work on next? -:PROPERTIES: -:CUSTOM_ID: WhatDoIWorkOnNext -:END: - -Start with deadlines and tasks scheduled today or earlier from the -daily agenda view. Then move on to tasks in the =Next Tasks= list in -the block agenda view. I tend to schedule current projects to 'today' -when I start work on them and they sit on my daily agenda reminding me -that they need to be completed. I normally only schedule one or two -projects to the daily agenda and unschedule things that are no longer -important and don't deserve my attention today. - -When I look for a new task to work on I generally hit =F12 SPC= to get -the block agenda and follow this order: - -- Pick something off today's agenda - - deadline for today (do this first - it's not late yet) - - deadline in the past (it's already late) - - a scheduled task for today (it's supposed to be done today) - - a scheduled task that is still on the agenda - - deadline that is coming up soon -- pick a NEXT task -- If you run out of items to work on look for a NEXT task in the current context - pick a task from the Tasks list of the current project. -*** Why keep it all on the =NEXT= list? -:PROPERTIES: -:CUSTOM_ID: CustomAgendaViewsNextList -:END: - -I've moved to a more GTD way of doing things. Now I just use a =NEXT= -list. Only projects get tasks with =NEXT= keywords since stuck projects -initiate the need for marking or creating =NEXT= tasks. A =NEXT= task -is something that is available to work on /now/, it is the next -logical step in some project. - -I used to have a special keyword =ONGOING= for things that I do a lot -and want to clock but never really start/end. I had a special agenda -view for =ONGOING= tasks that I would pull up to easily find the thing -I want to clock. - -Since then I've moved away from using the =ONGOING= todo keyword. -Having an agenda view that shows =NEXT= tasks makes it easy to pick -the thing to clock - and I don't have to remember if I need to look in -the =ONGOING= list or the =NEXT= list when looking for the task to -clock-in. The =NEXT= list is basically 'what is current' - any task -that moves a project forward. I want to find the thing to work on as -fast as I can and actually do work on it - not spend time hunting -through my org files for the task that needs to be clocked-in. - -To drop a task off the =NEXT= list simply move it back to the =TODO= -state. -** Reading email, newsgroups, and conversations on IRC -:PROPERTIES: -:CUSTOM_ID: ReadingMailNewsIRC -:END: - -When reading email, newsgroups, and conversations on IRC I just let -the default task (normally =** Organization=) clock the time I spend on -these tasks. To read email I go to Gnus and read everything in my -inboxes. If there are emails that require a response I use -org-capture to create a new task with a heading of 'Respond to ' -for each one. This automatically links to the email in the task and -makes it easy to find later. Some emails are quick to respond to and -some take research and a significant amount of time to complete. I -clock each one in it's own task just in case I need that clocked time -later. The capture template for Repond To tasks is now scheduled for -today so I can refile the task to the appropriate org file without -losing the task for a week. - -Next, I go to my newly created tasks to be refiled from the block -agenda with =F12 a= and clock in an email task and deal with it. -Repeat this until all of the 'Respond to ' tasks are marked -=DONE=. - -I read email and newgroups in Gnus so I don't separate clocked time -for quickly looking at things. If an article has a useful piece of -information I want to remember I create a note for it with =C-c c n= -and enter the topic and file it. This takes practically no time at -all and I know the note is safely filed for later retrieval. The time -I spend in the capture buffer is clocked with that capture note. -** Filtering -:PROPERTIES: -:CUSTOM_ID: CustomAgendaViewFiltering -:END: - -So many tasks, so little time. I have hundreds of tasks at any given -time (373 right now). There is so much stuff to look at it can be -daunting. This is where agenda filtering saves the day. - -It's 11:53AM and I'm in work mode just before lunch. I don't want to -see tasks that are not work related right now. I also don't want to -work on a big project just before lunch... so I need to find small -tasks that I can knock off the list. - -How do we do this? Get a list of NEXT tasks from the block agenda and -then narrow it down with filtering. Tasks are ordered in the NEXT -agenda view by estimated effort so the short tasks are first -- just -start at the top and work your way down. I can limit the displayed -agenda tasks to those estimates of 10 minutes or less with =/ + 1= and -I can pick something that fits the minutes I have left before I take -off for lunch. -*** Automatically removing context based tasks with / RET -:PROPERTIES: -:CUSTOM_ID: CustomAgendaViewFilteringContext -:END: - -=/ RET= in the agenda is really useful. This awesome feature was -added to org-mode by John Wiegley. It removes tasks automatically by -filtering based on a user-provided function. - -At work I have projects I'm working on which are assigned by my -manager. Sometimes priorities changes and projects are delayed to -sometime in the future. This means I need to stop working on these -immediately. I put the project task on =HOLD= and work on something -else. The =/ RET= filter removes =HOLD= tasks and subtasks (because -of tag inheritance). - -At home I have some tasks tagged with =farm= since these need to be -performed when I am physically at our family farm. Since I am there -infrequently I have added =farm= to the list of auto-excluded tags on -my system. I can always explicitly filter to just =farm= tasks with -=/ TAB farm RET= when I am physically there. - -I have the following setup to allow =/ RET= to filter tasks based on -the description above. - -#+header: :tangle yes -#+begin_src emacs-lisp -(defun bh/org-auto-exclude-function (tag) - "Automatic task exclusion in the agenda with / RET" - (and (cond - ((string= tag "hold") - t) - ((string= tag "farm") - t)) - (concat "-" tag))) - -(setq org-agenda-auto-exclude-function 'bh/org-auto-exclude-function) -#+end_src - -This lets me filter tasks with just =/ RET= on the agenda which removes tasks I'm not -supposed to be working on now from the list of returned results. - -This helps to keep my agenda clutter-free. -* Time Clocking -:PROPERTIES: -:CUSTOM_ID: Clocking -:END: - -Okay, I admit it. I'm a clocking fanatic. - -I clock everything at work. Org-mode makes this really easy. I'd -rather clock too much stuff than not enough so I find it's easier to -get in the habit of clocking everything. - -This makes it possible to look back at the day and see where I'm -spending too much time, or not enough time on specific projects. This -also helps a lot when you need to estimate how long something is going -to take to do -- you can use your clocking data from similar tasks to -help tune your estimates so they are more accurate. - -Without clocking data it's hard to tell how long something took to do -after the fact. - -I now use the concept of =punching in= and =punching out= at the start -and end of my work day. I punch in when I arrive at work, punch out -for lunch, punch in after lunch, and punch out at the end of the day. -Every minute is clocked between punch-in and punch-out times. - -Punching in defines a default task to clock time on whenever the clock -would normally stop. I found that with the default org-mode setup I -would lose clocked minutes during the day, a minute here, a minute -there, and that all adds up. This is especially true if you write -notes when moving to a DONE state - in this case the clock normally -stops before you have composed the note -- and good notes take a few -minutes to write. - -My clocking setup basically works like this: - -- Punch in (start the clock) - - This clocks in a predefined task by =org-id= that is the default - task to clock in whenever the clock normally stops -- Clock in tasks normally, and let moving to a DONE state clock out - - clocking out automatically clocks time on a parent task or moves - back to the predefined default task if no parent exists. -- Continue clocking whatever tasks you work on -- Punch out (stop the clock) - -I'm free to change the default task multiple times during the day but -with the clock moving up the project tree on clock out I no longer -need to do this. I simply have a single task that gets clocked in -when I punch-in. - -If I punch-in with a prefix on a task in =Project X= then that task -automatically becomes the default task and all clocked time goes on -that project until I either punch out or punch in some other task. - -My org files look like this: - -=todo.org=: -#+begin_src org :exports src -,#+FILETAGS: PERSONAL -... -,* Tasks -,** Organization - :PROPERTIES: - :CLOCK_MODELINE_TOTAL: today - :ID: eb155a82-92b2-4f25-a3c6-0304591af2f9 - :END: - ... -#+end_src - -If I am working on some task, then I simply clock in on the task. -Clocking out moves the clock up to a parent task with a todo keyword -(if any) which keeps the clock time in the same subtree. If there -is no parent task with a todo keyword then the clock moves back to -the default clocking task until I punch out or clock in some other -task. When an interruption occurs I start a capture task which -keeps clocked time on the interruption task until I close it with -C-c C-c. - -This works really well for me. - -For example, consider the following org file: - -#+begin_src org :exports src -,* TODO Project A -,** NEXT TASK 1 -,** TODO TASK 2 -,** TODO TASK 3 -,* Tasks -,** TODO Some miscellaneous task -#+end_src - -I'll work on this file in the following sequence: - -1. I punch in with =F9-I= at the start of my day - - That clocks in the =Organization= task by id in my =todo.org= file. - -2. =F12-SPC= to review my block agenda - - Pick 'TODO Some miscellaneous task' to work on next and clock that in with =I= - The clock is now on 'TODO Some miscellaneous task' - -3. I complete that task and mark it done with =C-c C-t d= - - This stops the clock and moves it back to the =Organization= task. - -4. Now I want to work on =Project A= so I clock in =Task 1= - - I work on Task 1 and mark it =DONE=. This clocks out =Task 1= and moves - the clock to =Project A=. Now I work on =Task 2= and clock that in. - -The entire time I'm working on and clocking some subtask of =Project A= -all of the clock time in the interval is applied somewhere to the =Project A= -tree. When I eventually mark =Project A= done then the clock will move -back to the default organization task. -** Clock Setup -:PROPERTIES: -:CUSTOM_ID: ClockSetup -:END: - -To get started we need to punch in which clocks in the default -task and keeps the clock running. This is now simply a matter of -punching in the clock with =F9 I=. You can do this anywhere. -Clocking out will now clock in the parent task (if there is one -with a todo keyword) or clock in the default task if not parent -exists. - -Keeping the clock running when moving a subtask to a =DONE= state -means clocking continues to apply to the project task. I can pick the -next task from the parent and clock that in without losing a minute or -two while I'm deciding what to work on next. - -I keep clock times, state changes, and other notes in the =:LOGBOOK:= -drawer. - -I have the following org-mode settings for clocking: - -#+header: :tangle yes -#+begin_src emacs-lisp -;; -;; Resume clocking task when emacs is restarted -(org-clock-persistence-insinuate) -;; -;; Show lot of clocking history so it's easy to pick items off the C-F11 list -(setq org-clock-history-length 23) -;; Resume clocking task on clock-in if the clock is open -(setq org-clock-in-resume t) -;; Change tasks to NEXT when clocking in -(setq org-clock-in-switch-to-state 'bh/clock-in-to-next) -;; Separate drawers for clocking and logs -(setq org-drawers (quote ("PROPERTIES" "LOGBOOK"))) -;; Save clock data and state changes and notes in the LOGBOOK drawer -(setq org-clock-into-drawer t) -;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration -(setq org-clock-out-remove-zero-time-clocks t) -;; Clock out when moving task to a done state -(setq org-clock-out-when-done t) -;; Save the running clock and all clock history when exiting Emacs, load it on startup -(setq org-clock-persist t) -;; Do not prompt to resume an active clock -(setq org-clock-persist-query-resume nil) -;; Enable auto clock resolution for finding open clocks -(setq org-clock-auto-clock-resolution (quote when-no-clock-is-running)) -;; Include current clocking task in clock reports -(setq org-clock-report-include-clocking-task t) - -(setq bh/keep-clock-running nil) - -(defun bh/clock-in-to-next (kw) - "Switch a task from TODO to NEXT when clocking in. -Skips capture tasks, projects, and subprojects. -Switch projects and subprojects from NEXT back to TODO" - (when (not (and (boundp 'org-capture-mode) org-capture-mode)) - (cond - ((and (member (org-get-todo-state) (list "TODO")) - (bh/is-task-p)) - "NEXT") - ((and (member (org-get-todo-state) (list "NEXT")) - (bh/is-project-p)) - "TODO")))) - -(defun bh/find-project-task () - "Move point to the parent (project) task if any" - (save-restriction - (widen) - (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) - (while (org-up-heading-safe) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (goto-char parent-task) - parent-task))) - -(defun bh/punch-in (arg) - "Start continuous clocking and set the default task to the -selected task. If no task is selected set the Organization task -as the default task." - (interactive "p") - (setq bh/keep-clock-running t) - (if (equal major-mode 'org-agenda-mode) - ;; - ;; We're in the agenda - ;; - (let* ((marker (org-get-at-bol 'org-hd-marker)) - (tags (org-with-point-at marker (org-get-tags-at)))) - (if (and (eq arg 4) tags) - (org-agenda-clock-in '(16)) - (bh/clock-in-organization-task-as-default))) - ;; - ;; We are not in the agenda - ;; - (save-restriction - (widen) - ; Find the tags on the current task - (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4)) - (org-clock-in '(16)) - (bh/clock-in-organization-task-as-default))))) - -(defun bh/punch-out () - (interactive) - (setq bh/keep-clock-running nil) - (when (org-clock-is-active) - (org-clock-out)) - (org-agenda-remove-restriction-lock)) - -(defun bh/clock-in-default-task () - (save-excursion - (org-with-point-at org-clock-default-task - (org-clock-in)))) - -(defun bh/clock-in-parent-task () - "Move point to the parent (project) task if any and clock in" - (let ((parent-task)) - (save-excursion - (save-restriction - (widen) - (while (and (not parent-task) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (if parent-task - (org-with-point-at parent-task - (org-clock-in)) - (when bh/keep-clock-running - (bh/clock-in-default-task))))))) - -(defvar bh/organization-task-id "eb155a82-92b2-4f25-a3c6-0304591af2f9") - -(defun bh/clock-in-organization-task-as-default () - (interactive) - (org-with-point-at (org-id-find bh/organization-task-id 'marker) - (org-clock-in '(16)))) - -(defun bh/clock-out-maybe () - (when (and bh/keep-clock-running - (not org-clock-clocking-in) - (marker-buffer org-clock-default-task) - (not org-clock-resolving-clocks-due-to-idleness)) - (bh/clock-in-parent-task))) - -(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append) -#+end_src - -I used to clock in tasks by ID using the following function but with -the new punch-in and punch-out I don't need these as much anymore. -=f9-SPC= calls =bh/clock-in-last-task= which switches the clock back -to the previously clocked task. - -#+header: :tangle yes -#+begin_src emacs-lisp -(require 'org-id) -(defun bh/clock-in-task-by-id (id) - "Clock in a task by id" - (org-with-point-at (org-id-find id 'marker) - (org-clock-in nil))) - -(defun bh/clock-in-last-task (arg) - "Clock in the interrupted task if there is one -Skip the default task and get the next one. -A prefix arg forces clock in of the default task." - (interactive "p") - (let ((clock-in-to-task - (cond - ((eq arg 4) org-clock-default-task) - ((and (org-clock-is-active) - (equal org-clock-default-task (cadr org-clock-history))) - (caddr org-clock-history)) - ((org-clock-is-active) (cadr org-clock-history)) - ((equal org-clock-default-task (car org-clock-history)) (cadr org-clock-history)) - (t (car org-clock-history))))) - (widen) - (org-with-point-at clock-in-to-task - (org-clock-in nil)))) -#+end_src -** Clocking in -:PROPERTIES: -:CUSTOM_ID: ClockingIn -:END: - -When I start or continue working on a task I clock it in with any of the following: - - - =C-c C-x C-i= - - =I= in the agenda - - =I= speed key on the first character of the heading line - - =f9 I= while on the task in the agenda - - =f9 I= while in the task in an org file -*** Setting a default clock task -:PROPERTIES: -:CUSTOM_ID: ClockingInDefaultTask -:END: - -I have a default =** Organization= task in my todo.org file that -I tend to put miscellaneous clock time on. This is the task I -clock in on when I punch in at the start of my work day with -=F9-I=. While reorganizing my org-files, reading email, -clearing my inbox, and doing other planning work that isn't for -a specific project I'll clock in this task. Punching-in -anywhere clocks in this Organization task as the default task. - -If I want to change the default clocking task I just visit the -new task in any org buffer and clock it in with =C-u C-u C-c C-x -C-i=. Now this new task that collects miscellaneous clock -minutes when the clock would normally stop. - -You can quickly clock in the default clocking task with =C-u C-c -C-x C-i d=. Another option is to repeatedly clock out so the -clock moves up the project tree until you clock out the -top-level task and the clock moves to the default task. -*** Using the clock history to clock in old tasks -:PROPERTIES: -:CUSTOM_ID: ClockingInByClockHistory -:END: - -You can use the clock history to restart clocks on old tasks you've -clocked or to jump directly to a task you have clocked previously. I -use this mainly to clock in whatever got interrupted by something. - -Consider the following scenario: - -- You are working on and clocking =Task A= (Organization) -- You get interrupted and switch to =Task B= (Document my use of org-mode) -- You complete =Task B= (Document my use of org-mode) -- Now you want to go back to =Task A= (Organization) again to continue - -This is easy to deal with. - -1. Clock in =Task A=, work on it -2. Go to =Task B= (or create a new task) and clock it in -3. When you are finished with =Task B= hit =C-u C-c C-x C-i i= - -This displays a clock history selection window like the following and -selects the interrupted =[i]= entry. - -*Clock history selection buffer for C-u C-c C-x C-i* -#+begin_example -Default Task -[d] norang Organization <-- Task B -The task interrupted by starting the last one -[i] norang Organization <-- Task B -Current Clocking Task -[c] org NEXT Document my use of org-mode <-- Task A -Recent Tasks -[1] org NEXT Document my use of org-mode <-- Task A -[2] norang Organization <-- Task B -... -[Z] org DONE Fix default section links <-- 35 clock task entries ago -#+end_example -** Clock Everything - Create New Tasks -:PROPERTIES: -:CUSTOM_ID: ClockEverythingWithNewTasks -:END: - -In order to clock everything you need a task for everything. That's -fine for planned projects but interruptions inevitably occur and you -need some place to record whatever time you spend on that -interruption. - -To deal with this we create a new capture task to record the thing we -are about to do. The workflow goes something like this: - -- You are clocking some task and an interruption occurs -- Create a quick capture task journal entry =C-c c j= -- Type the heading -- go do that thing (eat lunch, whatever) -- file it =C-c C-c=, this restores the clock back to the previous clocking task -- clock something else in or continue with the current clocking task - -This means you can ignore the details like where this task really -belongs in your org file layout and just get on with completing the -thing. Refiling a bunch of tasks later in a group when it is -convenient to refile the tasks saves time in the long run. - -If it's a one-shot uninteresting task (like a coffee break) I create -a capture journal entry for it that goes to the diary.org date tree. -If it's a task that actually needs to be tracked and marked done, and -applied to some project then I create a capture task instead which files it in -refile.org. -** Finding tasks to clock in -:PROPERTIES: -:CUSTOM_ID: FindTasksToClockIn -:END: - -To find a task to work on I use one of the following options -(generally listed most frequently used first) - -- Use the clock history C-u C-c C-x C-i - Go back to something I was clocking that is not finished -- Pick something off today's block agenda - =SCHEDULED= or =DEADLINE= items that need to be done soon -- Pick something off the =NEXT= tasks agenda view - Work on some unfinished task to move to completion -- Pick something off the other task list -- Use an agenda view with filtering to pick something to work on - -Punching in on the task you select will restrict the agenda view to that project -so you can focus on just that thing for some period of time. -** Editing clock entries -:PROPERTIES: -:CUSTOM_ID: EditingClockEntries -:END: - -Sometimes it is necessary to edit clock entries so they reflect -reality. I find I do this for maybe 2-3 entries in a week. - -Occassionally I cannot clock in a task on time because I'm away from -my computer. In this case the previous clocked task is still running -and counts time for both tasks which is wrong. - -I make a note of the time and then when I get back to my computer I -clock in the right task and edit the start and end times to correct -the clock history. - -To visit the clock line for an entry quickly use the agenda log mode. -=F12 a l= shows all clock lines for today. I use this to navigate to -the appropriate clock lines quickly. F11 goes to the current clocked -task but the agenda log mode is better for finding and visiting older -clock entries. - -Use =F12 a l= to open the agenda in log mode and show only logged -clock times. Move the cursor down to the clock line you need to edit -and hit =TAB= and you're there. - -To edit a clock entry just put the cursor on the part of the date you -want to edit (use the keyboard not the mouse - since the clicking on -the timestamp with the mouse goes back to the agenda for that day) and -hit the =S-= or =S-= keys to change the time. - -The following setting makes time editing use discrete minute intervals (no rounding) -increments: -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-time-stamp-rounding-minutes (quote (1 1))) -#+end_src - -Editing the time with the shift arrow combination also updates the -total for the clock line which is a nice convenience. - -I always check that I haven't created task overlaps when fixing time -clock entries by viewing them with log mode on in the agenda. There -is a new view in the agenda for this -- just hit =v c= in the daily -agenda and clock gaps and overlaps are identified. - -I want my clock entries to be as accurate as possible. - -The following setting shows 1 minute clocking gaps. -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-agenda-clock-consistency-checks - (quote (:max-duration "4:00" - :min-duration 0 - :max-gap 0 - :gap-ok-around ("4:00")))) -#+end_src -* Time reporting and tracking -:PROPERTIES: -:CUSTOM_ID: TimeReportingAndTracking -:END: -** Billing clients based on clocked time -:PROPERTIES: -:CUSTOM_ID: BillingClientsForClockedTime -:END: - -At the beginning of the month I invoice my clients for work done last -month. This is where I review my clocking data for correctness before -billing for the clocked time. - -Billing for clocked time basically boils down to the following steps: - -1. Verify that the clock data is complete and correct -2. Use clock reports to summarize time spent -3. Create an invoice based on the clock data - - I currently create invoices in an external software package - based on the org-mode clock data. - -4. Archive complete tasks so they are out of the way. - - See [[#Archiving][Archiving]] for more details. -*** Verify that the clock data is complete and correct -:PROPERTIES: -:CUSTOM_ID: VerifyingClockData -:END: - -Since I change tasks often (sometimes more than once in a minute) I -use the following setting to remove clock entries with a zero -duration. -#+header: :tangle yes -#+begin_src emacs-lisp -;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration -(setq org-clock-out-remove-zero-time-clocks t) -#+end_src - -This setting just keeps my clocked log entries clean - only keeping -clock entries that contribute to the clock report. - -Before invoicing for clocked time it is important to make sure your -clocked time data is correct. If you have a clocked time with an -entry that is not closed (ie. it has no end time) then that is a hole -in your clocked day and it gets counted as zero (0) for time spent on -the task when generating clock reports. Counting it as zero is almost -certainly wrong. - -To check for unclosed clock times I use the agenda-view clock check -(=v c= in the agenda). This view shows clocking gaps and overlaps in -the agenda. - -To check the last month's clock data I use =F12 a v m b v c= -which shows a full month in the agenda, moves to the previous -month, and shows the clocked times only. It's important to -remove any agenda restriction locks and filters when checking -the logs for gaps and overlaps. - -The clocked-time only display in the agenda makes it easy to quickly -scan down the list to see if an entry is missing an end time. If an -entry is not closed you can manually fix the clock entry based on -other clock info around that time. -*** Using clock reports to summarize time spent -:PROPERTIES: -:CUSTOM_ID: ClockReports -:END: - -Billable time for clients are kept in separate org files. - -To get a report of time spent on tasks for =XYZ.org= you simply visit -the =XYZ.org= file and run an agenda clock report for the last month -with =F12 < a v m b R=. This limits the agenda to this one file, -shows the agenda for a full month, moves to last month, and generates -a clock report. - -My agenda org clock report settings show 5 levels of detail with links -to the tasks. I like wider reports than the default compact setting -so I override the =:narrow= value. -#+header: :tangle yes -#+begin_src emacs-lisp -;; Agenda clock report parameters -(setq org-agenda-clockreport-parameter-plist - (quote (:link t :maxlevel 5 :fileskip0 t :compact t :narrow 80))) -#+end_src - -I used to have a monthly clock report dynamic block in each project -org file and manually updated them at the end of my billing cycle. I -used this as the basis for billing my clients for time spent on their -projects. I found updating the dynamic blocks fairly tedious when you -have more than a couple of files for the month. - -I have since moved to using agenda clock reports shortly after that -feature was added. I find this much more convenient. The data isn't -normally for consumption by anyone else so the format of the agenda -clock report format is great for my use-case. -** Task Estimates and column view -:PROPERTIES: -:CUSTOM_ID: TaskEstimates -:END: - -Estimating how long tasks take to complete is a difficult skill to -master. Org-mode makes it easy to practice creating estimates for -tasks and then clock the actual time it takes to complete. - -By repeatedly estimating tasks and reviewing how your estimate relates -to the actual time clocked you can tune your estimating skills. -*** Creating a task estimate with column mode -:PROPERTIES: -:CUSTOM_ID: CreatingTaskEstimates -:END: - -I use =properties= and =column view= to do project estimates. - -I set up column view globally with the following headlines -#+header: :tangle yes -#+begin_src emacs-lisp -; Set default column view headings: Task Effort Clock_Summary -(setq org-columns-default-format "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM") -#+end_src - -This makes column view show estimated task effort and clocked times -side-by-side which is great for reviewing your project estimates. - -A property called =Effort= records the estimated amount of time a -given task will take to complete. The estimate times I use are one -of: - -- 10 minutes -- 30 minutes -- 1 hour -- 2 hours -- 3 hours -- 4 hours -- 5 hours -- 6 hours -- 7 hours -- 8 hours - -These are stored for easy use in =column mode= in the global property -=Effort_ALL=. -#+header: :tangle yes -#+begin_src emacs-lisp -; global Effort estimate values -; global STYLE property values for completion -(setq org-global-properties (quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00") - ("STYLE_ALL" . "habit")))) -#+end_src - -To create an estimate for a task or subtree start column mode with -=C-c C-x C-c= and collapse the tree with =c=. This shows a table -overlayed on top of the headlines with the task name, effort estimate, -and clocked time in columns. - -With the cursor in the =Effort= column for a task you can easily set -the estimated effort value with the quick keys =1= through =9=. - -After setting the effort values exit =column mode= with =q=. -*** Saving your estimate -:PROPERTIES: -:CUSTOM_ID: SavingEstimate -:END: - -For fixed price jobs where you provide your estimate to a client, then -work to complete the project it is useful to save the original -estimate that is provided to the client. - -Save your original estimate by creating a dynamic clock report table -at the top of your estimated project subtree. Entering =C-c C-x i -RET= inserts a clock table report with your estimated values and any -clocked time to date. - -#+begin_src org :exports src -Original Estimate -,#+BEGIN: columnview :hlines 1 :id local -| Task | Estimated Effort | CLOCKSUM | -|-----------------------------+------------------+----------| -| ** TODO Project to estimate | 5:40 | | -| *** TODO Step 1 | 0:10 | | -| *** TODO Step 2 | 0:10 | | -| *** TODO Step 3 | 5:10 | | -| **** TODO Step 3.1 | 2:00 | | -| **** TODO Step 3.2 | 3:00 | | -| **** TODO Step 3.3 | 0:10 | | -| *** TODO Step 4 | 0:10 | | -,#+END: -#+end_src -I normally delete the =#+BEGIN:= and =#+END:= lines from the original -table after providing the estimate to the client to ensure I don't -accidentally update the table by hitting =C-c C-c= on the =#+BEGIN:= -line. - -Saving the original estimate data makes it possible to refine the -project tasks into subtasks as you work on the project without losing -the original estimate data. -*** Reviewing your estimate -:PROPERTIES: -:CUSTOM_ID: ReviewingEstimates -:END: - -=Column view= is great for reviewing your estimate. This shows your -estimated time value and the total clock time for the project -side-by-side. - -Creating a dynamic clock table with =C-c C-x i RET= is a great way to -save this project review if you need to make it available to other -applications. - -=C-c C-x C-d= also provides a quick summary of clocked time for the -current org file. -** Providing progress reports to others -:PROPERTIES: -:CUSTOM_ID: ProgressReporting -:END: -[2012-02-12 Sun 16:11] - -When someone wants details of what I've done recently I simple generate a -log report in the agenda with tasks I've completed and state changes combined -with a clock report for the appropriate time period. - -The following setting shows closed tasks and state changes in the -agenda. Combined with the agenda clock report ('R') I can quickly -generate all of the details required. - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Agenda log mode items to display (closed and state changes by default) -(setq org-agenda-log-mode-items (quote (closed state))) -#+end_src - -To generate the report I pull up the agenda for the appropriate time frame -(today, yesterday, this week, or last week) and hit the key sequence -=l R= to add the log report (without clocking data lines) and the agenda clock -report at the end. - -Then it's simply a matter of exporting the resulting agenda in some useful format -to provide to other people. =C-x C-w /tmp/agenda.html RET= exports to HTML -and =C-x C-w /tmp/agenda.txt RET= exports to plain text. Other formats are -available but I use these two the most. - -Combining this export with tag filters and =C-u R= can limit the -report to exactly the tags that people are interested in. - -* Tags -:PROPERTIES: -:CUSTOM_ID: Tags -:END: - -Tasks can have any number of arbitrary tags. Tags are used for: - -- filtering todo lists and agenda views -- providing context for tasks -- tagging notes -- tagging phone calls -- tagging meetings -- tagging tasks to be refiled -- tagging tasks in a WAITING state because a parent task is WAITING -- tagging cancelled tasks because a parent task is CANCELLED -- preventing export of some subtrees when publishing - -I use tags mostly for filtering in the agenda. This means you can -find tasks with a specific tag easily across your large number of -org-mode files. - -Some tags are mutually exclusive. These are defined in a group so -that only one of the tags can be applied to a task at a time -(disregarding tag inheritance). I use these types for tags for -applying context to a task. (Work tasks have an =@office= tag, and -are done at the office, Farm tasks have an =@farm= tag and are done at -the farm -- I can't change the oil on the tractor if I'm not at the -farm... so I hide these and other tasks by filtering my agenda view to -only =@office= tasks when I'm at the office.) - -Tasks are grouped together in org-files and a =#+FILETAGS:= entry -applies a tag to all tasks in the file. I use this to apply a tag to -all tasks in the file. My norang.org file creates a NORANG file tag -so I can filter tasks in the agenda in the norang.org file easily. -** Tags -:PROPERTIES: -:CUSTOM_ID: OrgTagAlist -:END: - -Here are my tag definitions with associated keys for filtering in the -agenda views. - -The startgroup - endgroup (=@XXX=) tags are mutually exclusive - -selecting one removes a similar tag already on the task. These are -the context tags - you can't be in two places at once so if a task is -marked with @farm and you add @office then the @farm tag is removed -automagically. - -The other tags =WAITING= .. =FLAGGED= are not mutually exclusive and -multiple tags can appear on a single task. Some of those tags are -created by todo state change triggers. The shortcut key is used to -add or remove the tag using =C-c C-q= or to apply the task for -filtering on the agenda. - -I have both =FARM= and =@farm= tags. =FARM= is set by a =FILETAGS= -entry and just gives me a way to filter anything farm related. The -=@farm= tag signifies that the task as to be done /at the farm/. If I -have to call someone about something that would have a =FARM= tag but -I can do that at home on my lunch break. I don't physically have to -be at the farm to make the call. - -#+header: :tangle yes -#+begin_src emacs-lisp -; Tags with fast selection keys -(setq org-tag-alist (quote ((:startgroup) - ("@errand" . ?e) - ("@office" . ?o) - ("@home" . ?H) - ("@farm" . ?f) - (:endgroup) - ("WAITING" . ?w) - ("HOLD" . ?h) - ("PERSONAL" . ?P) - ("WORK" . ?W) - ("FARM" . ?F) - ("ORG" . ?O) - ("NORANG" . ?N) - ("crypt" . ?E) - ("NOTE" . ?n) - ("CANCELLED" . ?c) - ("FLAGGED" . ??)))) - -; Allow setting single tags without the menu -(setq org-fast-tag-selection-single-key (quote expert)) - -; For tag searches ignore tasks with scheduled and deadline dates -(setq org-agenda-tags-todo-honor-ignore-options t) -#+end_src -** Filetags -:PROPERTIES: -:CUSTOM_ID: FileTags -:END: - -Filetags are a convenient way to apply one or more tags to all of the -headings in a file. - -Filetags look like this: - -#+begin_src org :exports src -,#+FILETAGS: NORANG @office -#+end_src - -I have the following =#+FILETAGS:= entries in my org-mode files: -*** Non-work related org-mode files -:PROPERTIES: -:CUSTOM_ID: TaggingNonWorkFiles -:END: - -| File | Tags | -|--------------+-----------------------| -| todo.org | PERSONAL | -| gsoc2009.org | GSOC PERSONAL | -| git.org | GIT WORK | -| org.org | ORG WORK | -| mark.org | MARK PERSONAL | -| farm.org | FARM PERSONAL | -*** Work related org-mode files -:PROPERTIES: -:CUSTOM_ID: TaggingWorkFiles -:END: - -| File | Tags | -|-------------+-----------------| -| norang.org | NORANG @office | -| ABC.org | ABC @office | -| XYZ.org | XYZ @office | -| ABC-DEF.org | ABC DEF @office | -| ABC-KKK.org | ABC KKK @office | -| YYY.org | YYY @office | -*** Refile tasks -:PROPERTIES: -:CUSTOM_ID: RefileTasks -:END: - -| File | Tags | -|------------+--------------| -| refile.org | REFILE | -|------------+--------------| -** State Trigger Tags -:PROPERTIES: -:CUSTOM_ID: StateTriggerTags -:END: - -The following tags are automatically added or removed by todo state -triggers described previously in [[#ToDoStateTriggers][ToDo state triggers]] - -- =WAITING= -- =CANCELLED= -* Handling Notes -:PROPERTIES: -:CUSTOM_ID: HandlingNotes -:END: - - Notes are little gems of knowledge that you come across during your - day. They are just like tasks except there is nothing to do (except - learn and memorize the gem of knowledge). Unfortunately there are way - too many gems to remember and my head explodes just thinking about it. - - org-mode to the rescue! - - Often I'll find some cool feature or thing I want to remember while - reading the org-mode and git mailing lists in Gnus. To create a note - I use my note capture template =C-c c n=, type a heading for the note - and =C-c C-c= to save it. The only other thing to do is to refile it - (later) to the appropriate project file. - - I have an agenda view just to find notes. Notes are refiled to an - appropriate project file and task. If there is no specific task it - belongs to it goes to the catchall =* Notes= task. I generally have a - catchall notes task in every project file. Notes are created with a - =NOTE= tag already applied by the capture template so I'm free to - refile the note anywhere. As long as the note is in a project file - that contributes to my agenda (ie. in org-agenda-files) then I can - find the note back easily with my notes agenda view by hitting the key - combination =F12 N=. I'm free to limit the agenda view of notes using - standard agenda tag filtering. - - Short notes with a meaningful headline are a great way to remember - technical details without the need to actually remember anything - - other than how to find them back when you need them using =F12 N=. - - Notes that are project related and not generally useful can be - archived with the project and removed from the agenda when the project - is removed. - - So my org notes go in org.org and my git notes go in git.org both - under the =* Notes= task. I'll forever be able to find those. A note - about some work project detail I want to remember with the project is - filed to the project task under the appropriate work org-mode file and - eventually gets removed from the agenda when the project is complete - and archived. -* Handling Phone Calls -:PROPERTIES: -:CUSTOM_ID: HandlinePhoneCalls -:END: - -Phone calls are interruptions and I use capture mode to deal with -these (like all interruptions). Most of the heavy lifting for phone -calls is done by capture mode. I use a special capture template for -phone calls combined with a custom function that replaces text with -information from my =bbdb= addressbook database. - -=C-c c p= starts a capture task normally and I'm free to enter notes -from the call in the template immediately. The cursor starts in the -template normally where the name of the caller would be inserted. I -can use a =bbdb= lookup function to insert the name with =f9-p= or I -can just type in whatever is appropriate. If a =bbdb= entry needs to -be created for the caller I can do that and replace the caller details -with =f9-p= anytime that is convenient for me. I found that -automatically calling the bbdb lookup function would interrupt my -workflow during the call in cases where the information about the -caller was not readily available. Sometimes I want to make notes first -and get the caller details later during the call. - -The phone call capture template starts the clock as soon as the phone -rings and I'm free to lookup and replace the caller in bbdb anytime -during or after the call. Capture mode starts the clock using the -=:clock-in t= setting in the template. - -When the phone call ends I simple do =C-c C-c= to close the capture -buffer and stop the clock. If I have to close it early and look up -other information during the call I just do =C-c C-c F9-SPC= to close -the capture buffer (which stops the clock) and then immediately switch -back to the last clocked item to continue the clock in the phone call -task. When the phone call ends I clock out which normally clocks in -my default task again (if any). - -Here is my set up for phone calls. I would like to thank Gregory -J. Grubbs for the original bbdb lookup functions which this version -is based on. - -Below is the partial capture template showing the phone call template -followed by the phone-call related lookup functions. - -#+header: :tangle no -#+begin_src emacs-lisp -;; Capture templates for: TODO tasks, Notes, appointments, phone calls, and org-protocol -(setq org-capture-templates - (quote (... - ("p" "Phone call" entry (file "~/git/org/refile.org") - "* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t) - ...))) -#+end_src - -#+header: :tangle yes -#+begin_src emacs-lisp -(require 'bbdb) -(require 'bbdb-com) - -(global-set-key (kbd " p") 'bh/phone-call) - -;; -;; Phone capture template handling with BBDB lookup -;; Adapted from code by Gregory J. Grubbs -(defun bh/phone-call () - "Return name and company info for caller from bbdb lookup" - (interactive) - (let* (name rec caller) - (setq name (completing-read "Who is calling? " - (bbdb-hashtable) - 'bbdb-completion-predicate - 'confirm)) - (when (> (length name) 0) - ; Something was supplied - look it up in bbdb - (setq rec - (or (first - (or (bbdb-search (bbdb-records) name nil nil) - (bbdb-search (bbdb-records) nil name nil))) - name))) - - ; Build the bbdb link if we have a bbdb record, otherwise just return the name - (setq caller (cond ((and rec (vectorp rec)) - (let ((name (bbdb-record-name rec)) - (company (bbdb-record-company rec))) - (concat "[[bbdb:" - name "][" - name "]]" - (when company - (concat " - " company))))) - (rec) - (t "NameOfCaller"))) - (insert caller))) -#+end_src -* GTD stuff -:PROPERTIES: -:CUSTOM_ID: GTD -:END: - -Most of my day is deadline/schedule driven. -I work off of the agenda first and then pick items from the todo lists as -outlined in [[#WhatDoIWorkOnNext][What do I work on next?]] -** Weekly Review Process -:PROPERTIES: -:CUSTOM_ID: GTDWeeklyReview -:END: - -The first day of the week (usually Monday) I do my weekly review. -I keep a list like this one to remind me what needs to be done. - -To keep the agenda fast I set -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-agenda-span 'day) -#+end_src -so only today's date is shown by default. I only need the weekly -view during my weekly review and this keeps my agenda generation -fast. - -I have a recurring task which keeps my weekly review checklist -handy. This pops up as a reminder on Monday's. This week I'm -doing my weekly review on Tuesday since Monday was a holiday. - -#+begin_src org :exports src -,* NEXT Weekly Review [0/6] - SCHEDULED: <2009-05-18 Mon ++1w> - :LOGBOOK:... - :PROPERTIES:... - - What to review: - - - [ ] Check follow-up folder - - [ ] Review weekly agenda =F12 a w //= - - [ ] Check clocking data for past week =v c= - - [ ] Review clock report for past week =R= - - Check where we spent time (too much or too little) and rectify this week - - [ ] Look at entire agenda for today =F12 SPC= - - [ ] Review projects =F12 SPC //= and =V= repeatedly to view each project - - - start work - - daily agenda first - knock off items - - then work on NEXT tasks -#+end_src -The first item [ ] Check follow-up folder makes me pull out the paper -file I dump stuff into all week long - things I need to take care of -but are in no particular hurry to deal with. Stuff I get in the mail -etc. that I don't want to deal with now. I just toss it in my -=Follow-Up= folder in the filing cabinet and forget about it until the -weekly review. - -I go through the folder and weed out anything that needs to be dealt -with. After that everything else is in =org-mode=. I tend to -schedule tasks onto the agenda for the coming week so that I don't -spend lots of time trying to find what needs to be worked on next. - -This works for me. Your mileage may vary ;) -** Project definition and finding stuck projects -:PROPERTIES: -:CUSTOM_ID: Projects -:END: - -I'm using a new lazy project definition to mark tasks as projects. -This requires zero effort from me. Any task with a subtask using a -todo keyword is a project. Period. - -Projects are 'stuck' if they have no subtask with a =NEXT= todo -keyword task defined. - -The org-mode stuck projects agenda view lists projects that have no -=NEXT= task defined. Stuck projects show up on my block agenda and I -tend to assign a =NEXT= task so the list remains empty. This helps to -keep projects moving forward. - -I disable the default org-mode stuck projects agenda view with the -following setting. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-stuck-projects (quote ("" nil nil ""))) -#+end_src - -This prevents org-mode from trying to show incorrect data if I select -the default stuck project view with =F12 #= from the agenda menu. My -customized stuck projects view is part of my block agenda displayed -with =F12 SPC=. - -Projects can have subprojects - and these subprojects can also be stuck. -Any project that is stuck shows up on the stuck projects list so I can -indicate or create a =NEXT= task to move that project forward. - -In the following example =Stuck Project A= is stuck because it has no -subtask which is =NEXT=. =Project C= is not stuck because it has -=NEXT= tasks =SubTask G= and =Task I=. =Stuck Sub Project D= is stuck -because =SubTask E= is not =NEXT= and there are no other tasks -available in this project. - -#+begin_src org :exports src -,* Category -,** TODO Stuck Project A -,*** TODO Task B -,** TODO Project C -,*** TODO Stuck Sub Project D -,**** TODO SubTask E -,*** TODO Sub Project F -,**** NEXT SubTask G -,**** TODO SubTask H -,*** NEXT Task I -,*** TODO Task J -#+end_src - -All of the stuck projects and subprojects show up in the stuck -projects list and that is my indication to assign or create =NEXT= -tasks until the stuck projects list is empty. Occasionally some -subtask is =WAITING= for something and the project is stuck until that -condition is satisfied. In this case I leave it on the stuck project -list and just work on something else. This stuck project 'bugs' me -regularly when I see it on the block agenda and this prompts me to -follow up on the thing that I'm waiting for. - -I have the following helper functions defined for projects which are -used by agenda views. -#+header: :tangle yes -#+begin_src emacs-lisp -(defun bh/is-project-p () - "Any task with a todo keyword subtask" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task has-subtask)))) - -(defun bh/is-project-subtree-p () - "Any task with a todo keyword that is in a project subtree. -Callers of this function already widen the buffer view." - (let ((task (save-excursion (org-back-to-heading 'invisible-ok) - (point)))) - (save-excursion - (bh/find-project-task) - (if (equal (point) task) - nil - t)))) - -(defun bh/is-task-p () - "Any task with a todo keyword and no subtask" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task (not has-subtask))))) - -(defun bh/is-subproject-p () - "Any task which is a subtask of another project" - (let ((is-subproject) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (while (and (not is-subproject) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq is-subproject t)))) - (and is-a-task is-subproject))) - -(defun bh/list-sublevels-for-projects-indented () - "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - This is normally used by skipping functions where this variable is already local to the agenda." - (if (marker-buffer org-agenda-restrict-begin) - (setq org-tags-match-list-sublevels 'indented) - (setq org-tags-match-list-sublevels nil)) - nil) - -(defun bh/list-sublevels-for-projects () - "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - This is normally used by skipping functions where this variable is already local to the agenda." - (if (marker-buffer org-agenda-restrict-begin) - (setq org-tags-match-list-sublevels t) - (setq org-tags-match-list-sublevels nil)) - nil) - -(defvar bh/hide-scheduled-and-waiting-next-tasks t) - -(defun bh/toggle-next-task-display () - (interactive) - (setq bh/hide-scheduled-and-waiting-next-tasks (not bh/hide-scheduled-and-waiting-next-tasks)) - (when (equal major-mode 'org-agenda-mode) - (org-agenda-redo)) - (message "%s WAITING and SCHEDULED NEXT Tasks" (if bh/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) - -(defun bh/skip-stuck-projects () - "Skip trees that are not stuck projects" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (bh/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - nil - next-headline)) ; a stuck project, has subtasks but no next task - nil)))) - -(defun bh/skip-non-stuck-projects () - "Skip trees that are not stuck projects" - ;; (bh/list-sublevels-for-projects-indented) - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (bh/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - next-headline - nil)) ; a stuck project, has subtasks but no next task - next-headline)))) - -(defun bh/skip-non-projects () - "Skip trees that are not projects" - ;; (bh/list-sublevels-for-projects-indented) - (if (save-excursion (bh/skip-non-stuck-projects)) - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - nil) - ((and (bh/is-project-subtree-p) (not (bh/is-task-p))) - nil) - (t - subtree-end)))) - (save-excursion (org-end-of-subtree t)))) - -(defun bh/skip-project-trees-and-habits () - "Skip trees that are projects" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - (t - nil))))) - -(defun bh/skip-projects-and-habits-and-single-tasks () - "Skip trees that are projects, tasks that are habits, single non-project tasks" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((org-is-habit-p) - next-headline) - ((and bh/hide-scheduled-and-waiting-next-tasks - (member "WAITING" (org-get-tags-at))) - next-headline) - ((bh/is-project-p) - next-headline) - ((and (bh/is-task-p) (not (bh/is-project-subtree-p))) - next-headline) - (t - nil))))) - -(defun bh/skip-project-tasks-maybe () - "Show tasks related to the current restriction. -When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. -When not restricted, skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max)))) - (limit-to-project (marker-buffer org-agenda-restrict-begin))) - (cond - ((bh/is-project-p) - next-headline) - ((org-is-habit-p) - subtree-end) - ((and (not limit-to-project) - (bh/is-project-subtree-p)) - subtree-end) - ((and limit-to-project - (bh/is-project-subtree-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - (t - nil))))) - -(defun bh/skip-project-tasks () - "Show non-project tasks. -Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - ((bh/is-project-subtree-p) - subtree-end) - (t - nil))))) - -(defun bh/skip-non-project-tasks () - "Show project tasks. -Skip project and sub-project tasks, habits, and loose non-project tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((bh/is-project-p) - next-headline) - ((org-is-habit-p) - subtree-end) - ((and (bh/is-project-subtree-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - ((not (bh/is-project-subtree-p)) - subtree-end) - (t - nil))))) - -(defun bh/skip-projects-and-habits () - "Skip trees that are projects and tasks that are habits" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((bh/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - (t - nil))))) - -(defun bh/skip-non-subprojects () - "Skip trees that are not projects" - (let ((next-headline (save-excursion (outline-next-heading)))) - (if (bh/is-subproject-p) - nil - next-headline))) -#+end_src -* Archiving -:PROPERTIES: -:CUSTOM_ID: Archiving -:END: -** Archiving Subtrees -:PROPERTIES: -:CUSTOM_ID: ArchivingSubtrees -:END: - -My archiving procedure has changed. I used to move entire subtrees to -a separate archive file for the project. Task subtrees in =FILE.org= -get archived to =FILE.org_archive= using the =a y= command in the -agenda. - -I still archive to the same archive file as before but now I archive -any done state todo task that is old enough to archive. Tasks to -archive are listed automatically at the end of my block agenda and -these are guaranteed to be old enough that I've already billed any -time associated with these tasks. This cleans up my project trees and -removes the old tasks that are no longer interesting. The archived -tasks get extra property data created during the archive procedure so -that it is possible to reconstruct exactly where the archived entry -came from in the rare case where you want to unarchive something. - -My archive files are huge but so far I haven't found a need to split -them by year (or decade) :) - -Archivable tasks show up in the last section of my block agenda when a -new month starts. Any tasks that are done but have no timestamps this -month or last month (ie. they are over 30 days old) are available to -archive. Timestamps include closed dates, notes, clock data, etc - any -active or inactive timestamp in the task. - -Archiving is trivial. Just mark all of the entries in the block agenda -using the =m= key and then archive them all to the appropriate place -with =B $=. This normally takes less than 5 minutes once a month. -** Archive Setup -:PROPERTIES: -:CUSTOM_ID: ArchiveSetup -:END: - -I no longer use an =ARCHIVE= property in my subtrees. Tasks can just -archive normally to the =Archived Tasks= heading in the archive file. - -The following setting ensures that task states are untouched when they -are archived. This makes it possible to archive tasks that are not -marked =DONE=. By default tasks are archived under the heading =* -Archived Tasks= in the archive file. - -This archiving function does not keep your project trees intact. It -archives done state tasks after they are old enough to they are -removed from the main org file. It should be possible to reconstruct -the original tree from the archive detail properties but I've never -needed to do this yet. The archived detail is very useful the few -times a year I actually need to look for some archived data but most -of the time I just move it out of the way and keep it for historical -purposes. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-archive-mark-done nil) -(setq org-archive-location "%s_archive::* Archived Tasks") -#+end_src - -#+header: :tangle yes -#+begin_src emacs-lisp -(defun bh/skip-non-archivable-tasks () - "Skip trees that are not available for archiving" - (save-restriction - (widen) - ;; Consider only tasks with done todo headings as archivable candidates - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (if (member (org-get-todo-state) org-todo-keywords-1) - (if (member (org-get-todo-state) org-done-keywords) - (let* ((daynr (string-to-int (format-time-string "%d" (current-time)))) - (a-month-ago (* 60 60 24 (+ daynr 1))) - (last-month (format-time-string "%Y-%m-" (time-subtract (current-time) (seconds-to-time a-month-ago)))) - (this-month (format-time-string "%Y-%m-" (current-time))) - (subtree-is-current (save-excursion - (forward-line 1) - (and (< (point) subtree-end) - (re-search-forward (concat last-month "\\|" this-month) subtree-end t))))) - (if subtree-is-current - subtree-end ; Has a date in this month or last month, skip it - nil)) ; available to archive - (or subtree-end (point-max))) - next-headline)))) -#+end_src -** Archive Tag - Hiding Information -:PROPERTIES: -:CUSTOM_ID: ArchiveTagHidesInfo -:END: - -The only time I set the ARCHIVE tag on a task is to prevent it from -opening by default because it has tons of information I don't really -need to look at on a regular basis. I can open the task with C-TAB if -I need to see the gory details (like a huge table of data related to -the task) but normally I don't need that information displayed. -** When to Archive -:PROPERTIES: -:CUSTOM_ID: WhenToArchive -:END: - -Archiving monthly works well for me. I keep completed tasks around -for at least 30 days before archiving them. This keeps current -clocking information for the last 30 days out of the archives. This -keeps my files that contribute to the agenda fairly current (this -month, and last month, and anything that is unfinished). I only -rarely visit tasks in the archive when I need to pull up ancient -history for something. - -Archiving keeps my main working files clutter-free. If I ever need -the detail for the archived tasks they are available in the -appropriate archive file. -* Publishing and Exporting -:PROPERTIES: -:CUSTOM_ID: Publishing -:END: - -I don't do a lot of publishing for other people but I do keep a set of -private client system documentation online. Most of this -documentation is a collection of notes exported to HTML. - -Everything at http://doc.norang.ca/ is generated by publishing -org-files. This includes the index pages on this site. - -Org-mode can export to a variety of publishing formats including (but not limited to) - -- ASCII - (plain text - but not the original org-mode file) -- HTML -- LaTeX -- Docbook - which enables getting to lots of other formats like ODF, XML, etc -- PDF - via LaTeX or Docbook -- iCal - -I haven't begun the scratch the surface of what org-mode is capable of -doing. My main use case for org-mode publishing is just to create -HTML documents for viewing online conveniently. Someday I'll get time -to try out the other formats when I need them for something. -** New Exporter Setup -[2013-04-20 Sat 08:18] - -The new exporter created by Nicolas Goaziou was introduced in org 8.0. - -I have the following setup for the exporters I use. - -Alphabetical listing options need to be set before the exporters are -loaded for filling to work correctly. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-alphabetical-lists t) - -;; Explicitly load required exporters -(require 'ox-html) -(require 'ox-latex) -(require 'ox-ascii) -#+end_src - - -*** Conversion from the old exporter to the new exporter -[2013-04-20 Sat 08:20] - -Here is the list of changes I made to move from the old exporter (pre -org 8.0) to the new exporter. - -- Explicitly require exporters - - - Add =ox-html= - - - Add =ox-latex= - - - Add =ox-ascii= - -- Rename variables - - - =org-export-html-style-extra= to =org-html-head-extra= - - - =org-export-html-validation-link= to =org-html-validation-link= - - - =org-export-html-inline-images= to =org-html-inline-images= - - - =org-export-html-style-include-default= to =org-html-head-include-default-style= - - - =org-export-html-xml-declaration= to =org-html-xml-declaration= - - - =org-export-latex-listings= to =org-latex-listings= - - - =org-export-html-style-include-scripts= to =org-html-head-include-scripts= - -- Publishing changes - - - Rename =:publishing-function= - - - =org-publish-org-to-html= to =org-html-publish-to-html= - - - =org-publish-org-to-org= to =org-org-publish-to-org= - - - Change =:style= to =:html-head= - -- Change =bh/is-late-deadline= to handle modified deadline string in agenda - -- Reverse agenda sorting for late deadlines - - These are no longer reported with negative values on the agenda - -- Add a blank line after my inactive timestamps following headings to - prevent them from being exported. - -** Org-babel Setup -:PROPERTIES: -:CUSTOM_ID: OrgBabel -:END: - -Org-babel makes it easy to generate decent graphics using external -packages like ditaa, graphviz, PlantUML, and others. - -The setup is really easy. =ditaa= is provided with the org-mode -source. You'll have to install the =graphviz= and =PlantUML= packages -on your system. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-ditaa-jar-path "~/git/org-mode/contrib/scripts/ditaa.jar") -(setq org-plantuml-jar-path "~/java/plantuml.jar") - -(add-hook 'org-babel-after-execute-hook 'bh/display-inline-images 'append) - -; Make babel results blocks lowercase -(setq org-babel-results-keyword "results") - -(defun bh/display-inline-images () - (condition-case nil - (org-display-inline-images) - (error nil))) - -(org-babel-do-load-languages - (quote org-babel-load-languages) - (quote ((emacs-lisp . t) - (dot . t) - (ditaa . t) - (R . t) - (python . t) - (ruby . t) - (gnuplot . t) - (clojure . t) - (sh . t) - (ledger . t) - (org . t) - (plantuml . t) - (latex . t)))) - -; Do not prompt to confirm evaluation -; This may be dangerous - make sure you understand the consequences -; of setting this -- see the docstring for details -(setq org-confirm-babel-evaluate nil) - -; Use fundamental mode when editing plantuml blocks with C-c ' -(add-to-list 'org-src-lang-modes (quote ("plantuml" . fundamental))) -#+end_src - -Now you just create a =begin-src= block for the appropriate tool, edit -the text, and build the pictures with =C-c C-c=. After evaluating the -block results are displayed. You can toggle display of inline images -with =C-c C-x C-v= - -I disable startup with inline images because when I access my -org-files from an SSH session without X this breaks (say from my -Android phone) it fails when trying to display the images on a non-X -session. It's much more important for me to be able to access my -org files from my Android phone remotely than it is to see images on -startup. - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Don't enable this because it breaks access to emacs from my Android phone -(setq org-startup-with-inline-images nil) -#+end_src -** Playing with ditaa -:PROPERTIES: -:CUSTOM_ID: playingwithditaa -:END: - -[[http://ditaa.sourceforge.net/][ditaa]] is a great tool for quickly generating graphics to convey ideas -and =ditaa= is distributed with org-mode! All of the graphics in this -document are automatically generated by org-mode using plain text -source. - -Artist mode makes it easy to create boxes and lines for ditaa -graphics. - -The source for a ditaa graphic looks like this in org-mode: -#+begin_src org :exports src -,#+begin_src ditaa :file some_filename.png :cmdline -r -s 0.8 - -,#+end_src -#+end_src -Here's an example without the =#+begin_src= and =#+end_src= lines. - -#+begin_src ditaa :file communication.png :cmdline -r -s 0.8 :exports both :cache yes - +-----------+ +---------+ - | PLC | | | - | Network +<------>+ PLC +<---=---------+ - | cRED | | c707 | | - +-----------+ +----+----+ | - ^ | - | | - | +----------------|-----------------+ - | | | | - v v v v - +----------+ +----+--+--+ +-------+---+ +-----+-----+ Windows clients - | | | | | | | | +----+ +----+ - | Database +<----->+ Shared +<---->+ Executive +<-=-->+ Operator +<---->|cYEL| . . .|cYEL| - | c707 | | Memory | | c707 | | Server | | | | | - +--+----+--+ |{d} cGRE | +------+----+ | c707 | +----+ +----+ - ^ ^ +----------+ ^ +-------+---+ - | | | - | +--------=--------------------------+ - v -+--------+--------+ -| | -| Millwide System | -------- Data --------- -| cBLU | --=----- Signals ---=-- -+-----------------+ -#+end_src - -#+results[57642756cd4e509e2a4f67c40a5147ecb935933e]: -[[file:communication.png]] - -** Playing with graphviz -:PROPERTIES: -:CUSTOM_ID: Graphviz -:END: - -[[http://www.graphviz.org/][Graphviz]] is another great tool for creating graphics in your documents. - -The source for a graphviz graphic looks like this in org-mode: -#+begin_src org :exports src -,#+begin_src dot :file some_filename.png :cmdline -Kdot -Tpng - -,#+end_src -#+end_src - -#+begin_src dot :file gv01.png :cmdline -Kdot -Tpng :exports both :cache yes -digraph G { - size="8,6" - ratio=expand - edge [dir=both] - plcnet [shape=box, label="PLC Network"] - subgraph cluster_wrapline { - label="Wrapline Control System" - color=purple - subgraph { - rank=same - exec - sharedmem [style=filled, fillcolor=lightgrey, shape=box] - } - edge[style=dotted, dir=none] - exec -> opserver - exec -> db - plc -> exec - edge [style=line, dir=both] - exec -> sharedmem - sharedmem -> db - plc -> sharedmem - sharedmem -> opserver - } - plcnet -> plc [constraint=false] - millwide [shape=box, label="Millwide System"] - db -> millwide - - subgraph cluster_opclients { - color=blue - label="Operator Clients" - rankdir=LR - labelloc=b - node[label=client] - opserver -> client1 - opserver -> client2 - opserver -> client3 - } -} -#+end_src - -#+results[4bf665d19d319ee40e628cfc80170af69cfb776f]: -[[file:gv01.png]] - -The =-Kdot= is optional (defaults to =dot=) but you can substitute other graphviz -types instead here (ie. =twopi=, =neato=, =circo=, etc). -** Playing with PlantUML -:PROPERTIES: -:CUSTOM_ID: PlantUML -:END: - -I have just started using [[http://plantuml.sourceforge.net/][PlantUML]] which is built on top of [[http://www.graphviz.org/][Graphviz]]. -I'm still experimenting with this but so far I like it a lot. The -todo state change diagrams in this document are created with PlantUML. - -The source for a PlantUML graphic looks like this in org-mode: -#+begin_src org :exports src -,#+begin_src plantuml :file somefile.png - -,#+end_src -#+end_src -*** Sequence Diagram -:PROPERTIES: -:CUSTOM_ID: PlantUMLSequence -:END: -[2011-04-29 Fri 19:03] - -#+begin_src plantuml :file sequence.png :exports both :cache yes -title Example Sequence Diagram -activate Client -Client -> Server: Session Initiation -note right: Client requests new session -activate Server -Client <-- Server: Authorization Request -note left: Server requires authentication -Client -> Server: Authorization Response -note right: Client provides authentication details -Server --> Client: Session Token -note left: Session established -deactivate Server -Client -> Client: Saves token -deactivate Client -#+end_src - -#+results[6aff72a7a7c6801812c59c389114f65d462a61a0]: -[[file:sequence.png]] - -*** Activity Diagram -:PROPERTIES: -:CUSTOM_ID: PlantUMLActivity -:END: -[2011-09-10 Sat 08:36] - -#+begin_src plantuml :file activity.png :exports both :cache yes -title Example Activity Diagram -note right: Example Function -(*)--> "Step 1" ---> "Step 2" --> "Step 3" ---> "Step 4" ---> === STARTLOOP === -note top: For each element in the array -if "Are we done?" then - -> [no] "Do this" - -> "Do that" - note bottom: Important note\ngoes here - -up-> "Increment counters" - --> === STARTLOOP === -else - --> [yes] === ENDLOOP === -endif ---> "Last Step" ---> (*) -#+end_src - -#+results[1a0bdaefe8858ab0a55252b9c57fc16f57e27ea5]: -[[file:activity.png]] - -*** Usecase Diagram -:PROPERTIES: -:CUSTOM_ID: PlantUMLUseCase -:END: - -#+begin_src plantuml :file usecase.png :exports both :cache yes -LabUser --> (Runs Simulation) -LabUser --> (Analyses Results) -#+end_src - -#+results[14e8911f8940efbc6b90b57dcfa4eecce4a31d9f]: -[[file:usecase.png]] - -*** Object Diagram -:PROPERTIES: -:CUSTOM_ID: PlantUMLObject -:END: - -#+begin_src plantuml :file object.png :exports both :cache yes -Object1 <|-- Object2 -Object1: someVar -Object1: execute() -Object2: getState() -Object2: setState() -Object2: state -#+end_src - -#+results[43eece3c12be40bac32cf12898e47d66ec1251da]: -[[file:object.png]] - -*** State Diagram -:PROPERTIES: -:CUSTOM_ID: PlantUMLState -:END: - -#+begin_src plantuml :file plantuml_example_states.png :exports both :cache yes -[*] --> Start -Start -> State2 -State2 -> State3 -note right of State3: Notes can be\nattached to states -State2 --> State4 -State4 -> Finish -State3 --> Finish -Finish --> [*] -#+end_src - -#+results[d349aa79d785fec37ad60b1bcf43ced6df10aeb6]: -[[file:plantuml_example_states.png]] - -** Publishing Single Files -:PROPERTIES: -:CUSTOM_ID: PublishingSingleFiles -:END: - -Org-mode exports the current file to one of the standard formats by -invoking an export function. The standard key binding for this is -=C-c C-e= followed by the key for the type of export you want. - -This works great for single files or parts of files -- if you narrow -the buffer to only part of the org-mode file then you only get the -narrowed detail in the export. -** Publishing Projects -:PROPERTIES: -:CUSTOM_ID: PublishingProjects -:END: - -I mainly use publishing for publishing multiple files or projects. I -don't want to remember where the created export file needs to move to -and org-mode projects are a great solution to this. - -The [[http://doc.norang.ca]] website (and a bunch of other files that are -not publicly available) are all created by editing org-mode files and -publishing the project the file is contained in. This is great for -people like me who want to figure out the details once and forget -about it. I love stuff that Just Works(tm). - -I have 5 main projects I use org-mode publishing for currently: - -- norang (website) -- doc.norang.ca (website, published documents) -- doc.norang.ca/private (website, non-published documents) -- www.norang.ca/tmp (temporary publishing site for testing org-mode stuff) -- org files (which are selectively included by other websites) - -Here's my publishing setup: - -#+header: :tangle yes -#+begin_src emacs-lisp -; experimenting with docbook exports - not finished -(setq org-export-docbook-xsl-fo-proc-command "fop %s %s") -(setq org-export-docbook-xslt-proc-command "xsltproc --output %s /usr/share/xml/docbook/stylesheet/nwalsh/fo/docbook.xsl %s") -; -; Inline images in HTML instead of producting links to the image -(setq org-html-inline-images t) -; Do not use sub or superscripts - I currently don't need this functionality in my documents -(setq org-export-with-sub-superscripts nil) -; Use org.css from the norang website for export document stylesheets -(setq org-html-head-extra "") -(setq org-html-head-include-default-style nil) -; Do not generate internal css formatting for HTML exports -(setq org-export-htmlize-output-type (quote css)) -; Export with LaTeX fragments -(setq org-export-with-LaTeX-fragments t) -; Increase default number of headings to export -(setq org-export-headline-levels 6) - -; List of projects -; norang - http://www.norang.ca/ -; doc - http://doc.norang.ca/ -; org-mode-doc - http://doc.norang.ca/org-mode.html and associated files -; org - miscellaneous todo lists for publishing -(setq org-publish-project-alist - ; - ; http://www.norang.ca/ (norang website) - ; norang-org are the org-files that generate the content - ; norang-extra are images and css files that need to be included - ; norang is the top-level project that gets published - (quote (("norang-org" - :base-directory "~/git/www.norang.ca" - :publishing-directory "/ssh:www-data@www:~/www.norang.ca/htdocs" - :recursive t - :table-of-contents nil - :base-extension "org" - :publishing-function org-html-publish-to-html - :style-include-default nil - :section-numbers nil - :table-of-contents nil - :html-head "" - :author-info nil - :creator-info nil) - ("norang-extra" - :base-directory "~/git/www.norang.ca/" - :publishing-directory "/ssh:www-data@www:~/www.norang.ca/htdocs" - :base-extension "css\\|pdf\\|png\\|jpg\\|gif" - :publishing-function org-publish-attachment - :recursive t - :author nil) - ("norang" - :components ("norang-org" "norang-extra")) - ; - ; http://doc.norang.ca/ (norang website) - ; doc-org are the org-files that generate the content - ; doc-extra are images and css files that need to be included - ; doc is the top-level project that gets published - ("doc-org" - :base-directory "~/git/doc.norang.ca/" - :publishing-directory "/ssh:www-data@www:~/doc.norang.ca/htdocs" - :recursive nil - :section-numbers nil - :table-of-contents nil - :base-extension "org" - :publishing-function (org-html-publish-to-html org-org-publish-to-org) - :style-include-default nil - :html-head "" - :author-info nil - :creator-info nil) - ("doc-extra" - :base-directory "~/git/doc.norang.ca/" - :publishing-directory "/ssh:www-data@www:~/doc.norang.ca/htdocs" - :base-extension "css\\|pdf\\|png\\|jpg\\|gif" - :publishing-function org-publish-attachment - :recursive nil - :author nil) - ("doc" - :components ("doc-org" "doc-extra")) - ("doc-private-org" - :base-directory "~/git/doc.norang.ca/private" - :publishing-directory "/ssh:www-data@www:~/doc.norang.ca/htdocs/private" - :recursive nil - :section-numbers nil - :table-of-contents nil - :base-extension "org" - :publishing-function (org-html-publish-to-html org-org-publish-to-org) - :style-include-default nil - :html-head "" - :auto-sitemap t - :sitemap-filename "index.html" - :sitemap-title "Norang Private Documents" - :sitemap-style "tree" - :author-info nil - :creator-info nil) - ("doc-private-extra" - :base-directory "~/git/doc.norang.ca/private" - :publishing-directory "/ssh:www-data@www:~/doc.norang.ca/htdocs/private" - :base-extension "css\\|pdf\\|png\\|jpg\\|gif" - :publishing-function org-publish-attachment - :recursive nil - :author nil) - ("doc-private" - :components ("doc-private-org" "doc-private-extra")) - ; - ; Miscellaneous pages for other websites - ; org are the org-files that generate the content - ("org-org" - :base-directory "~/git/org/" - :publishing-directory "/ssh:www-data@www:~/org" - :recursive t - :section-numbers nil - :table-of-contents nil - :base-extension "org" - :publishing-function org-html-publish-to-html - :style-include-default nil - :html-head "" - :author-info nil - :creator-info nil) - ; - ; http://doc.norang.ca/ (norang website) - ; org-mode-doc-org this document - ; org-mode-doc-extra are images and css files that need to be included - ; org-mode-doc is the top-level project that gets published - ; This uses the same target directory as the 'doc' project - ("org-mode-doc-org" - :base-directory "~/git/org-mode-doc/" - :publishing-directory "/ssh:www-data@www:~/doc.norang.ca/htdocs" - :recursive t - :section-numbers nil - :table-of-contents nil - :base-extension "org" - :publishing-function (org-html-publish-to-html) - :plain-source t - :htmlized-source t - :style-include-default nil - :html-head "" - :author-info nil - :creator-info nil) - ("org-mode-doc-extra" - :base-directory "~/git/org-mode-doc/" - :publishing-directory "/ssh:www-data@www:~/doc.norang.ca/htdocs" - :base-extension "css\\|pdf\\|png\\|jpg\\|gif\\|org" - :publishing-function org-publish-attachment - :recursive t - :author nil) - ("org-mode-doc" - :components ("org-mode-doc-org" "org-mode-doc-extra")) - ; - ; http://doc.norang.ca/ (norang website) - ; org-mode-doc-org this document - ; org-mode-doc-extra are images and css files that need to be included - ; org-mode-doc is the top-level project that gets published - ; This uses the same target directory as the 'doc' project - ("tmp-org" - :base-directory "/tmp/publish/" - :publishing-directory "/ssh:www-data@www:~/www.norang.ca/htdocs/tmp" - :recursive t - :section-numbers nil - :table-of-contents nil - :base-extension "org" - :publishing-function (org-html-publish-to-html org-org-publish-to-org) - :html-head "" - :plain-source t - :htmlized-source t - :style-include-default nil - :auto-sitemap t - :sitemap-filename "index.html" - :sitemap-title "Test Publishing Area" - :sitemap-style "tree" - :author-info t - :creator-info t) - ("tmp-extra" - :base-directory "/tmp/publish/" - :publishing-directory "/ssh:www-data@www:~/www.norang.ca/htdocs/tmp" - :base-extension "css\\|pdf\\|png\\|jpg\\|gif" - :publishing-function org-publish-attachment - :recursive t - :author nil) - ("tmp" - :components ("tmp-org" "tmp-extra"))))) - -; I'm lazy and don't want to remember the name of the project to publish when I modify -; a file that is part of a project. So this function saves the file, and publishes -; the project that includes this file -; -; It's bound to C-S-F12 so I just edit and hit C-S-F12 when I'm done and move on to the next thing -(defun bh/save-then-publish (&optional force) - (interactive "P") - (save-buffer) - (org-save-all-org-buffers) - (let ((org-html-head-extra) - (org-html-validation-link "Validate XHTML 1.0")) - (org-publish-current-project force))) - -(global-set-key (kbd "C-s-") 'bh/save-then-publish) -#+end_src - -The main projects are =norang=, =doc=, =doc-private=, =org-mode-doc=, -and =tmp=. These projects publish directly to the webserver directory -on a remote web server that serves the site. Publishing one of these -projects exports all modified pages, generates images, and copies the -resulting files to the webserver so that they are immediately -available for viewing. - -The http://doc.norang.ca/ site contains subdirectories with client and -private documentation that are restricted by using Apache Basic -authentication. I don't create links to these sites from the publicly -viewable pages. http://doc.norang.ca/someclient/ would show the index -for any org files under =~/git/doc.norang.ca/someclient/= if that is -set up as a viewable website. I use most of the information myself -but give access to clients if they are interested in the -information/notes that I keep about their systems. - -This works great for me - I know where my notes are and I can access -them from anywhere on the internet. I'm also free to share notes with -other people by simply giving them the link to the appropriate site. - -All I need to remember to do is edit the appropriate org file and -publish it with C-S-F12 -- not exactly hard :) - -I added a temporary publishing site for testing exports and -validation. This is the =tmp= site which takes files from -=/tmp/publish= and exports those files to a website publishing -directory. This makes it easy to try new throw-away things on a live -server. -** Miscellaneous Export Settings -:PROPERTIES: -:CUSTOM_ID: MiscBabelExportSettings -:END: - -This is a collection of export and publishing related settings that I -use. -*** Fontify Latex listings for source blocks -:PROPERTIES: -:CUSTOM_ID: FontifyLatexListings -:END: - -For export to latex I use the following setting to get fontified -listings from source blocks: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-latex-listings t) -#+end_src -*** Export HTML without XML header -:PROPERTIES: -:CUSTOM_ID: ExportHTMLWithoutXMLHeader -:END: - -I use the following setting to remove the xml header line for HTML -exports. This xml line was confusing Open Office when opening the -HTML to convert to ODT. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-html-xml-declaration (quote (("html" . "") - ("was-html" . "") - ("php" . "\"; ?>")))) -#+end_src -*** Allow binding variables on export without confirmation -:PROPERTIES: -:CUSTOM_ID: AllowVariableBindingForExport -:END: - -The following setting allows #+BIND: variables to be set on export -without confirmation. In rare situations where I want to override -some org-mode variable for export this allows exporting the document -without a prompt. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-export-allow-BIND t) -#+end_src -* Reminders -:PROPERTIES: -:CUSTOM_ID: Reminders -:END: - -I use appt for reminders. It's simple and unobtrusive -- putting -pending appointments in the status bar and beeping as 12, 9, 6, 3, -and 0 minutes before the appointment is due. - -Everytime the agenda is displayed (and that's lots for me) the -appointment list is erased and rebuilt from the current agenda -details for today. This means everytime I reschedule something, add -or remove tasks that are time related the appointment list is -automatically updated the next time I look at the agenda. -** Reminder Setup -:PROPERTIES: -:CUSTOM_ID: ReminderSetup -:END: - -#+header: :tangle yes -#+begin_src emacs-lisp -; Erase all reminders and rebuilt reminders for today from the agenda -(defun bh/org-agenda-to-appt () - (interactive) - (setq appt-time-msg-list nil) - (org-agenda-to-appt)) - -; Rebuild the reminders everytime the agenda is displayed -(add-hook 'org-finalize-agenda-hook 'bh/org-agenda-to-appt 'append) - -; This is at the end of my .emacs - so appointments are set up when Emacs starts -(bh/org-agenda-to-appt) - -; Activate appointments so we get notifications -(appt-activate t) - -; If we leave Emacs running overnight - reset the appointments one minute after midnight -(run-at-time "24:01" nil 'bh/org-agenda-to-appt) -#+end_src -* Productivity Tools -:PROPERTIES: -:CUSTOM_ID: ProductivityTools -:NOBLOCKING: t -:END: - -This section is a miscellaneous collection of Emacs customizations that I use -with org-mode so that it Works-For-Me(tm). -** Abbrev-mode and Skeletons -:PROPERTIES: -:CUSTOM_ID: AbbrevMode -:END: -[2011-09-26 Mon 05:44] - -I use skeletons with abbrev-mode to quickly add preconfigured blocks to my -Emacs edit buffers. - -I have blocks for creating: - - - generic blocks in org-mode - - plantuml blocks in org-mode - - plantuml activity diagram block in org-mode - - plantuml sequence diagram block in org-mode - - graphviz dot blocks in org-mode - - ditaa blocks in org-mode - - elisp source blocks in org-mode - -I still use =< e TAB= and =< s TAB= for creating example blocks and -simple shell script blocks that need no further parameters. - -Here's my current setup for org-mode related skeletons. Each one -defines an abbrev-mode shortcut so I can type =splantumlRET= to create -a Plantuml block. This prompts for the filename (without extension) for -the generated image file. - -At work I add a =:tangle= header to the skeleton and explicitly -include the =@startuml= and =@enduml= marker lines in the skeleton so -I can tangle the source file and share it with my colleagues. This -makes the tangled source useable in Notepad and the =PlantUML= jar -file running standalone. - -I have put the =s= (src) prefix on the shortcuts to prevent -abbrev-mode from trying to expand =PlantUML= when I'm typing it in a -sentence. - -For convenience in activity diagrams I added =sif= and =sfor= and just -change the labels for the synchronization bars. - - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Enable abbrev-mode -(add-hook 'org-mode-hook (lambda () (abbrev-mode 1))) - -;; Skeletons -;; -;; sblk - Generic block #+begin_FOO .. #+end_FOO -(define-skeleton skel-org-block - "Insert an org block, querying for type." - "Type: " - "#+begin_" str "\n" - _ - \n - "#+end_" str "\n") - -(define-abbrev org-mode-abbrev-table "sblk" "" 'skel-org-block) - -;; splantuml - PlantUML Source block -(define-skeleton skel-org-block-plantuml - "Insert a org plantuml block, querying for filename." - "File (no extension): " - "#+begin_src plantuml :file " str ".png :cache yes\n" - _ - \n - "#+end_src\n") - -(define-abbrev org-mode-abbrev-table "splantuml" "" 'skel-org-block-plantuml) - -(define-skeleton skel-org-block-plantuml-activity - "Insert a org plantuml block, querying for filename." - "File (no extension): " - "#+begin_src plantuml :file " str "-act.png :cache yes :tangle " str "-act.txt\n" - (bh/plantuml-reset-counters) - "@startuml\n" - "skinparam activity {\n" - "BackgroundColor<> Cyan\n" - "}\n\n" - "title " str " - \n" - "note left: " str "\n" - "(*) --> \"" str "\"\n" - "--> (*)\n" - _ - \n - "@enduml\n" - "#+end_src\n") - -(defvar bh/plantuml-if-count 0) - -(defun bh/plantuml-if () - (incf bh/plantuml-if-count) - (number-to-string bh/plantuml-if-count)) - -(defvar bh/plantuml-loop-count 0) - -(defun bh/plantuml-loop () - (incf bh/plantuml-loop-count) - (number-to-string bh/plantuml-loop-count)) - -(defun bh/plantuml-reset-counters () - (setq bh/plantuml-if-count 0 - bh/plantuml-loop-count 0) - "") - -(define-abbrev org-mode-abbrev-table "sact" "" 'skel-org-block-plantuml-activity) - -(define-skeleton skel-org-block-plantuml-activity-if - "Insert a org plantuml block activity if statement" - "" - "if \"\" then\n" - " -> [condition] ==IF" (setq ifn (bh/plantuml-if)) "==\n" - " --> ==IF" ifn "M1==\n" - " -left-> ==IF" ifn "M2==\n" - "else\n" - "end if\n" - "--> ==IF" ifn "M2==") - -(define-abbrev org-mode-abbrev-table "sif" "" 'skel-org-block-plantuml-activity-if) - -(define-skeleton skel-org-block-plantuml-activity-for - "Insert a org plantuml block activity for statement" - "Loop for each: " - "--> ==LOOP" (setq loopn (bh/plantuml-loop)) "==\n" - "note left: Loop" loopn ": For each " str "\n" - "--> ==ENDLOOP" loopn "==\n" - "note left: Loop" loopn ": End for each " str "\n" ) - -(define-abbrev org-mode-abbrev-table "sfor" "" 'skel-org-block-plantuml-activity-for) - -(define-skeleton skel-org-block-plantuml-sequence - "Insert a org plantuml activity diagram block, querying for filename." - "File appends (no extension): " - "#+begin_src plantuml :file " str "-seq.png :cache yes :tangle " str "-seq.txt\n" - "@startuml\n" - "title " str " - \n" - "actor CSR as \"Customer Service Representative\"\n" - "participant CSMO as \"CSM Online\"\n" - "participant CSMU as \"CSM Unix\"\n" - "participant NRIS\n" - "actor Customer" - _ - \n - "@enduml\n" - "#+end_src\n") - -(define-abbrev org-mode-abbrev-table "sseq" "" 'skel-org-block-plantuml-sequence) - -;; sdot - Graphviz DOT block -(define-skeleton skel-org-block-dot - "Insert a org graphviz dot block, querying for filename." - "File (no extension): " - "#+begin_src dot :file " str ".png :cache yes :cmdline -Kdot -Tpng\n" - "graph G {\n" - _ - \n - "}\n" - "#+end_src\n") - -(define-abbrev org-mode-abbrev-table "sdot" "" 'skel-org-block-dot) - -;; sditaa - Ditaa source block -(define-skeleton skel-org-block-ditaa - "Insert a org ditaa block, querying for filename." - "File (no extension): " - "#+begin_src ditaa :file " str ".png :cache yes\n" - _ - \n - "#+end_src\n") - -(define-abbrev org-mode-abbrev-table "sditaa" "" 'skel-org-block-ditaa) - -;; selisp - Emacs Lisp source block -(define-skeleton skel-org-block-elisp - "Insert a org emacs-lisp block" - "" - "#+begin_src emacs-lisp\n" - _ - \n - "#+end_src\n") - -(define-abbrev org-mode-abbrev-table "selisp" "" 'skel-org-block-elisp) -#+end_src - -I also use abbrev-mode when taking notes at work. I tend to write -first names for people which get expanded to their complete name in my -notes. So if I write =mickey= it gets automatically expanded to -=Mickey Mouse= as I type. To create an abbreviation just type in the -short form followed by =C-x a i l= to create an abbreviation for the -current mode I'm in. - -The only thing you have to be careful with is not to use a common word for your -abbreviation since abbrev-mode will try to expand it everytime you enter it. -I found this annoying when I used =plantuml= as one of my abbreviations. - -I also use skeletons and abbrev-mode for C source files at work. -This works really well for me. -*** Example PlantUml Activity Diagram Generation -:PROPERTIES: -:CUSTOM_ID: ActivityDiagramExample -:END: -[2013-07-20 Sat 03:27] - -When creating activity diagrams I can use 'sif' and 'sfor' to add -IF and FOR blocks to the diagram with unique numbering automatically -generated. - -Example: Create a new diagram and enter 2 IFs and 2 FOR blocks - -Create diagram: "sact RET test RET" - -gives - -#+begin_src plantuml :file test-act.png :cache yes :tangle test-act.txt :exports both -@startuml -skinparam activity { -BackgroundColor<> Cyan -} - -title test - -note left: test -(*) --> "test" ---> (*) - -@enduml -#+end_src - -#+results[e196c6f48d5adbbf2b0300c87127c560d9913669]: -[[file:test-act.png]] - -Put cursor on --> (*) and enter "sif RET" - -gives - -#+begin_src plantuml :file test-act2.png :cache yes :tangle test-act2.txt :exports both -@startuml -skinparam activity { -BackgroundColor<> Cyan -} - -title test - -note left: test -(*) --> "test" -if "" then - -> [condition] ==IF1== - --> ==IF1M1== - -left-> ==IF1M2== -else -end if ---> ==IF1M2== ---> (*) - -@enduml -#+end_src - -#+results[44839e6d5984e19cc3be9d5392f18fc11aade43c]: -[[file:test-act2.png]] - -repeat on --> (*) line - -gives - -#+begin_src plantuml :file test-act3.png :cache yes :tangle test-act3.txt :exports both -@startuml -skinparam activity { -BackgroundColor<> Cyan -} - -title test - -note left: test -(*) --> "test" -if "" then - -> [condition] ==IF1== - --> ==IF1M1== - -left-> ==IF1M2== -else -end if ---> ==IF1M2== -if "" then - -> [condition] ==IF2== - --> ==IF2M1== - -left-> ==IF2M2== -else -end if ---> ==IF2M2== ---> (*) - -@enduml -#+end_src - -#+results[4f0d2bf2fed3fe0dc067e922132e8629d11bd224]: -[[file:test-act3.png]] - -and add two for loops at the end with "sfor RET line in file RET" and -"sfor RET address in addressbook RET" - -gives - -#+begin_src plantuml :file test-act4.png :cache yes :tangle test-act4.txt :exports both -@startuml -skinparam activity { -BackgroundColor<> Cyan -} - -title test - -note left: test -(*) --> "test" -if "" then - -> [condition] ==IF1== - --> ==IF1M1== - -left-> ==IF1M2== -else -end if ---> ==IF1M2== -if "" then - -> [condition] ==IF2== - --> ==IF2M1== - -left-> ==IF2M2== -else -end if ---> ==IF2M2== ---> ==LOOP1== -note left: Loop1: For each line in file ---> ==ENDLOOP1== -note left: Loop1: End for each line in file ---> ==LOOP2== -note left: Loop2: For each address in addressbook ---> ==ENDLOOP2== -note left: Loop2: End for each address in addressbook - ---> (*) - -@enduml -#+end_src - -#+results[178bbf661c1d4b459cc11b7b88ca339a4d9f85d1]: -[[file:test-act4.png]] - -I use rectangular cut and paste if I need to indent generated blocks. - -** Focus On Current Work -:PROPERTIES: -:CUSTOM_ID: FocusOnCurrentWork -:END: - -There is more than one way to do this. Use what works for you. -*** Narrowing to a subtree with =bh/org-todo= -:PROPERTIES: -:CUSTOM_ID: NarrowToSubtree -:END: - -=f5= and =S-f5= are bound the functions for narrowing and widening the -emacs buffer as defined below. - -We now use: - - - T (tasks) for C-c / t on the current buffer - - N (narrow) narrows to this task subtree - - U (up) narrows to the immediate parent task subtree without moving - - P (project) narrows to the parent project subtree without moving - - F (file) narrows to the current file or file of the existing restriction - -The agenda keeps widening the org buffer so this gives a convenient -way to focus on what we are doing. - -#+header: :tangle yes -#+begin_src emacs-lisp -(global-set-key (kbd "") 'bh/org-todo) - -(defun bh/org-todo (arg) - (interactive "p") - (if (equal arg 4) - (save-restriction - (bh/narrow-to-org-subtree) - (org-show-todo-tree nil)) - (bh/narrow-to-org-subtree) - (org-show-todo-tree nil))) - -(global-set-key (kbd "") 'bh/widen) - -(defun bh/widen () - (interactive) - (if (equal major-mode 'org-agenda-mode) - (progn - (org-agenda-remove-restriction-lock) - (when org-agenda-sticky - (org-agenda-redo))) - (widen))) - -(add-hook 'org-agenda-mode-hook - '(lambda () (org-defkey org-agenda-mode-map "W" (lambda () (interactive) (setq bh/hide-scheduled-and-waiting-next-tasks t) (bh/widen)))) - 'append) - -(defun bh/restrict-to-file-or-follow (arg) - "Set agenda restriction to 'file or with argument invoke follow mode. -I don't use follow mode very often but I restrict to file all the time -so change the default 'F' binding in the agenda to allow both" - (interactive "p") - (if (equal arg 4) - (org-agenda-follow-mode) - (widen) - (bh/set-agenda-restriction-lock 4) - (org-agenda-redo) - (beginning-of-buffer))) - -(add-hook 'org-agenda-mode-hook - '(lambda () (org-defkey org-agenda-mode-map "F" 'bh/restrict-to-file-or-follow)) - 'append) - -(defun bh/narrow-to-org-subtree () - (widen) - (org-narrow-to-subtree) - (save-restriction - (org-agenda-set-restriction-lock))) - -(defun bh/narrow-to-subtree () - (interactive) - (if (equal major-mode 'org-agenda-mode) - (progn - (org-with-point-at (org-get-at-bol 'org-hd-marker) - (bh/narrow-to-org-subtree)) - (when org-agenda-sticky - (org-agenda-redo))) - (bh/narrow-to-org-subtree))) - -(add-hook 'org-agenda-mode-hook - '(lambda () (org-defkey org-agenda-mode-map "N" 'bh/narrow-to-subtree)) - 'append) - -(defun bh/narrow-up-one-org-level () - (widen) - (save-excursion - (outline-up-heading 1 'invisible-ok) - (bh/narrow-to-org-subtree))) - -(defun bh/get-pom-from-agenda-restriction-or-point () - (or (and (marker-position org-agenda-restrict-begin) org-agenda-restrict-begin) - (org-get-at-bol 'org-hd-marker) - (and (equal major-mode 'org-mode) (point)) - org-clock-marker)) - -(defun bh/narrow-up-one-level () - (interactive) - (if (equal major-mode 'org-agenda-mode) - (progn - (org-with-point-at (bh/get-pom-from-agenda-restriction-or-point) - (bh/narrow-up-one-org-level)) - (org-agenda-redo)) - (bh/narrow-up-one-org-level))) - -(add-hook 'org-agenda-mode-hook - '(lambda () (org-defkey org-agenda-mode-map "U" 'bh/narrow-up-one-level)) - 'append) - -(defun bh/narrow-to-org-project () - (widen) - (save-excursion - (bh/find-project-task) - (bh/narrow-to-org-subtree))) - -(defun bh/narrow-to-project () - (interactive) - (if (equal major-mode 'org-agenda-mode) - (progn - (org-with-point-at (bh/get-pom-from-agenda-restriction-or-point) - (bh/narrow-to-org-project) - (save-excursion - (bh/find-project-task) - (org-agenda-set-restriction-lock))) - (org-agenda-redo) - (beginning-of-buffer)) - (bh/narrow-to-org-project) - (save-restriction - (org-agenda-set-restriction-lock)))) - -(add-hook 'org-agenda-mode-hook - '(lambda () (org-defkey org-agenda-mode-map "P" 'bh/narrow-to-project)) - 'append) - -(defvar bh/project-list nil) - -(defun bh/view-next-project () - (interactive) - (let (num-project-left current-project) - (unless (marker-position org-agenda-restrict-begin) - (goto-char (point-min)) - ; Clear all of the existing markers on the list - (while bh/project-list - (set-marker (pop bh/project-list) nil)) - (re-search-forward "Tasks to Refile") - (forward-visible-line 1)) - - ; Build a new project marker list - (unless bh/project-list - (while (< (point) (point-max)) - (while (and (< (point) (point-max)) - (or (not (org-get-at-bol 'org-hd-marker)) - (org-with-point-at (org-get-at-bol 'org-hd-marker) - (or (not (bh/is-project-p)) - (bh/is-project-subtree-p))))) - (forward-visible-line 1)) - (when (< (point) (point-max)) - (add-to-list 'bh/project-list (copy-marker (org-get-at-bol 'org-hd-marker)) 'append)) - (forward-visible-line 1))) - - ; Pop off the first marker on the list and display - (setq current-project (pop bh/project-list)) - (when current-project - (org-with-point-at current-project - (setq bh/hide-scheduled-and-waiting-next-tasks nil) - (bh/narrow-to-project)) - ; Remove the marker - (setq current-project nil) - (org-agenda-redo) - (beginning-of-buffer) - (setq num-projects-left (length bh/project-list)) - (if (> num-projects-left 0) - (message "%s projects left to view" num-projects-left) - (beginning-of-buffer) - (setq bh/hide-scheduled-and-waiting-next-tasks t) - (error "All projects viewed."))))) - -(add-hook 'org-agenda-mode-hook - '(lambda () (org-defkey org-agenda-mode-map "V" 'bh/view-next-project)) - 'append) -#+end_src - -This makes it easy to hide all of the other details in your org-file -temporarily by limiting your view to this task subtree. Tasks are -folded and hilighted so that only tasks which are incomplete are -shown. - -I hit =f5= (or the =T= speed key) a lot. This basically does a -=org-narrow-to-subtree= and =C-c / t= combination leaving the buffer -in a narrowed state. I use =S-f5= (or some other widening speed key -like =U=, =W=, =F=) to widen back to the normal view. - -I also have the following setting to force showing the next headline. -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-show-entry-below (quote ((default)))) -#+end_src - -This prevents too many headlines from being folded together when I'm -working with collapsed trees. -*** Limiting the agenda to a subtree -:PROPERTIES: -:CUSTOM_ID: AgendaNarrowToSubtree -:END: - -=C-c C-x <= turns on the agenda restriction lock for the current -subtree. This keeps your agenda focused on only this subtree. Alarms -and notifications are still active outside the agenda restriction. -=C-c C-x >= turns off the agenda restriction lock returning your -agenda view back to normal. - -I have added key bindings for the agenda to allow using =C-c C-x <= in -the agenda to set the restriction lock to the current task directly. -The following elisp accomplishes this. -#+header: :tangle yes -#+begin_src emacs-lisp -(add-hook 'org-agenda-mode-hook - '(lambda () (org-defkey org-agenda-mode-map "\C-c\C-x<" 'bh/set-agenda-restriction-lock)) - 'append) - -(defun bh/set-agenda-restriction-lock (arg) - "Set restriction lock to current task subtree or file if prefix is specified" - (interactive "p") - (let* ((pom (bh/get-pom-from-agenda-restriction-or-point)) - (tags (org-with-point-at pom (org-get-tags-at)))) - (let ((restriction-type (if (equal arg 4) 'file 'subtree))) - (save-restriction - (cond - ((and (equal major-mode 'org-agenda-mode) pom) - (org-with-point-at pom - (org-agenda-set-restriction-lock restriction-type)) - (org-agenda-redo)) - ((and (equal major-mode 'org-mode) (org-before-first-heading-p)) - (org-agenda-set-restriction-lock 'file)) - (pom - (org-with-point-at pom - (org-agenda-set-restriction-lock restriction-type)))))))) -#+end_src - -This allows me to set the restriction lock from agenda to task directly. -I work from the agenda a lot and I find this very convenient. - -Setting the restriction directly to the task is less surprising than -automatically moving up the tree to the project level task -- which is -what I was doing before. If the select task is too restrictive it's -easy to move the restriction lock up a level by visiting the task in -the org file and going up and resetting the lock - in case you want to -see move of the project. - -Selecting the entire project sometimes has too many tasks in it and I -want to limit the view to part of the subtree. This is why I keep the =N= and -=U= key bindings for adjusting the narrowed region. - -I've added new convenience keys for restricting the agenda and org-buffer to -subtree, parent task, and project task, as well as removing the restriction. -These keys work both in the agenda and as speed commands on a headline in the -org-file. - -- =N= narrows to the current task subtree - - This is the same as same as =C-c C-x <= - -- =U= narrows to the parent subtree of this task - - This goes up one level and narrows to that subtree. - -- =P= narrows to the entire project containing this task - - This goes up the tree to the top-level =TODO= keyword and selects - that as the subtree to narrow to - -- =W= removes the restriction, widening the buffer - -I like the highlighting for a restriction to only affect the headline -and not the entire body of the agenda restriction. I use the -following setting to keep the highlight on the heading only (as was -the case for pre-8.0 versions of org-mode) - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Limit restriction lock highlighting to the headline only -(setq org-agenda-restriction-lock-highlight-subtree nil) -#+end_src - -*** Limiting the agenda to a file -:PROPERTIES: -:CUSTOM_ID: AgendaNarrowToFile -:END: - -You can limit the agenda view to a single file in multiple ways. - -You can use the agenda restriction lock =C-c C-x <= on the any -line before the first heading to set the agenda restriction lock -to this file only. This is equivalent using a prefix argumment -(=C-u C-c C-x <=) anywhere in the file. This lock stays in -effect until you remove it with =C-c C-x >=. - -This also works in the agenda with my =C-u C-c c-x <= key binding. - -Another way is to invoke the agenda with =F12 < a= while visiting an -org-mode file. This limits the agenda view to just this file. I -occasionally use this to view a file not in my =org-agenda-files= in -the agenda. -** Tuning the Agenda Views -:PROPERTIES: -:CUSTOM_ID: TuningAgendaViews -:END: - -Various customizations affect how the agenda views show task details. -This section shows each of the customizations I use in my workflow. -*** Highlight the current agenda line -:PROPERTIES: -:CUSTOM_ID: HighlightCurrentAgendaLine -:END: - -The following code in my =.emacs= file keeps the current agenda line -highlighted. This makes it obvious what task will be affected by -commands issued in the agenda. No more acting on the wrong task by -mistake! - -The clock modeline time is also shown with a reverse background. - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Always hilight the current agenda line -(add-hook 'org-agenda-mode-hook - '(lambda () (hl-line-mode 1)) - 'append) -#+end_src - -#+header: :tangle no -#+begin_src emacs-lisp -;; The following custom-set-faces create the highlights -(custom-set-faces - ;; custom-set-faces was added by Custom. - ;; If you edit it by hand, you could mess it up, so be careful. - ;; Your init file should contain only one such instance. - ;; If there is more than one, they won't work right. - '(org-mode-line-clock ((t (:background "grey75" :foreground "red" :box (:line-width -1 :style released-button)))) t)) -#+end_src -*** Keep tasks with timestamps visible on the global todo lists -:PROPERTIES: -:CUSTOM_ID: GlobalTodoListsShowAllTasks -:END: - -Tasks with dates (=SCHEDULED:=, =DEADLINE:=, or active dates) show up -in the agenda when appropriate. The block agenda view (=F12 a=) tries -to keep tasks showing up only in one location (either in the calendar -or other todo lists in later sections of the block agenda.) I now -rarely use the global todo list search in org-mode (=F12 t=, =F12 m=) -and when I do I'm trying to find a specific task quickly. These lists -now include _everything_ so I can just search for the item I want and -move on. - -The block agenda prevents display of tasks with deadlines or scheduled -dates in the future so you can safely ignore these until the -appropriate time. -#+header: :tangle yes -#+begin_src emacs-lisp -;; Keep tasks with dates on the global todo lists -(setq org-agenda-todo-ignore-with-date nil) - -;; Keep tasks with deadlines on the global todo lists -(setq org-agenda-todo-ignore-deadlines nil) - -;; Keep tasks with scheduled dates on the global todo lists -(setq org-agenda-todo-ignore-scheduled nil) - -;; Keep tasks with timestamps on the global todo lists -(setq org-agenda-todo-ignore-timestamp nil) - -;; Remove completed deadline tasks from the agenda view -(setq org-agenda-skip-deadline-if-done t) - -;; Remove completed scheduled tasks from the agenda view -(setq org-agenda-skip-scheduled-if-done t) - -;; Remove completed items from search results -(setq org-agenda-skip-timestamp-if-done t) -#+end_src -*** Use the Diary for Holidays and Appointments -:PROPERTIES: -:CUSTOM_ID: DiaryForAppointments -:END: - -I don't use the emacs Diary for anything but I like seeing the -holidays on my agenda. This helps with planning for those days when -you're not supposed to be working. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-agenda-include-diary nil) -(setq org-agenda-diary-file "~/git/org/diary.org") -#+end_src - -The diary file keeps =date-tree= entries created by the capture mode -'appointment' template. I use this also for miscellaneous tasks I -want to clock during interruptions. - -I don't use a =~/diary= file anymore. That is just there as a -zero-length file to keep Emacs happy. I use org-mode's diary -functions instead. Inserting entries with =i= in the emacs agenda -creates date entries in the =~/git/org/diary.org= file. - -I include holidays from the calendar in my =todo.org= file as follows: -#+begin_src org :exports src -,#+FILETAGS: PERSONAL -,* Appointments - :PROPERTIES: - :CATEGORY: Appt - :ARCHIVE: %s_archive::* Appointments - :END: -,** Holidays - :PROPERTIES: - :Category: Holiday - :END: - %%(org-calendar-holiday) -,** Some other Appointment - ... -#+end_src - -I use the following setting so any time strings in the heading are -shown in the agenda. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-agenda-insert-diary-extract-time t) -#+end_src -*** Searches include archive files -:PROPERTIES: -:CUSTOM_ID: SearchesIncludeArchiveFiles -:END: - -I keep a single archive file for each of my org-mode project files. -This allows me to search the current file and the archive when I need -to dig up old information from the archives. - -I don't need this often but it sure is handy on the occasions that -I do need it. - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Include agenda archive files when searching for things -(setq org-agenda-text-search-extra-files (quote (agenda-archives))) -#+end_src -*** Agenda view tweaks -:PROPERTIES: -:CUSTOM_ID: AgendaViewTweaks -:END: - -The following agenda customizations control -- display of repeating tasks -- display of empty dates on the agenda -- task sort order -- start the agenda weekly view with Sunday -- display of the grid -- habits at the bottom - -I use a custom sorting function so that my daily agenda lists tasks in -order of importance. Tasks on the daily agenda are listed in the -following order: - -1. tasks with times at the top so they are hard to miss -2. entries for today (active timestamp headlines that are not scheduled or deadline tasks) -3. deadlines due today -4. late deadline tasks -5. scheduled items for today -6. pending deadlines (due soon) -7. late scheduled items -8. habits - -The lisp for this isn't particularly pretty but it works. - -Here are the =.emacs= settings: -#+header: :tangle yes -#+begin_src emacs-lisp -;; Show all future entries for repeating tasks -(setq org-agenda-repeating-timestamp-show-all t) - -;; Show all agenda dates - even if they are empty -(setq org-agenda-show-all-dates t) - -;; Sorting order for tasks on the agenda -(setq org-agenda-sorting-strategy - (quote ((agenda habit-down time-up user-defined-up effort-up category-keep) - (todo category-up effort-up) - (tags category-up effort-up) - (search category-up)))) - -;; Start the weekly agenda on Monday -(setq org-agenda-start-on-weekday 1) - -;; Enable display of the time grid so we can see the marker for the current time -(setq org-agenda-time-grid (quote ((daily today remove-match) - #("----------------" 0 16 (org-heading t)) - (0900 1100 1300 1500 1700)))) - -;; Display tags farther right -(setq org-agenda-tags-column -102) - -;; -;; Agenda sorting functions -;; -(setq org-agenda-cmp-user-defined 'bh/agenda-sort) - -(defun bh/agenda-sort (a b) - "Sorting strategy for agenda items. -Late deadlines first, then scheduled, then non-late deadlines" - (let (result num-a num-b) - (cond - ; time specific items are already sorted first by org-agenda-sorting-strategy - - ; non-deadline and non-scheduled items next - ((bh/agenda-sort-test 'bh/is-not-scheduled-or-deadline a b)) - - ; deadlines for today next - ((bh/agenda-sort-test 'bh/is-due-deadline a b)) - - ; late deadlines next - ((bh/agenda-sort-test-num 'bh/is-late-deadline '> a b)) - - ; scheduled items for today next - ((bh/agenda-sort-test 'bh/is-scheduled-today a b)) - - ; late scheduled items next - ((bh/agenda-sort-test-num 'bh/is-scheduled-late '> a b)) - - ; pending deadlines last - ((bh/agenda-sort-test-num 'bh/is-pending-deadline '< a b)) - - ; finally default to unsorted - (t (setq result nil))) - result)) - -(defmacro bh/agenda-sort-test (fn a b) - "Test for agenda sort" - `(cond - ; if both match leave them unsorted - ((and (apply ,fn (list ,a)) - (apply ,fn (list ,b))) - (setq result nil)) - ; if a matches put a first - ((apply ,fn (list ,a)) - (setq result -1)) - ; otherwise if b matches put b first - ((apply ,fn (list ,b)) - (setq result 1)) - ; if none match leave them unsorted - (t nil))) - -(defmacro bh/agenda-sort-test-num (fn compfn a b) - `(cond - ((apply ,fn (list ,a)) - (setq num-a (string-to-number (match-string 1 ,a))) - (if (apply ,fn (list ,b)) - (progn - (setq num-b (string-to-number (match-string 1 ,b))) - (setq result (if (apply ,compfn (list num-a num-b)) - -1 - 1))) - (setq result -1))) - ((apply ,fn (list ,b)) - (setq result 1)) - (t nil))) - -(defun bh/is-not-scheduled-or-deadline (date-str) - (and (not (bh/is-deadline date-str)) - (not (bh/is-scheduled date-str)))) - -(defun bh/is-due-deadline (date-str) - (string-match "Deadline:" date-str)) - -(defun bh/is-late-deadline (date-str) - (string-match "\\([0-9]*\\) d\. ago:" date-str)) - -(defun bh/is-pending-deadline (date-str) - (string-match "In \\([^-]*\\)d\.:" date-str)) - -(defun bh/is-deadline (date-str) - (or (bh/is-due-deadline date-str) - (bh/is-late-deadline date-str) - (bh/is-pending-deadline date-str))) - -(defun bh/is-scheduled (date-str) - (or (bh/is-scheduled-today date-str) - (bh/is-scheduled-late date-str))) - -(defun bh/is-scheduled-today (date-str) - (string-match "Scheduled:" date-str)) - -(defun bh/is-scheduled-late (date-str) - (string-match "Sched\.\\(.*\\)x:" date-str)) -#+end_src -*** Sticky Agendas -:PROPERTIES: -:CUSTOM_ID: StickyAgendas -:END: -[2013-06-23 Sun 10:16] - -Sticky agendas allow you to have more than one agenda view created simultaneously. -You can quickly switch to the view without incurring an agenda rebuild by invoking -the agenda custom command key that normally generates the agenda. If it already -exists it will display the existing view. =g= forces regeneration of the agenda view. - -I normally have two views displayed (=F12 a= for the daily/weekly -agenda and =F12 SPC= for my project management view) - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Use sticky agenda's so they persist -(setq org-agenda-sticky t) -#+end_src -** Checklist handling -:PROPERTIES: -:CUSTOM_ID: ChecklistHandling -:END: - -Checklists are great for repeated tasks with lots of things that need -to be done. For a long time I was manually resetting the check boxes -to unchecked when marking the repeated task =DONE= but no more! -There's a contributed =org-checklist= that can uncheck the boxes -automagically when the task is marked done. - -Add the following to your =.emacs= - -#+header: :tangle no -#+begin_src emacs-lisp -(add-to-list 'load-path (expand-file-name "~/git/org-mode/contrib/lisp")) - -(require 'org-checklist) -#+end_src - -#+header: :tangle yes -#+begin_src emacs-lisp :exports none -;; The following setting is different from the document so that you -;; can override the document path by setting your path in the variable -;; org-mode-user-contrib-lisp-path -;; -(if (boundp 'org-mode-user-contrib-lisp-path) - (add-to-list 'load-path org-mode-user-contrib-lisp-path) - (add-to-list 'load-path (expand-file-name "~/git/org-mode/contrib/lisp"))) - -(require 'org-checklist) -#+end_src - -and then to use it in a task you simply set the property =RESET_CHECK_BOXES= to =t= -like this - -#+begin_src org :exports src -,* TODO Invoicing and Archive Tasks [0/7] - DEADLINE: <2009-07-01 Wed +1m -0d> - :PROPERTIES: - :RESET_CHECK_BOXES: t - :END: - - - [ ] Do task 1 - - [ ] Do task 2 - ... - - [ ] Do task 7 -#+end_src -** Backups -:PROPERTIES: -:CUSTOM_ID: Backups -:END: - -=Backups that you have to work hard at don't get done=. - -I lost a bunch of data over 10 years ago due to not having a working -backup solution. At the time I said =I'm not going to lose any -important data ever again=. So far so good :) - -My backups get done religiously. What does this have to do with -org-mode? Not much really, other than I don't spend time doing -backups -- they just happen -- which saves me time for other more -interesting things. - -My backup philosophy is to make it possible to recover your data -- -not necessarily easy. It doesn't have to be easy/fast to do the -recovery because I'll rarely have to recover data from the backups. -Saving time for recovery doesn't make sense to me. I want the backup -to be fast and painless since I do those all the time. - -I set up an automated network backup over 10 years ago that is still -serving me well today. All of my systems gets daily backups to a -network drive. These are collected monthly and written to an external -removable USB disk. - -Once a month my task for backups prompts me to move the current -collection of montly backups to the USB drive for external storage. -Backups take minimal effort currently and I'm really happy about that. - -Since then =git= came into my life, so backups of =git= repositories -that are on multiple machines is much less critical than it used to -be. There is an automatic backup of everything pushed to the remote -repository. -** Handling blocked tasks -:PROPERTIES: -:CUSTOM_ID: HandlingBlockedTasks -:END: - -Blocked tasks are tasks that have subtasks which are not in a done -todo state. Blocked tasks show up in a grayed font by default in the -agenda. - -To enable task blocking set the following variable: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-enforce-todo-dependencies t) -#+end_src - -This setting prevents tasks from changing to =DONE= if any subtasks -are still open. This works pretty well except for repeating tasks. I -find I'm regularly adding =TODO= tasks under repeating tasks and not -all of the subtasks need to be complete before the next repeat cycle. - -You can override the setting temporarily by changing the task with -=C-u C-u C-u C-c C-t= but I never remember that. I set a permanent -property on the repeated tasks as follows: - -#+begin_src org :exports src -,* TODO New Repeating Task - SCHEDULED: <2009-06-16 Tue +1w> - :PROPERTIES: - :NOBLOCKING: t - :END: - ... -,** TODO Subtask -#+end_src - -This prevents the =New Repeating Task= from being blocked if some of -the items under it are not complete. - -Occassionally I need to complete tasks in a given order. Org-mode has -a property =ORDERED= that enforces this for subtasks. - -#+begin_src org :exports src -,* TODO Some Task - :PROPERTIES: - :ORDERED: t - :END: -,** TODO Step 1 -,** TODO Step 2 -,** TODO Step 3 -#+end_src - -In this case you need to complete =Step 1= before you can complete -=Step 2=, etc. and org-mode prevents the state change to a done task -until the preceding tasks are complete. -** Org Task structure and presentation -:PROPERTIES: -:CUSTOM_ID: OrgTaskStructureAndPresentation -:END: - -This section describes various org-mode settings I use to control how -tasks are displayed while I work on my org mode files. -*** Controlling display of leading stars on headlines -:PROPERTIES: -:CUSTOM_ID: DisplayLeadingStars -:END: - -Org-mode has the ability to show or hide the leading stars on task -headlines. It's also possible to have headlines at odd levels only so -that the stars and heading task names line up in sublevels. - -To make org show leading stars use - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-hide-leading-stars nil) -#+end_src - -I now use org-indent mode which hides leading stars. -*** org-indent mode -:PROPERTIES: -:CUSTOM_ID: OrgIndentMode -:END: - -I recently started using org-indent mode. I like this setting a lot. -It removes the indentation in the org-file but displays it as if it -was indented while you are working on the org file buffer. - -org-indent mode displays as if org-odd-levels-only is true but it has -a really clean look that I prefer over my old setup. - -I have org-indent mode on by default at startup with the following -setting: -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-startup-indented t) -#+end_src -*** Handling blank lines -:PROPERTIES: -:CUSTOM_ID: HandlingBlankLines -:END: - -Blank lines are evil :). They keep getting inserted in between -headlines and I don't want to see them in collapsed (contents) views. -When I use =TAB= to fold (cycle) tasks I don't want to see any blank -lines between headings. - -The following setting hides blank lines between headings which keeps -folded view nice and compact. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-cycle-separator-lines 0) -#+end_src - -I find extra blank lines in lists and headings a bit of a nuisance. -To get a body after a list you need to include a blank line between -the list entry and the body -- and indent the body appropriately. -Most of my lists have no body detail so I like the look of collapsed -lists with no blank lines better. - -The following setting prevents creating blank lines before headings -but allows list items to adapt to existing blank lines around the items: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-blank-before-new-entry (quote ((heading) - (plain-list-item . auto)))) -#+end_src -*** Adding new tasks quickly without disturbing the current task content -:PROPERTIES: -:CUSTOM_ID: AddingNewTasks -:END: - -To create new headings in a project file it is really convenient to -use =C-RET=, =C-S-RET=, =M-RET=, and =M-S-RET=. This inserts a new headline -possibly with a =TODO= keyword. With the following setting - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-insert-heading-respect-content nil) -#+end_src - -org inserts the heading at point for the =M-= versions and respects -content for the =C-= versions. The respect content setting is -temporarily turned on for the =C-= versions which adds the new heading -after the content of the current item. This lets you hit =C-S-RET= in -the middle of an entry and the new heading is added after the body of -the current entry but still allow you to split an entry in the middle -with =M-S-RET=. -*** Notes at the top -:PROPERTIES: -:CUSTOM_ID: NotesAtTop -:END: - -I enter notes for tasks with =C-c C-z= (or just =z= in the agenda). -Changing tasks states also sometimes prompt for a note (e.g. moving to -=WAITING= prompts for a note and I enter a reason for why it is -waiting). These notes are saved at the top of the task so unfolding -the task shows the note first. -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-reverse-note-order nil) -#+end_src -*** Searching and showing results -:PROPERTIES: -:CUSTOM_ID: SearchingResults -:END: - -Org-mode's searching capabilities are really effective at finding data -in your org files. =C-c / /= does a regular expression search on the -current file and shows matching results in a collapsed view of the -org-file. - -I have org-mode show the hierarchy of tasks above the matched entries -and also the immediately following sibling task (but not all siblings) -with the following settings: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-show-following-heading t) -(setq org-show-hierarchy-above t) -(setq org-show-siblings (quote ((default)))) -#+end_src - -This keeps the results of the search relatively compact and mitigates -accidental errors by cutting too much data from your org file with -=C-k=. Cutting folded data (including the ...) can be really -dangerous since it cuts text (including following subtrees) which you -can't see. For this reason I always show the following headline when -displaying search results. -*** Editing and Special key handling -:PROPERTIES: -:CUSTOM_ID: SpecialKeyHandling -:END: - -Org-mode allows special handling of the C-a, C-e, and C-k keys while -editing headlines. I also use the setting that pastes (yanks) -subtrees and adjusts the levels to match the task I am pasting to. -See the docstring (=C-h v org-yank-adjust-subtrees=) for more details -on each variable and what it does. - -I have =org-special-ctrl-a/e= set to enable easy access to the -beginning and end of headlines. I use =M-m= or =C-a C-a= to get to the -beginning of the line so the speed commands work and =C-a= to give -easy access to the beginning of the heading text when I need that. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-special-ctrl-a/e t) -(setq org-special-ctrl-k t) -(setq org-yank-adjusted-subtrees t) -#+end_src -** Attachments -:PROPERTIES: -:CUSTOM_ID: Attachments -:END: -Attachments are great for getting large amounts of data related to -your project out of your org-mode files. Before attachments came -along I was including huge blocks of SQL code in my org files to keep -track of changes I made to project databases. This bloated my org -file sizes badly. - -Now I can create the data in a separate file and attach it to my -project task so it's easily located again in the future. - -I set up org-mode to generate unique attachment IDs with -=org-id-method= as follows: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-id-method (quote uuidgen)) -#+end_src - -Say you want to attach a file =x.sql= to your current task. Create -the file data in =/tmp/x.sql= and save it. - -Attach the file with =C-c C-a a= and enter the filename: =x.sql=. -This generates a unique ID for the task and adds the file in the -attachment directory. - -#+begin_src org :exports src -,* Attachments :ATTACH: - :PROPERTIES: - :Attachments: x.sql - :ID: f1d38e9a-ff70-4cc4-ab50-e8b58b2aaa7b - :END: -#+end_src - -The attached file is saved in -=data/f1/d38e9a-ff70-4cc4-ab50-e8b58b2aaa7b/=. Where it goes exactly -isn't important for me -- as long as it is saved and retrievable -easily. Org-mode copies the original file =/tmp/x.sql= into the -appropriate attachment directory. - -Tasks with attachments automatically get an =ATTACH= tag so you can -easily find tasks with attachments with a tag search. - -To open the attachment for a task use =C-c C-a o=. This prompts for -the attachment to open and =TAB= completion works here. - -The =ID= changes for every task header when a new =ID= is generated. - -It's possible to use named directories for attachments but I haven't -needed this functionality yet -- it's there if you need it. - -I store my org-mode attachments with my org files in a subdirectory -=data=. These are automatically added to my =git= repository along -with any other org-mode changes I've made. -** Deadlines and Agenda Visibility -:PROPERTIES: -:CUSTOM_ID: DeadlinesAndAgendaVisibility -:END: - -Deadlines and due dates are a fact or life. By default I want to see -deadlines in the agenda 30 days before the due date. - -The following setting accomplishes this: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-deadline-warning-days 30) -#+end_src - -This gives me plenty of time to deal with the task so that it is -completed on or before the due date. - -I also use deadlines for repeating tasks. If the task repeats more -often than once per month it would be always bugging me on the agenda -view. For these types of tasks I set an explicit deadline warning -date as follows: - -#+begin_src org :exports src -,* TODO Pay Wages - DEADLINE: <2009-07-01 Wed +1m -0d> -#+end_src - -This example repeats monthly and shows up in the agenda on the day it -is due (with no prior warning). You can set any number of lead days -you want on DEADLINES using -Nd where N is the number of days in -advance the task should show up in the agenda. If no value is -specified the default =org-deadline-warning-days= is used. -** Exporting Tables to CSV -:PROPERTIES: -:CUSTOM_ID: TableExportToCSV -:END: - -I generate org-mode tables with details of task specifications and -record structures for some of my projects. My clients like to use -spreadsheets for this type of detail. - -It's easy to share the details of the org-mode table by exporting in -HTML but that isn't easy for anyone else to work with if they need to -edit data. - -To solve this problem I export my table as comma delimited values -(CSV) and then send that to the client (or read it into a spreadsheet -and email the resulting spreadsheet file). - -Org-mode can export tables as TAB or comma delimited formats. I set -the default format to CSV with: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-table-export-default-format "orgtbl-to-csv") -#+end_src - -Exporting to CSV format is the only one I use and this provides the -default so I can just hit RETURN when prompted for the format. - -To export the following table I put the cursor inside the table and -hit =M-x org-table-export= which prompts for a filename and the format -which defaults to orgtbl-to-csv from the setting above. - -| One | Two | Three | -|-------+--------+-------| -| 1 | 1 | 2 | -| 3 | 6 | 5 | -| fred | kpe | mary | -| 234.5 | 432.12 | 324.3 | - -This creates the file with the following data - -#+begin_src csv -One,Two,Three -1,1,2 -3,6,5 -fred,kpe,mary -234.5,432.12,324.3 -#+end_src -** Minimize Emacs Frames -:PROPERTIES: -:CUSTOM_ID: MinimizeFrames -:END: - -Links to emails, web pages, and other files are sprinkled all over my -org files. The following setting control how org-mode handles opening -the link. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-link-frame-setup (quote ((vm . vm-visit-folder) - (gnus . org-gnus-no-new-news) - (file . find-file)))) - -; Use the current window for C-c ' source editing -(setq org-src-window-setup 'current-window) -#+end_src - -I like to keep links in the same window so that I don't end up with a -ton of frames in my window manager. I normally work in a full-screen -window and having links open in the same window just works better for -me. - -If I need to work in multiple files I'll manually create the second -frame with =C-x 5 2= or split the window with =C-x 4 2= or =C-X 4 3=. -When I visit files in Emacs I normally want to replace the current -window with the new content. - -** Logging stuff -:PROPERTIES: -:CUSTOM_ID: LoggingStuff -:END: - -Most of my logging is controlled by the global =org-todo-keywords= - -My logging settings are set as follows: -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-log-done (quote time)) -(setq org-log-into-drawer t) -(setq org-log-state-notes-insert-after-drawers nil) -#+end_src - -My =org-todo-keywords= are set as follows: - -#+header: :tangle no -#+begin_src emacs-lisp -(setq org-todo-keywords - (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") - (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING")))) -#+end_src - -This adds a log entry whenever a task moves to any of the following states: -- to or out of =DONE= status -- to =WAITING= status (with a note) or out of =WAITING= status -- to =HOLD= status -- to =CANCELLED= status (with a note) or out of =CANCELLED= status - -I keep clock times and states in the =LOGBOOK= drawer to keep my tasks -uncluttered. If a task is WAITING then the reason for why it is -waiting is near the top of the LOGBOOK and unfolding the LOGBOOK -drawer provides that information. From the agenda simply hitting -=SPC= on the task will reveal the LOGBOOK drawer. -** Limiting time spent on tasks -:PROPERTIES: -:CUSTOM_ID: LimitingTimeSpentOnTasks -:END: - -Org-mode has this great new feature for signalling alarms when the -estimated time for a task is reached. I use this to limit the amount -of time I spend on a task during the day. - -As an example, I've been working on this document for over two months -now. I want to get it finished but I can't just work on it solely -until it's done because then nothing else gets done. I want to do a -little bit every day but limit the total amount of time I spend -documenting org-mode to an hour a day. - -To this end I have a task - -#+begin_src org :exports src -,* NEXT Document my use of org-mode - :LOGBOOK:... - :PROPERTIES: - :CLOCK_MODELINE_TOTAL: today - :Effort: 1:00 - :END: -#+end_src - -The task has an estimated effort of 1 hour and when I clock in the -task it gives me a total in the mode-line like this - -: --:** org-mode.org 91% (2348,73) Git:master (Org Fly yas Font)-----[0:35/1:00 (Document my use of org-mode)]------- - -I've spent 35 minutes of my 1 hour so far today on this document and -other help on IRC. - -I set up an alarm so the Star Trek door chime goes off when the -total estimated time is hit. (Yes I'm a Trekkie :) ) - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-clock-sound "/usr/local/lib/tngchime.wav") -#+end_src - -When the one hour time limit is hit the alarm sound goes off and a -message states that I should be done working on this task. If I -switch tasks and try to clock in this task again I get the sound each -and every time I clock in the task. This nags me to go work on -something else :) - -You can use similar setups for repeated tasks. By default the last -repeat time is recorded as a property when a repeating task is marked -done. For repeating tasks the mode-line clock total counts since the -last repeat time by default. This lets you accumulate time over -multiple days and counts towards your estimated effort limit. -** Habit Tracking -:PROPERTIES: -:CUSTOM_ID: HabitTracking -:END: - -John Wiegley recently added support for Habit tracking to org-mode. - -I have lots of habits (some bad) but I'd still like to improve and -build new good habits. This is what habit tracking is for. It shows -a graph on the agenda of how well you have been doing on developing -your habits. - -I have habits like: - -- Hand wash the dishes -- 30 minute brisk walk -- Clean the house - -etc. and most of these need a push to get done regularly. Logging of -the done state needs to be enabled for habit tracking to work. - -A habit is just like a regular task except it has a special =PROPERTY= -value setting and a special =SCHEDULED= date entry like this: - -#+begin_src org :exports src -,* TODO Update Org Mode Doc - SCHEDULED: <2009-11-21 Sat .+7d/30d> - [2009-11-14 Sat 11:45] - :PROPERTIES: - :STYLE: habit - :END: -#+end_src - -This marks the task as a habit and separates it from the regular task -display on the agenda. When you mark a habit done it shows up on your -daily agenda the next time based on the first interval in the -SCHEDULED entry (=.+7d=) - -The special =SCHEDULED= entry states that I want to do this every day -but at least every 2 days. If I go 3 days without marking it DONE it -shows up RED on the agenda indicating that I have been neglecting this -habit. - -The world isn't going to end if you neglect your habits. You can hide -and display habits quickly using the =K= key on the agenda. - -These are my settings for habit tracking. - -#+header: :tangle yes -#+begin_src emacs-lisp -; Enable habit tracking (and a bunch of other modules) -(setq org-modules (quote (org-bbdb - org-bibtex - org-crypt - org-gnus - org-id - org-info - org-jsinfo - org-habit - org-inlinetask - org-irc - org-mew - org-mhe - org-protocol - org-rmail - org-vm - org-wl - org-w3m))) - -; position the habit graph on the agenda to the right of the default -(setq org-habit-graph-column 50) -#+end_src - -During the day I'll turn off the habit display in the agenda with =K=. -This is a persistent setting and since I leave my Emacs running for -days at a time my habit display doesn't come back. To make sure I -look at the habits daily I have the following settings to redisplay -the habits in the agenda each day. This turns the habit display on -again at 6AM each morning. - -#+header: :tangle yes -#+begin_src emacs-lisp -(run-at-time "06:00" 86400 '(lambda () (setq org-habit-show-habits t))) -#+end_src -** Habits only log DONE state changes -:PROPERTIES: -:CUSTOM_ID: HabitsLogDone -:END: - -I tend to keep habits under a level 1 task =* Habits= with a special -logging property that only logs changes to the =DONE= state. This -allows me to cancel a habit and not record a timestamp for it since -that messes up the habit graph. Cancelling a habit just to get it off -my agenda because it's undoable (like get up before 6AM) should not -mark the habit as done today. I only cancel habits that repeat every -day. - -My habit tasks look as follows - and I tend to have one in every org -file that can have habits defined -#+begin_src org :exports src -,* Habits - :PROPERTIES: - :LOGGING: DONE(!) - :ARCHIVE: %s_archive::* Habits - :END: -#+end_src -** Auto revert mode -:PROPERTIES: -:CUSTOM_ID: AutoRevertMode -:END: - -I use git to synchronize my org-mode files between my laptop and my -workstation. This normally requires saving all the current changes, -pushing to a bare repo, and fetching on the other system. After that -I need to revert all of my org-mode files to get the updated -information. - -I used to use =org-revert-all-org-buffers= but have since discovered -=global-auto-revert-mode=. With this setting any files that change on -disk where there are no changes in the buffer automatically revert to -the on-disk version. - -This is perfect for synchronizing my org-mode files between systems. - -#+header: :tangle yes -#+begin_src emacs-lisp -(global-auto-revert-mode t) -#+end_src -** Handling Encryption -:PROPERTIES: -:CUSTOM_ID: HandlingEncryption -:END: - -I used to keep my encrypted data like account passwords in a separate -GPG encrypted file. Now I keep them in my org-mode files with a -special tag instead. Encrypted data is kept in the org-mode file that -it is associated with. - -=org-crypt= allows you to tag headings with a special tag =crypt= and -org-mode can keep data in these headings encrypted when saved to disk. -You decrypt the heading temporarily when you need access to the data -and org-mode re-encrypts the heading as soon as you save the file. - -I use the following setup for encryption: -#+header: :tangle yes -#+begin_src emacs-lisp -(require 'org-crypt) -; Encrypt all entries before saving -(org-crypt-use-before-save-magic) -(setq org-tags-exclude-from-inheritance (quote ("crypt"))) -; GPG key to use for encryption -(setq org-crypt-key "F0B66B40") -#+end_src - -=M-x org-decrypt-entry= will prompt for the passphrase associated with -your encryption key and replace the encrypted data where the point is -with the plaintext details for your encrypted entry. As soon as you -save the file the data is re-encrypted for your key. Encrypting does -not require prompting for the passphrase - that's only for looking at -the plain text version of the data. - -I tend to have a single level 1 encrypted entry per file (like =* -Passwords=). I prevent the =crypt= tag from using inheritance so that -I don't have encrypted data inside encrypted data. I found =M-x -org-decrypt-entries= prompting for the passphrase to decrypt data over -and over again (once per entry to decrypt) too inconvenient. - -I leave my entries encrypted unless I have to look up data - I decrypt -on demand and then save the file again to re-encrypt the data. This -keeps the data in plain text as short as possible. -*** Auto Save Files -:PROPERTIES: -:CUSTOM_ID: AutoSaveFiles -:END: -[2011-09-26 Mon 04:57] - -Emacs temporarily saves your buffer in an autosave file while you are -editing your org buffer and a sufficient number of changes have -accumulated. If you have decrypted subtrees in your buffer these will -be written to disk in plain text which possibly leaks sensitive information. -To combat this org-mode now asks if you want to disable the autosave -functionality in this buffer. - -Personally I really like the autosave feature. 99% of the time my encrypted -entries are perfectly safe to write to the autosave file since they are -still encrypted. I tend to decrypt an entry, read the details for what -I need to look up and then immediately save the file again with =C-x C-s= -which re-encrypts the entry immediately. This pretty much guarantees that -my autosave files never have decrypted data stored in them. - -I disable the default org crypt auto-save setting as follows: -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-crypt-disable-auto-save nil) -#+end_src -** Speed Commands -:PROPERTIES: -:CUSTOM_ID: SpeedCommands -:END: - -There's an exciting feature called =org-speed-commands= in the -org-mode. - -Speed commands allow access to frequently used commands when on the -beginning of a headline - similar to one-key agenda commands. Speed -commands are user configurable and org-mode provides a good set of -default commands. - -I have the following speed commands set up in addition to the -defaults. I don't use priorities so I override the default settings -for the 1, 2, and 3 keys. I also disable cycling with 'c' and add 'q' -as a quick way to get back to the agenda and update the current view. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-use-speed-commands t) -(setq org-speed-commands-user (quote (("0" . ignore) - ("1" . ignore) - ("2" . ignore) - ("3" . ignore) - ("4" . ignore) - ("5" . ignore) - ("6" . ignore) - ("7" . ignore) - ("8" . ignore) - ("9" . ignore) - - ("a" . ignore) - ("d" . ignore) - ("h" . bh/hide-other) - ("i" progn - (forward-char 1) - (call-interactively 'org-insert-heading-respect-content)) - ("k" . org-kill-note-or-show-branches) - ("l" . ignore) - ("m" . ignore) - ("q" . bh/show-org-agenda) - ("r" . ignore) - ("s" . org-save-all-org-buffers) - ("w" . org-refile) - ("x" . ignore) - ("y" . ignore) - ("z" . org-add-note) - - ("A" . ignore) - ("B" . ignore) - ("E" . ignore) - ("F" . bh/restrict-to-file-or-follow) - ("G" . ignore) - ("H" . ignore) - ("J" . org-clock-goto) - ("K" . ignore) - ("L" . ignore) - ("M" . ignore) - ("N" . bh/narrow-to-org-subtree) - ("P" . bh/narrow-to-org-project) - ("Q" . ignore) - ("R" . ignore) - ("S" . ignore) - ("T" . bh/org-todo) - ("U" . bh/narrow-up-one-org-level) - ("V" . ignore) - ("W" . bh/widen) - ("X" . ignore) - ("Y" . ignore) - ("Z" . ignore)))) - -(defun bh/show-org-agenda () - (interactive) - (if org-agenda-sticky - (switch-to-buffer "*Org Agenda( )*") - (switch-to-buffer "*Org Agenda*")) - (delete-other-windows)) -#+end_src - -The variable =org-speed-commands-default= sets a lot of useful -defaults for speed command keys. The default keys I use the most are -=I= and =O= for clocking in and out and =t= to change todo state. - -=J= jumps to the current or last clocking task. - -=c= and =C= are disabled so they self insert. I use =TAB= and =S-TAB= -for cycling - I don't need =c= and =C= as well. =TAB= works -everywhere while =c= and =C= only works on the headline and sometimes -I accidentally cycle when I don't intend to. -** Org Protocol -:PROPERTIES: -:CUSTOM_ID: OrgProtocol -:END: - -[[http://orgmode.org/worg/org-contrib/org-protocol.php][Org protocol]] is a great way to create capture notes in org-mode from -other applications. I use this to create tasks to review interesting -web pages I visit in Firefox. - -I have a special capture template set up for org-protocol to use (set -up with the =w= key). - -My org-mode setup for org-protocol is really simple. It enables -org-protocol and creates a single org-protocol capture template as -described in [[#CaptureTemplates][Capture Templates]]. -#+header: :tangle yes -#+begin_src emacs-lisp -(require 'org-protocol) -#+end_src -The bulk of the setup is in the Firefox application so that C-c c on a -page in Firefox will trigger the org-protocol capture template with -details of the page I'm currently viewing in firefox. - -I set up org-protocol in firefox as described in [[http://orgmode.org/worg/org-contrib/org-protocol.php#sec-9][Keybindings for Firefox]]. -** Require a final newline when saving files -:PROPERTIES: -:CUSTOM_ID: RequireFinalNewline -:END: - -The following setting was mainly for editing yasnippets where I want to -be able to expand a snippet but stay on the same line. I used this -mainly for replacing short strings or initials with full names for -people during meeting notes. I now use =abbrev-mode-= for this and -no longer need this setting. - -#+header: :tangle no -#+begin_src emacs-lisp -(setq require-final-newline nil) -#+end_src - -When I save a file in Emacs I want a final newline - this fits better -with the source code projects I work on. This is the setting I use now: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq require-final-newline t) -#+end_src -** Insert inactive timestamps and exclude from export -:PROPERTIES: -:CUSTOM_ID: InsertInactiveTimestamps -:END: - -I insert inactive timestamps when working on org-mode files. - -For remember tasks the timestamp is in the remember template but for regular -structure editing I want the timestamp automatically added when I create the headline. - -I have a function that is run by an org-mode hook to automatically insert the inactive -timestamp whenever a headline is created. - -Adding the timestamp can be controlled by =f9 T= which toggles the -creation of the timestamp on and off for new headlines. - - -#+header: :tangle yes -#+begin_src emacs-lisp -(defvar bh/insert-inactive-timestamp t) - -(defun bh/toggle-insert-inactive-timestamp () - (interactive) - (setq bh/insert-inactive-timestamp (not bh/insert-inactive-timestamp)) - (message "Heading timestamps are %s" (if bh/insert-inactive-timestamp "ON" "OFF"))) - -(defun bh/insert-inactive-timestamp () - (interactive) - (org-insert-time-stamp nil t t nil nil nil)) - -(defun bh/insert-heading-inactive-timestamp () - (save-excursion - (when bh/insert-inactive-timestamp - (org-return) - (org-cycle) - (bh/insert-inactive-timestamp)))) - -(add-hook 'org-insert-heading-hook 'bh/insert-heading-inactive-timestamp 'append) -#+end_src - -Everytime I create a heading with =M-RET= or =M-S-RET= the hook invokes the function -and it inserts an inactive timestamp like this - -#+begin_src org :exports src -,* - [2009-11-22 Sun 18:45] -#+end_src - -This keeps an automatic record of when tasks are created which I find very useful. - -I also have a short cut key defined to invoke this function on demand so that I can -insert the inactive timestamp anywhere on demand. - -#+header: :tangle no -#+begin_src emacs-lisp -(global-set-key (kbd " t") 'bh/insert-inactive-timestamp) -#+end_src - -To prevent the timestamps from being exported in documents I use the following setting - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-export-with-timestamps nil) -#+end_src -** Return follows links -:PROPERTIES: -:CUSTOM_ID: ReturnFollowsLink -:END: - -The following setting make =RET= insert a new line instead of opening -links. This setting is a love-hate relationship for me. When it -first came out I immediately turned it off because I wanted to insert -new lines in front of my links and =RET= would open the link instead -which at the time I found extremely annoying. Since then I've -retrained my fingers to hit RET at the end of the previous line. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-return-follows-link t) -#+end_src -** Highlight clock when running overtime -:PROPERTIES: -:CUSTOM_ID: HighlightClockOvertime -:END: - -The current clocking task is displayed on the modeline. If this has -an estimated time and we run over the limit I make this stand out on -the modeline by changing the background to red as follows - -#+header: :tangle yes -#+begin_src emacs-lisp -(custom-set-faces - ;; custom-set-faces was added by Custom. - ;; If you edit it by hand, you could mess it up, so be careful. - ;; Your init file should contain only one such instance. - ;; If there is more than one, they won't work right. - '(org-mode-line-clock ((t (:foreground "red" :box (:line-width -1 :style released-button)))) t)) -#+end_src -** Meeting Notes -:PROPERTIES: -:CUSTOM_ID: MeetingNotes -:END: - -I take meeting notes with org-mode. I record meeting conversations in -point-form using org-mode lists. If action items are decided on in -the meeting I'll denote them with a bullet and a TODO: or DONE: flag. - -A meeting is a task and it is complete when the meeting is over. The -body of the task records all of the interesting meeting details. If -TODO items are created in the meeting I make separate TODO tasks from -those. - -I use the function =bh/prepare-meeting-notes= to prepare the meeting -notes for emailing to the participants (in a fixed-width font like -"Courier New"). As soon as the meeting is over the notes are -basically ready for distribution -- there's not need to waste lots of -time rewriting the minutes before they go out. I haven't bothered -with fancy HTML output -- the content is more important than the -style. - -#+begin_src org :exports src -,* TODO Sample Meeting - - Attendees - - [ ] Joe - - [X] Larry - - [X] Mary - - [X] Fred - - Joe is on vacation this week - - Status Updates - + Larry - - did this - - and that - - TODO: Needs to follow up on this - + Mary - - got a promotion for her recent efforts - + Fred - - completed all his tasks 2 days early - - needs more work - - DONE: everything -#+end_src - -#+begin_src org :exports src -,* TODO Sample Meeting - - Attendees - - [ ] Joe - - [X] Larry - - [X] Mary - - [X] Fred - - Joe is on vacation this week - - Status Updates - + Larry - - did this - - and that ->>>>>>>> TODO: Needs to follow up on this - + Mary - - got a promotion for her recent efforts - + Fred - - completed all his tasks 2 days early - - needs more work ->>>>>>>> DONE: everything -#+end_src - -Here is the formatting function. Just highlight the region for the -notes and it turns tabs into spaces, and highlights todo items. The -resulting notes are in the kill buffer ready to paste to another -application. - -#+header: :tangle yes -#+begin_src emacs-lisp -(defun bh/prepare-meeting-notes () - "Prepare meeting notes for email - Take selected region and convert tabs to spaces, mark TODOs with leading >>>, and copy to kill ring for pasting" - (interactive) - (let (prefix) - (save-excursion - (save-restriction - (narrow-to-region (region-beginning) (region-end)) - (untabify (point-min) (point-max)) - (goto-char (point-min)) - (while (re-search-forward "^\\( *-\\\) \\(TODO\\|DONE\\): " (point-max) t) - (replace-match (concat (make-string (length (match-string 1)) ?>) " " (match-string 2) ": "))) - (goto-char (point-min)) - (kill-ring-save (point-min) (point-max)))))) -#+end_src -** Remove Highlights after changes -:PROPERTIES: -:CUSTOM_ID: HighlightPersistAfterEdit -:END: - -I'm finding I use org-occur =C-c / /= a lot when trying to find -details in my org-files. The following setting keeps the highlighted -results of the search even after modifying the text. This allows me -to edit the file without having to reissue the org-occur command to -find the other matches in my file. =C-c C-c= removes the highlights. - -#+header: :tangle no -#+begin_src emacs-lisp -(setq org-remove-highlights-with-change nil) -#+end_src - -Setting this variable to t will automatically remove the yellow -highlights as soon as the buffer is modified. - -I've gone back to automatically removing the highlights with change -which is the default setting. I've been using regular =M-x occur= a -lot more lately to find things in any Emacs buffer. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-remove-highlights-with-change t) -#+end_src - - -** Getting up to date org-mode info documentation -:PROPERTIES: -:CUSTOM_ID: OrgModeInfoDocumentation -:END: - -I use the org-mode info documentation from the git repository so I set -up emacs to find the info files from git before the regular (out of -date) system versions. - -#+header: :tangle yes -#+begin_src emacs-lisp -(add-to-list 'Info-default-directory-list "~/git/org-mode/doc") -#+end_src -** Prefer future dates or not? -:PROPERTIES: -:CUSTOM_ID: FutureDates -:END: - -By default org-mode prefers dates in the future. This means that if -today's date is May 2 and you enter a date for April 30th (2 days ago) -org-mode will jump to April 30th of next year. I used to find this -annoying when I wanted to look at what happened last Friday since I have -to specify the year. Now I've trained my fingers to go back relatively -in the agenda with =b= so this isn't really an issue for me anymore. - -To make org-mode prefer the current year when entering dates set -the following variable -#+header: :tangle no -#+begin_src emacs-lisp -(setq org-read-date-prefer-future nil) -#+end_src - -I now have this variable set to ='time= so times before now (with no -date specified) will default to tomorrow.. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-read-date-prefer-future 'time) -#+end_src -** Automatically change list bullets -:PROPERTIES: -:CUSTOM_ID: ListBullets -:END: - -I take point-form notes during meetings. Having the same list bullet -for every list level makes it hard to read the details when lists are -indented more than 3 levels. - -Org-mode has a way to automatically change the list bullets when you -change list levels. - -| Current List Bullet | Next indented list bullet | -|---------------------+---------------------------| -| + | - | -| * | - | -| 1. | - | -| 1) | - | -| A) | - | -| B) | - | -| a) | - | -| b) | - | -| A. | - | -| B. | - | -| a. | - | -| b. | - | - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-list-demote-modify-bullet (quote (("+" . "-") - ("*" . "-") - ("1." . "-") - ("1)" . "-") - ("A)" . "-") - ("B)" . "-") - ("a)" . "-") - ("b)" . "-") - ("A." . "-") - ("B." . "-") - ("a." . "-") - ("b." . "-")))) -#+end_src -** Remove indentation on agenda tags view -:PROPERTIES: -:CUSTOM_ID: IndentationOnTagsView -:END: - -I don't like the indented view for sublevels on a tags match in the -agenda but I want to see all matching tasks (including sublevels) when -I do a agenda tag search (=F12 m=). - -To make all of the matched headings for a tag show at the same level -in the agenda set the following variable: -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-tags-match-list-sublevels t) -#+end_src -** Fontify source blocks natively -:PROPERTIES: -:CUSTOM_ID: FontifySrcBlocksNatively -:END: - -I use babel for including source blocks in my documents with - -#+begin_src org :exports src -,#+begin_src LANG -, ... -,#+end_src -#+end_src - -where LANG specifies the language to use (ditaa, dot, sh, emacs-lisp, -etc) This displays the language contents fontified in both the -org-mode source buffer and the exported document. - -See this [[#git-sync][Git Repository synchronization]] in this document for an example.. -** Agenda persistent filters -:PROPERTIES: -:CUSTOM_ID: AgendaPersistentFilters -:END: - -This is a great feature! Persistent agenda filters means if you limit -a search with =/ TAB SomeTag= the agenda remembers this filter until -you change it. - -Enable persistent filters with the following variable - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-agenda-persistent-filter t) -#+end_src - -The current filter is displayed in the modeline as ={+SomeTag}= so you -can easily see what filter currently applies to your agenda view. - -I use this with =FILETAGS= to limit the displayed results to a single -client or context. -** Add tags for flagged entries -:PROPERTIES: -:CUSTOM_ID: TagFlaggedEntries -:END: - -Everyone so often something will come along that is really important -and you know you want to be able to find it back fast sometime in the -future. - -For these types of notes and tasks I add a special =:FLAGGED:= tag. -This tag gets a special fast-key =?= which matches the search key in -the agenda for flagged items. See [[#OrgTagAlist][Tags]] for the setup of -=org-tag-alist= for the =FLAGGED= entry. - -Finding flagged entries is then simple - just =F12 ?= and you get them all. -** Mail links open compose-mail -:PROPERTIES: -:CUSTOM_ID: MailLinksOpenComposeMail -:END: - -The following setting makes org-mode open =mailto:= links -using compose-mail. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-link-mailto-program (quote (compose-mail "%a" "%s"))) -#+end_src -** Composing mail from org mode subtrees -:PROPERTIES: -:CUSTOM_ID: MailingSubtrees -:END: - -It's possible to create mail from an org-mode subtree. I use =C-c -M-o= to start an email message with the details filled in from the -current subtree. I use this for repeating reminder tasks where I need -to send an email to someone else. The email contents are already -contained in the org-mode subtree and all I need to do is =C-c M-o= -and any minor edits before sending it off. -** Use smex for M-x ido-completion -:PROPERTIES: -:CUSTOM_ID: SmexAndIdo -:END: - -I discovered smex for IDO-completion for M-x commands after reading a -post of the org-mode mailing list. I actually use M-x a lot now -because IDO completion is so easy. - -Here's the smex setup I use -#+header: :tangle yes -#+begin_src emacs-lisp -(add-to-list 'load-path (expand-file-name "~/.emacs.d")) -(require 'smex) -(smex-initialize) - -(global-set-key (kbd "M-x") 'smex) -(global-set-key (kbd "C-x x") 'smex) -(global-set-key (kbd "M-X") 'smex-major-mode-commands) -#+end_src -** Use Emacs bookmarks for fast navigation -:PROPERTIES: -:CUSTOM_ID: BookmarksFastNavigation -:END: - -I've started using emacs bookmarks to save a location and return to it easily. -Normally I want to get back to my currently clocking task and that's easy - just hit =F11=. -When I'm working down a long checklist I find it convenient to set a bookmark on the next -item to check, then go away and work on it, and return to the checkbox to mark it done. - -I use Emacs bookmarks for this setup as follows: - -#+header: :tangle yes -#+begin_src emacs-lisp -;; Bookmark handling -;; -(global-set-key (kbd "") '(lambda () (interactive) (bookmark-set "SAVED"))) -(global-set-key (kbd "") '(lambda () (interactive) (bookmark-jump "SAVED"))) -#+end_src - -When I want to save the current location I just hit =C-f6= and then I -can return to it with =f6= anytime. I overwrite the same bookmark -each time I set a new position. -** Using org-mime to email -:PROPERTIES: -:CUSTOM_ID: OrgMimeMail -:END: - -I'm experimenting with sending mime mail from org. I've added =C-c M=o= key bindings -in the =org-mode-hook= to generate mail from an org-mode subtree. - -#+header: :tangle yes -#+begin_src emacs-lisp -(require 'org-mime) -#+end_src -** Remove multiple state change log details from the agenda -:PROPERTIES: -:CUSTOM_ID: StateChangeDetailsInAgenda -:END: -[2011-04-30 Sat 11:14] - -I skip multiple timestamps for the same entry in the agenda view with the following setting. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-agenda-skip-additional-timestamps-same-entry t) -#+end_src - -This removes the clutter of extra state change log details when multiple timestamps -exist in a single entry. -** Drop old style references in tables -:PROPERTIES: -:CUSTOM_ID: OldTableReferences -:END: -[2011-04-30 Sat 11:19] - -I drop the old A3/B4 style references from tables when editing with the -following setting. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-table-use-standard-references (quote from)) -#+end_src -** Use system settings for file-application selection -:PROPERTIES: -:CUSTOM_ID: SystemSettingsForApplicationSelection -:END: -[2011-04-30 Sat 14:38] - -To get consistent applications for opening tasks I set the =org-file-apps= variable as follows: - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-file-apps (quote ((auto-mode . emacs) - ("\\.mm\\'" . system) - ("\\.x?html?\\'" . system) - ("\\.pdf\\'" . system)))) -#+end_src - -This uses the entries defined in my system =mailcap= settings when -opening file extensions. This gives me consistent behaviour when -opening an link to some HTML file with =C-c C-o= or when previewing an export. -** Use the current window for the agenda -:PROPERTIES: -:CUSTOM_ID: CurrentWindowForAgenda -:END: -[2011-05-28 Sat 21:20] - -#+header: :tangle yes -#+begin_src emacs-lisp -; Overwrite the current window with the agenda -(setq org-agenda-window-setup 'current-window) -#+end_src -** Delete IDs when cloning -:PROPERTIES: -:CUSTOM_ID: DeleteIdsWhenCloning -:END: -[2011-05-28 Sat 21:27] - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-clone-delete-id t) -#+end_src -** Cycling plain lists -:PROPERTIES: -:CUSTOM_ID: CyclePlainLists -:END: - -Org mode can fold (cycle) plain lists. -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-cycle-include-plain-lists t) -#+end_src - -I find this setting useful when I have repeating tasks with lots of sublists with -checkboxes. I can fold the completed list entries and focus on what is remaining easily. -** Showing source block syntax highlighting -:PROPERTIES: -:CUSTOM_ID: ShowSrcBlockSyntax -:END: - -It is possible to display org-mode source blocks fontified in their -native mode. This allows colourization of keywords for C and shell -script source etc. If I edit the source I use =C-c '= (control-c single -quote) to bring up the source window which is then rendered with -syntax highlighting in the native mode. This setting also shows the -syntax highlighting when viewing in the org-mode buffer. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-src-fontify-natively t) -#+end_src -** Inserting Structure Template Blocks -:PROPERTIES: -:CUSTOM_ID: StructureTemplateBlocks -:END: -[2012-03-04 Sun 11:42] - -There is a shortcut key sequence in org-mode to insert structure templates -quickly into your org files. - -I use example and source blocks often in my org files. - -| Key Sequence | Expands to | -|--------------+-----------------------------------| -| < s TAB | #+begin_src ... #+end_src | -| < e TAB | #+begin_example ... #+end_example | - -I've added a block for saving email text which I copy from MS Outlook at work so I have context -associated with my org-mode tasks. - -The following lisp makes the blocks lowercase instead of the default upper case in -org-mode. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-structure-template-alist - (quote (("s" "#+begin_src ?\n\n#+end_src" "\n\n") - ("e" "#+begin_example\n?\n#+end_example" "\n?\n") - ("q" "#+begin_quote\n?\n#+end_quote" "\n?\n") - ("v" "#+begin_verse\n?\n#+end_verse" "\n?\n") - ("c" "#+begin_center\n?\n#+end_center" "
\n?\n
") - ("l" "#+begin_latex\n?\n#+end_latex" "\n?\n") - ("L" "#+latex: " "?") - ("h" "#+begin_html\n?\n#+end_html" "\n?\n") - ("H" "#+html: " "?") - ("a" "#+begin_ascii\n?\n#+end_ascii") - ("A" "#+ascii: ") - ("i" "#+index: ?" "#+index: ?") - ("I" "#+include %file ?" "")))) -#+end_src - -** NEXT is for tasks -:PROPERTIES: -:CUSTOM_ID: NextTasks -:END: -[2012-03-04 Sun 12:41] - -=NEXT= keywords are for *tasks* and not *projects*. I've added a -function to the todo state change hook and clock in hook so that any -parent tasks marked =NEXT= automagically change from =NEXT= to =TODO= -since they are now projects and not tasks. - -#+header: :tangle yes -#+begin_src emacs-lisp -(defun bh/mark-next-parent-tasks-todo () - "Visit each parent task and change NEXT states to TODO" - (let ((mystate (or (and (fboundp 'org-state) - state) - (nth 2 (org-heading-components))))) - (when mystate - (save-excursion - (while (org-up-heading-safe) - (when (member (nth 2 (org-heading-components)) (list "NEXT")) - (org-todo "TODO"))))))) - -(add-hook 'org-after-todo-state-change-hook 'bh/mark-next-parent-tasks-todo 'append) -(add-hook 'org-clock-in-hook 'bh/mark-next-parent-tasks-todo 'append) -#+end_src -** Startup in folded view -:PROPERTIES: -:CUSTOM_ID: StartupView -:END: -[2012-04-08 Sun 07:26] - -Startup in folded view. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-startup-folded t) -#+end_src - -I used to use content view by default so I could review org subtrees -before archiving but my archiving workflow has changed so I no longer -need this manual step. -** Allow alphabetical list entries -:PROPERTIES: -:CUSTOM_ID: AlphabeticalLists -:END: -[2012-06-06 Wed 22:23] - -The following setting adds alphabetical lists like - -#+begin_src org :exports src -a. item one -b. item two -#+end_src - -#+header: :tangle no -#+begin_src emacs-lisp -(setq org-alphabetical-lists t) -#+end_src - -In order for filling to work correctly this needs to be set before the -exporters are loaded. -** Using orgstruct mode for mail -:PROPERTIES: -:CUSTOM_ID: OrgStructModeForMail -:END: -[2012-06-24 Sun 11:16] - -=orgstruct++-mode= is enabled in =Gnus= message buffers to aid in -creating structured email messages. - -#+header: :tangle yes -#+begin_src emacs-lisp -(add-hook 'message-mode-hook 'orgstruct++-mode 'append) -(add-hook 'message-mode-hook 'turn-on-auto-fill 'append) -(add-hook 'message-mode-hook 'bbdb-define-all-aliases 'append) -(add-hook 'message-mode-hook 'orgtbl-mode 'append) -(add-hook 'message-mode-hook 'turn-on-flyspell 'append) -(add-hook 'message-mode-hook - '(lambda () (setq fill-column 72)) - 'append) -#+end_src -** Using flyspell mode to reduce spelling errors -:PROPERTIES: -:CUSTOM_ID: FlySpellModeChecksSpelling -:END: -[2012-06-24 Sun 11:17] - -=flyspell-mode= is enabled for almost everything to help prevent -creating documents with spelling errors. - -#+header: :tangle yes -#+begin_src emacs-lisp -;; flyspell mode for spell checking everywhere -(add-hook 'org-mode-hook 'turn-on-flyspell 'append) - -;; Disable keys in org-mode -;; C-c [ -;; C-c ] -;; C-c ; -;; C-c C-x C-q cancelling the clock (we never want this) -(add-hook 'org-mode-hook - '(lambda () - ;; Undefine C-c [ and C-c ] since this breaks my - ;; org-agenda files when directories are include It - ;; expands the files in the directories individually - (org-defkey org-mode-map "\C-c[" 'undefined) - (org-defkey org-mode-map "\C-c]" 'undefined) - (org-defkey org-mode-map "\C-c;" 'undefined) - (org-defkey org-mode-map "\C-c\C-x\C-q" 'undefined)) - 'append) - -(add-hook 'org-mode-hook - (lambda () - (local-set-key (kbd "C-c M-o") 'bh/mail-subtree)) - 'append) - -(defun bh/mail-subtree () - (interactive) - (org-mark-subtree) - (org-mime-subtree)) -#+end_src - -** Preserving source block indentation -:PROPERTIES: -:CUSTOM_ID: PreserveSourceIndentations -:END: -I do not preserve indentation for source blocks mainly because this doesn't look -nice with indented org-files. The only reason I've found to preserve indentation is -when TABs in files need to be preserved (e.g. Makefiles). I don't normally edit -these files in org-mode so I leave this setting turned off. - -I've changed the default block indentation so that it is not indented -from the text in the org file. This allows editing source blocks in -place without requiring use of =C-c '= so that code lines up correctly. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-src-preserve-indentation nil) -(setq org-edit-src-content-indentation 0) -#+end_src -** Prevent editing invisible text -:PROPERTIES: -:CUSTOM_ID: PreventInvisibleEdits -:END: -[2012-07-20 Fri 22:26] - -The following setting prevents accidentally editing hidden text when the point is inside a folded region. -This can happen if you are in the body of a heading and globally fold the org-file with =S-TAB= - -I find invisible edits (and undo's) hard to deal with so now I can't edit invisible text. -=C-c C-r= (org-reveal) will display where the point is if it is buried in invisible text -to allow editing again. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-catch-invisible-edits 'error) -#+end_src -** Use utf-8 as default coding system -:PROPERTIES: -:CUSTOM_ID: DefaultCodingSystem -:END: -[2013-01-01 Tue 13:49] - -I use =utf-8= as the default coding system for all of my org files. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-export-coding-system 'utf-8) -(prefer-coding-system 'utf-8) -(set-charset-priority 'unicode) -(setq default-process-coding-system '(utf-8-unix . utf-8-unix)) -#+end_src - -** Keep clock durations in hours -:PROPERTIES: -:CUSTOM_ID: ClockDurationsNoDays -:END: -[2013-02-17 Sun 12:37] - -The default for clock durations has changed to include days which is -24 hours. At work I like to think of a day as 6 hours of work (the -rest of the time is lost in meetings and other overhead on average) so -displaying clock durations in days doesn't make sense to me. - -The following setting displays clock durations (from =C-c C-x C-d= in -hours and minutes. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-time-clocksum-format - '(:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t)) -#+end_src -** Create unique IDs for tasks when linking -:PROPERTIES: -:CUSTOM_ID: LinkingToTaskCreatesId -:END: -[2013-06-23 Sun 10:38] - -The following setting creates a unique task ID for the heading in the -=PROPERTY= drawer when I use =C-c l=. This allows me to move the task -around arbitrarily in my org files and the link to it still works. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id) -#+end_src -* Things I Don't Use (Anymore) -:PROPERTIES: -:CUSTOM_ID: Unused -:END: - -This is a partial list of things I know about but do not use. -=org-mode= is huge with tons of features. There are features out -there that I don't know about yet or haven't explored so this list is -not going to be complete. -** Archive Sibling -:PROPERTIES: -:CUSTOM_ID: ArchiveSibling -:END: - -This was a cute idea but I find archiving entire complete subtrees -better. I don't mind having a bunch of tasks marked =DONE= (but not -archived) -** Strike-through emphasis -:PROPERTIES: -:CUSTOM_ID: StrikeThroughEmphasis -:END: - -Strike-through emphasis is just unreadable and tends to only show up -when pasting data from other files into org-mode. This just removes -the strike-through completely which I find a lot nicer. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-emphasis-alist (quote (("*" bold "" "") - ("/" italic "" "") - ("_" underline "" "") - ("=" org-code "" "" verbatim) - ("~" org-verbatim "" "" verbatim)))) -#+end_src -** Subscripts and Superscripts -:PROPERTIES: -:CUSTOM_ID: SubscriptsAndSuperscripts -:END: - -I don't currently write documents that need subscripts and superscript -support. I disable handling of =_= and =^= for subscript and -superscripts with - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-use-sub-superscripts nil) -#+end_src -** Yasnippet -:PROPERTIES: -:CUSTOM_ID: Yasnippets -:END: - -[[http://code.google.com/p/yasnippet/][Yasnippet]] is cool but I don't use this anymore. I've replaced -yasnippet with a combination of =abbrev-mode= and =skeletons= which -are available by default in Emacs. - -The following description applies to yasnippet version 0.5.10. The setup -requirements may have changed with newer versions. - -You type the snippet name and =TAB= and yasnippet expands the name -with the contents of the snippet text - substituting snippet variables -as appropriate. - -Yasnippet comes with lots of snippets for programming languages. I -used a few babel related snippets with =org-mode=. - -I downloaded and installed the unbundled version of yasnippet so that -I can edit the predefined snippets. I unpacked the yasnippet software -in my =~/.emacs.d/plugins= directory, renamed =yasnippet0.5.10= to -=yasnippet= and added the following setup in my =.emacs=: - -#+header: :tangle no -#+begin_src emacs-lisp -(add-to-list 'load-path (expand-file-name "~/.emacs.d/plugins")) - -(require 'yasnippet) -(yas/initialize) -(yas/load-directory "~/.emacs.d/plugins/yasnippet/snippets") - -;; Make TAB the yas trigger key in the org-mode-hook and enable flyspell mode and autofill -(add-hook 'org-mode-hook - (lambda () - ;; yasnippet - (make-variable-buffer-local 'yas/trigger-key) - (org-set-local 'yas/trigger-key [tab]) - (define-key yas/keymap [tab] 'yas/next-field-group) - ;; flyspell mode for spell checking everywhere - (flyspell-mode 1) - ;; auto-fill mode on - (auto-fill-mode 1))) -#+end_src - -I used snippets for the following: - - =begin= for generic =#+begin_= blocks - - =dot= for graphviz - - =uml= for PlantUML graphics - - =sh= for bash shell scripts - - =elisp= for emacs lisp code - - initials of a person converts to their full name - I used this while taking meeting notes - -Here is the definition for the =begin= snippet: - -org-mode Yasnippet: ~/.emacs.d/plugins/yasnippet/snippets/text-mode/org-mode/begin -: #name : #+begin_...#+end_ -: # -- -: #+begin_$1 $2 -: $0 -: #+end_$1 - -I used this to create =#+begin_*= blocks like -- =#+begin_example= -- =#+begin_src= -- etc. - -Simply type =begin= and then =TAB= it replaces the =begin= text with -the snippet contents. Then type =src TAB emacs-lisp TAB= and your -snippet block is done. I've shortened this specific sequence to just -=elisp TAB= since I use it fairly often. - -Hit =C-c SingeQuote(')= and insert whatever emacs-lisp code you need. -While in this block you're in a mode that knows how to format and -colourize emacs lisp code as you enter it which is really nice. =C-c -SingleQuote(')= exits back to org-mode. This recognizes any emacs -editing mode so all you have to do is enter the appropriate mode name -for the block. - -=dot= -: #dot : #+begin_src dot ... #+end_src -: # -- -: #+begin_src dot :file $1 :cmdline -Kdot -Tpng -: $0 -: #+end_src - -=uml= -: #uml : #+begin_src plantuml ... #+end_src -: # -- -: #+begin_src plantuml :file $1 -: $0 -: #+end_src - -=sh= -: #sh: #+begin_src sh ... #+end_src -: # -- -: #+begin_src sh :results output -: $0 -: #+end_src - - -=elisp= -: #elisp : #+begin_src emacs-lisp ...#+end_src emacs-lisp -: # -- -: #+begin_src emacs-lisp -: $0 -: #+end_src - -This is a great time saver. -** Show headings at odd levels only or odd-even levels -:PROPERTIES: -:CUSTOM_ID: HeadingLevelsOddEven -:END: -This has been replaced by org-indent-mode - -I've converted my files between odd-levels-only and odd-even using the -functions =org-convert-to-odd-levels= and -=org-convert-to-oddeven-levels= functions a number of times. I ended -up going back to odd-even levels to reduce the amount of leading -whitespace on tasks. I didn't find that lining up the headlines and -tasks in odd-levels-only to be all that helpful. - -#+header: :tangle yes -#+begin_src emacs-lisp -(setq org-odd-levels-only nil) -#+end_src -** Propagate STARTED to parent tasks -:PROPERTIES: -:CUSTOM_ID: PropagateStartedToParent -:END: - -I used to have a =STARTED= and =NEXT= task state. These were -basically the same except =STARTED= indicated that I've clocked some -time on the task. Since then I've just moved to using =NEXT= for -this. - -The following code used to propagate the =STARTED= task up the project -tree but I don't use this anymore. - -When a task is marked =STARTED= (either manually or by clocking it in) the =STARTED= -state propagates up the tree to any parent tasks of this task that are =TODO= or =NEXT=. -As soon as I work on the first =NEXT= task in a tree the project is also marked =STARTED=. -This helps me keep track of things that are in progress. - -Here's the setup I use to propagate =STARTED= to parent tasks: - -#+header: :tangle no -#+begin_src emacs-lisp -;; Mark parent tasks as started -(defvar bh/mark-parent-tasks-started nil) - -(defun bh/mark-parent-tasks-started () - "Visit each parent task and change TODO states to STARTED" - (unless bh/mark-parent-tasks-started - (when (equal org-state "STARTED") - (let ((bh/mark-parent-tasks-started t)) - (save-excursion - (while (org-up-heading-safe) - (when (member (nth 2 (org-heading-components)) (list "TODO" "NEXT")) - (org-todo "STARTED")))))))) - -(add-hook 'org-after-todo-state-change-hook 'bh/mark-parent-tasks-started 'append) -#+end_src -** Automatically clocking tasks -:PROPERTIES: -:CUSTOM_ID: AutomaticallyClockingTasks -:END: - -I used to spend time on an open source project called BZFlag. During -work for releases I want to clock the time I spend testing the new -BZFlag client. I have a key binding in my window manager that runs a -script which starts the clock on my testing task, runs the BZFlag -client, and on exit resumes the clock on the previous clocking task. - -The testing task has an ID property of -=dcf55180-2a18-460e-8abb-a9f02f0893be= and the following elisp code -starts the clock on this task. - -#+header: :tangle no -#+begin_src emacs-lisp -(defun bh/clock-in-bzflagt-task () - (interactive) - (bh/clock-in-task-by-id "dcf55180-2a18-460e-8abb-a9f02f0893be")) -#+end_src - -This is invoked by a bash shell script as follows: - -#+begin_src sh :results output -#!/bin/sh -emacsclient -e '(bh/clock-in-bzflagt-task)' -~/git/bzflag/trunk/bzflag/src/bzflag/bzflag -directory ~/git/bzflag/trunk/bzflag/data $* -emacsclient -e '(bh/resume-clock)' -#+end_src - -The resume clock function just returns the clock to the previous clocking task - -#+header: :tangle no -#+begin_src emacs-lisp -(defun bh/resume-clock () - (interactive) - (if (marker-buffer org-clock-interrupted-task) - (org-with-point-at org-clock-interrupted-task - (org-clock-in)) - (org-clock-out))) -#+end_src - -If no task was clocking =bh/resume-clock= just stops the clock. -** q buries the agenda view buffer -:PROPERTIES: -:CUSTOM_ID: QBuriesAgenda -:END: -[2011-12-20 Tue 23:52] - -With [[#StickyAgendas][Sticky Agendas]] burying the buffer is the default behaviour for -the =q= key so this is not needed anymore. - -I change the =q= key in the agenda so instead of killing the agenda buffer -it merely buries it to the end of the buffer list. This allows me to -pull it back up quickly with the =q= speed key or =f9 f9= and regenerate -the results with =g=. - -#+header: :tangle no -#+begin_src emacs-lisp -(add-hook 'org-agenda-mode-hook - (lambda () - (define-key org-agenda-mode-map "q" 'bury-buffer)) - 'append) -#+end_src -** Task Priorities -:PROPERTIES: -:CUSTOM_ID: TaskPriorities -:END: - -I use the agenda to figure out what to do work on next. I don't use -priorities at all normally but at work I occasionally get priorities -from my manager. In this case I mark my tasks with the priorities -from the external source just to track the values and force the agenda -to display tasks in the priority order. - -I use priorities A-E where tasks without a specific priority are lowest priority E. -#+header: :tangle no -#+begin_src emacs-lisp -(setq org-enable-priority-commands t) -(setq org-default-priority ?E) -(setq org-lowest-priority ?E) -#+end_src -* Using Git for Automatic History, Backups, and Synchronization -:PROPERTIES: -:CUSTOM_ID: GitSync -:END: - -Editing folded regions of your org-mode file can be hazardous to your -data. My method for dealing with this is to put my org files in a -=Git= source repository. - -My setup saves all of my org-files every hour and creates a commit -with my changes automatically. This lets me go back in time and view -the state of my org files for any given hour over the lifetime of the -document. I've used this once or twice to recover data I accidentally -removed while editing folded regions. -** Automatic Hourly Commits -:PROPERTIES: -:CUSTOM_ID: HourlyCommits -:END: - -My Emacs setup saves all org buffers at 1 minute before the hour using -the following code in my =.emacs= - -#+header: :tangle yes -#+begin_src emacs-lisp -(run-at-time "00:59" 3600 'org-save-all-org-buffers) -#+end_src - -A =cron= job runs at the top of the hour to commit any changes just -saved by the call to =org-save-all-org-buffers= above. I use a script -to create the commits so that I can run it on demand to easily commit -all modified work when moving from one machine to another. - -=crontab= details: -#+begin_example -0 * * * * ~/bin/org-git-sync.sh >/dev/null -#+end_example -*** ~/bin/org-git-sync.sh -:PROPERTIES: -:CUSTOM_ID: OrgGitSyncSh -:END: - -Here is the shell script I use to create a =git= commit for each of my -org-repositories. This loops through multiple repositories and -commits any modified files. I have the following org-mode -repositories: - -- org - - for all of my organization project files and todo lists - -- doc-norang.ca - - for any changes to documents under http://doc.norang.ca/ - -- www.norang.ca - - for any changes to my other website http://www.norang.ca/ - -This script does not create empty commits - =git= only creates a commit -if something was modified. -#+begin_src sh -#!/bin/sh -# Add org file changes to the repository -REPOS="org doc.norang.ca www.norang.ca" - -for REPO in $REPOS -do - echo "Repository: $REPO" - cd ~/git/$REPO - # Remove deleted files - git ls-files --deleted -z | xargs -0 git rm >/dev/null 2>&1 - # Add new files - git add . >/dev/null 2>&1 - git commit -m "$(date)" -done -#+end_src - -I use the following =.gitignore= file in my org-mode =git= -repositories to keep export generated files out of my =git= -repositories. If I include a graphic from some other source than -ditaa or graphviz then I'll add it to the repository manually. By -default all PNG graphic files are ignored (since I assume they are -produced by ditaa during export) -#+begin_example -core -core.* -,*.html -,*~ -.#* -\#*\# -,*.txt -,*.tex -,*.aux -,*.dvi -,*.log -,*.out -,*.ics -,*.pdf -,*.xml -,*.org-source -*.png -*.toc -#+end_example -** Git - Edit files with confidence -:PROPERTIES: -:CUSTOM_ID: GitEditWithConfidence -:END: - -I use =git= in all of my directories where editing a file should be -tracked. - -This means I can edit files with confidence. I'm free to change stuff -and break things because it won't matter. It's easy to go back to a -previous working version or to see exactly what changed since the last -commit. This is great when editing configuration files (such as -apache webserver, bind9 DNS configurations, etc.) - -I find this extremely useful where your edits might break things and -having =git= tracking the changes means if you break it you can just -go back to the previous working version easily. This is also true for -package upgrades for software where the upgrade modifies the -configuration files. - -I have every version of my edits in a local =git= repository. -** Git Repository synchronization -:PROPERTIES: -:CUSTOM_ID: git-sync -:END: - -I acquired a Eee PC 1000 HE which now serves as my main road-warrior -laptop replacing my 6 year old Toshiba Tecra S1. - -I have a server on my LAN that hosts bare git repositories for all of -my projects. The problem I was facing is I have to leave in 5 minutes -and want to make sure I have up-to-date copies of everything I work on -when I take it on the road (without Internet access). - -To solve this I use a server with bare git repositories on it. This -includes my org-mode repositories as well as any other git -repositories I'm interested in. - -Just before I leave I run the =git-sync= script on my workstation to -update the bare git repositories and then I run it again on my Eee PC -to update all my local repositories on the laptop. For any -repositories that give errors due to non-fast-forward merges I -manually merge as required and rerun =git-sync= until it reports no -errors. This normally takes a minute or two to do. Then I grab my -Eee PC and leave. When I'm on the road I have full up-to-date history -of all my git repositories. - -The =git-sync= script replaces my previous scripts with an all-in-one -tool that basically does this: - -- for each repository on the current system - - fetch objects from the remote - - for each branch that tracks a remote branch - - Check if the ref can be moved - - fast-forwards if behind the remote repository and is fast-forwardable - - Does nothing if ref is up to date - - Pushes ref to remote repository if ref is ahead of remote repository and fast-forwardable - - Fails if ref and remote have diverged - -This automatically advances changes on my 35+ git repositories with -minimal manual intervention. The only time I need to manually do -something in a repository is when I make changes on my Eee PC and my -workstation at the same time - so that a merge is required. - -Here is the =git-sync= script - -#+begin_src sh -#!/bin/sh -# - -# Local bare repository name -syncrepo=norang -reporoot=~/git - -# Display repository name only once -log_repo() { - [ "x$lastrepo" == "x$repo" ] || { - printf "\nREPO: ${repo}\n" - lastrepo="$repo" - } -} - -# Log a message for a repository -log_msg() { - log_repo - printf " $1\n" -} - -# fast-forward reference $1 to $syncrepo/$1 -fast_forward_ref() { - log_msg "fast-forwarding ref $1" - current_ref=$(cat .git/HEAD) - if [ "x$current_ref" = "xref: refs/heads/$1" ] - then - # Check for dirty index - files=$(git diff-index --name-only HEAD --) - git merge refs/remotes/$syncrepo/$1 - else - git branch -f $1 refs/remotes/$syncrepo/$1 - fi -} - -# Push reference $1 to $syncrepo -push_ref() { - log_msg "Pushing ref $1" - if ! git push --tags $syncrepo $1 - then - exit 1 - fi -} - -# Check if a ref can be moved -# - fast-forwards if behind the sync repo and is fast-forwardable -# - Does nothing if ref is up to date -# - Pushes ref to $syncrepo if ref is ahead of syncrepo and fastforwardable -# - Fails if ref and $syncrop/ref have diverged -check_ref() { - revlist1=$(git rev-list refs/remotes/$syncrepo/$1..$1) - revlist2=$(git rev-list $1..refs/remotes/$syncrepo/$1) - if [ "x$revlist1" = "x" -a "x$revlist2" = "x" ] - then - # Ref $1 is up to date. - : - elif [ "x$revlist1" = "x" ] - then - # Ref $1 is behind $syncrepo/$1 and can be fast-forwarded. - fast_forward_ref $1 || exit 1 - elif [ "x$revlist2" = "x" ] - then - # Ref $1 is ahead of $syncrepo/$1 and can be pushed. - push_ref $1 || exit 1 - else - log_msg "Ref $1 and $syncrepo/$1 have diverged." - exit 1 - fi -} - -# Check all local refs with matching refs in the $syncrepo -check_refs () { - git for-each-ref refs/heads/* | while read sha1 commit ref - do - ref=${ref/refs\/heads\//} - git for-each-ref refs/remotes/$syncrepo/$ref | while read sha2 commit ref2 - do - if [ "x$sha2" != "x" -a "x$sha2" != "x" ] - then - check_ref $ref || exit 1 - fi - done - done -} - -# For all repositories under $reporoot -# Check all refs matching $syncrepo and fast-forward, or push as necessary -# to synchronize the ref with $syncrepo -# Bail out if ref is not fastforwardable so user can fix and rerun -time { - retval=0 - if find $reporoot -type d -name '*.git' | { - while read repo - do - repo=${repo/\/.git/} - cd ${repo} - upd=$(git remote update $syncrepo 2>&1 || retval=1) - [ "x$upd" = "xFetching $syncrepo" ] || { - log_repo - printf "$upd\n" - } - check_refs || retval=1 - done - exit $retval - } - then - printf "\nAll done.\n" - else - printf "\nFix and redo.\n" - fi -} - -exit $retval -#+end_src diff --git a/doc/emacs-notes.org b/emacs-notes.org similarity index 100% rename from doc/emacs-notes.org rename to emacs-notes.org