☰
jrnl 外部编辑器配置完全指南:editor 选项、阻塞进程要求与主流编辑器实战
2026/9/28 2:56:08 网站建设 项目流程
  • CLI

【免费下载链接】jrnl

Collect your thoughts and notes without leaving the command line.

项目地址:https://gitcode.com/gh_mirrors/jr/jrnl
点击查看免费下载

导读

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.plist

4.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()):

  1. 创建临时文件:tempfile.mkstemp(prefix="jrnl", text=True, suffix=".jrnl")生成一个以jrnl开头、.jrnl结尾的明文临时文件(若配置了template,后缀会变为-模板文件名,见下文第六部分)。
  2. 预填内容:若调用方传入模板或命令行开头文字(如jrnl yesterday: ... --edit),先把这些内容写入临时文件。
  3. 阻塞调用编辑器:subprocess.call(split_args(config["editor"]) + [tmpfile]),等待编辑器进程退出。
  4. 读回内容:编辑器保存并关闭后,jrnl 以 UTF-8 读回临时文件的全部文本。
  5. 删除临时文件:无论成败,finally中都会os.remove(tmpfile)清理。
  6. 空内容报错:若编辑器被直接清空并保存(常发生在误删日记内容时),raw为空,jrnl 会抛出NoTextReceived错误,提示 "No text received from editor. Were you trying to delete all the entries?"(该文案在 BDD 测试 tests/bdd/features/actions.feature 中也有断言)。
  7. 编辑器命令不存在:如果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.

项目地址:https://gitcode.com/gh_mirrors/jr/jrnl
点击查看免费下载

相关推荐

上一篇:终极rrweb沙箱机制安全指南:保护Web回放的完整方案
下一篇:League Akari:英雄联盟玩家的智能游戏伴侣

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询