真・懒

订阅 Twitter GitHub 联系

记一款小工具的诞生

我用 Calibre 管理电子书籍已有很多年。它推出阅读器也有一段时间了,虽然没有 iBooks 那么美观,但胜在方便,而且直接支持 mobi 格式,渐渐我就用它替换了 iBooks。

Calibre 阅读器并非 native 的实现,选择文本后无法使用 macOS 的系统字典进行查询,也无法通过 PopClip 这种工具来转接。但它提供了一个自定义词典功能,可以通过 HTTP 地址进行查询。虽然有很多选择,但我最想用的还是系统字典。那么,能够通过 HTTP 查询系统字典,是我想做到的。

调研

一番搜索,Core ServicesDictionary Services 提供了查询接口,遗憾的是功能有限,没有能覆盖到 Dictionary.app 提供的功能。然而,API 是藏不住的,https://nshipster.com/dictionary-services/ 提供了这些私有接口。

一开始我想直接创建一个原生应用程序提供 HTTP 服务,但仔细看 API,它的输出有纯文本,也有 HTML (带 CSS 或者不带)。既然有纯文本,做成一个命令行工具,用途可以更宽广。然后再通过 Node 简单封装一下 HTTP 服务,开发效率会高很多。

实现

命令行工具

我一直希望能脱离 Xcode 用 make 来管理一下项目,这个小项目正是一个好机会。Core Services 类型都是 Core Foundation 类型,我也决定不用 ObjC,用纯 C 来练练手。

最终我把它命名为 dicmd,开源在 https://github.com/cxa/dicmd。为了方便安装,学会了简单的 homebrew formulae

HTTP 服务

我选择了简单直接的 micro,这个倒没有什么好说。难点在于,词条的输出就是一个完整的 HTML 文档,如何将多词条拼凑在同一个页面。iframe 并不能自适应尺寸,Shadow DOM 是一个优雅的解决方案。具体可参考 dicsrv,开源在 https://github.com/cxa/dicsrv

效果

如图。

Screen shot