最近Notion大火,从二手买卖到菜谱分享,隔三差五就会看到它的推荐和应用。出于好奇,我也去开了个帐户用了一番,确实不错,然而我对其持谨慎态度。一方面,作为在线产品,它的使用场景灵活,但又会受网络限制,假如所在单位或者地区禁止使用,那就徒增烦恼。而且,它并非开源产品,公司一旦跑路或者改变其业务重心,那会造成非常高的转移成本,前车之鉴便有Evernote。另一方面,它作为一个笔记产品,架构强大,也更复杂,有着较高的学习成本,也许用起来很sexy,但也会让人疑惑在有更好替代品的情况下,是否值得花费这么多时间来学习使用这个产品。

说了这么多,其实我只是想引出这个更好的替代品,也就是我用了多年的Emacs。

在数字化时代,我们需要用到各种各样的工具来记录管理我们的生活,这也催生了各种工具和网站。比如日程管理有Things、Bear等,文献管理软件有Endnote、NoteExpress等,记帐软件有随手记、Splitwise等,编辑器有VSCode、Atom等,博客写作软件有Typora、MWeb等,菜谱有下厨房。但是工具太多协作性便会变弱,在线产品更是逃不脱对厂商的依赖,一旦厂商缺钱改成了订阅付费模式,除了叫苦不迭也只能乖乖付钱,而如果厂商保持免费,那也有可能通过其他方式比如出售隐私增加广告来保持盈利。其实对于这些,Emacs的Org mode都可以胜任。

Emacs是什么呢?最简单的解释,便是Emacs是一种基于Lisp的具有可扩展性的文本编辑器。文本编辑器,意味着平时不管在上面记录什么,大小都以kb计,最基础的Dropbox plan就能轻松对其进行云端备份,哪怕在一个没有Emacs的环境,也能用任何文本编辑器打开使用Emacs处理的文档。而Lisp的强扩展性,则赋予Emacs一切可能,你可以用它记笔记(Org-mode),管理文件(Dired),编辑远程档案(Tramp),版本控制(Magit),收发邮件(Gnus),用作IDE,甚至上网发推。有一个著名的说法称Emacs为操作系统,倒也并非言过其实。不过我也不至于真的将Emacs当操作系统使用,毕竟我们已经一只脚跨入了Meta时代(狗头)。不过Emacs,尤其是无人可出其右的Org-mode,也确实渗透了我的学习、工作、生活。

那么,Org-mode又是什么呢?Org-mode是Emacs的一种支持内容分级显示的主编辑模式。在Emacs中,每种主模式都有特殊的Emacs Lisp变量和函数来使处理文档变得更便捷,而Org作为Emacs特有的文本格式,更是有着非常出色的原生支持。其他主流编辑器(Vim, Atom, VSCode, Sublime)也都有对应相应的Org模式,但只能支持基础的语法高亮功能。

Org-mode的宣传语就是 your life in plain text,可以说很好地概括了Org-mode的能力。最重要的一点是Org是纯文本文档,具有体积小结构简单的优点。在此我先简单介绍一下Org-mode的特性,就不一一展开了。毕竟如果展开来讲,那可能得出一个系列文章。

Org-mode的几点特性

  • 标记语言:Org-mode有自己的标记语言,虽然和最流行的Markdown不同,但是可以通过pandoc进行双向转换。那为什么不用Markdown呢,因为标记只是Org-mode最基础的特性。
1
2
3
4
5
6
7
8
*加粗*
/斜体/
_下划线_
=逐字=
~代码~
+删除线+
[[https://blindwith.science][链接]]
[[file:文件.txt]]
  • 树状结构:Org-mode的一大特色就是采用星号来标定所属层级,可以通过 C-c *C-c - 快速地转换为大纲或列表,并可通过Tab键切换是否折叠显示层级、列表和代码块,还可以通过 C-c C-n/p/f/b/u 这样来浏览同级或上级标题。在大纲处还可以通过 C-c C-c 来加入标签,方便跳转。这样哪怕在一篇Org文档中记了几万行文字,也可以轻松导览到所需内容。
1
2
* 一级大纲
** 二级大纲
  • 表格:Org-mode采用纯文本的方式管理表格,通过Tab键补完表格并调整大小。而且它还支持表格运算,可以通过 C-c ' 来插入公式。
1
2
3
| a | b | a + b |
| 1 | 2 |     3 |
#+TBLFM: $3=$1+$2
  • 文学编程:Org-mode最令人心动的则是Babel功能,可以直接在Org文件中通过 C-c C-c 直接运行代码块,并直接储存结果。由于Org-mode是纯文本文件,这可比Jupyter-notebook好用多了。
1
2
3
4
5
6
#+BEGIN_SRC python :results output
print('Hello World!')
#+END_SRC

#+RESULTS:
: Hello World!
  • 导出发布:Org作为纯文本文档,可以很方便地分享给任何人用任何文本编辑器来查看内容。但是如果朋友是见到奇怪后缀就会发怵的人,也可以通过 C-c C-e 将文档导出为pdf, odt, markdown或网页。
  • 任务管理:Org-mode中可以很方便地通过 S-<left>S-<right> 来修改大纲或列表的任务状态来管理代办事项,添加 [%][/] 来跟踪任务进度,通过 [ ] 来标记任务完成情况,而且支持自定义不同级别的任务状态(默认有TODO和DONE)。
  • 日程管理:Org-mode的日程管理功能也非常优异,可以通过 C-c [ 来将当前文件加入任务清单,通过 C-c C-sC-c C-d 来设置计划时间和截止时间,通过 C-c C-x C-iC-c C-x C-o 来记录在每项任务上的时间花费。另外,还可以通过 C-c a a 进入日程表视图,通过移动光标来显示每个条目所在的源文件。
  • 高度可定制:如果这些还不能满足你,还可以通过添加扩展包,写org-capture和写lisp函数的方式来进一步定制你的Org-mode。

那么这些特性在实际生活中有什么用呢?用处可大了。在此我便抛砖引玉,聊一聊我都用Emacs和Org-mode来做什么。

文献记录 org-ref

读博的时候,看Paper基本上是每日必需。我虽然懒惰,但是也读了不少文献。在国内的时候我用过NoteExpress,来美国后便用了Endnote,虽然都是成熟产品,但还是有很多问题。比如导入pdf操作不是很方便,而且还会为pdf强制重命名,我离开软件就无法分辨这些pdf谁才是谁。而且这些软件价格普遍不便宜,虽然学校图书馆会提供免费使用的版本,但是还是让人担心毕业之后怎么办。另外,这些软件只能写一些纯文本的笔记,有的时候想写个化学式就无处下手。而基于Org-mode的org-ref,不仅提供了Endnote所有我需要的功能,还完美解决了这些痛点。这好像是CMU化学系的一个教授开发的,他们组似乎会直接使用Org-mode写paper,所以理科文献记录的痛点他们都会考虑到。需要用doi或者arxiv导入文献?没问题!想要写个化学式或者数学表达式?没问题!想要自动导入pdf并关联打开?没问题!想要使用多个bibtex来和Latex联动?没问题!想要使用标签或者交叉引用?没问题!这个工具真的是极大地节约了我花在文献综述上的时间。而使用起来也很简单, C-c ] 即可插入引用,拖pdf或者 M-x doi-add-bibtex-entry 即可添加引用。以下是一个例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
* 文献
** TODO [#A] 2009 - Imp Dehydrogenase: Structure, Mechanism, and Inhibition :review:
 :PROPERTIES:
  :Custom_ID: hedstrom-2009-cr
  :AUTHOR: Lizbeth Hedstrom
  :JOURNAL: Chemical Reviews
  :YEAR: 2009
  :VOLUME: 109
  :PAGES: 2903-2928
  :DOI: 10.1021/cr900021w
  :URL: https://doi.org/10.1021/cr900021w
 :END:

cite:hedstrom-2009-cr

最棒的IMPDH综述!

面试准备

我转行找工作的时候,Org-mode也派上了大用场。它特别适合用来刷题。可以用超链接来跳转原题页面,用任务管理来看自己的刷题进度,高亮重点题目,用日程来安排每日刷题时间,也可以加标签来做专题复习,最棒的是每道题写完后可以直接运行代码,检查对错。这样可以将所有刷过的题目和解答都放在一个文档中,方便浏览复习。我的刷题文档大概长这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
* NEXT Leetcode [1/1]
  SCHEDULED: <2021-11-03 Wed 22:00 .+1w>
  :PROPERTIES:
  :STYLE: habit
  :END:
** NEXT [[https://leetcode.com/problems/two-sum/][1. Two Sum]]                               :Array:HashTable:Amazon:%:
#+BEGIN_EXAMPLE
Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
#+END_EXAMPLE
*** Solution
#+BEGIN_SRC python
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        d = {}
        for i, num in enumerate(nums):
            if target - num in d:
                return (d[target - num], i)
            d[num] = i
#+END_SRC

而当进行面试的时候,Org-mode也特别适合用来放各种面试相关的准备材料,跟踪各个公司的进度,记录各个公司的面试经历。我将每个公司单列一级,并为任务状态增加了Screen, Tech, Onsite, Reject和Offer几项,这样可以更直观地显示每个公司到了那一步。

工作笔记

我很喜欢给我所负责的项目做记录。在实验室的时候,大家都用耐酸碱且能经历时间考验的厚重的实验记录本,但是我总觉得纸质的东西虽然方便翻找,但还是容易丢失毁损。所以我都会用Org-mode整理我的工作笔记。等工作以后,我也依然保持着用Org-mode记录工作的习惯。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
* 会议记录
** 老板
1:1记录
* 项目记录
** 项目甲
我对项目甲做了什么
** 项目乙
我对项目乙做了什么
* 实验/工作日志
** Week 1-2 / Sprint A
*** [2021-11-03 Wed]
- [X] 写博客

Org-mode的文学编程在这儿也特别好用。一方面可以将一些code snippets以及diff和自己的想法方便地记录,另一方面也可以记录很多adhoc操作。我平时会有一些terminal上的操作和数据库的操作,比如给别人权限,query一个小table,或者查看数据库的状态。这些小操作单独存档很麻烦也没必要,但是如果不记录的话过几天可能就不记得自己做了什么。这时我就会写在我的工作笔记上,然后直接运行,这样运行结果也会一同保存在文档中,非常方便。这是一个直接query数据库的例子:

1
2
3
4
5
6
7
8
9
* SQL
  :PROPERTIES:
  :header-args:sql: :engine postgresql :dbhost host :dbuser user :dbpassword pwd :database dbname
  :header-args: :exports both
  :END:
** query table_a
#+BEGIN_SRC sql
SELECT * FROM table_a LIMIT 10
#+END_SRC

写博客 ox-hugo

我几年前从hexo转投hugo后,就一直以hugo作为我博客的后端。Hugo中,每篇博客都是一个Markdown文档。如果博客数量不多的话,管理起来还挺方便的。但是我有几百篇博客,哪怕我用一个高效的方式去命名每篇博客,真找起来也比较头疼。而我也正是由于几百篇博客在hexo上渲染太慢才转投hugo的,以前还因为某tag系统有上限而给其file过bug。

解决方案则是使用Org-mode,我可以方便地在Org-mode里写博客,将所有博客都放在一个Org-mode中。但是怎么将一个Org文档到处为几百个Markdown文件呢?有一个很好用的插件叫ox-hugo。有了这个轮子,我可以将任意大纲级别下的日记导出为Hugo需要的markdown格式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
* 博客
  :PROPERTIES:
  :EXPORT_HUGO_SECTION: post
  :END:
** 技术                                                       :@技术宅:
*** DONE 继续吹一波Org-mode                                 :Org_mode:Emacs:
    :PROPERTIES:
    :EXPORT_FILE_NAME: 20211108-org-mode
    :EXPORT_HUGO_SLUG: 466.html
    :EXPORT_HUGO_WEIGHT: -466
    :END:
最近Notion大火,从二手买卖到菜谱分享,隔三差五就会看到它的推荐和应用。……

记帐 beancount

这个我在之前的三部曲(1 2 3)里已经详细提过了,Emacs可以使用beancount-mode轻松处理Beancount文件,在此便不赘述。