{"id":47732293,"url":"https://github.com/yuniqueunic/schemaui","last_synced_at":"2026-04-26T08:09:54.448Z","repository":{"id":322966256,"uuid":"1091644829","full_name":"YuniqueUnic/schemaui","owner":"YuniqueUnic","description":"schemaui turns JSON Schema documents into fully interactive terminal UIs powered by ratatui, crossterm, and jsonschema.  The library parses rich schemas (nested sections, $ref, arrays, key/value maps, pattern properties…) into a navigable form tree, renders it as a keyboard-first editor, and validates the result after every edit","archived":false,"fork":false,"pushed_at":"2026-04-14T16:18:34.000Z","size":13215,"stargazers_count":43,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-14T18:16:16.537Z","etag":null,"topics":["json","json-schema","rust","toml","tui","web","yaml"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/schemaui","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YuniqueUnic.png","metadata":{"files":{"readme":"README.ZH.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-07T10:03:20.000Z","updated_at":"2026-04-14T16:18:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/YuniqueUnic/schemaui","commit_stats":null,"previous_names":["yuniqueunic/schemaui"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/YuniqueUnic/schemaui","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuniqueUnic%2Fschemaui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuniqueUnic%2Fschemaui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuniqueUnic%2Fschemaui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuniqueUnic%2Fschemaui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YuniqueUnic","download_url":"https://codeload.github.com/YuniqueUnic/schemaui/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuniqueUnic%2Fschemaui/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32000740,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","json-schema","rust","toml","tui","web","yaml"],"created_at":"2026-04-02T21:49:37.066Z","updated_at":"2026-04-19T09:02:05.286Z","avatar_url":"https://github.com/YuniqueUnic.png","language":"Rust","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://signature4u.vercel.app/schemaui?font=satisfy\u0026fontSize=153\u0026speed=2.8\u0026charSpacing=0\u0026borderRadius=0\u0026cardPadding=24\u0026fill=multi\u0026fill1=001bb7\u0026fill2=ec4899\u0026stroke=001bb7\u0026stroke2=ec4899\u0026strokeMode=multi\u0026strokeEnabled=1\u0026bg=transparent\u0026bgMode=solid\u0026bg2=1e3a8a\u0026texture=cross\u0026texColor=566486\u0026texSize=30\u0026texThickness=1\u0026texOpacity=0.4\u0026colors=001bb7-001bb7-001bb7-001bb7-001bb7-001bb7-ff8040-fcb53b\u0026linkFillStroke=1\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://signature4u.vercel.app/api/sign?text=schemaui\u0026font=satisfy\u0026fontSize=153\u0026speed=2.8\u0026charSpacing=0\u0026borderRadius=0\u0026cardPadding=24\u0026fill=multi\u0026fill1=001bb7\u0026fill2=ec4899\u0026stroke=001bb7\u0026stroke2=ec4899\u0026strokeMode=multi\u0026strokeEnabled=1\u0026bg=transparent\u0026bgMode=solid\u0026bg2=1e3a8a\u0026texture=cross\u0026texColor=566486\u0026texSize=30\u0026texThickness=1\u0026texOpacity=0.4\u0026colors=001bb7-001bb7-001bb7-001bb7-001bb7-001bb7-ff8040-fcb53b\u0026linkFillStroke=1\" align=\"center\"  alt=\"schemaui signature\"/\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n[![Crates.io](https://img.shields.io/crates/v/schemaui.svg)](https://crates.io/crates/schemaui)\n[![Documentation](https://docs.rs/schemaui/badge.svg)](https://docs.rs/schemaui)\n[![License](https://img.shields.io/crates/l/schemaui)](https://github.com/yuniqueunic/schemaui#license)\n![Crates.io Total Downloads](https://img.shields.io/crates/d/schemaui)\n\n\u003c!-- ![Deps.rs Crate Dependencies (latest)](https://img.shields.io/deps-rs/schemaui/latest) --\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://asciinema.org/a/7IBbhRJAUBlIQaPWSrspEgZtE\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://asciinema.org/a/7IBbhRJAUBlIQaPWSrspEgZtE.svg\" width=\"500\" /\u003e\n  \u003c/a\u003e\n\n[English](./README.md) | [中文文档](./README.ZH.md)\n\n\u003c/div\u003e\n\n`schemaui` 将 JSON Schema\n文档转换为由`ratatui`、`crossterm`和`jsonschema`驱动的完全交互式的终端用户界面。\n\n该库解析丰富的模式（嵌套部分、`$ref`、数组、键值映射、模式属性等），将其转换为可导航的表单树，将其呈现为键盘优先的编辑器，并在每次编辑后验证结果，以便用户在保存之前始终可以看到完整的错误列表。\n\n\u003c!-- AUTO-GENERATED:CLI-QUICKLINK:BEGIN --\u003e\n\n\u003e CLI 可用：`schemaui-cli` 会安装 `schemaui` 可执行文件。想直接使用 CLI？跳转到\n\u003e [CLI 安装与用法](#cli-schemaui-cli)。\n\n\u003c!-- AUTO-GENERATED:CLI-QUICKLINK:END --\u003e\n\n## 功能亮点\n\n- **模式保真度** –\n  `draft-07`，包括`$ref`、`definitions`、、`patternProperties`、枚举、数值范围以及嵌套的对象/数组。\n- **部分和覆盖层** –\n  顶层属性成为根标签，嵌套对象被展平为部分，复杂节点（复合体、键值集合、数组条目）打开具有自身验证器的专用覆盖层。\n- **即时验证** –\n  每次按键都可以触发`jsonschema::Validator`，所有错误（字段作用域 +\n  全局）都被收集并一起显示。\n- **可插拔的 I/O** – `io::input`可以处理\n  JSON/YAML/TOML（通过功能标志），而`io::output`可以输出到标准输出和/或任何启用格式的多个文件。\n- **内置 CLI** –\n  `schemaui-cli`提供了与库相同的流程，包括多目标输出、stdin/内联规范和聚合诊断。\n\n## Config Schema 自动检测\n\n当你只传 `--config` 而不显式传 `--schema` 时，`schemaui-cli`\n现在会按以下优先级解析 schema：\n\n1. 显式 `--schema`\n2. 配置文件内声明的 schema\n3. `schema_from_data_value` 自动推断\n\n支持的声明形式：\n\n- **JSON**：根级 `$schema`\n- **TOML**：`#:schema ./schema.json`\n- **YAML**：`# yaml-language-server: $schema=...`\n- **YAML fallback**：`# @schema ...`\n\n本地与远程 schema 都支持。相对本地路径会按配置文件所在目录解析；如果配置来自\nstdin/内联文本，则回退到当前工作目录。对于 JSON 配置，根级 `$schema`\n只作为元数据使用，会在内存中的 defaults\n里剥离，避免编辑器提示字段污染最终校验与输出。\n\n远程 `http(s)` schema 加载只存在于 `schemaui-cli`，并且 CLI 默认开启\n`remote-schema` feature；如果你希望二进制只保留本地能力，可以关闭它。 `schemaui`\n这个库默认不会开启任何远程 schema 加载能力。\n\n两者的默认 feature 按使用场景刻意分开：\n\n- `schemaui-cli` 默认走“开箱即用”路径：TUI + Web + 远程 schema 加载都开启。\n- `schemaui` 作为库默认开 `tui + json`，这样保留最基础的 JSON\n  能力，同时不默认引入 Web 与联网相关能力。\n- `json`、`yaml`、`toml` 都是真正落在代码路径上的 feature\n  gate；三者不能全关，否则会直接给出清晰的编译期错误。\n\n参考：\n\n- JSON Schema\n  `$schema`：\u003chttps://json-schema.org/understanding-json-schema/reference/schema\u003e\n- Taplo `#:schema`\n  指令：\u003chttps://taplo.tamasfe.dev/configuration/directives.html\u003e\n- YAML language server\n  modeline：\u003chttps://github.com/redhat-developer/yaml-language-server\u003e\n\n## 快速开始\n\n```toml\n[dependencies]\nschemaui = \"0.8.0\"\nserde_json = \"1\"\n```\n\n```rust\nuse schemaui::prelude::*;\nuse serde_json::json;\n\nfn main() -\u003e color_eyre::Result\u003c()\u003e {\n    color_eyre::install()?;\n    let schema = json!({\n        \"$schema\": \"http://json-schema.org/draft-07/schema# \",\n        \"title\": \"服务运行时\",\n        \"type\": \"object\",\n        \"properties\": {\n            \"metadata\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"serviceName\": {\"type\": \"string\"},\n                    \"environment\": {\n                        \"type\": \"string\",\n                        \"enum\": [\"dev\", \"staging\", \"prod\"]\n                    }\n                },\n                \"required\": [\"serviceName\"]\n            },\n            \"runtime\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"http\": {\n                        \"type\": \"object\",\n                        \"properties\": {\n                            \"host\": {\"type\": \"string\", \"default\": \"0.0.0.0\"},\n                            \"port\": {\"type\": \"integer\", \"minimum\": 1024, \"maximum\": 65535}\n                        }\n                    }\n                }\n            }\n        },\n        \"required\": [\"metadata\", \"runtime\"]\n    });\n\n    let options = UiOptions::default();\n    let ui = SchemaUI::new(schema)\n        .with_title(\"SchemaUI 演示\")\n        .with_options(options.clone());\n    let frontend = TuiFrontend { options };\n    let value = ui.run_with_frontend(frontend)?;\n    println!(\"{}\", serde_json::to_string_pretty(\u0026value)?);\n    Ok(())\n}\n```\n\n## 公共 API 入口\n\n在作为库集成 schemaui 时，主要的入口包括：\n\n- **TUI 运行时**：`crate::tui::app::{SchemaUI, UiOptions}`（配合\n  `crate::tui::session::TuiFrontend` 使用）\n- **TUI 状态**：`crate::tui::state::*`（例如\n  `FormState`、`FormCommand`、`FormEngine`、`SectionState` 等）\n- **Schema 后端**：`crate::ui_ast::build_ui_ast` 配合\n  `crate::tui::model::form_schema_from_ui_ast`（先生成规范 UI AST，再派生\n  `FormSchema`）\n\n## 架构快照\n\n```\n┌─────────────┐   解析/合并     ┌──────────────┐   布局+类型          ┌───────────────┐\n│ io::input   ├────────────────▶│ schema       ├────────────────────▶│ tui::state    │\n└─────────────┘                 │ (loader/     │                     │ (FormState,   │\n                                │ resolver/    │                     │ sections,     │\n┌─────────────┐   输出值        │ build_form_  │   FormSchema        │ reducers)     │\n│ io::output  ◀─────────────────┴────pipeline──┘                     └────────┬──────┘\n└─────────────┘                                             焦点/编辑          │\n                                                                               │\n                                                                        ┌──────▼──────────┐\n                                                                        │ tui::app::runtime │\n                                                                        │ (输入路由器,      │\n                                                                        │ 覆盖层, 状态)    │\n                                                                        └──────┬──────────┘\n                                                                               │ 绘制\n                                                                        ┌──────▼──────────┐\n                                                                        │ tui::view::*    │\n                                                                        │ (ratatui 视图)  │\n                                                                        └─────────────────┘\n```\n\n此布局反映了`src/`下的实际模块，便于将任何代码更改映射到其架构责任。\n\n## 输入与输出设计\n\n- `io::input::parse_document_str`将\n  JSON/YAML/TOML（通过`serde_json`、`serde_yaml`、`toml`）转换为`serde_json::Value`。功能标志（`json`、`yaml`、`toml`）不仅控制依赖项，也会真实控制`DocumentFormat`的解析与探测路径。\n- `schema_from_data_value/str`从活动配置中推断模式，注入草稿 -07\n  元数据和默认值，以便 UI 加载现有值。\n- `schema_with_defaults`将规范模式与用户数据合并，通过`properties`、`patternProperties`、`additionalProperties`、`dependencies`、`dependentSchemas`、数组和`$ref`目标传播默认值，而不修改原始树。\n- `io::output::OutputOptions`封装了序列化格式、美观/紧凑切换以及`OutputDestination::{Stdout, File}`的向量。支持多个目标；冲突在输出前被捕获。\n- `SchemaUI::with_output`将这些选项集成到运行时中，以便在会话结束后自动写入最终的`serde_json::Value`。\n\n## JSON Schema → TUI 映射\n\n`build_ui_ast` 先把解析后的模式规范化为 UI AST，再由 `form_schema_from_ui_ast`\n将每个子树映射为 `FormSection`/`FieldSchema`：\n\n| 模式功能                                                     | 结果控件                                                |\n| ------------------------------------------------------------ | ------------------------------------------------------- |\n| `type: string`, `integer`, `number`                          | 带有数值保护的内联文本编辑器                            |\n| `type: boolean`                                              | 切换/复选框                                             |\n| `enum`                                                       | 弹出选择器（单选或多选用于数组枚举）                    |\n| 数组                                                         | 内联列表摘要 + 每个项目的覆盖层编辑器                   |\n| `patternProperties`, `propertyNames`, `additionalProperties` | 带有模式支持验证的键值编辑器                            |\n| `$ref`, `definitions`                                        | 在布局前解析；被视为内联模式                            |\n| `oneOf` / `anyOf`                                            | 变体选择器 + 覆盖层表单，将非活动变体排除在最终负载之外 |\n\n根对象生成标签；嵌套对象成为带有面包屑标题的部分。每个字段记录其 JSON\n指针（例如`/runtime/http/port`），以便焦点管理和验证可以精确映射错误。\n\n## 验证生命周期\n\n- `jsonschema::validator_for`在`SchemaUI::run`开始时编译完整模式一次。\n- 每次编辑都会触发`FormCommand::FieldEdited`。`FormEngine`通过`FormState::try_build_value`重建当前文档，运行验证器，并将错误反馈到`FieldState`或全局状态行。\n- 覆盖层（复合变体、键值映射、列表条目）会根据当前正在编辑的子模式启动自己的验证器，因此问题会在离开覆盖层之前浮出水面。\n\n```\n┌─────────────┐ 解析模式   ┌───────────────────────────────┐ 膨胀状态        ┌────────────┐\n│ SchemaUI::run├──────────▶│ form_schema_from_ui_ast       ├───────────────▶│ FormState  │\n└─────┬───────┘            │ (tui::model::FormSchema)      │                 └──────┬─────┘\n      │ validator_for()    └───────────────────────────────┘           编辑         │\n      │                                                        ┌──────▼─────────┐\n      └────────────────────────────────────────────────────── ▶│ app::runtime   │\n                                                               │ (状态, 输入)   │\n                                                               └──────┬─────────┘\n                                                                      │ FormCommand\n                                                               ┌──────▼──────────┐\n                                                               │ FormEngine      │\n                                                               │ + jsonschema    │\n                                                               └─────────────────┘\n```\n\n`App`是`FormState`的唯一所有者；即使是覆盖层编辑也会通过`FormEngine`流动，以保持验证规则集中。\n\n## TUI 构建块与快捷键\n\n- **快捷键单一来源** –\n  `keymap/default.keymap.json`列出了每个快捷键（上下文、组合键、动作）。`app::keymap::keymap_source!()`宏将此文件拉入二进制文件中，`InputRouter`使用它对`KeyEvent`进行分类，运行时页脚从相同的数据中呈现帮助文本——保持文档和行为\n  DRY。\n- **根标签与部分** –\n  焦点通过`Ctrl+J / Ctrl+L`（根）和`Ctrl+Tab / Ctrl+Shift+Tab`（部分）循环。普通`Tab`/`Shift+Tab`在各个字段之间移动。\n- **字段** –\n  渲染标签、描述和内联错误消息。枚举/复合字段显示当前选择；数组总结长度和选定条目。\n- **弹出窗口与覆盖层** – 按下`Enter`键打开枚举/oneOf\n  选择器的弹出窗口；`Ctrl+E`打开复合编辑器的全屏覆盖层。覆盖层暴露集合快捷键（`Ctrl+N`、`Ctrl+D`、`Ctrl+←/→`、`Ctrl+↑/↓`）以及`Ctrl+S`提交。\n- **状态与帮助** –\n  页脚突出显示脏状态、未解决的验证错误和上下文感知帮助文本。当自动验证启用时，每次编辑都会立即更新这些计数器。\n\n### 自动生成的快捷键参考\n\n\u003c!-- AUTO-GENERATED:SHORTCUTS:BEGIN --\u003e\n\n#### 默认上下文\n\n| 快捷键              | 动作                                  | 类型   |\n| ------------------- | ------------------------------------- | ------ |\n| `Tab` / `Down`      | 下一个字段                            | `命令` |\n| `BackTab` / `Up`    | 上一个字段                            | `命令` |\n| `Ctrl+Tab`          | 下一个分区                            | `命令` |\n| `Ctrl+Shift+Tab`    | 上一个分区                            | `命令` |\n| `Ctrl+L`            | 下一个根标签                          | `命令` |\n| `Ctrl+J`            | 上一个根标签                          | `命令` |\n| `Enter`             | 打开弹窗 / 应用选择                   | `命令` |\n| `Ctrl+E`            | 打开复合编辑器                        | `命令` |\n| `Ctrl+S`            | 保存并验证（覆盖层保持打开）          | `命令` |\n| `Ctrl+Q` / `Ctrl+C` | 退出（脏状态需确认）                  | `命令` |\n| `Esc`               | 取消 / 清除状态（覆盖层：弹出当前层） | `命令` |\n| `Ctrl+?` / `Ctrl+H` | 显示帮助与错误摘要                    | `命令` |\n\n#### 集合上下文\n\n| 快捷键              | 动作               | 类型   |\n| ------------------- | ------------------ | ------ |\n| `Ctrl+E`            | 打开复合编辑器     | `命令` |\n| `Ctrl+N`            | 添加条目           | `命令` |\n| `Ctrl+D`            | 删除条目           | `命令` |\n| `Ctrl+Left`         | 选择上一个条目     | `命令` |\n| `Ctrl+Right`        | 选择下一个条目     | `命令` |\n| `Ctrl+Up`           | 条目上移           | `命令` |\n| `Ctrl+Down`         | 条目下移           | `命令` |\n| `Ctrl+?` / `Ctrl+H` | 显示帮助与错误摘要 | `命令` |\n\n#### 覆盖层上下文\n\n| 快捷键              | 动作                                  | 类型   |\n| ------------------- | ------------------------------------- | ------ |\n| `Tab` / `Down`      | 下一个字段                            | `命令` |\n| `BackTab` / `Up`    | 上一个字段                            | `命令` |\n| `Ctrl+N`            | 添加条目                              | `命令` |\n| `Ctrl+D`            | 删除条目                              | `命令` |\n| `Ctrl+Left`         | 选择上一个条目                        | `命令` |\n| `Ctrl+Right`        | 选择下一个条目                        | `命令` |\n| `Ctrl+Up`           | 条目上移                              | `命令` |\n| `Ctrl+Down`         | 条目下移                              | `命令` |\n| `Ctrl+S`            | 保存并验证（覆盖层保持打开）          | `命令` |\n| `Esc`               | 取消 / 清除状态（覆盖层：弹出当前层） | `命令` |\n| `Ctrl+?` / `Ctrl+H` | 显示帮助与错误摘要                    | `命令` |\n\n#### 帮助上下文\n\n| 快捷键                      | 动作           | 类型   |\n| --------------------------- | -------------- | ------ |\n| `Esc` / `Ctrl+H` / `Ctrl+?` | 关闭帮助       | `命令` |\n| `Tab`                       | 下一页错误     | `命令` |\n| `BackTab`                   | 上一页错误     | `命令` |\n| `Up` / `k`                  | 快捷键向上滚动 | `命令` |\n| `Down` / `j`                | 快捷键向下滚动 | `命令` |\n| `PageUp`                    | 快捷键上翻页   | `命令` |\n| `PageDown`                  | 快捷键下翻页   | `命令` |\n| `Home`                      | 快捷键跳到顶部 | `命令` |\n| `End`                       | 快捷键跳到底部 | `命令` |\n| `h`                         | 错误文本左滚   | `命令` |\n| `l`                         | 错误文本右滚   | `命令` |\n\n#### 文本字段上下文\n\n| 快捷键      | 动作           | 类型       |\n| ----------- | -------------- | ---------- |\n| `Left`      | 光标左移       | `局部编辑` |\n| `Right`     | 光标右移       | `局部编辑` |\n| `Home`      | 跳到行首       | `局部编辑` |\n| `End`       | 跳到行尾       | `局部编辑` |\n| `Backspace` | 删除前一个字符 | `局部编辑` |\n| `Delete`    | 删除后一个字符 | `局部编辑` |\n| `Ctrl+W`    | 删除前一个单词 | `局部编辑` |\n| `Ctrl+Z`    | 撤销文本编辑   | `局部编辑` |\n| `Ctrl+Y`    | 重做文本编辑   | `局部编辑` |\n\n#### 数值字段上下文\n\n| 快捷键        | 动作           | 类型       |\n| ------------- | -------------- | ---------- |\n| `Left`        | 数值减一步     | `局部编辑` |\n| `Right`       | 数值加一步     | `局部编辑` |\n| `Shift+Left`  | 数值快速减一步 | `局部编辑` |\n| `Shift+Right` | 数值快速加一步 | `局部编辑` |\n| `Backspace`   | 删除前一个字符 | `局部编辑` |\n| `Delete`      | 删除后一个字符 | `局部编辑` |\n| `Ctrl+Z`      | 撤销数值编辑   | `局部编辑` |\n| `Ctrl+Y`      | 重做数值编辑   | `局部编辑` |\n\n\u003c!-- AUTO-GENERATED:SHORTCUTS:END --\u003e\n\n### 快捷键系统\n\n将每个快捷键放入`keymap/default.keymap.json`中，以便运行时逻辑、帮助覆盖层和自动生成的\nREADME 快捷键参考都使用单一信息源。\n\n- **格式** – 每个 JSON\n  对象声明一个`id`、英文`description`、双语`descriptionZh`、`contexts`（任何`\"default\"`、`\"collection\"`、`\"overlay\"`、`\"help\"`、`\"text\"`、`\"numeric\"`），一个`action`区分联合类型以及文本`combos`列表。例如：\n\n  ```json\n  {\n    \"id\": \"list.move.up\",\n    \"description\": \"Move entry up\",\n    \"descriptionZh\": \"条目上移\",\n    \"contexts\": [\"collection\", \"overlay\"],\n    \"action\": { \"kind\": \"ListMove\", \"delta\": -1 },\n    \"combos\": [\"Ctrl+Up\"]\n  }\n  ```\n\n- **宏 + 解析器** – `app::keymap::keymap_source!()` `include_str!`s\n  JSON，`once_cell::sync::Lazy`在启动时一次解析，并将每个组合键编译为`KeyPattern`（键码、所需修饰符、美观显示字符串）。\n- **集成** –\n  `InputRouter::classify`委托给`keymap::classify_key`，该函数返回嵌入在 JSON\n  中的`KeyAction`。`keymap::help_text`根据`KeymapContext`过滤绑定，连接用于`StatusLine`和覆盖层说明的片段。\n- **生成文档** – `build.rs`会解析 `keymap/default.keymap.json`，并通过显式 HTML\n  marker 刷新 `README.md` 与 `README.ZH.md` 中的快捷键块；因此常规 Cargo\n  构建就会让双语快捷键参考与运行时行为保持同步。\n- **扩展** – 要添加快捷键，编辑\n  JSON，选择暴露帮助文本的上下文，并在引入新的语义命令时在`KeyBindingMap`中连接结果`KeyAction`。\n\n## 运行时层\n\n| 层           | 模块 (s)                                                      | 责任                                                           |\n| ------------ | ------------------------------------------------------------- | -------------------------------------------------------------- |\n| 摄取         | `io::input`, `schema::loader`, `schema::resolver`             | 解析 JSON/TOML/YAML，解析`$ref`，并规范化元数据。              |\n| 布局类型     | `ui_ast::build_ui_ast`, `tui::model::form_schema_from_ui_ast` | 从规范 UI AST 生成 `FormSchema`（根/部分/字段）。              |\n| 表单状态     | `tui::state::{form_state, section, field}`                    | 跟踪焦点、指针、脏标志、强制转换和错误。                       |\n| 命令与简化器 | `tui::state::{actions, reducers}`, `tui::app::validation`     | 定义 `FormCommand`，突变状态，并路由验证结果。                 |\n| 运行时控制器 | `tui::app::{runtime, overlay, popup, status, keymap}`         | 事件循环，输入路由器分发，覆盖层生命周期，帮助文本，状态更新。 |\n| 呈现         | `tui::view` 和 `tui::view::components::*`                     | 通过 `ratatui` 呈现标签、字段列表、弹出窗口、覆盖层和页脚。    |\n\n每个模块保持在约 600 行代码以下（硬上限 800），以尊重 KISS\n原则并使重构易于管理。\n\n## CLI (`schemaui-cli`)\n\n\u003c!-- AUTO-GENERATED:CLI-INSTALL:BEGIN --\u003e\n\n### 安装\n\n安装后的实际可执行文件名始终是 `schemaui`，所以常规入口仍然是\n`schemaui -c ./config.json`。\n\n选择下面任意一种支持的分发方式：\n\n#### Cargo（`cargo install`）\n\n使用 Cargo 从 crates.io 编译安装。\n\n```bash\ncargo install schemaui-cli\n```\n\n#### Cargo binstall\n\n通过 cargo-binstall 拉取预构建的 GitHub release 二进制。\n\n```bash\ncargo binstall schemaui-cli\n```\n\n#### Homebrew\n\n在 macOS 或 Linux 上通过仓库 tap 安装。\n\n```bash\nbrew install YuniqueUnic/schemaui/schemaui\n```\n\n#### Scoop\n\n在 Windows 上通过仓库内维护的 Scoop manifest 安装。\n\n```bash\nscoop install https://raw.githubusercontent.com/YuniqueUnic/schemaui/main/packaging/scoop/schemaui-cli.json\n```\n\n#### 直接下载\n\n从 `https://github.com/YuniqueUnic/schemaui/releases/latest`\n下载对应平台压缩包，解压 `schemaui` / `schemaui.exe` 后放到 `PATH` 中。\n\n#### winget manifests\n\n使用 `packaging/winget` 中的 versioned manifests 配合\n`winget install --manifest \u003cdir\u003e` 安装，或将其提交到社区仓库。\n\n\u003c!-- AUTO-GENERATED:CLI-INSTALL:END --\u003e\n\n```bash\nschemaui \\\n  --schema ./schema.json \\\n  --config ./defaults.yaml \\\n  -o - \\\n  -o ./config.toml ./config.json\n```\n\n```\n┌────────┐  argh args   ┌──────────────┐ read stdin/files ┌─────────────┐\n│  CLI   ├─────────────▶│ InputSource  ├─────────────────▶│ io::input   │\n└────┬───┘              └──────┬───────┘                  └────┬────────┘\n     │ diagnostics             │ schema/default Value          │\n┌────▼─────────┐        ┌──────▼──────┐                        |\n│Diagnostic    │◀───────┤ FormatHint  │                        │\n│Collector     │        └──────┬──────┘                        │\n└────┬─────────┘               │ pass if clean                 │\n     │                         │                               │\n┌────▼────────┐  build options └────────────┐                  │\n│Output logic ├────────────────────────────▶│ OutputOptions    │\n└────┬────────┘                             └────────────┬─────┘\n     │ SchemaUI::new / with_*                        ┌───▼────────┐\n     └──────────────────────────────────────────────▶│ SchemaUI   │\n                                                     │ (library)  │\n                                                     └────────────┘\n```\n\n- 输入 – `--schema` /\n  `--config`接受文件路径、内联有效载荷或`-`用于标准输入（但不能同时使用两者）。如果只提供配置，CLI\n  通过`schema_from_data_value`推断模式。\n- 诊断 –\n  `DiagnosticCollector`累积格式问题、功能标志不匹配、标准输入冲突和现有输出文件，以执行前的诊断。\n- 输出 –\n  `-o/--output`可重复使用，并且可以混合文件路径与`-`用于标准输出。当未设置目标时，工具直接写到\n  stdout；如果你明确想走回退文件，可以传`--temp-file \u003cPATH\u003e`。扩展名决定格式；拒绝冲突的扩展名。\n- 标志 –\n  `--no-pretty`切换紧凑输出，`--force/--yes`允许覆盖文件，`--title`传递到`SchemaUI::with_title`。\n- Shell completion – `schemaui completion \u003cbash|zsh|fish|nushell\u003e` 会从同一套\n  `argh` 命令树生成补全脚本。PowerShell 暂未暴露，因为上游 `argh_complete`\n  目前没有提供 PowerShell generator。\n\n## 关键依赖项\n\n| 库                                          | 用途                                      |\n| ------------------------------------------- | ----------------------------------------- |\n| `serde`, `serde_json`, `serde_yaml`, `toml` | 解析和序列化模式/配置数据。               |\n| `schemars`                                  | draft-07 模式表示，由 `schema` 模块使用。 |\n| `jsonschema`                                | 表单和覆盖层的运行时验证。                |\n| `ratatui`                                   | 渲染小部件、布局、覆盖层和页脚。          |\n| `crossterm`                                 | 输入路由器消耗的终端事件。                |\n| `indexmap`                                  | 模式遍历的顺序保持映射。                  |\n| `once_cell`                                 | 懒解析快捷键 JSON。                       |\n| `argh`, `argh_complete`, `color-eyre` (CLI) | 参数解析、Shell 补全生成和友好的诊断。    |\n\n## 文档映射\n\n- `README.md` – 概述 + 架构快照（英文版本为事实来源）。\n- `README.ZH.md` – 本中文概览文档（尽量与英文保持同步）。\n- `docs/en/structure_design.md` – 英文版模式/布局/运行时设计，带有流程图。\n- `docs/zh/structure_design.md` – 本中文架构指南，与英文版对应。\n- `docs/en/cli_usage.md` – 英文 CLI 使用手册（输入、输出、管道、示例）。\n- `docs/zh/cli_usage.zh.md` – 中文 CLI 使用手册，与英文版对应。\n\n## 开发\n\n- 定期运行`cargo fmt \u0026\u0026 cargo test`；大多数模块通过`include!`嵌入`tests/`中的文件，以覆盖私有\n  API。\n- 将模块保持在约 600 行代码以下（硬上限\n  800）。一旦行为增长，就拆分帮助程序，以保持 KISS 完整。\n- 优先使用成熟的库（`serde_*`、`schemars`、`jsonschema`、`ratatui`、`crossterm`、`once_cell`），除非更改微不足道，否则不要编写定制代码。\n- 每当管道、快捷键或 CLI 语义演变时，更新`docs/*`，以确保面向用户文档的真实性。\n\n## 参考项目\n\n1. https://github.com/rjsf-team/react-jsonschema-form\n2. https://ui-schema.bemit.codes/examples\n\n## 路线图\n\n- [x] 在运行时解析 JSON Schema 并生成 TUI\n- [x] 在运行时解析 JSON Schema 并生成 Web UI\n- [x] 在编译时解析 JSON Schema，然后生成 TUI 代码，为运行时暴露必要的 API\n- [x] 在编译时解析 JSON Schema，然后生成 Web UI 代码，为运行时暴露必要的 API\n- [ ] 在运行时解析 JSON Schema 并生成交互式 CLI\n- [ ] 在编译时解析 JSON Schema，然后生成交互式 CLI 代码，为运行时暴露必要的 API\n\n## 许可证\n\n根据您的选择，本项目可在以下许可证下授权：\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) 或\n  http://www.apache.org/licenses/LICENSE-2.0 )\n- MIT license ([LICENSE-MIT](LICENSE-MIT) 或 http://opensource.org/licenses/MIT\n  )\n\n### 贡献\n\n欢迎贡献！请随时提交拉取请求。\n\n祝您编程愉快！\n\n## Star 历史\n\n\u003ca href=\"https://www.star-history.com/#YuniqueUnic/schemaui\u0026type=date\u0026legend=top-left\"\u003e\n\u003cpicture\u003e\n  \u003csource\n    media=\"(prefers-color-scheme: dark)\"\n    srcset=\"\n      https://api.star-history.com/svg?repos=YuniqueUnic/schemaui\u0026type=date\u0026legend=top-left\u0026theme=dark\n    \"\n  /\u003e\n  \u003csource\n    media=\"(prefers-color-scheme: light)\"\n    srcset=\"\n      https://api.star-history.com/svg?repos=YuniqueUnic/schemaui\u0026type=date\u0026legend=top-left\n    \"\n  /\u003e\n  \u003cimg\n    alt=\"Star History Chart\"\n    src=\"https://api.star-history.com/svg?repos=YuniqueUnic/schemaui\u0026type=date\u0026legend=top-left\"\n  /\u003e\n\u003c/picture\u003e\n\u003c/a\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuniqueunic%2Fschemaui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyuniqueunic%2Fschemaui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuniqueunic%2Fschemaui/lists"}