Skip to content

从零编写第一个插件 ​

这一页做一个最小的命令插件。它不解析博客、不读取 Core 内部状态,只接收一个命令参数并输出结果。完成后你会理解 luox 的三个关键点:plugin.json 如何注册命令,Host 如何找到插件,插件如何自己解释参数。

第一步:创建目录 ​

在项目外新建插件目录:

hello-plugin/
├── plugin.json
└── hello-plugin.exe

hello-plugin.exe 可以由 Rust、Go、C++、Python 打包程序或其它语言生成。开发阶段可以先用一个已有的可执行程序模拟,发布阶段必须放入真正的编译产物。

第二步:编写清单 ​

plugin.json:

{
  "id": "example.hello",
  "name": "Hello Plugin",
  "version": "1.0.0",
  "api_version": 1,
  "commands": {
    "hello": "hello-plugin.exe"
  },
  "capabilities": ["example-command"]
}

id 是生态中的稳定身份,不能因为文件名变化就随意改变。commands 的 key 是用户输入的命令,value 是相对于该插件目录的可执行文件。

第三步:理解参数转发 ​

用户执行:

luox hello world

Host 会寻找提供 hello 的插件,然后等价启动:

hello-plugin.exe hello world

Host 不会知道 world 是什么,也不会修改它。插件可以把它当作名字、文件路径、配置选项或自己的子命令。

第四步:编写插件程序 ​

下面是 Rust 形式的最小实现思路:

fn main() {
    let mut args = std::env::args().skip(1);
    match args.next().as_deref() {
        Some("hello") => {
            let name = args.next().unwrap_or_else(|| "world".into());
            println!("Hello, {name}!");
        }
        _ => eprintln!("usage: hello hello <name>"),
    }
}

编译后只把 hello-plugin.exe 和 plugin.json 放入最终包,不需要把 Rust 源码、Cargo 或 target 目录交给用户。

第五步:测试 ​

从包含 luox.exe、luox_core.dll 和 plugins/ 的项目根目录执行:

luox hello luox

预期输出:

Hello, luox!

如果提示找不到命令,检查 plugin.json 是否位于 plugins/ 的直接子目录,以及 commands 中的入口文件是否存在。

下一步 ​

命令插件只是入门。需要定义文章目录时实现 project-model,需要处理 Markdown 时实现 parser,需要生成 HTML 时实现 theme,需要复制 CSS/JS 时实现 asset-provider,需要发布 GitHub Pages 时实现 deployer。

一切皆插件 · luox