- CLI
【免费下载链接】jrnl
Collect your thoughts and notes without leaving the command line.
导读
jrnl 是一款"不离开命令行即可收集想法与笔记"的日记工具,而配置外部编辑器是它最重要的写作体验之一:把editor选项指向你熟悉的编辑器后,jrnl会以临时文件为媒介,把命令行写作与完整编辑器的排版、补全、快捷键能力无缝衔接。本文以 docs/external-editors.md 为核心,逐一讲解editor配置项的正确写法、编辑器必须是"阻塞进程"的原因、Sublime Text / VS Code / Vim / emacs 等主流编辑器的实战配置,并结合仓库源码(jrnl/editor.py、jrnl/controller.py)揭示其底层临时文件机制与隐私风险。读完本文,你将能针对任意编辑器写出可复制、可运行的配置,并理解 jrnl 与编辑器交互的完整数据流。
一、配置前的准备:editor选项与配置文件位置
外部编辑器的入口是配置文件中的editor键。配置文件默认位于~/.config/jrnl/jrnl.yaml(设置了XDG_CONFIG_HOME时则为$XDG_CONFIG_HOME/jrnl/jrnl.yaml;Windows 下通常在%USERPROFILE%\.config\jrnl\jrnl.yaml)。可以通过jrnl --list随时查看当前配置文件的真实位置。
配置语法很简单:
editor: "vim"两点基础要求(见 docs/external-editors.md):
- 如果编辑器可执行文件不在操作系统
PATH环境变量中,就必须填写完整路径(例如 Windows 下 VS Code 的code.exe默认不在 PATH 中,需写全路径)。 editor的值会作为一条命令被解析执行:编辑器的路径、参数会以空格拆分,随后 jrnl 把临时文件路径追加在命令末尾(详见后文源码剖析)。
如果你只是临时想换一次编辑器,而不想改动配置文件,可以使用--config-override(别名--co)做一次性覆盖,这在 jrnl/args.py 的帮助文本中有明确示例:
jrnl --config-override editor "nano"二、三种进入外部编辑器的写作方式
配置好editor后,jrnl 提供三种互补的写作入口,全部来自 docs/external-editors.md:
1. 直接调用jrnl,以编辑器中的新文档开始写作
jrnl此时 jrnl 会在编辑器里打开一个临时文件。像命令行写日记一样,你可以在文档第一行指定时间和标题,例如yesterday: 今天……,其余内容即正文。
2. 跳过编辑器,快速写下一条
jrnl yesterday: All my troubles seemed so far away.3. 命令行起笔、编辑器续写:--edit标志
jrnl yesterday: All my troubles seemed so far away. --edit先在命令行写好开头,--edit会把这段文字预填进编辑器,让你接着写下去。这一行为在 jrnl/controller.py 的append_mode()中有清晰对应:当args.text与args.edit同时存在时,raw = _write_in_editor(config, raw)会把命令行文字作为预填内容送入编辑器。
注意:无论哪种方式,都必须保存并关闭编辑器的文件,jrnl 才会真正把内容写入日记。
三、为什么编辑器必须是"阻塞进程"(blocking process)
这是配置外部编辑器最容易踩的坑,原文档明确强调:所有编辑器必须是阻塞进程才能与 jrnl 协作。所谓阻塞,是指 jrnl 调用编辑器命令后,必须等待编辑器退出才能继续执行;如果编辑器启动后立即把控制权还给终端(典型如直接启动 GUI 版code、subl而不带等待参数),jrnl 就会"打开编辑器后立刻结束运行",什么都写不进去。
从源码看,阻塞是硬性要求而非可选优化。在 jrnl/editor.py 中,jrnl 调用编辑器的方式是:
subprocess.call(split_args(config["editor"]) + [tmpfile])subprocess.call本身就是阻塞式调用——它会等待子进程退出后才返回。因此编辑器进程必须保持存活直到用户关闭文件,jrnl 才能继续读取临时文件内容并写入日记。
部分编辑器(如 micro)默认就是阻塞的,直接配置即可;另一些编辑器则需要附加参数来"等待",本文第四部分列出的各编辑器配置中的-w、--wait、-f、-Wn等标志,作用都在于此。
四、主流编辑器逐一配置实战
以下全部配置示例均来自 docs/external-editors.md,可直接复制进jrnl.yaml使用。
4.1 Sublime Text
安装 Sublime Text 的命令行工具后,配置如下:
editor: "subl -w"-w(wait)标志让 jrnl 一直等待 Sublime Text 关闭文件后再写入日记。
4.2 Visual Studio Code
VS Code 同样需要一个"等待文件关闭再退出"的标志:
editor: "code --wait"Windows 上注意:code默认不在 PATH 中,你需要填code.exe的完整路径,或者手动把 VS Code 目录加入PATH环境变量。
4.3 MacVim
与 Sublime Text 类似,MacVim 需要通过-f标志告诉进程"等待文件关闭后再把控制权交还给 jrnl":
editor: "mvim -f"4.4 Vim / Neovim(Linux)
在 Linux 下使用任意 Vim 衍生版,直接把editor设为可执行文件名即可:
editor: "vim" # or editor: "nvim"Vim 类编辑器默认在前台终端中阻塞运行,因此通常无需额外等待参数。
4.5 iA Writer(macOS)
在 OS X 上可以通过open命令按 bundle identifier 启动 iA Writer:
editor: "open -b pro.writer.mac -Wn"参数含义:open -b ...按应用的 bundle identifier(每个应用的唯一字符串)打开文件;-Wn表示等待应用关闭后再交还控制权,并新开一个应用实例。
如果pro.writer.mac这个 bundle id 在你系统上不存在,可以在 shell 中检查 iA Writer 的Info.plist找出正确的字符串:
grep -A 1 CFBundleIdentifier /Applications/iA\ Writer.app/Contents/Info.plist4.6 Notepad++(Windows)
editor: "C:\\Program Files (x86)\\Notepad++\\notepad++.exe -multiInst -nosession"两点说明:
- 双反斜杠是 YAML 字符串转义的要求——YAML 双引号字符串中
\\才会被解析成单个\,最终 jrnl 拿到的是C:\Program Files (x86)\Notepad++\notepad++.exe这样的真实路径。 -multiInst -nosession让 jrnl 打开属于自己(独立于现有会话)的 Notepad++ 窗口。
值得一提的是,jrnl/os_compat.py 的split_args()正是用shlex.split(args, posix=on_posix())拆分编辑器命令:在 Windows 上posix=False,反斜杠不会被当作转义字符处理,从而保证C:\Program Files\...这类路径能被正确拆分。
4.7 emacs
editor: emacsclient -a "" -c编辑完成后,保存文件并按C-x #关闭缓冲区并退出 emacsclient 进程,jrnl 随即接管写入。-a ""表示若服务未启动则自动启动一个,-c表示以图形/新客户端方式打开。
4.8 gedit
editor: "gedit -w"-w(即--wait)告诉 gedit 等待文件关闭后再把控制权交还给 jrnl。
4.9 其他编辑器
如果你的编辑器不在上述列表中,判断标准仍是一条:它是否是阻塞进程。不是的话,去查它"等待文件关闭"对应的命令行参数即可,用法与上面的-w/-f/--wait完全同构。若你成功配置了新的编辑器,欢迎按 CONTRIBUTING.md 的文档编辑指引补充进官方文档。
五、源码级原理:临时文件的完整生命周期
理解了"阻塞"之后,再看 jrnl 与编辑器协作的完整数据流(实现位于 jrnl/editor.py 的get_text_from_editor()):
- 创建临时文件:
tempfile.mkstemp(prefix="jrnl", text=True, suffix=".jrnl")生成一个以jrnl开头、.jrnl结尾的明文临时文件(若配置了template,后缀会变为-模板文件名,见下文第六部分)。 - 预填内容:若调用方传入模板或命令行开头文字(如
jrnl yesterday: ... --edit),先把这些内容写入临时文件。 - 阻塞调用编辑器:
subprocess.call(split_args(config["editor"]) + [tmpfile]),等待编辑器进程退出。 - 读回内容:编辑器保存并关闭后,jrnl 以 UTF-8 读回临时文件的全部文本。
- 删除临时文件:无论成败,
finally中都会os.remove(tmpfile)清理。 - 空内容报错:若编辑器被直接清空并保存(常发生在误删日记内容时),
raw为空,jrnl 会抛出NoTextReceived错误,提示 "No text received from editor. Were you trying to delete all the entries?"(该文案在 BDD 测试 tests/bdd/features/actions.feature 中也有断言)。 - 编辑器命令不存在:如果
editor配置拼写错误导致可执行文件找不到,subprocess.call抛出FileNotFoundError,jrnl 会报"编辑器配置有误"并给出出错的具体命令字符串。
BDD 测试 tests/bdd/features/file_storage.feature 直接验证了临时文件的命名行为:使用editor.yaml配置时,"the editor filename should end with.jrnl";使用带 markdown 模板的editor_markdown_extension.yaml时,临时文件应以-extension.md结尾。单元测试 tests/unit/test_editor.py 则覆盖了模板读取、路径解析、非法 UTF-8 输入等边界情况。
六、模板(template)与临时文件扩展名
配置项template(或在命令行用--template指定)可为新条目提供初始文本。它与外部编辑器深度绑定,依据 docs/reference-config-file.md 的说明:
template只在配置了editor时生效;- 使用模板后,编辑器的临时文件会沿用模板文件的扩展名。
对应源码在 jrnl/editor.py:
suffix = ".jrnl" if config["template"]: template_filename = Path(config["template"]).name suffix = "-" + template_filename即默认后缀是.jrnl;配置了模板后变成-模板文件名(如模板叫notes.md,临时文件就是jrnl-xxxx-notes.md)。这一命名细节直接影响两个场景:一是编辑器的语法高亮/文件类型识别会跟随扩展名变化;二是下文隐私部分提到的编辑器历史排除规则、Vim/Neovim 的 autocmd 匹配模式都要随之调整。
模板文件的查找顺序(见 jrnl/editor.py):先查$XDG_DATA_HOME/jrnl/templates/目录下是否存在同名文件,找不到再按本地路径或绝对路径解析。
七、用外部编辑器批量编辑与删除条目
外部编辑器不只是写作工具,还是批量修改、批量删除条目的高效通道,入口是--edit标志。典型用法:
# 打开所有包含 @texas 且 @history、写于 1950 年之前的条目 jrnl -to 1950 @texas -and @history --edit # 打开 work 日记中最新的 1 条 jrnl work -n 1 --edit底层流程在 jrnl/controller.py 的_edit_search_results()中:先检查editor是否配置(未配置会报EditorNotConfigured错误并提示配置文件路径),然后把筛选出的条目序列化成可编辑文本送入编辑器;用户修改、保存并关闭后,jrnl 通过journal.parse_editable_str(edited)解析回写,重新排序并落盘。若你清空编辑器后保存,jrnl 会给出NoEditsReceivedJournalNotDeleted警告——空编辑不会删除整个日记,这是一道重要的安全护栏。
同理,删除大量条目也可以借助编辑器:先用过滤器选出目标条目并用--edit打开,全选删除、保存、关闭,这些条目即被移除(相关示例见 docs/usage.md 的删除章节)。
八、隐私与安全:编辑器历史、临时文件泄漏
外部编辑器是把双刃剑:它让写作更舒适,但也可能把敏感内容泄漏到磁盘。原文档明确指引读者阅读 docs/privacy-and-security.md 的相关章节,核心风险与对策如下:
8.1 编辑器历史(editor history)
许多编辑器会把使用历史写入磁盘(如最近搜索词、命令历史),这在记日记的场景下可能泄漏敏感信息。
- Visual Studio Code:默认保存本地历史以支持内容恢复。可全局关闭
workbench.localHistory.enabled,或通过workbench.localHistory.exclude设置**/jrnl*.jrnl模式排除 jrnl 临时文件(Windows 下历史位于%APPDATA%\Code\User\History)。 - Vim:
~/.viminfo文件包含命令行历史、搜索模式、寄存器内容等;异常关闭时还会留下 swap 文件。可在editor中追加安全参数:
editor: "vim -c 'set viminfo= noswapfile noundofile nobackup nowritebackup noshelltemp history=0 nomodeline secure'"也可在~/.vimrc中加 autocommand,让 Vim 编辑.jrnl文件时自动应用这些安全设置:
autocmd BufNewFile,BufReadPre *.jrnl setlocal viminfo= noswapfile noundofile nobackup nowritebackup noshelltemp history=0 nomodeline secure- Neovim:与 Vim 类似,区别是 viminfo 由 ShaDa 文件取代(位于
~/.local/state/nvim,v0.8.0 之前是~/.local/share/nvim),同样可禁:
editor: "nvim -c 'set shada= noswapfile noundofile nobackup nowritebackup noshelltemp history=0 nomodeline secure'"Neovim 还可使用 Lua 版 autocommand 实现同样的防护。注意:使用模板时,autocmd 的匹配模式要换成模板的扩展名(而非.jrnl)。
8.2 编辑器与 jrnl 之间传输的文件
写作/编辑期间,jrnl 在磁盘上使用的是未加密的临时文件。正常流程下编辑器关闭后 jrnl 会立刻删除它;但如果在"已保存但未关闭编辑器"时电脑断电、或 jrnl 进程被异常终止,未加密临时文件会残留在磁盘上。对策:养成"保存后立即关闭"的习惯,并定期清理临时目录中名为jrnl*.jrnl的文件(使用模板时后缀随模板扩展名变化)。
九、常见问题排查速查表
| 现象 | 原因 | 对策 |
|---|---|---|
| jrnl 打开编辑器后立刻结束运行 | 编辑器不是阻塞进程 | 为编辑器补充等待参数(-w/--wait/-f/-Wn),参考第四部分 |
| 报错"编辑器配置有误"(misconfigured editor) | editor命令拼写错误或不在 PATH | 改用可执行文件完整路径,或用which/where确认路径 |
| 报 "No text received from editor" | 编辑器内容被清空后保存 | 属正常保护行为;如需删除条目应使用筛选 + 编辑后全删,或--delete交互删除 |
提示EditorNotConfigured | 使用--edit但未配置editor | 先在 配置文件 中设置editor键 |
| Windows 下 Notepad++ 路径解析失败 | YAML 反斜杠转义问题 | 使用C:\\Program Files\\...双反斜杠写法 |
结语
jrnl 的外部编辑器机制并不复杂:一个editor配置键 + 一条"必须阻塞"的纪律 + 一段临时文件生命周期,就能把任何主流编辑器变成日记写作前端。结合本文的源码剖析(jrnl/editor.py、jrnl/controller.py)与配置参考(docs/reference-config-file.md),你现在既可以按需配置 Sublime Text、VS Code、Vim、emacs、Notepad++ 等具体编辑器,也能举一反三适配任何其他编辑器;同时,针对编辑器历史与明文临时文件的隐私加固手段,能让敏感写作场景下的风险降到最低。更多写作、筛选、加密相关能力可继续阅读 docs/usage.md 与 docs/encryption.md。
- CLI
【免费下载链接】jrnl
Collect your thoughts and notes without leaving the command line.
相关推荐
aider 编辑器配置指南:定制 /editor 命令与阻塞模式编辑器的完整方案
aider 编辑器配置指南:定制 /editor 命令与阻塞模式编辑器的完整方案 本文基于 aider 仓库的官方编辑器配置文档( editor.md http
人工智能大模型AI Agent代码智能体交互助手CLI开发工具Neovide 外部工具集成指南:jrnl 编辑器配置与 macOS Quake 下拉模式搭建
Neovide 外部工具集成指南:jrnl 编辑器配置与 macOS Quake 下拉模式搭建 本文基于仓库文档 website/docs/integratio
桌面应用开发工具Jedi与编辑器集成:VSCode、Vim等主流编辑器的配置教程
Jedi与编辑器集成:VSCode、Vim等主流编辑器的配置教程 Jedi是一个强大的Python代码自动补全、静态分析和重构库,它能够为你的编辑器提供智能的代
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考