> ## Documentation Index
> Fetch the complete documentation index at: https://openidea.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# 快速开始

> 安装插件工具，生成一个 Rust 插件，构建后链接到 OpenIDEA 并运行它的命令。

本文从零创建一个带两个命令的代码插件：先跑单元测试，再构建成 WebAssembly，最后不经安装直接加载到 IDE 中。

## 准备

* 已安装 OpenIDEA。
* 通过 [rustup](https://rustup.rs) 安装的 Rust。`openidea-plugin build` 发现缺少 `wasm32-wasip2` target 时会通过 rustup 自动安装；也可以自己执行 `rustup target add wasm32-wasip2`。

**1. 安装 openidea-plugin 工具**

```sh theme={null}
cargo install --locked --git https://github.com/l0ng-ai/openidea ide-host --bin openidea-plugin
```

这会从 `main` 分支构建工具。想和某个已发布的 IDE 版本保持一致，加上 `--tag v<version>`（例如 `--tag v0.1.40`）。每个 release 也附带 Linux x64 版本的二进制 `openidea-plugin-linux-x86_64.gz`。

`openidea-plugin --version` 会打印工具版本和它所校验的插件 API 版本。

**2. 生成插件**

```sh theme={null}
openidea-plugin new hello --id acme.hello
cd hello
```

默认的 `command` 模板会生成：

| 文件 | 内容 |
| - | - |
| `plugin.toml` | 清单：id `acme.hello`，名称 `Hello`，两个命令，`editor.read` 能力 |
| `Cargo.toml` | 依赖 SDK 的 `cdylib` crate |
| `src/lib.rs` | 两个命令的实现，以及基于 SDK 模拟宿主的单元测试 |
| `README.md`、`.gitignore` | |

id 的格式是 `<publisher>.<name>`。发布时用前缀（这里是 `acme`）对应的发布者密钥签名；不传 `--id` 时 id 由文件夹名推导。`--name` 设置显示名称。

SDK 依赖指向本仓库中与工具版本对应的 tag（`{ git = "https://github.com/l0ng-ai/openidea", tag = "v…" }`）。传 `--sdk <path to sdk/rust/openidea-plugin>` 可以改用本地检出的 SDK。

其他模板：`--template theme`、`--template icon-theme`、`--template language`，这些都不需要代码。

**3. 运行单元测试**

```sh theme={null}
cargo test
```

在本机上 SDK 连接的是一个模拟宿主，所以不启动 IDE 也能测试命令逻辑。见 [测试与调试](https://openidea.sh/zh/plugins/testing.md)。

**4. 构建组件**

```sh theme={null}
openidea-plugin build
```

它会执行 `cargo build --release --target wasm32-wasip2`，把产物复制到 `dist/plugin.wasm`（清单里 `wasm` 指定的路径），然后运行 `openidea-plugin check`。`check` 按安装时完全相同的规则校验插件包，并打印用户安装时会被要求授予的权限：

```text theme={null}
acme.hello 0.1.0 — Hello
  code: dist/plugin.wasm (…, plugin API 1.4)
  categories: tools
  contributes 2 × commands
  capability editor.read (required, Low risk): Read the focused editor's file and selection
ok
```

`openidea-plugin build --debug` 生成调试构建。

**5. 把文件夹链接到 IDE**

```sh theme={null}
openidea-plugin link
```

`link` 会把当前文件夹写入 IDE 插件目录下的 `links.json`。链接的插件直接从文件夹读取，开发期间不用反复安装。`openidea-plugin links` 列出已链接的文件夹，`openidea-plugin unlink` 取消链接。

> [!NOTE]
>
> 插件目录是 `$OPENIDEA_PLUGINS_DIR`，未设置时为系统应用数据目录下的 `ai.l0ng.openidea/plugins`。从源码运行的 OpenIDEA 开发构建使用自己的数据目录，链接前请把 `OPENIDEA_PLUGINS_DIR` 指向它的 `plugins` 文件夹。见 [数据目录](https://openidea.sh/zh/reference/data-directories.md)。

**6. 授权并运行命令**

1. 打开 **设置 › 插件**（macOS 上 `⌘,`，Windows/Linux 上 `Ctrl+Alt+S`）。插件出现在 **为开发而链接** 分组下，状态为 **需要授权**。
2. 选中它，点击 **查看权限…**，在“允许 Hello 运行？”对话框中点 **允许**。
3. 打开 **查找操作**（`⌘⇧A` / `Ctrl+Shift+A`），运行 **Hello: Say Hello**，会弹出通知 *Hello #1 from Hello!*。
4. 打开任意文件，运行 **Hello: Line Count of Active File**。命令返回的文本会显示给你。

## 开发循环

1. 修改 `src/lib.rs`（或 `plugin.toml`）。
2. 执行 `openidea-plugin build`。
3. 在 **设置 › 插件** 中选中插件，点击详情里的 **从磁盘重新加载** 按钮；或者在 **查找操作** 中运行 **重新加载插件**。

出问题时，**设置 › 插件** 的插件详情会显示其状态和失败原因。日志的查看方式见 [测试与调试](https://openidea.sh/zh/plugins/testing.md)。

## 代码说明

```rust theme={null}
use openidea_plugin::{Error, Invocation, NotificationLevel, Plugin, host, register_plugin};

#[derive(Default)]
pub struct Main {
    greetings: u32,
}

impl Plugin for Main {
    fn run_command(&mut self, id: &str, ctx: &Invocation, _arg: Option<&str>) -> Result<Option<String>, Error> {
        match id {
            "say-hello" => {
                self.greetings += 1;
                let body = format!("Hello #{} from Hello!", self.greetings);
                host::notify(NotificationLevel::Info, "Hello", &body);
                Ok(None)
            }
            "line-count" => {
                let editor = ctx.editor().ok_or("no file is open")?;
                let text = editor.document()?.text;
                Ok(Some(format!("{} lines in {}", text.lines().count(), editor.path())))
            }
            _ => Err(format!("unknown command {id}").into()),
        }
    }
}

register_plugin!(Main);
```

* 命令在 `plugin.toml` 中声明（`[[contributes.commands]]`），所以代码加载前它们就已出现在 **查找操作** 中。
* `run_command` 收到命令 id 和调用上下文（所在窗口的项目和当前编辑器）。
* `greetings` 保存在实例内存里，插件空闲被回收后会清零。需要持久保存的数据放进 `host::storage`（见 [生命周期与事件](https://openidea.sh/zh/plugins/lifecycle.md)）。
* 读取编辑器需要 `editor.read` 能力；没有它时 `editor.document()` 返回 `Error::Denied`。

## 下一步

* [Manifest](https://openidea.sh/zh/plugins/manifest.md)：`plugin.toml` 的每个字段。
* [命令与动作](https://openidea.sh/zh/plugins/guides/commands.md)：菜单、快捷键、`when` 子句和命令参数。
* [示例插件](https://openidea.sh/zh/plugins/examples.md)：可以直接参考的完整插件。
* [打包与签名](https://openidea.sh/zh/plugins/publishing/packaging.md)：把文件夹打成 `.oiplugin` 包。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.