My Organizational Workflow
How I use org-mode and other tools to streamline my life
This is an up-to-date document on my org-mode workflow. This is inspired by “A Guide to My Organizational Workflow: How to Streamline Your Life” and other articles like Getting Boxes Done, Getting Boxes Done, the Code, Refiling Trees to Files. In a gist this is about how I take notes and how I keep track on what I work on and what I need to work on.
This is part of My Emacs System.
Introduction
I am not sure exactly when, but overtime, my life grew in complexity, and I decide along the way to use org-mode to help me with that. Even though org-mode could be considered as an implementation detail of my workflow, it’s really hard to separate from it. I’ll try my best to describe the workflow without mentionning org-mode and from there, we’ll see how my setup does it.
Many of the ideas presented here derive from the Getting Things Done methodology, but adapted and expanded to meet my personal needs. With that workflow, I am trying to spint my time more wisely and focus on what’s important to me. This is not a silver bullet though, and is an always in progress work.
Goals
I really liked the goal list from “A Guide to My Organizational Workflow: How to Streamline Your Life”, so I kinda took heavy inspiration from it.
In order to determine how effective an organizational system is, it is important to have clearly enumerated aims: what is the system being designed to enable? Your goals may be different, but my system is structured to prioritize the following:
- Ensure that I never miss a task, meeting, or deadline (note: the meeting part is tricky);
- Manage tasks that I need to work on;
- Manage tasks that I share with and have assigned to others (when I depend on it);
- Keep a permanent record of my work and research, and in a way that can be easily shared with others if necessary;
- Collect my thoughts, writings, and half-baked ideas;
- Ensure that my local progress—on a daily or monthly basis—is in service of my long-term goals (this is kinda hard to do);
- Finally: ensure I enjoy my life and make time for fun and friends! My system is meant to organize, not confine.
One key idea to keep in mind as well is that an organizational system should be flexible. Life is complicated and unexpected items—both good and bad—can appear at a moment’s notice. While it may not be immediately clear where a new task or project belongs, one should always have the ability to add new files or lists to which the new items can be added. Additionally, I do occasionally discover a file or project will outgrow the way I decided to structure it at its inception. My tools support fast and easy refactoring when necessary so that I can restructure a project to reflect my updated understanding of the problems it was intended to solve. The greater the effort required to reorganize when necessary, the less frequently it will happen and the effectiveness of the organizational system will decline. The tools I will describe later on work well for me, but you should find those tools that work best for you.
The above is the reason why I am using org-mode : it’s plain text, it’s flexible — you can
add data (properties, tags, …), you can define your behavior (using emacs-lisp
code).
My workflow
As described earlier, my workflow is loosely based on some concept from the Getting Things Done methodology, but adapted and expanded to meet my personal needs. One of the core principles of the Getting Things Done methodology, is that “the mind is for thinking, not remembering”. Everything that may need to be accomplished—or that you might someday want to accomplish—should be written down.
I also really like the boxes comparison from Getting Boxes Done.
On my workbench is a box. Actually, a few boxes. Each uncompleted project goes into a box… no lost screws. Sure unpacking and packing between each session is a hassle, but since the best projects take a few weekends, boxes are required.
Non-workbench-oriented projects go into mental boxes, and I’m thinking of my self organization in terms of boxes. Thoughts don’t go into physical boxes, but in my world, they live in text files. […]
My usual workflow for solving a problem involves breaking up a high-level objective into increasingly smaller goals until I can make progress towards accomplishing it. org-mode allows me to collect my tasks and projects when needed and build the lists. As I work, I log my progress, my thoughts, where I get stuck, temporary images or figures, intermediate results, how to reproduce my work, and so on. Note taking is a critical part of my thinking process, so notes and their parent tasks should coexist.
If we talk in files now, this looks like the following:
- archive
- this is where I archive my project and notes if they don’t make sense anymore.
- notes
- this is my notes boxes, where I keep my journal entry (monthly files), private and public notes (the one published here).
- projects
- this is my project boxes, where I keep a set of files containing tasks I
need to do for specific projects (related to my work, or personal). Each file represent
a project and should be archived at some point, except a bunch of special ones
(
inbox
,incubate
,next
, …)inbox
is where I capture ideas, task and links that I need to review later.incubate
is where ideas (captured previously in inbox) are going while waiting for being picked up.next
is where I put small task that can be quickly done, like a doing a quick backup, etc. My wish is to have the least amount of tasks innext
.
Implementation
Constants and registers
Let’s dig into the files and folders I’ll use across the rest of my configuration.
(defconst org-directory "~/desktop/org/" "org-mode directory, where most of the org-mode file lives") (defconst org-projects-dir (expand-file-name "projects" org-directory) "Primary tasks directory.") (defconst org-notes-dir (expand-file-name "notes" org-directory) "Directory of shareable, technical notes.") (defconst org-archive-dir (expand-file-name "archive" org-directory) "Directory of shareable, technical notes.") (defconst org-completed-dir (expand-file-name "projects" org-archive-dir) "Directory of completed project files.") (defconst org-inbox-file (expand-file-name "inbox.org" org-projects-dir) "New stuff collected in this file.") (defconst org-next-file (expand-file-name "next.org" org-projects-dir) "Todo *next* collected in this file.") (defconst org-incubate-file (expand-file-name "incubate.org" org-projects-dir) "Ideas simmering on back burner.") (defconst org-babel-library-file (expand-file-name "org_library_of_babel.org" org-notes-dir) "Org babel library.")
I’m also using registers to quickly access some files, mainly the inbox
file, the
incubate
file and the next
file.
(set-register ?i `(file . ,org-inbox-file)) (set-register ?I `(file . ,org-incubate-file)) (set-register ?n `(file . ,org-next-file))
TODO Main configuration
(use-package org :ensure org-plus-contrib ;; load from the package instead of internal :mode (("\\.org$" . org-mode) ("\\.org.draft$" . org-mode)) :commands (org-agenda org-capture) :bind (("C-c o l" . org-store-link) ("C-c o r r" . org-refile) ("C-c o a a" . org-agenda) ("C-c o a r" . my/reload-org-agenda-files) ("C-c o s" . org-sort) ("<f12>" . org-agenda) ("C-c o c" . org-capture) ;; Skeletons ("C-c o i p" . vde/org-project) ("C-c o i n" . vde/org-www-post)) :config (define-skeleton vde/org-project "new org-mode project" nil > "#+TITLE: " (skeleton-read "Title: ") \n > "#+FILETAGS: " (skeleton-read "Tags: ") \n > _ \n > "#+BEGIN: clocktable :scope file :maxlevel 2 :emphasize nil :link t" \n > "#+END:" \n > _ \n) (define-skeleton vde/org-www-post "new www post" nil > "#+title: " (skeleton-read "Title: ") \n > "#+date: " (format-time-string "<%Y-%M-%d %a>") \n > "#+filetags: " (skeleton-read "Tags: ") \n > "#+setupfile: ../templates/post.org" \n > _ \n > "* Introduction" ) ;; Org Babel configurations (when (file-exists-p org-babel-library-file) (org-babel-lob-ingest org-babel-library-file)) (defun my/org-agenda-files () `(,org-projects-dir "~/src/home/tasks.org" "~/src/www/tasks.org")) (defun my/reload-org-agenda-files () (interactive) (setq org-agenda-files (my/org-agenda-files))) (setq org-agenda-files (my/org-agenda-files) org-agenda-file-regexp "^[a-zA-Z0-9-_]+.org$" org-use-speed-commands t org-special-ctrl-a/e t org-special-ctrl-k t org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "STARTED(s)" "|" "DONE(d!)" "CANCELED(c@/!)") (sequence "WAITING(w@/!)" "SOMEDAY(s)" "|" "CANCELED(c@/!)") (sequence "IDEA(i)" "|" "CANCELED(c@/!)")) org-todo-state-tags-triggers '(("CANCELLED" ("CANCELLED" . t)) ("WAITING" ("WAITING" . t)) (done ("WAITING")) ("TODO" ("WAITING") ("CANCELLED")) ("NEXT" ("WAITING") ("CANCELLED")) ("DONE" ("WAITING") ("CANCELLED"))) org-use-tag-inheritance t org-tag-alist '(("linux") ("nixos") ("emacs") ("org") ("openshift") ("redhat") ("tektoncd") ("kubernetes") ("knative" ) ("docker") ("docs") ("code") ("review") (:startgroup . nil) ("#home" . ?h) ("#work" . ?w) ("#errand" . ?e) ("#health" . ?l) (:endgroup . nil) (:startgroup . nil) ("#link" . ?i) ("#read" . ?r) ("#project" . ?p) (:endgroup . nil)) org-log-done 'time org-log-redeadline 'time org-log-reschedule 'time org-log-into-drawer t org-enforce-todo-dependencies t org-refile-targets (append '((org-inbox-file :level . 0)) (->> (directory-files org-projects-dir nil ".org") (--remove (s-starts-with? "." it)) (--map (format "%s/%s" org-projects-dir it)) (--map `(,it :level . 1)))) org-refile-use-outline-path 'file org-refile-allow-creating-parent-nodes 'confirm org-outline-path-complete-in-steps nil org-columns-default-format "%80ITEM(Task) %TODO %3PRIORITY %10Effort(Effort){:} %10CLOCKSUM" org-fontify-whole-heading-line t org-pretty-entities t org-ellipsis " ⤵" org-archive-location (concat org-completed-dir "/%s::datetree/") org-use-property-inheritance t org-priority 67 org-priority-faces '((?A . "#ff2600") (?B . "#ff5900") (?C . "#ff9200") (?D . "#747474")) 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"))) org-blank-before-new-entry '((heading . t) (plain-list-item . nil)) org-insert-heading-respect-content t org-yank-adjusted-subtrees t org-image-actual-width nil org-startup-with-inline-images nil org-list-demote-modify-bullet '(("+" . "-") ("-" . "+")) org-catch-invisible-edits 'error ;; Put theses into a minor mode org-indent-indentation-per-level 1 org-cycle-separator-lines 1 org-adapt-indentation nil org-hide-leading-stars t org-hide-emphasis-markers t) (setcar (nthcdr 4 org-emphasis-regexp-components) 10) :hook (org-mode . vde/org-mode-hook)) (defun vde/org-mode-hook () "Org-mode hook" (setq show-trailing-whitespace t) (when (not (eq major-mode 'org-agenda-mode)) (setq fill-column 90) (auto-revert-mode) (auto-fill-mode) (org-indent-mode) (set (make-local-variable 'company-backends) '(company-emoji company-capf company-files company-dabbrev)) (company-mode 1) (add-hook 'before-save-hook #'save-and-update-includes nil 'make-it-local)))
TODO Agenda
(use-package org-agenda :after org :commands (org-agenda) :bind (("C-c o a a" . org-agenda) ("<f12>" . org-agenda) ("C-c o r a" . org-agenda-refile)) :config (use-package org-super-agenda :config (org-super-agenda-mode)) (setq org-agenda-span 'day org-agenda-start-on-weekday 1 org-agenda-include-diary t org-agenda-window-setup 'current-window org-agenda-skip-scheduled-if-done nil org-agenda-compact-blocks t org-agenda-sticky t org-super-agenda-header-separator "" org-agenda-custom-commands `(("w" "Agenda" ((agenda "") (tags-todo "-goals-incubate-inbox+TODO=\"STARTED\"" ((org-agenda-overriding-header "Ongoing"))) (tags-todo "-goals-incubate-inbox+TODO=\"NEXT\"" ((org-agenda-overriding-header "Next")))) ((org-super-agenda-groups '((:name "Important" :priority "A") (:name "Scheduled" :time-grid t) (:habit t)))) (org-agenda-list)))))
(use-package org-gcal :after (org) :commands (org-gcal-fetch) :config (require 'netrc) (setq-default org-gcal-remove-cancelled-events t) (defun get-authinfo (host port) (let* ((netrc (netrc-parse (expand-file-name "~/.authinfo.gpg"))) (hostentry (netrc-machine netrc host port port))) (when hostentry (netrc-get hostentry "password")))) (setq org-gcal-client-id "959564825992-kvc7ofe9640cpc8ibgjqqgpi15e89nkn.apps.googleusercontent.com" org-gcal-client-secret (get-authinfo "gcal.api" "9999") org-gcal-file-alist '(("vdemeest@redhat.com" . "~/desktop/org/projects/schedule.org"))))
TODO Habits
(use-package org-habit :after (org) :config (setq org-habit-show-habits-only-for-today nil org-habit-graph-column 80))
TODO Capture
(use-package org-capture :after org :commands (org-capture) :config (add-to-list 'org-capture-templates `("l" "Link" entry (file ,org-inbox-file) "* %a\n%U\n%?\n%i" :empty-lines 1)) (add-to-list 'org-capture-templates `("t" "Tasks")) (add-to-list 'org-capture-templates `("tt" "New task" entry (file ,org-inbox-file) "* %?\n:PROPERTIES:\n:CREATED:%U\n:END:\n\n%i\n\nFrom: %a" :empty-lines 1)) (add-to-list 'org-capture-templates `("tr" "PR Review" entry (file ,org-inbox-file) "* TODO review gh:%^{issue} :review:\n:PROPERTIES:\n:CREATED:%U\n:END:\n\n%i\n%?\nFrom: %a" :empty-lines 1)) ;; (add-to-list 'org-capture-templates ;; `("m" "Meeting notes" entry ;; (file+datetree ,org-meeting-notes-file) ;; (file ,(concat user-emacs-directory "/etc/orgmode/meeting-notes.org")))) (add-to-list 'org-capture-templates `("w" "Writing")) :bind (("C-c o c" . org-capture))) (use-package org-capture-pop-frame :after org)
TODO Templates
* %^{meeting} - Actions :: | What | Who | When | State | |-------------------------------------+------------+------+-------| - Decisions :: | Decisions | |-----------| ** Present at meeting - [ ] ** Agenda - %? ** Notes - Use =:Decision:= tag for decision - Use entry with =TODO= (or =DONE=) for actions
** %(format-time-string org-journal-time-format) weekly review :weekly:review: %U - [ ] review ~inbox.org~ Clean the file by either - refiling it to ~incubate.org~ - removing it / archiving it - [ ] review ~incubate.org~ - Is something worth becoming a project - Is something not worth thinking about anymore ? - [ ] empty mail inbox (and create task if needed) - [ ] work - [ ] perso - [ ] Review next week ~F12 n w f~ - [ ] review ~org-mode~ workflow - *what works, what doesn't ?* - *is there task / stuck projects ?* - *enhancement possible ?* - [ ] export previous agenda (somewhere)
TODO Protocol
(use-package org-protocol
:after org)
TODO Clocking
(use-package org-clock :after org :commands (org-clock-in org-clock-out org-clock-goto) :config ;; Setup hooks for clock persistance (org-clock-persistence-insinuate) (setq org-clock-clocked-in-display nil ;; Show lot of clocking history so it's easy to pick items off the C-F11 list org-clock-history-length 23 ;; Change tasks to STARTED when clocking in org-clock-in-switch-to-state 'vde/clock-in-to-started ;; Clock out when moving task to a done state org-clock-out-when-done t ;; Save the running clock and all clock history when exiting Emacs, load it on startup org-clock-persist t) (use-package find-lisp) (defun vde/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 vde/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 (vde/find-project-task) (if (equal (point) task) nil t)))) (defun vde/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 vde/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 vde/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 vde/clock-in-to-started (kw) "Switch a task from TODO to STARTED when clocking in. Skips capture tasks, projects, and subprojects. Switch projects and subprojects from STARTED back to TODO" (when (not (and (boundp 'org-capture-mode) org-capture-mode)) (cond ((and (member (org-get-todo-state) (list "TODO")) (vde/is-task-p)) "STARTED") ((and (member (org-get-todo-state) (list "STARTED")) (vde/is-project-p)) "TODO")))) :bind (("<f11>" . org-clock-goto)))
TODO Notes taking
(use-package org-roam :commands (org-roam org-roam-build-cache) ;; :hook ;; (after-init . org-roam-mode) :bind (("C-c o n" . org-roam-mode) :map org-roam-mode-map (("C-c n l" . org-roam) ("C-c n f" . org-roam-find-file) ("C-c n g" . org-roam-show-graph) ("C-c n b" . org-roam-switch-to-buffer)) :map org-mode-map (("C-c n i" . org-roam-insert))) :custom (org-roam-directory org-notes-dir) :custom-face (org-roam-link ((t (:inherit org-link :foreground "#C991E1")))) :config (require 'org-roam-protocol) ;; (defun jethro/conditional-hugo-enable () ;; (save-excursion ;; (if (cdr (assoc "SETUPFILE" (org-roam--extract-global-props '("SETUPFILE")))) ;; (org-hugo-auto-export-mode +1) ;; (org-hugo-auto-export-mode -1)))) ;; ;; (with-eval-after-load 'org ;; (defun my/org-roam--backlinks-list (file) ;; (if (org-roam--org-roam-file-p file) ;; (--reduce-from ;; (concat acc (format "- [[file:%s][%s]]\n" ;; (file-relative-name (car it) org-roam-directory) ;; (org-roam--get-title-or-slug (car it)))) ;; "" (org-roam-sql [:select [file-from] ;; :from file-links ;; :where (= file-to $s1) ;; :and file-from :not :like $s2] file "%private%")) ;; "")) ;; (defun my/org-export-preprocessor (_backend) ;; (let ((links (my/org-roam--backlinks-list (buffer-file-name)))) ;; (unless (string= links "") ;; (save-excursion ;; (goto-char (point-max)) ;; (insert (concat "\n* Backlinks\n" links)))))) ;; (add-hook 'org-export-before-processing-hook 'my/org-export-preprocessor)) (setq org-roam-capture-ref-templates '(("r" "ref" plain #'org-roam-capture--get-point "" :file-name "${slug}" :head "#+title: ${title}\n#+roam_key: ${ref}\n\n${body}" :unnarrowed t))) (setq org-roam-capture-templates '(("d" "default" plain (function org-roam--capture-get-point) "%?" :file-name "${slug}" #+TITLE: ${title}\n" :unnarrowed t) ("p" "private" plain (function org-roam--capture-get-point) "%?" :file-name "${slug}.private" :head "#+TITLE: ${title}\n" :unnarrowed t))))
TODO Rebuild configurations files
Most of my configuration files are store in my home
monorepo. That said, most of those
are actually automatically generated from litterate org-mode
files coming from my notes.
I want to be able to update those all in one go. Even better, I would like to make sure I update those before killing emacs.
(use-package org :defer 2 :config (defun vde/tangle-all-notes () "Produce files from my notes folder. This function will attempt to tangle all org files from `org-notes-dir'. The assumption is that those will generate configuration file (in `~/src/home'), and thus keeping the configuration source up-to-date" (mapc (lambda (x) (org-babel-tangle-file x)) (ignore-errors (directory-files-recursively org-notes-dir "\.org$")))))
TODO Journaling
(use-package org-journal :commands (org-journal-new-entry org-capture) :after (org-capture) :bind (("C-c n j" . org-journal-new-entry) ("C-c o j" . org-journal-new-entry)) :init (defun org-journal-find-location () "Open today's journal, but inhibiting inserting the heading, leaving that to the template." (org-journal-new-entry t) ;; position pont on the journal's top-level heading so that org-capture will add the new entry as a child. (goto-char (point-max))) (add-to-list 'org-capture-templates `("j" "Journal")) (add-to-list 'org-capture-templates `("jj" "Journal entry" entry (function org-journal-find-location) "** %(format-time-string org-journal-time-format)%^{Title}\n%i%?" :empty-lines 1 :clock-in t :clock-resume t)) (add-to-list 'org-capture-templates `("je" "Weekly review" entry (function org-journal-find-location) (file ,(expand-file-name "etc/orgmode/weekly.org" user-emacs-directory)) :empty-lines 1 :clock-in t :clock-resume t)) :custom (org-journal-date-prefix "* ") (org-journal-file-header "#+TITLE: %Y-v%m Journal\n\n") (org-journal-file-format "%Y-%m.private.org") (org-journal-file-type 'monthly) (org-journal-dir org-notes-dir) (org-journal-date-format "%A, %d %B %Y") (org-journal-enable-agenda-integration nil))
TODO Litterate programming
Although not really in my “organization” workflow, this is related to org-mode so this leaves here for now.
(use-package org-src :after (org) :config (setq org-src-fontify-natively t org-src-tab-acts-natively t org-src-window-setup 'current-window org-edit-src-content-indentation 0))
TODO Links
;; my personal (use-package ol-github :after (org)) (use-package ol-gitlab :after (org)) (use-package ol-ripgrep :after (org)) (use-package ol-rg :disabled :after (org)) (use-package ol-grep :after (org)) ;; built-in org-mode (use-package ol-eshell :after (org)) (use-package ol-git-link :defer 2 :after (org)) (use-package ol-gnus :defer 2 :after (org)) (use-package ol-irc :defer 2 :after (org)) (use-package ol-info :defer 2 :after (org)) (use-package ol-man :defer 2 :after (org)) (use-package ol-notmuch :defer 2 :after (org))
(use-package orgit
:after org)
TODO Babel
(use-package ob-async :after org :commands (ob-async-org-babel-execute-src-block)) (use-package ob-css :after org :commands (org-babel-execute:css)) (use-package ob-dot :after org :commands (org-babel-execute:dot)) (use-package ob-ditaa :after org :commands (org-babel-execute:ditaa) :config (setq org-ditaa-jar-path "/home/vincent/.nix-profile/lib/ditaa.jar")) (use-package ob-emacs-lisp :after org :commands (org-babel-execute:emacs-lisp org-babel-execute:elisp)) (use-package ob-go :after org :commands (org-babel-execute:go)) (use-package ob-gnuplot :after org :commands (org-babel-execute:gnuplot)) (use-package ob-http :after org :commands (org-babel-execute:http)) (use-package ob-js :after org :commands (org-babel-execute:js)) (use-package ob-latex :after org :commands (org-babel-execute:latex)) (use-package ob-python :after org :commands (org-babel-execute:python)) (use-package ob-shell :after org :commands (org-babel-execute:ash org-babel-execute:bash org-babel-execute:csh org-babel-execute:dash org-babel-execute:fish org-babel-execute:ksh org-babel-execute:mksh org-babel-execute:posh org-babel-execute:sh org-babel-execute:shell org-babel-execute:zsh)) (use-package ob-doc-makefile :after org :commands (org-babel-execute:makefile))
TODO Diary
(use-package diary-lib :after (org) :config (setq diary-entry-marker "diary") (setq diary-show-holidays-flag t) (setq diary-header-line-flag nil) (setq diary-mail-days 3) (setq diary-number-of-entries 3) (setq diary-comment-start ";") (setq diary-comment-end "") (setq diary-date-forms '((day "/" month "[^/0-9]") (day "/" month "/" year "[^0-9]") (day " *" monthname " *" year "[^0-9]") (monthname " *" day "[^,0-9]") (monthname " *" day ", *" year "[^0-9]") (year "[-/]" month "[-/]" day "[^0-9]") (dayname "\\W"))))
TODO Miscellaneous
(use-package org-id :after org :commands contrib/org-id-headlines :config (setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id) (defun contrib/org-get-id (&optional pom create prefix) "Get the CUSTOM_ID property of the entry at point-or-marker POM. If POM is nil, refer to the entry at point. If the entry does not have an CUSTOM_ID, the function returns nil. However, when CREATE is non nil, create a CUSTOM_ID if none is present already. PREFIX will be passed through to `org-id-new'. In any case, the CUSTOM_ID of the entry is returned." (org-with-point-at pom (let ((id (org-entry-get nil "CUSTOM_ID"))) (cond ((and id (stringp id) (string-match "\\S-" id)) id) (create (setq id (org-id-new (concat prefix "h"))) (org-entry-put pom "CUSTOM_ID" id) (org-id-add-location id (buffer-file-name (buffer-base-buffer))) id))))) (defun contrib/org-id-headlines () "Add CUSTOM_ID properties to all headlines in the current file which do not already have one." (interactive) (org-map-entries (funcall 'contrib/org-get-id (point) 'create))))
(use-package org-crypt :after (org) :config (org-crypt-use-before-save-magic) (setq org-tags-exclude-from-inheritance '("crypt")))
(use-package org-tempo
:after (org))
(use-package org-attach :after org :config (setq org-link-abbrev-alist '(("att" . org-attach-expand-link))))
(use-package ox-publish :after org :commands (org-publish org-publish-all org-publish-project org-publish-current-project org-publish-current-file) :config (setq org-html-coding-system 'utf-8-unix))
Triage
# -*- mode: org; eval: (add-hook 'after-save-hook (lambda () (org-babel-tangle)) nil t) -*-
- Remove slack from phone (or personal tablets) With working remote, it’s even more important to draw the line
- Have timeboxed « slacking off » session by slacking off, I mean twitter, reddit, …
- Take a medium to long walk during the day Better in the middle, by medium to long I mean at least an hour walk
- It’s ok to set smaller pomodoro from time to time, 25 is the “longest” limit, not the lowest one
- Apply it as much as you can (i.e. not interruption)
- Pomodoro technique
- https://thelifelifebalance.com/pros-and-cons-of-pomodoro/
- Phone / tablet
- Remove most apps
- Remove most notifications
- Grayscale most of the time
TODO org-mode
Workflow
Logbook
nil
This goes into emacs.org
.
Ideas:
- filter org file(s) with a tags & co
- use case:
journal.org
with weekly-review only, worklog only, … - subject (go, emacs, …) to build article or gather thoughts, idea, reviews, …
- use case:
- Heavy usage of
org-protocol
to list reviews done, and more quickly capture content from the browser
The rest is deprecated 😅
Deprecated
Let’s try to think about “TODOs” management in the light of todoist
and org-mode
.
Reasons to use todoist
are :
- write task/todo items on-the-go on any devices — this is way harder with
org-mode
. - list and mark task/todo as done from anywhere
- share some list with others (mainly @houbeb)
- have some nice stats
Reasons to use org-mode
are :
- integrated with my editor, agenda, notes, mail, …
- easily customizable (dashboard, agenda, search, filters, org-links, …)
- all text, data are own by me, replicated
- clock possibility (related to work, so adding some context to it)
One idea is to be able to synchronize org-mode
and todoist
- only part of the
org-mode
todo list (i.e. atodoist.org
file) - mainly (and at first) used
todoist -> org-mode
- syncing two ways the means adding a new element that doesn’t have the required
properties in the
todoist.org
file
TODO Do some writeup about org-mode usage and workflow
A bit à-la-howardisms
TODO Add a reviewing org-protocol capture template
Properties
:CREATED:
That way I track more easily the long review by just using a bookmark.
TODO Better worklog entries
- Substree in a datetime tree (see if it is possible)
- In a separate journal ?
TODO Fix meetings notes
Properties
:CREATED:
- Capture template doesn’t work
- Can we make Actions and Decision per “tree” ? (if not, meeting notes might be one file for each meeting)
- Ideas
- New tree
- Better template
- Stay in the capture while it’s happening
From: Decisions
TODO quick writing org-mode template
Logbook
nilProperties
:CREATED:
blog post (insrc/github.com/vdemeester/blog
)technical post (indesktop/org/technical
)meetings.org
in~/desktop/org/projects
See Using org-mode for meeting minutes • egli.dev for inspiration- Make it easier to take notes See [[file:///home/vincent/desktop/org/projects/inbox.html::*[[https://dpitt.me/blog/2020/03/zettelkasten/\][dpitt.me :: Using Emacs’s org-mode As Your Zettelkästen]\]][dpitt.me :: Using Emacs’s org-mode As Your Zettelkästen]]
- articles
- posts
- for new docs ?
- Read Template elements (The Org Manual)
- rg:org-capture-template:/mnt/synodine/volumeUSB2/usbshare/src/github.com/vdemeester/configs
^^ some of those could be normal template instead of org-mode
capture templates
TODO org-protocol support for more templates
- reviews, task, …
- https://github.com/abo-abo/orca
TODO org-mode
entry ordering
- By TODO keyword, then priority
- Bind it to sthg (else than
^
)
Legacy
(use-package org :defer t :config (defvar org-capture-templates (list)) (setq org-protocol-default-template-key "l") ;; images (setq org-image-actual-width nil org-startup-with-inline-images nil) ;; Tasks (-> inbox) ;; Journal (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" ":END:")) (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" "#\\+END_SRC")) (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_EXAMPLE" "#\\+END_EXAMPLE")) ;; org-links ;; from http://endlessparentheses.com/use-org-mode-links-for-absolutely-anything.html (org-link-set-parameters "tag" :follow #'endless/follow-tag-link) (defun endless/follow-tag-link (tag) "Display a list of TODO headlines with tag TAG. With prefix argument, also display headlines without a TODO keyword." (org-tags-view (null current-prefix-arg) tag)) (org-link-set-parameters "org" :complete (lambda () (+org-link-read-file "org" org-directory)) :follow (lambda (link) (find-file (expand-file-name link org-directory))) :face (lambda (link) (if (file-exists-p (expand-file-name link org-directory)) 'org-link 'error))) (defun +org-link-read-file (key dir) (let ((file (read-file-name (format "%s: " (capitalize key)) dir))) (format "%s:%s" key (file-relative-name file dir)))) )
Foobar
(message "foo")
(message "bar")
;; Yo <<foo>> <<bar>>
Configuration layout
Here we define the config-org
file that gets generated by the source blocks in our Org
document. This is the file that actually gets loaded on startup. The placeholders in
angled brackets correspond to the NAME
directives above the SRC
blocks throughout this
document.
;;; config-org.el --- -*- lexical-binding: t; -*- ;;; Commentary: ;;; Configuration of orgmode. ;;; Code: (use-package s) <<constants-and-registers>> <<main>> <<agenda>> <<capture>> <<protocol>> <<clock>> <<habits>> <<src>> <<links>> <<babel>> <<notes>> <<journaling>> <<misc>> <<diary>> <<legacy>> (provide 'config-org) ;;; config-org.el ends here