为了更方便地管理个人笔记,我开发了自己的笔记软件:NNW #
序言 #
写文章和整理自己的笔记可以说是使用计算机最常见的需求,可以说再常见不过了。不过,仔细想起来,为了找到一个对我来说最满意的笔记软件,我可是费了不少劲,在许多笔记软件之间迁移来迁移去的,就在这种迁移中,不知不觉就浮现出了我心目中最满意的笔记管理方式。个人认为,我使用的笔记软件的迁移,实质上也是一种思维方式的迁移。
我的笔记软件使用史 #
黑暗时代 #
就在几年前,我的笔记和文章管理可以说是在一个名副其实的黑暗时代。我当时使用的是同时支持手机端和电脑端的云文档工具WPS,因为WPS确实很方便解决了多端同步的问题,让我可以随时使用文档。 WPS陪伴了我中学的大部分时光,不过毕业后,因为我还有协作需求,于是又转向了腾讯文档。之所以说是黑暗时代,是因为,这段时间,不仅仅是在互联网上导出留自己的信息,隐私最糟糕的时代,也是文件体系管理一塌糊涂的时代。所有个人知识、档案、笔记等文件都平铺在一个视图中,很难查找翻阅。
启蒙时代 #
事情开始有了转机,随着2020年这个标志性的时代,OpenAI发布的人工智能大模型的热潮也开始出现,当时因为Notion有跟风的缘故也接入了一个AI助理,因为这个炫酷的功能吸引了我的注意,于是我就将我的笔记迁移到了Notion上,当时我用Notion做了很长的索引,无缝使用AI的感觉当时一时间还是很爽的,有很多个人思路和学习甚至都开始用AI补全了。不过Notion也给了我一个启发,因为Notion的标签列表让我能优雅地整理笔记,于是我第一次开始养成了随时用笔记来记录个人灵感的习惯。不过很快,我就遇到了问题,因为Notion本身是部署在纯云端上的,所以一直都感觉将数据存储在notion上并不安全,万一Notion公司倒闭了呢?之类的问题有点劝退我。
动手时代 #
接下来就到了动手时代,我决定迁移到纯本地的obsidian,然后靠github插件来同步笔记,我将Notion上的内容迁移到了Obsidian上,并费尽心思做了很多花里胡哨的各个表单界面,还花了点功夫实现了下勉强接近Notion标签的灵感管理和快速记录系统。不过接下来的问题也随之而来,我开始要在管理文件上花费大量功夫和精力,而且Obsidian也的git也经常掉线,这点对我来说也是不太妙。
新的曙光? #
接下来出场的,就是我一直用到现在的编辑器,Emacs!加入Emacs邪教的契机是我更换操作系统到Gentoo那时候,正好我也顺带把电脑的操作系统换成Gentoo+Hyprland了,因为我开始学习和习惯基于键盘的操作体系,顺其自然地我决定尝试Emacs的Org-roam来管理知识体系,花了几周的时间折腾OrgRoam,最终迁移到了Org-Roam,从此我也得到了第一个能长期使用和稳定维护的笔记软件体系。对我而言,OrgRoam最方便的地方莫过于和Org Captrue配合,以及Org Roam Webui生成的知识图谱,那段时间我会经常管理知识图谱。但这样依然有个问题,我需要在管理知识图谱和节点连接上花费大量精力。难不成,就没有什么软件,可以让你很方便地快速记录和管理吗?
破晓 #
当然有,这个软件同样也是Emacs的插件,据说是大名鼎鼎的Emacs Hacker开发的软件,它就是EKG,这是一个基于标签的知识管理体系,它通过标签化的管理和快速查找,解决了传统知识管理软件需要维护大量双向的痛点,当然缺点就是,你不能看酷酷的知识图谱了,而且EKG对图片和外链也没太好的支持。不过,EKG还有个很酷的特性,就是可以接入LLM,通过向量索引的方式,让LLM帮你整理、索引及查找你的知识与条目,基于语义相似和向量模型匹配的模糊搜索自然而然比传统的搜索方式要强得多,因为EKG是基于标签的语义匹配,所以针对AI索引自然优化更好。这个笔记工具,完美契合了我的快速笔记、快速查找的需求,我只需要写完条目打个标签,就能快速搜索。
黎明 #
ummm……既然EKG这么好用,那么为什么我还要开发自己的软件呢?理由很简单,因为EKG虽然很好用,但是有一个非常致命的缺点…………它是基于数据库为中心的。因为基于数据库中心,笔记条目不够透明,因此很难在别的设备上兼容和打开,用syncthing同步笔记的时候也经常会因为数据库状态问题而发生不少冲突,每一次冲突都要重新合并或打开文件让我感觉非常麻烦。因为基于数据库中心,要开协作也不方便,只能靠手动复制文档再单独开个在线文档,这对我这种希望Emacs为中心来协作的流派来说,感觉使用体验也非常不爽。综合上述几点,我才决心开发一款基于终端来管理笔记的软件,软件名就叫NNW。
仓库地址 #
首先,当然是先放上仓库地址啦:Codeberg
NNW的由来与哲学 #
NNW这个名字,其实我是模仿的GNU的缩写Gnu’s Not Unix。我的NNW的缩写叫 NNW is Not just a Writer or a Neko Writer. 起这个名字的理由当然是因为酷毙了,很有黑客范儿 。
最初本来是打算做成一个多模态、支持远程协作的Emacs和一个集大成的编辑器的,不过最后放弃了编辑器这个想法,因为开发这玩意太难了。所以最后我的NNW就决定做成一个以终端为核心的,存储后端无关的知识库管理软件,当然这里以终端为核心并不是要你完全用终端来管理知识,而是方便别的软件通过终端和管道来对接我的NNW来灵活定制前端。毕竟我现在一直都推崇工具内核要尽可能简单,我见过太多复杂臃肿的软件换个桌面环境就变得极难兼容和运行了。
NNW的灵感自然而然来自EKG,我借鉴了EKG的标签管理系统,并通过迭代原型决定了一套以Card为中心的知识整理体系。
EKG的哲学是,一切信息,无论纯文本、图片、音乐、视频、SXML都是Card对象,每个Card都用标签进行分类和过滤,且Card相互之间可以引用和链接。通过对Card的引用和链接的解析,前端可以实现Card的链接。当然Card之间的引用和链接关系我还没做就是了,预计未来会改用SXML风格的HTML格式来表示Card内部的内容,这样方便任何格式转成SXML格式的Card,估计要实现链接也只能靠SXML格式的Card来实现了。
NNW开发过程 #
NNW这个软件,最初我是试图开发成一个后端无关的,甚至可以自己任意决定前端的多模态笔记软件,当时写了一堆乱七八糟的需求,但这样也导致软件完不成。为了让这个软件能更容易完成,我最终放弃了自己做个新的Emacs的执念,决定从最简单最基础的命令行软件配Emacs前端的方案开始做起,当然现在看来,事实证明了,终端配Emacs的方案才是最好的组合。
开发NNW我选择的编程语言是Guile,一方面是因为我的操作系统是Guix系统,用Guile比较好打包,另一方面则是,我认为Guile是一个非常优雅,且前途的编程语言,毕竟Guile是永久自由的GNU项目,Guile的Lisp语言和函数式特性等也能让你非常优雅地写程序。
当然,我开始开发NNW不久之后才发现,Guile还有一个非常强大的去中心化协作网络库实现,Goblins!这意味着,未来如果要考虑引入远程协作等功能,只需要对接Goblins就能轻松实现。
当然,开发过程并不是一帆风顺的,最初的NNW版本,我设计的是一套View和Card双轨的架构,并试图借助AI来辅助开发。但在实际投入开发过程中发现这套架构不太合理,实现难度和复杂度非常高,而且bug也不好修,所以最后彻底放弃了旧的架构,开始构思了一套新的架构。这套新的架构就是现在nnw的单card对象和后端无关的架构模式了。
在做这个项目之前,我一直都是抱着一种,不就是终端软件嘛,有那么难吗?类似这样的心态开发。
直到实际投入开发我才意识到,我可能把很多事情想得太简单了,虽然前面的一部分简单的输入、输出、存储实现确实是不难,但其实有很多隐性成本是我没考虑到的,就比如说搜索、索引等功能。
我一开始并没有单独弄索引层,而是将索引和存储后端耦合,结果实际操作发现,这样的设计非常糟糕,因为我很难靠纯文件来做一个高效的搜索和索引,而如果改成数据库中心,那又和ekg没什么两样了。
最后我决定设计成将索引和文件存储端分离的架构,设计了一套基于文件为中心方便随时重建索引的模式,将索引作为只接收卡片对象的抽象层,并将存储层针对不同索引层有不同逻辑的接口预留好,这样的设计果然好了很多,因为存储层只需要实现自己的增量逻辑,就能很方便地对接索引层实现增量索引,这样也没必要在索引层塞复杂的原文来实现全文搜索了。
补充 #
除了索引坑外,实际上实现了NNW后,修NNW存在的bug也是个大坑,就是这个坑使得我又多花了几天时间提交更多热更新来修bug。就在写这篇文章的时候,我也正好又因遇到了一个重复同步的bug,所以又花了一两个小时的功夫才修好这个bug。
外部阅读 #
在开发NNW的途中,我顺带看了看Wiwi的Blog,里面这篇文章也让我很是认同。很多时候,我们其实并不需要什么花里胡哨的复杂APP,也许只需要简单的档案,就足够记录自己的各种东西了。当然,对于这点,我也有自己的看法,我的看法主要包括下面几个方面:
关于Emacs #
Wiwi的Blog也引起了我的思考,其实很多时候,比起用会让你的电脑装几十多个Chromium内核的各类界面花里胡哨的Electron软件,其实还不如一个能胜任所有文本编辑工作的编辑器,也许大多数情况,我们真的并不需要一个花里胡哨的多模态编辑器、炫酷的RSS阅读器、各类媒体和文件管理系统,其实只需要一个Emacs就足以胜任几乎所有与文字打交道的工作。
虽然我也承认,Emacs的单线程和媒体不友好是它最大的,也几乎是唯一的局限性。 当然还有一个,就是Emacs类似Linux一样,要吃蛋糕必须先从养鸡开始。
其它方面,Emacs靠强大的插件系统,不管是电子邮箱、文件管理、RSS整理和阅读、写博客、管理知识库、管理文件,对我个人而言体验都非常完美。所以,或许我们真的并不需要各种花里胡哨的软件,只需要一个Emacs这样的万能文本类型数据编辑器。
关于APP的用途 #
虽然我认同很多时候,我们大部分工作和生活比起APP,更需要的是档案。但是有时候,我觉得APP其实还是必须的,因为APP有个很重要的好处是,它可以解决档案整理和归档的问题。
如果我希望能随时随地方便地记录和查看我的灵感笔记,如果我不想在整理层级化的文件浪费大量时间和精力,那么开发一款整理知识库和档案的APP是最好的选择。如果我不想花时间维护一个重大的表单,如果我想让我的造语工作流变得统一,将制作字体、建立词典、生成字体及输入法码表、制作输入法等繁琐和复杂的工作流程整合在一起,那么开发一个一条龙式造语的APP是最好的选择。
换言之,个人认为,APP解决的是工作流整合和统一的专业问题,可以给新手和不愿浪费大量时间与精力在无用及重复工作上的人提供便利的工具,固然建立自己独立的工作流才是最好的选择,不过既然一件事情已经有很多人踩过坑了,那大部分人自然而然是会选择使用APP吧。
不然我也没必要花费那么多时间和精力去专门开发自己的NNW了。