Emacs 完全指南 / 第 09 章:Org-mode 进阶
第 09 章:Org-mode 进阶
9.1 Org Capture(快速捕获)
Capture 是 Org-mode 的"快速记录"功能,可以在任何上下文中快速捕获想法、任务和笔记。
基本配置
;; 设置 Capture 模板
(setq org-capture-templates
'(("t" "待办任务" entry (file+headline "~/org/inbox.org" "收件箱")
"* TODO %?\n %U\n %a"
:clock-in t :clock-resume t)
("j" "日记" entry (file+datetree "~/org/journal.org")
"* %?\n%U\n"
:clock-in t :clock-resume t)
("n" "笔记" entry (file "~/org/notes.org")
"* %? :笔记:\n%U\n"
:clock-in t :clock-resume t)
("m" "会议记录" entry (file+datetree "~/org/meetings.org")
"* %^{会议主题} :会议:\n:PROPERTIES:\n:参与人: %^{参与人}\n:END:\n%U\n\n** 议题\n%?\n\n** 行动项\n"
:clock-in t :clock-resume t)
("w" "Web 书签" entry (file "~/org/bookmarks.org")
"* %^{标题} :书签:\n:PROPERTIES:\n:URL: %^{URL}\n:END:\n%U\n%?"
:immediate-finish t)
("r" "代码片段" entry (file "~/org/code-snippets.org")
"* %^{标题} :代码:\n:PROPERTIES:\n:语言: %^{语言}\n:END:\n#+BEGIN_SRC %^{语言}\n%?\n#+END_SRC\n")))
;; 快捷键
(global-set-key (kbd "C-c c") 'org-capture)
;; 定义 inbox 文件
(setq org-default-notes-file "~/org/inbox.org")
Capture 占位符
| 占位符 | 说明 |
|---|---|
%? | 捕获完成后光标位置 |
%t | 日期 <2026-05-10 Sat> |
%T | 日期时间 <2026-05-10 Sat 14:30> |
%u | 非活跃日期 [2026-05-10 Sat] |
%U | 非活跃日期时间 |
%a | 当前位置的链接(从 agenda 或文件) |
%i | 选中的文本内容 |
%^{提示} | 交互式输入 |
%f | 当前文件名 |
%n | 用户名 |
%x | 剪贴板内容 |
Capture 工作流
1. 在任意位置按 C-c c
2. 选择模板(如 t = 待办任务)
3. 输入内容(%? 处光标停留)
4. C-c C-c 保存到目标文件
典型工作流:
浏览网页时想到一件事 → C-c c t → 输入任务 → C-c C-c → 回到原工作
Re-file(归档)
;; Re-file 将 Capture 的内容从收件箱归档到正确的位置
(setq org-refile-targets
'(("~/org/work.org" :maxlevel . 2)
("~/org/personal.org" :maxlevel . 2)
("~/org/projects.org" :maxlevel . 3)))
;; 在标题上按 C-c C-w refile
;; 选择目标标题 → 移动过去
9.2 时间记录(Clocking)
Org-mode 内置了强大的时间记录功能。
时钟命令
| 快捷键 | 命令 | 说明 |
|---|---|---|
C-c C-x C-i | org-clock-in | 开始计时 |
C-c C-x C-o | org-clock-out | 停止计时 |
C-c C-x C-j | org-clock-goto | 跳转到正在计时的任务 |
C-c C-x C-r | org-clock-report | 插入时钟报告 |
C-c C-x C-d | org-clock-display | 显示总耗时 |
C-c C-x C-q | org-clock-cancel | 取消当前计时 |
时钟报告表格
,#+BEGIN: clocktable :scope file :maxlevel 2 :block today
,#+CAPTION: Clock summary at [2026-05-10 Sat]
| Headline | Time | |
|-----------------+--------+------|
| *总计* | *5:30* | |
| TODO 完成报告 | 2:15 | |
| 代码审查 | 1:30 | |
| 团队会议 | 1:00 | |
| 学习 Elisp | 0:45 | |
,#+END:
9.3 Babel(可执行代码)
Org Babel 让你在 Org 文件中嵌入和执行代码,支持 60+ 种编程语言。
基本用法
,#+BEGIN_SRC python :results output
import sys
print(f"Python {sys.version}")
print("Hello from Org Babel!")
,#+END_SRC
,#+RESULTS:
: Python 3.11.0
: Hello from Org Babel!
; 执行代码块:C-c C-c
; 在 Org 文档标题处按 C-c C-c 会执行该标题下的所有代码块
代码块参数
| 参数 | 说明 | 示例 |
|---|---|---|
:results | 结果类型 | output, value, table |
:exports | 导出内容 | code, results, both, none |
:session | 会话名 | "python" |
:var | 传入变量 | "x=10" |
:dir | 执行目录 | "/tmp" |
:cache | 缓存结果 | yes |
:eval | 是否可执行 | no-export, never |
:file | 输出到文件 | "plot.png" |
链式代码块
,#+NAME: data
,#+BEGIN_SRC python :results output
data = [1, 2, 3, 4, 5]
print(sum(data))
,#+END_SRC
,#+BEGIN_SRC python :results output :var input=data
print(f"收到数据: {input}")
,#+END_SRC
画图示例
,#+BEGIN_SRC python :results file :file plot.png
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.figure(figsize=(8, 4))
plt.plot(x, y)
plt.title("Sine Wave")
plt.savefig("plot.png")
return "plot.png"
,#+END_SRC
,#+RESULTS:
[[file:plot.png]]
Babel 语言配置
;; 启用的语言
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)
(shell . t)
(emacs-lisp . t)
(js . t)
(sql . t)
(latex . t)
(ditaa . t)
(plantuml . t)))
;; 安全确认
(setq org-confirm-babel-evaluate
(lambda (lang body)
(not (member lang '("python" "emacs-lisp" "shell")))))
;; 代码块不询问确认的快捷方式
;; 在代码块头部添加 :eval no-export
9.4 Org Roam(知识图谱)
Org Roam 实现了类似 Roam Research 的双向链接知识管理系统。
安装配置
(use-package org-roam
:custom
(org-roam-directory "~/roam")
(org-roam-db-location "~/roam/.org-roam.db")
(org-roam-completion-everywhere t)
(org-roam-capture-templates
'(("d" "default" plain
"%?"
:target (file+head "${slug}.org"
"#+title: ${title}\n#+date: %U\n")
:unnarrowed t)
("r" "reference" plain
"%?"
:target (file+head "references/${slug}.org"
"#+title: ${title}\n#+author: %^{作者}\n#+date: %U\n:PROPERTIES:\n:URL: %^{URL}\n:END:\n")
:unnarrowed t)))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
("C-c n g" . org-roam-graph))
:config
(org-roam-db-autosync-mode))
Roam 使用场景
日常工作流:
1. 创建笔记节点:
C-c n f → 输入标题 → 自动生成以标题命名的 .org 文件
2. 在笔记中链接到其他节点:
C-c n i → 搜索节点名 → 插入双向链接
3. 查看当前节点的反向链接:
C-c n l → 打开侧边栏,显示所有链接到当前节点的笔记
4. 捕获想法:
C-c n c → 选择模板 → 快速记录
知识图谱示例:
┌──────────┐ ┌──────────┐
│ Python │────→│ LSP │
└────┬─────┘ └────┬─────┘
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ Django │←────│ Emacs │
└──────────┘ └──────────┘
9.5 Org Publish(站点发布)
;; 配置发布项目
(setq org-publish-project-alist
'(("blog-notes"
:base-directory "~/org/blog/"
:base-extension "org"
:publishing-directory "~/public/blog/"
:recursive t
:publishing-function org-html-publish-to-html
:headline-levels 4
:auto-preamble t
:auto-sitemap t
:sitemap-title "博客索引"
:sitemap-filename "index.org"
:sitemap-sort-files anti-chronologically)
("blog-static"
:base-directory "~/org/blog/"
:base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf"
:publishing-directory "~/public/blog/"
:recursive t
:publishing-function org-publish-attachment)
("blog" :components ("blog-notes" "blog-static"))))
;; 发布命令
;; M-x org-publish RET → 选择项目
;; M-x org-publish-all → 发布所有项目
;; M-x org-publish-current-file → 发布当前文件
9.6 本章小结
| 功能 | 快捷键 | 说明 |
|---|---|---|
| Capture | C-c c | 快速捕获任务、笔记 |
| Re-file | C-c C-w | 归档到目标位置 |
| 时钟 | C-c C-x C-i/o | 开始/停止计时 |
| Babel | C-c C-c | 执行代码块 |
| Roam | C-c n f/i/l | 知识图谱操作 |
| 发布 | M-x org-publish | 站点发布 |
9.7 扩展阅读
← 上一章 第 08 章:Org-mode 基础 | 下一章 → 第 10 章:编程环境