Files
openidea/docs/zh/languages/adding.mdx
T

166 lines
22 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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) 中添加同名条目。