深入 alfred-devdocs 源码:一个 PHP 脚本如何驱动完整的 Alfred 工作流
深入 alfred-devdocs 源码:一个 PHP 脚本如何驱动完整的 Alfred 工作流
【免费下载链接】alfred-devdocsAlfred workflow for devdocs.io项目地址: https://gitcode.com/gh_mirrors/al/alfred-devdocs
alfred-devdocs 是一个用 PHP 编写的 Alfred 工作流,核心目标只有一个:让开发者在不离开键盘的情况下,随时搜索 devdocs.io 上数百份权威开发文档。这个项目最巧妙的地方在于,它不依赖任何重型框架,仅凭几个轻量 PHP 脚本,就完成了从文档下载、本地缓存、索引搜索到结果渲染的全流程,甚至还能动态重写工作流自身的配置文件。接下来,我们就从源码出发,一步步拆解这套精妙的设计。
alfred-devdocs 是什么?PHP 打造 Alfred 工作流的核心思路
Alfred 工作流的本质,是把「输入关键词 → 执行脚本 → 输出 XML 结果」串成一条流水线。alfred-devdocs 选择 PHP 作为唯一开发语言,整个核心只依赖几个文件,结构非常清爽:
| 文件 | 职责 |
|---|---|
| devdocs.php | 主搜索引擎,处理用户查询并输出候选结果 |
| conf.php | 配置管理,负责增删文档、维护别名 |
| workflows.php | 通用工具箱,封装 XML 输出、缓存与网络请求 |
| plist.phtml | 工作流配置模板,动态生成 info.plist |
| composer.json | 依赖声明,引入 plist 解析库 |
这套分层设计把「业务逻辑」和「Alfred 交互细节」彻底分离:任何脚本只要输出标准 XML,Alfred 就能把它渲染成候选列表。这正是 PHP 驱动 Alfred 工作流的最简范式,也是新手理解 Alfred 插件开发的最佳入门样本。
工作流启动的一瞬间:Script Filter 如何调用 PHP 脚本
在 info.plist 中,doc这个 Script Filter 定义了工作流的入口。它的配置只有一行核心代码:
$query = "{query}"; require_once("scripts/devdocs.php");当你在 Alfred 输入框中键入doc xxx时,Alfred 会把查询文本替换进{query},然后交给 devdocs.php 处理。这个文件开头做了一件很重要的事:ini_set('memory_limit', '-1'),关闭内存上限,因为一次性载入整份文档索引需要不小的内存。
alfred-devdocs 源码解析:本地缓存与三级搜索机制
搜索速度是这类工具的生命线。devdocs.php 通过两层本地缓存,把网络请求降到最低:
- 文档列表缓存:从
https://devdocs.io/docs/docs.json拉取全部可用文档清单,存为cache/docs.json,默认 7 天内不重复下载(可通过CACHE_LIFE环境变量调整,设为-1则永不过期)。 - 索引缓存:为每个已添加的文档下载
docs/{slug}/index.json索引文件,同样按天级缓存,由checkCache()方法统一管理。
搜索逻辑集中在processDocumentation()方法中(devdocs.php),它把匹配结果分成三个优先级,依次填充:
if (strpos($value, $query) === 0) { // 名称前缀匹配:最精准,排第一梯队 } else if (strpos($value, $query) > 0) { // 名称包含匹配:第二梯队 } else if (strpos($description, $query) !== false) { // 描述文本匹配:兜底梯队 }这种「三级搜索」策略保证了查询结果始终按相关度排序:前缀命中最靠前,模糊包含次之,描述命中垫底。值得一提的是,同一名称会通过$found数组去重,避免重复条目。
最终,每条结果经过模板变量替换生成目标 URL(默认模板$baseUrl$documentation/$path,可用TEMPLATE变量自定义),再调用 workflows.php 中的result()方法组装结果项,最后通过toxml()转成 Alfred 能识别的 XML 输出。
动态生成 info.plist:plist.phtml 模板的魔法
这是整个项目最惊艳的设计。常规 Alfred 工作流中,info.plist是一个写死的配置文件,新增一个文档就要手动编辑。而 alfred-devdocs 让 conf.php 在运行时动态重写配置。
当你执行cdoc:add javascript时,调用链是这样的:
addCmd()把文档写入本地配置;- 调用
regeneratePlist(),通过ob_start()引入 plist.phtml 模板,捕获渲染出的完整 plist 内容; - 将新内容写回 info.plist,完成「自我升级」。
模板中有一个foreach ($documentations as $doc)循环,为每个文档生成一个独立的 Script Filter——这意味着添加一个文档,就自动多出一个专属搜索关键词(比如javascript、angular~4_typescript)。别名(alias)机制也走同样流程,在模板中额外生成别名关键词。整个过程不需要你手动碰任何 XML,堪称「配置即代码」的典范。
workflows.php:被复用的 Alfred 工具箱
workflows.php 引用自 David Ferguson 的经典 Workflows 类,是整个项目的「地基」。它解决了 Alfred 开发的几个通用痛点:
- 目录管理:自动识别 Alfred 的缓存目录(
alfred_workflow_cache)与数据目录(alfred_workflow_data),不存在则自动创建; - XML 输出:
result()负责收集结果,toxml()用 SimpleXML 生成标准 Alfred 反馈; - 网络请求:
fetch()支持 HTTP 代理,读取HTTP_PROXY环境变量,并可选携带HTTP_PROXY_AUTHORIZATION进行代理认证——这对企业内网用户非常实用。
理解了它,你就掌握了 Alfred 工作流开发 80% 的通用套路,今后写任何 PHP 工作流都能直接复用。
快速上手:常用 cdoc 命令与个性化配置
无论你是想尝鲜还是深入改造,记住下面这张命令速查表就够了:
| 命令 | 作用 |
|---|---|
cdoc:list | 列出所有可添加的文档库 |
cdoc:add <名称> | 添加指定文档库 |
cdoc:remove <名称> | 移除文档库 |
cdoc:refresh | 强制刷新缓存索引 |
cdoc:alias <别名> <文档> | 为文档创建快捷别名 |
cdoc:all/cdoc:nuke | 一键添加全部 / 清空全部 |
此外,四个环境变量BASE_URL、CACHE_LIFE、TEMPLATE、HTTP_PROXY可以分别控制文档源、缓存周期、URL 生成规则和代理,让你按需定制。
写在最后:从源码中学到什么
读完 alfred-devdocs 的源码,最值得学习的不是某个算法,而是它的工程思维:用模板动态生成配置、用缓存换速度、用分层隔离复杂度。对新手来说,它是一份完美的 Alfred 工作流开发教程;对老手来说,它展示了 PHP 在桌面自动化领域的独特价值。
想亲自把玩这份源码?克隆仓库到本地即可:
git clone https://gitcode.com/gh_mirrors/al/alfred-devdocs对照本文提到的几个文件,动手给自己的工作流加上「动态关键词」能力,你会发现 Alfred 的世界远比想象中广阔。
【免费下载链接】alfred-devdocsAlfred workflow for devdocs.io项目地址: https://gitcode.com/gh_mirrors/al/alfred-devdocs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考