使用 Golang 完整复刻 React Ink 框架,实现声明式终端 UI 开发体验。
本项目基于 React Ink 进行复刻实现,当前对标版本:
| 项目 | 版本 | Commit | 日期 |
|---|---|---|---|
| React Ink | v6.8.0 | be1b1bb6ec65056e2ed60ef3c5ae642704b82d31 |
2025-01 |
| Go-React-Ink | v0.1.0 | - | 2026-04 |
注意: 当 React Ink 发布新版本时,我们会持续同步更新。请关注 CHANGELOG.md 获取最新同步状态。
- 🎨 JSX 语法 - 使用类似 React 的 JSX 语法编写终端 UI
- ⚡ Fiber 架构 - 采用 React Fiber 协调器架构,支持可中断渲染
- 📐 Flexbox 布局 - 纯 Go 实现的 Flexbox 布局引擎
- 🎯 Hooks API - 完整的 React-like Hooks 支持
- 🖥️ 跨平台 - 支持 Windows、macOS、Linux
go get github.com/ayanmw/go-react-ink安装 CLI 编译器:
go install github.com/ayanmw/go-react-ink/cmd/gox@latest// app.gox
package main
import (
"github.com/ayanmw/go-react-ink/pkg/core"
"github.com/ayanmw/go-react-ink/pkg/components"
)
func App() core.Element {
return (
<Box flexDirection="column">
<Text color="green">Hello, World!</Text>
<Text>Count: 42</Text>
</Box>
)
}
func main() {
app := App()
println(app.Render())
}# 编译到标准输出
gox app.gox
# 编译到指定文件 (注意: -o 必须在输入文件之前)
gox -o app.go app.goxgo run app.go容器组件,支持 Flexbox 布局:
<Box
flexDirection="column" // row, column, row-reverse, column-reverse
justifyContent="center" // flex-start, flex-end, center, space-between
alignItems="center" // flex-start, flex-end, center, stretch
padding={1}
margin={1}
>
{/* children */}
</Box>文本组件:
<Text
color="green" // 文本颜色
bold={true} // 粗体
italic={true} // 斜体
underline={true} // 下划线
>
Hello, World!
</Text>空白填充:
<Box flexDirection="row">
<Text>Left</Text>
<Spacer />
<Text>Right</Text>
</Box>换行:
<Text>Hello</Text>
<Newline />
<Text>World</Text>状态管理:
func Counter() core.Element {
count, setCount := hooks.UseState(ctx, 0)
return (
<Box>
<Text>Count: {count}</Text>
</Box>
)
}副作用处理:
hooks.UseEffect(ctx, func() func() {
// 初始化
return func() {
// 清理
}
}, []any{deps})键盘输入处理:
input := input.UseInput(ctx, func(key input.Key) {
if key.Name == "enter" {
// 处理回车
}
})焦点管理:
isFocused, focus := input.UseFocus(ctx)Go-Ink 使用纯 Go 实现的 Flexbox 布局引擎:
root := layout.NewNode()
root.Direction = layout.DirectionColumn
root.Width = 80
root.Height = 24
header := layout.NewNode()
header.Height = 1
content := layout.NewNode()
content.FlexGrow = 1
footer := layout.NewNode()
footer.Height = 1
root.AddChild(header)
root.AddChild(content)
root.AddChild(footer)
root.CalculateLayout(80, 24)# 编译单个文件
gox app.gox -o app.go
# 编译目录
gox ./src
# 监听模式
gox -watch ./src
# 显示帮助
gox -help
# 显示版本
gox -version| 选项 | 说明 |
|---|---|
-o |
输出文件路径 |
-pkg |
组件包名 (默认: ink) |
-watch |
监听文件变化 |
-version |
显示版本 |
-help |
显示帮助 |
┌─────────────────────────────────────────────────────┐
│ Go-Ink 架构 │
├─────────────────────────────────────────────────────┤
│ │
│ 编译时 (.gox → .go) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Scanner │──▶│ Lexer │──▶│ Parser │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │
│ ▼ │
│ ┌─────────┐ ┌─────────┐ │
│ │ CodeGen │◀──│Compiler │ │
│ └─────────┘ └─────────┘ │
│ │
│ 运行时 │
│ ┌─────────────────────────────────────────────┐ │
│ │ Fiber Reconciler │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Scheduler│ │ WorkLoop│ │ Commit │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Layout Engine │ │
│ │ Flexbox • Measure • Position • Align │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Renderer │ │
│ │ Buffer • Diff • ANSI • Terminal │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
Go-Ink 致力于与 React Ink API 保持一致:
| 功能 | React Ink | Go-Ink | 状态 |
|---|---|---|---|
| Box | ✅ | ✅ | 完成 |
| Text | ✅ | ✅ | 完成 |
| Spacer | ✅ | ✅ | 完成 |
| Newline | ✅ | ✅ | 完成 |
| Static | ✅ | ✅ | 完成 |
| Transform | ✅ | ✅ | 完成 |
| useState | ✅ | ✅ | 完成 |
| useEffect | ✅ | ✅ | 完成 |
| useRef | ✅ | ✅ | 完成 |
| useMemo | ✅ | ✅ | 完成 |
| useInput | ✅ | ✅ | 完成 |
| useApp | ✅ | ✅ | 完成 |
| useFocus | ✅ | ✅ | 完成 |
| useCursor | ✅ | ✅ | 完成 |
| useAnimation | ✅ | ✅ | 完成 |
| Flexbox | ✅ | ✅ | 完成 |
查看 examples 目录获取更多示例。
func Counter() core.Element {
count, setCount := hooks.UseState(ctx, 0)
input.UseInput(ctx, func(key input.Key) {
if key.Name == "up" {
setCount(count.(int) + 1)
} else if key.Name == "down" {
setCount(count.(int) - 1)
}
})
return (
<Box flexDirection="column">
<Text>Count: {count}</Text>
<Text dim>Use Up/Down arrows to change</Text>
</Box>
)
}# 运行所有测试
go test ./...
# 运行特定包测试
go test ./pkg/layout/... -v
# 运行覆盖率
go test -cover ./...# 构建所有包
go build ./...
# 构建 CLI
go build -o gox ./cmd/gox欢迎贡献代码!请查看 CONTRIBUTING.md 了解详情。
# 克隆项目
git clone https://github.com/ayanmw/go-react-ink.git
cd go-react-ink
# 安装依赖
go mod download
# 运行测试
go test ./...
# 运行示例
cd examples/hello-world && go run main.goMIT License - 详见 LICENSE 文件