I’ve put some work into my org-mode setup in Emacs over the last while, and I’ve recently gotten pretty content with a setup with the following affordances:
org-roam
org-agenda
that pulls events and TODOs from a wide variety of sources, including my notesIt looks like this:
Yes, I do actually use the graph. It’s hard to get it into a web page, but you can browse the underlying notes here.
I was thinking it would be nice to document it in case it’s useful to anyone attempting something similar, so here we go. All the configuration I reference here can be found in my dotfiles repo.
I have a folder, ~/org
, that holds most everything I need for my setup. It has this structure:
~/org
├ gtd
│ ├ inbox.org
│ ├ next.org
│ ├ someday.org
│ ├ read.org
│ └ calendars
│ ├ personal.org
│ ├ stanford-law.org
│ └ more calendars...
├ library
└ zettelkasten
~/org/gtd
holds my main agenda files, ~/org/library
holds my reference material, and ~/org/zettelkasten
holds an org-roam
Zettelkasten-ish.
The thing I use org-mode
for most, on a median day, is my agenda. It mostly lives in ~/org/gtd
, which is so named because of my aspiration to something like a GTD methodology.Similar to Jethro Kuan’s. My agenda is built from inbox.org
, next.org
, someday.org
, read.org
, any files in ~/org/zettelkasten
containing TODO items,I was somewhat worried that looking through my entire Zettelkasten for TODOs would be slow, but ripgrep is very, very fast (the search takes about 10 milliseconds). and calendars. The code for the non-calendar part looks like this (the calendar bit is below):
(setq who/org-agenda-directory "~/org/gtd/")
(require 'find-lisp)
(defun who/find-org-files (directory)
(find-lisp-find-files directory "\.org$"))
(defun who-org/agenda-files-update (&rest _)
(let ((todo-zettels (->> "rg --files-with-matches '(TODO)|(NEXT)|(HOLD)|(WAITING)' ~/org/zettelkasten"
(shell-command-to-string)
(s-lines)
(-filter (lambda (line) (not (s-blank? line)))))))
(setq org-agenda-files (append (who/find-org-files who/org-agenda-directory)
todo-zettels))))
(advice-add 'org-agenda :before #'who-org/agenda-files-update)
Each of the files in ~/org/gtd
has a different purpose, mostly emerging from GTD ideas:
inbox.org
is mostly a destination for capture templates, but sometimes I write things into it manually on my phoneThis does suck a bit. I just enter the bare minimum to jog my memory later. using Markor (syncing via Syncthing). I jot stuff in here so I can stop thinking about it in the moment and come back to it later.next.org
is for stuff that I’m currently working on or ought to start working on soon.someday.org
is for stuff that I’ll get to whenever I get to it, possibly never.read.org
is for media that I intend to consume at some point: books, movies, music, etc.I capture stuff into inbox.org
and eventually refile it into the most appropriate out of the other three, or sometimes into one of my Zettels, using Jethro Kuan’s method. I try to do this pretty often and maintain inbox zero when possible. My capture templates look like this:
(setq org-capture-templates
`(("i" "inbox" entry (file ,(concat who/org-agenda-directory "inbox.org"))
"* TODO %?\n")
("a" "appointment" entry (file "~/org/gtd/calendars/personal.org" ))
("e" "email" entry (file+headline ,(concat who/org-agenda-directory "inbox.org") "Emails")
"* TODO [#B] %a" :immediate-finish t)
("l" "link" entry (file ,(concat who/org-agenda-directory "inbox.org"))
"* TODO %(org-cliplink-capture)" :immediate-finish t)
("c" "org-protocol-capture" entry (file ,(concat who/org-agenda-directory "inbox.org"))
"* TODO [[%:link][%:description]]\n\n %i" :immediate-finish t)))
The two of these I use most are "org-protocol-capture"
, for collecting links to websites I have open in my browser, and also "email"
. I use notmuch
for email, and I have a keybinding that lets me trigger the "email"
template from there by pressing c
. If an email is going to take a while to answer, I capture it to get it out of my relatively unmanageable email inbox and into Org. "org-protocol-capture"
works in conjunction with alphapapa’s nice bookmarklet. I use it when I’m feeling overwhelmed by tabs in Firefox and I want to close some of them while remembering they exist.
I also have some habits I track with org-habit
. As the screenshot shows I was a bit overambitious in terms of how many habits I thought I could keep up.
Lastly, I added a custom alert style for org-wild-notifier
agenda alerts to make them stay visible until I explicitly dismiss them (I’m often not looking at my screen).
(alert-define-style 'who/alert-style-reminder
:title "Agenda reminders"
:notifier (lambda (info)
(alert-libnotify-notify (plist-put info :persistent t))))
(add-to-list 'alert-user-configuration
'(((:title . "Agenda"))
who/alert-style-reminder))
n.b. This relies on org-wild-notifier-notification-title
having its default value, "Agenda"
.
The files under ~/org/gtd/calendars
reflect various Google calendars that I sync with. I use org-gcal
for that as follows:
(defun who/get-file-contents (filename)
"Return the contents of FILENAME."
(with-temp-buffer
(insert-file-contents filename)
(buffer-string)))
(use-package org-gcal
:after org
:commands (org-gcal-request-token)
:config
(setq org-gcal-token-file "~/.config/org-gcal/.org-gcal-token"
org-gcal-client-id (who/get-file-contents "~/.config/org-gcal/.org-gcal-client-id")
org-gcal-client-secret (who/get-file-contents "~/.config/org-gcal/.org-gcal-client-secret")
org-gcal-fetch-file-alist '(("email_obfuscated@gmail.com" . "~/org/gtd/calendars/personal.org")
("email_obfuscated@law.stanford.edu" . "~/org/gtd/calendars/stanford-law.org"))
org-gcal-local-timezone "Canada/Pacific"))
Getting Google sync stuff working in general has been a nightmare, especially wrt Gmail. Eventually I got that working using oauth2l
plus a locally-built copy of isync
, which I still have to rebuild manually when there’s an update for it to get it to notice the XOAUTH2 SASL plugin. I handle most of that stuff with Nix via home-manager
(see my home.nix
). It isn’t strictly Org-related, but getting email working was key to the GTD inbox concept working at all.
~/org/library
holds reference material in a single, flat
folder. I don’t really have much use for a folder hierarchy here,
because I don’t really ever go looking for stuff directly in the
library. I might look through my Zettelkasten for things and find links
from there, or I might look in Zotero, or I might use Recoll for a text
search, but at the level of what files are where on the disk, I don’t
really care.
When I capture something with Zotero (usually via the Zotero browser extension), it goes in this folder and Zotero makes an entry linking to it.Via the ZotFile plugin. I also have a lot of stuff that I just download from somewhere and dump in here. Usually I link to it somehow, from a Zettel or something, so it’s not just adding to the trash heap (I hope).
I use org-roam
for a knowledge base that’s almost a Zettelkasten, but I’m
not super strict on the principles. In particular I have a number of
not-at-all-atomic notes that are really just kind of scratchpads, e.g. a
note titled “Stanford” that’s just so I have something to open when I
need to write down work-related stuff. The graph is org-roam-ui
,
and I also use notdeft
for
full-text search. I install that by adding it to
dotspacemacs-configuration-layers
:
(notdeft :variables
notdeft-directories '("~/org/zettelkasten")
;; Ignore property drawers at the start of files (as created by org-roam)
notdeft-allow-org-property-drawers t)
Other than that, I haven’t made a ton of customizations to org-roam
because it honestly just works pretty well.
The main thing I did some customization around was writing notes on
materials from my reference library. My approach is very similar to the
one described by Rohit Goswami,
but a few things have changed in the 2.5 years since that post.
Basically, what I want is to have Zotero handle the metadata for the
materials in my library, and use that metadata from Emacs when I’m
writing notes on those materials in the form of org-roam
Zettels. I use org-noter
to take notes on PDFs.
So, a little basic configuration to start out. Zotero automatically
produces a BibTeX file of the contents of its library every time I
change it, thanks to the Better BibTeX
plugin. That file is ~/org/master.bib
, and
bibtex-completion
needs to know about it, as well as some
other boring stuff:
(setq bibtex-completion-bibliography '("~/org/master.bib"))
(setq bibtex-completion-pdf-field "file")
(setq bibtex-completion-notes-path org-roam-directory)
(setq orb-roam-ref-format 'org-cite)
Now helm-bibtex
knows where to look for my bibliography.
When I select an entry via helm-bibtex
that doesn’t have an
associated notes file, it will offer to create one for me, which is
exactly what I want, but I need to define a template for it to use for
the note:
(setq org-roam-capture-templates
'(("d" "default" plain "#+title: ${title}\n\n%?"
:target (file "%<%Y%m%d%H%M%S>-${slug}.org")
:unnarrowed t)
("n" "bibliography notes" plain "%?"
:target (file+head "${citekey}.org" "#+title: ${title}\n#+filetags: :bib:\n\n* Notes\n:PROPERTIES:\n:NOTER_DOCUMENT: ${file}\n:END:\n")
:unnarrowed t)))
I think there’s probably a way to get helm-bibtex
to
select that template automatically, but whatever.
Sometimes I download stuff outside of Zotero, and still want a convenient way to make a notes file for it. To do that, I just pick the most recently modified file in the library, and forget about all the BibTeX stuff:
(defun who/mtime (file) (let ((attrs (file-attributes file))) (nth 5 attrs)))
(defun who/latest-file (path)
(let ((e (f-entries path)))
(car (sort e (lambda (a b)
(not (time-less-p (who/mtime a)
(who/mtime b))))))))
(defun who/org-noter-latest ()
(interactive)
(save-excursion
(search-backward "#+title")
(move-end-of-line nil)
(insert "\n#+roam_tags: bib"))
(insert "* Notes\n")
(let* ((file (who/latest-file "~/org/library"))
(relative-file (file-relative-name file "~/org/zettelkasten")))
(org-set-property "NOTER_DOCUMENT" relative-file)
(org-noter)))
This gives me a pretty smooth two-step of “click Save to Zotero in browser (or download something manually) → create note in Emacs”.
Getting this stuff working has been both very difficult and very valuable for me, and I hope my meagre notes are of use to someone trying to run something similar. You may also want to look at some of the work that inspired it (including a lot of directly stolen code):
org-roam
)If you’re having trouble with any of this, feel free to send me an email.
网站优化免费测试分类网站优化工作江北区网站优化方案seo网站的诊断优化郑州做网站优化外包瑞安网站seo优化mg的网站app优化快速优化网站顺云速捷声名上海专业网站优化设计绵阳网站优化哪家好建湖网站优化公司方案西城网站优化公司哪家好苏州网站快速优化排名常州科教城网站优化seo网站优化书长安电子网站优化品牌沈阳口碑好的网站优化九江百度网络推广网站优化公司对网站进行优化后的心得体会云浮首页网站关键词优化费用初创创业公司网站优化及维护文山网站优化价格苏州网站建设优化济南网站首页优化梅州外贸网站关键词优化哪家好中医医院网站优化方案奎屯网站怎么优化怀化网站优化承诺守信推广西安网站优化公司哪家好华强北在线网站优化开阳网站关键词优化公司网站优化外包怎么收费网站推广网站优化网络营销方案网站推广优化卩金苹果专业阝网站快速优化适合火25星网站模型主题优化的方法长春网站优化与推广用什么方法咨询营销型网站优化有没有带有优化效果的网站网站排名优化亿金手指花总香港网站优化建设seo网站关键词优化设计常熟网站关键词优化定位网站优化湖北标准网站优化价格对比济南网站的排名优化湛江企业网站关键词优化多少钱建筑行业网站优化外包锚文本在网站优化中的作用原装网站优化咨询电话玉屏网站优化公司佛山怎样优化网站衡水网站seo优化价格新塘网站权重优化怎样优化网站潘刳乚云速捷宁德网站seo优化有哪些网站产品优化具体云速捷首选贵州网站优化在线咨询平谷网站建设优化推广如何优化网站崭杏-大将军1宁波网站优化定制宁波网站优化排名推广江门网站优化是什么北城网站优化费用潍坊网站建设优化排名福田品牌网站优化网站推广优化选_复仇者下拉长安电子网站优化比较好的网站制作百度优化杜桥网站优化公司简阳网站优化推广多少钱密云网站优化曲靖网站优化外包凤台网站排名优化公司中山网站优化首页网站的文章优化方法李沧区网站优化推广嘉定网站优化服务网站应该优化济南移动网站优化价格网站图片怎样做seo优化重庆网站快速排名优化民治网站排名优化信阳网站建设优化推广公司新乡设计网站优化招商甘肃网站优化推广公司费用常州优化网站推广德州做网站优化河南网站如何做优化福州网站优化排名推广优化网站排名注意事项教程阜康企业网站优化韶关外贸网站关键词优化推广网站如何优化相信大将军21首页网站运营如何优化网站速度广州按天网站优化服务网页科技怎么优化网站访问速度山东商祺网站建设优化盘锦网站优化seo曲阜市网站seo优化排名宁夏网站搜索引擎优化快速优化网站包年多少钱焦作专业网站优化seo网站的优化方法如何优化网站和提高网站排名具体来说网站优化方式有哪些呢网站的优化策略有哪些伊宁网站关键字优化铁门关网站seo优化公司清远外贸网站关键词优化费用tdk优化网站会同县网站seo优化排名济源郴州企业网站优化方案瓷砖网站优化规划博客优化网站seo怎么写荆门很好的网站优化用户体验青羊网站优化多少钱佛山网站优化定制宝鸡做网站优化公司印刷网站优化哪家便宜黟县手机网站优化优化网站排名收费阳江公司网站关键词优化推广通信行业的网站优化有哪些岳阳很好的网站优化用户体验陈江网站优化推广顺德网站优化优势网站建设优化就找s火20星深圳高端网站优化网站首页优化搜行者SEO网站搜索排名优化解密易速达网站如何提高seo优化凤城怎么优化网站把网站栏目页当作首页来优化从江县网站优化营销优化网站架构设置黑龙江省网站seo优化大理网站优化策略荔湾外贸网站优化推广价格连云港网站seo优化多少钱鼎湖百度网站优化揭阳网站排名优化吉林企业网站优化哪家靠谱有南昌网站优化哪家好长沙网站优化网络推广网站优化和搜索引擎优化的关系宁陵县网站优化排名台前怎么做网站优化网站优化 日常工作有做网站优化高手吗钟祥市网站关键词排名优化价格集团官方网站优化方案网站怎么提交订单不卡优化兰州网站排名优化哪里有优化深圳专业的传统行业网站优化奉化百度网站优化信息化网站搭建优化做一个seo优化网站多少钱闵行区公司网站优化公司武汉规模大的销售行业网站优化淮安网站优化广告位重庆涪陵网站优化有哪些网站关键词优化要求优化网站咨询a火27星舒心网站怎么优化料嗜云速捷精选苏州网站优化指导益阳网站优化公司信阳网站运营优化营销东莞谷歌网站seo优化网站排名优化软件是什么网站怎么优化星四川关键词优化网站如何优化网站ck金手指靠谱网站优化合同制老师吉水网站seo优化网站做优化哪家好mars22呈贡网站建设优化中新网站关键词优化优化网站联系a火15星新手优化网站楚雄网站优化排名重庆销售行业网站优化怎样制定网站seo优化目标网站文件资源优化蚌埠网站优化哪个好百度快排网站优化网站动作优化在哪里下载seo优化网站推广方案栖霞品牌网站优化延安网站优化公司苏州seo网站优化方案武清区网络优化网站上海专业的网站优化seo价格东莞门窗网站优化软件鸡西网站优化哪家好洛阳网站seo优化价格专业网站优化排名销售吉林网站综合优化河南专业网站关键词优化多少钱菏泽网站自然优化