mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-14 16:07:52 +00:00
166 lines
22 KiB
Plaintext
166 lines
22 KiB
Plaintext
---
|
||
title: "添加新语言"
|
||
description: "语言定义文件的格式:文件识别、注释、高亮、语言服务器、调试器和格式化工具。"
|
||
---
|
||
|
||
OpenIDEA 认识的每种语言都是一个 TOML 文件,格式如本页所述。有三种用法:
|
||
|
||
- **为自己修改内置语言**:在配置目录的 `languages` 文件夹里放一个 `id` 相同的文件。它会整体替换内置定义(字段不会合并),所以最好从内置文件复制一份再改。
|
||
- **为自己添加语言**:在同一个文件夹里放一个使用新 `id` 的文件。
|
||
- **把语言提供给别人**:放进插件(见 [通过插件提供语言](#通过插件提供语言)),或者加到仓库的 `languages/` 目录。
|
||
|
||
配置目录位置:
|
||
|
||
| 系统 | 文件夹 |
|
||
| ------- | ----------------------------------------------------------- |
|
||
| macOS | `~/Library/Application Support/ai.l0ng.openidea/languages/` |
|
||
| Windows | `%APPDATA%\ai.l0ng.openidea\languages\` |
|
||
| Linux | `~/.config/ai.l0ng.openidea/languages/` |
|
||
|
||
这个文件夹只在启动时读取一次,修改后需要重启 IDE。无法解析的文件会被跳过,原因写在日志里。
|
||
|
||
## 示例
|
||
|
||
一个完整的定义,包含 tree-sitter 语法、语言服务器和调试器:
|
||
|
||
```toml languages/zig.toml
|
||
id = "zig"
|
||
name = "Zig"
|
||
extensions = ["zig", "zon"]
|
||
line-comment = "//"
|
||
indent = { tab-size = 4, insert-spaces = true }
|
||
tree-sitter = "zig"
|
||
|
||
[[language-servers]]
|
||
name = "zls"
|
||
command = "zls"
|
||
root-markers = ["build.zig", "build.zig.zon"]
|
||
install-hint = "Install ZLS matching your Zig version (https://github.com/zigtools/zls/releases)"
|
||
|
||
[debugger]
|
||
adapter = "codelldb"
|
||
command = "codelldb"
|
||
args = ["--port", "${port}"]
|
||
transport = "tcp"
|
||
install-hint = "Install CodeLLDB in Settings › Languages & Frameworks › Language Servers"
|
||
```
|
||
|
||
所有键都使用 kebab-case。只有 `id` 和 `name` 是必填的;只写这两项时,这类文件至少会在界面上显示正确的语言名。
|
||
|
||
## 语言字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| -------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| `id` | 字符串 | 稳定的语言 id,例如 `python`。可用字母、数字、`-`、`_`、`.`、`+`(最多 64 个字符)。 |
|
||
| `name` | 字符串 | 界面上显示的名称。 |
|
||
| `extensions` | 字符串数组 | 不带点的扩展名,不区分大小写。支持复合扩展名:`html.erb`、`tftest.hcl`。 |
|
||
| `filenames` | 字符串数组 | 精确文件名(`Dockerfile`、`go.mod`),或带 `*`、`?` 的模式(`Dockerfile.*`)。 |
|
||
| `first-line` | 字符串 | 文件名和扩展名都没匹配上时,用来匹配第一行的正则表达式,例如 `^#!.*\\bpython[0-9.]*\\b`。 |
|
||
| `line-comment` | 字符串 | 行注释符号,例如 `//`。**使用行注释** 会用到它。 |
|
||
| `block-comment` | `[开始, 结束]` | 块注释符号,例如 `["/*", "*/"]`。 |
|
||
| `indent` | 表 | `{ tab-size = 4, insert-spaces = true }`。写了这个表时两个键都必须给出。 |
|
||
| `ui-mode` | 字符串 | 用于即时高亮的 CodeMirror 模式。可以是 `@codemirror/language-data` 中的模式名(`Rust`、`Python`、`C++`、`Properties files` 等),也可以是 IDE 自带的模式(如 `CMake`、`Vue`、`Astro`、`ERB`、`JSP`、`Log`、`GoMod`)。 |
|
||
| `framework-ui-modes` | 表数组 | 在某个框架的项目中替换 `ui-mode` 的模式,见下文。 |
|
||
| `tree-sitter` | 字符串 | 内置的 tree-sitter 语法,用于大纲、折叠和项目符号。没有 `ui-mode` 时也用它高亮。可用语法见下方列表。 |
|
||
| `language-servers` | 表数组 | 语言服务器,按顺序排列,见下文。 |
|
||
| `debugger` | 表 | 调试适配器,见下文。 |
|
||
| `formatter` | 表 | 外部格式化工具,见下文。 |
|
||
| `scratch-template` | 字符串 | 新建该语言草稿文件时的内容,`$END$` 表示光标位置。 |
|
||
|
||
内置的 tree-sitter 语法:`bash`、`c`、`cmake`、`cpp`、`csharp`、`css`、`dart`、`elixir`、`gdscript`、`go`、`graphql`、`haskell`、`hcl`、`html`、`java`、`javascript`、`json`、`kotlin`、`lua`、`make`、`markdown`、`nix`、`ocaml`、`ocaml_interface`、`php`、`proto`、`python`、`ruby`、`rust`、`scala`、`swift`、`toml`、`tsx`、`typescript`、`xml`、`yaml`、`zig`。新的语法需要编译进 IDE;没有语法的语言可以改由插件提供高亮和结构(见 [语言功能](/zh/plugins/guides/language-features))。
|
||
|
||
### `[[framework-ui-modes]]`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| -------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||
| `ui-mode` | 字符串 | 用来替换 `ui-mode` 的模式。 |
|
||
| `root-markers` | 字符串数组 | 文件上方(直到项目根目录为止)的某个目录中存在其中任一标记时,该模式生效。匹配规则与语言服务器的 `root-markers` 相同。 |
|
||
|
||
按顺序第一个找到标记的条目生效。HTML 用它来支持 Angular 模板:
|
||
|
||
```toml
|
||
[[framework-ui-modes]]
|
||
ui-mode = "Angular Template"
|
||
root-markers = ["angular.json", "node_modules/@angular/core"]
|
||
```
|
||
|
||
## `[[language-servers]]`
|
||
|
||
每一项启动一个 LSP 服务器。服务器按顺序列出:普通服务器同时运行;`fallback` 服务器只有在排在它前面的服务器都缺失时才运行。
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||
| `name` | 字符串 | 稳定名称,例如 `rust-analyzer`。用户设置用它引用服务器(`languageServers.<name>`);IDE 有对应安装程序时也靠它选择。 |
|
||
| `command` | 字符串 | 要启动的可执行文件。先在 IDE 的工具文件夹中查找,再查 `PATH`。 |
|
||
| `args` | 字符串数组 | 参数,例如 `["--stdio"]`。 |
|
||
| `env` | 表 | 额外的环境变量。 |
|
||
| `root-markers` | 字符串数组 | 标记工作区根目录的文件。文件上方(项目内)最外层包含标记的目录就是服务器的根目录。标记可以是相对路径、带一个 `*` 的模式(`*.csproj`),或用 `file#table` 要求 TOML 文件中有某个表(`pyproject.toml#tool.ruff`)。 |
|
||
| `require-root-marker` | 布尔 | 只服务根标记下面的文件,而不是整个项目。适合与语言自身服务器并存的框架服务器。 |
|
||
| `initialization-options` | 表 | 服务器启动时作为 `initializationOptions` 发送。 |
|
||
| `settings` | 表 | 用于响应服务器的 `workspace/configuration` 请求。不写时,从 `initialization-options` 中查找请求的配置节。 |
|
||
| `install-hint` | 字符串 | 服务器缺失且 IDE 无法安装时显示的提示。 |
|
||
| `fallback` | 布尔 | 作为前面服务器的备选,只在它们都未安装时使用。 |
|
||
| `features` | 字符串数组 | 只把服务器用于这些功能;为空表示全部。可选值:`completion`、`inline-completion`、`hover`、`signature-help`、`definition`、`declaration`、`type-definition`、`implementation`、`references`、`document-highlight`、`document-symbol`、`workspace-symbol`、`code-action`、`code-lens`、`rename`、`formatting`、`inlay-hint`、`semantic-tokens`、`document-link`、`call-hierarchy`、`type-hierarchy`、`folding-range`、`selection-range`、`diagnostics`。 |
|
||
| `code-action-kinds` | 字符串数组 | 只保留这些种类的代码操作,按前缀匹配(`refactor` 包含 `refactor.extract`);为空则全部保留。 |
|
||
| `connect` | 字符串 | 通过 TCP 提供 LSP 的服务器地址 `host:port`,见 [TCP 服务器](#tcp-服务器)。 |
|
||
| `max-java` | 整数 | 服务器能运行的最高 Java 版本。`JAVA_HOME` 更新时,改用已安装的、符合要求的最新 JDK。 |
|
||
| `tsserver-project` | 布尔 | 用于 TypeScript 服务器:目录中没有 `tsconfig.json` / `jsconfig.json` 时,把源文件注册给 tsserver。 |
|
||
| `resync-on-configuration` | 布尔 | `workspace/configuration` 应答后重新发送已打开的文档,适用于只在解析文档时才应用某些设置的服务器。 |
|
||
|
||
大部分配置用户都能在 **设置 › 语言和框架 › 语言服务器** 里按服务器覆盖(可执行文件、实参、环境变量、初始化选项、工作区配置),无需修改定义文件。
|
||
|
||
### TCP 服务器
|
||
|
||
有些服务器只监听 TCP 端口,比如 Godot 编辑器内置的服务器。配置 `connect` 后,如果该地址有程序在监听,IDE 直接连接;否则启动 `command`(已安装时),等它可以接受连接后再连接:参数里有 `${port}` 时连接 `127.0.0.1:${port}`(端口由 IDE 选一个空闲的),否则连接 `connect` 地址。参数中的 `${root}` 是工作区根目录。不是由 IDE 启动的服务器,IDE 也不会关闭它。
|
||
|
||
```toml
|
||
[[language-servers]]
|
||
name = "godot"
|
||
command = "godot"
|
||
args = ["--headless", "--editor", "--path", "${root}", "--lsp-port", "${port}"]
|
||
connect = "127.0.0.1:6005"
|
||
root-markers = ["project.godot"]
|
||
```
|
||
|
||
## `[debugger]`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| -------------- | ---------- | --------------------------------------------------------------------------------------------------------------- |
|
||
| `adapter` | 字符串 | 调试适配器名称,例如 `codelldb`、`debugpy`、`js-debug`、`delve`。IDE 有对应安装程序时也靠它选择。 |
|
||
| `command` | 字符串 | 启动适配器的可执行文件。 |
|
||
| `args` | 字符串数组 | 参数。使用 `tcp` 时,`${port}` 会替换为一个空闲端口。 |
|
||
| `transport` | 字符串 | `stdio`(默认)或 `tcp`。 |
|
||
| `connect` | 字符串 | 仅 `tcp`:运行在其他程序(如 Godot 编辑器)内部的适配器地址 `host:port`。能连上时直接使用,否则启动 `command`。 |
|
||
| `install-hint` | 字符串 | 适配器缺失时显示的提示。 |
|
||
|
||
配置了 `[debugger]` 的语言,可以在其文件中设置断点。
|
||
|
||
## `formatter`
|
||
|
||
外部格式化工具,在没有语言服务器能格式化该文件、或在设置中选择了它时使用:
|
||
|
||
```toml
|
||
formatter = { tool = "prettier", parser = "typescript", range = true }
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| -------- | ------ | -------------------------------------------------------------------------------------- |
|
||
| `tool` | 字符串 | `prettier`、`oxfmt` 或 `ruff`。 |
|
||
| `parser` | 字符串 | 该工具针对这种语言的解析器(Prettier 的 `--parser`,例如 `css`、`markdown`、`yaml`)。 |
|
||
| `range` | 布尔 | 该工具能格式化选区。仅 Prettier 和 Ruff 支持;oxfmt 总是格式化整个文件。 |
|
||
|
||
## 通过插件提供语言
|
||
|
||
插件附带同样格式的文件,并在清单中声明:
|
||
|
||
```toml plugin.toml
|
||
[[contributes.languages]]
|
||
path = "languages/solidity.toml"
|
||
```
|
||
|
||
定义里启动的每个程序(`language-servers.command`、`debugger.command`)都需要 `process:<program>` 权限;未获授权的服务器会被忽略,但语言本身仍然可用。内置定义和用户定义优先:插件不能占用它们的 id、扩展名或文件名。插件侧的写法见 [语言功能](/zh/plugins/guides/language-features),完整示例见 [`plugins/official/solidity`](https://github.com/l0ng-ai/openidea/blob/main/plugins/official/solidity)。
|
||
|
||
## 添加内置语言
|
||
|
||
要把语言加入 OpenIDEA 本身,新增 `languages/<id>.toml`,并在 [`crates/ide-language/src/registry.rs`](https://github.com/l0ng-ai/openidea/blob/main/crates/ide-language/src/registry.rs) 的 `BUILTIN` 表中注册(这些文件在构建时嵌入)。要让它的服务器支持一键安装,还需要在 [`crates/ide-tools/src/registry.rs`](https://github.com/l0ng-ai/openidea/blob/main/crates/ide-tools/src/registry.rs) 中添加同名条目。
|