用 Java 写出像 top/htop 这样的酷炫命令行界面?

jink 开源框架做到了

一个 Java 版的终端 UI 框架,用声明式的方式构建带颜色、边框、动画的命令行应用。兼容 Java 8,纯 Maven 依赖,拿来即用。

Gitee: https://gitee.com/free/jink
GitHub: https://github.com/abel533/jink


它能做什么?

先看效果,比解释更直观。

下面这个类似 top/htop 的系统监控界面,完全用 Java 写出来的:
在这里插入图片描述

  • 实时 CPU 使用率(进度条 + 颜色告警)
  • 系统内存、JVM 堆、线程数
  • 进程列表,支持排序和实时搜索
  • 鼠标滚轮滚动
  • 方向键导航,选中行高亮

还有这个控制台迷宫游戏:
加载中…在这里插入图片描述

  • 随机 Prim 算法生成完美迷宫
  • 方向键移动,绿色轨迹记录路径
  • 自适应终端尺寸

这个框架叫 jink,是 ink(React for CLI)的 Java 版实现。


核心概念:3 行代码理解它

// 就像 React 一样,Box = div,Text = span
Ink.renderOnce(
    Box.of(
        Text.of("Hello, jink!").color(Color.GREEN).bold()
    ).borderStyle(BorderStyle.ROUND)
     .borderColor(Color.BRIGHT_MAGENTA)
     .paddingX(1),
    40, 5
);

输出:

╭──────────────────────────────────────╮
│ Hello, jink!                         │
╰──────────────────────────────────────╯

没有手写 ANSI 转义码,没有坐标计算,就像写 HTML 一样自然。


它是怎么运作的?

整个渲染管道分 4 步:

组件树(Box/Text)
    ↓
虚拟 DOM(ElementNode)
    ↓
Flexbox 布局计算(纯 Java 实现)
    ↓
VirtualScreen → ANSI 字符串 → 终端

Flexbox 布局是纯 Java 实现的,不依赖任何 native 库(ink 用的是 Facebook 的 Yoga C++ 引擎)。支持 flexDirectionjustifyContentalignItemsflexGrowgappaddingmargin,和 CSS Flexbox 一脉相承。


写一个有状态的交互组件

类似 React 的 useState + useEffect

public class Counter extends Component<Counter.State> {

    // 状态定义(用普通类或 record 都行)
    static class State {
        final int count;
        State(int count) { this.count = count; }
    }

    public Counter() { super(new State(0)); }

    @Override
    public void onMount() {
        // 类比 useEffect:组件挂载后启动定时器
        scheduler.scheduleAtFixedRate(() -> {
            setState(new State(getState().count + 1));
        }, 100, 100, TimeUnit.MILLISECONDS);
    }

    @Override
    public void onUnmount() {
        scheduler.shutdownNow();
    }

    @Override
    public Renderable render() {
        return Text.of(getState().count + " tests passed")
                   .color(Color.GREEN);
    }
}

setState() 触发重渲染,框架自动做差量更新,只刷新变化的行——和 React 的虚拟 DOM diff 思路一样。


键盘交互

重写 onInput 方法即可:

@Override
public void onInput(String input, Key key) {
    if (key.upArrow()) {
        setState(new State(getState().selected - 1));
    } else if (key.downArrow()) {
        setState(new State(getState().selected + 1));
    } else if ("q".equals(input)) {
        System.exit(0);
    }
}

Key 对象封装了方向键、功能键、Ctrl 组合键、PageUp/Down 等常用按键的判断方法,不用再手动解析 ANSI 转义序列。


样式系统:丰富但不繁琐

Text.of("粗体红色").bold().color(Color.RED)
Text.of("RGB 真彩色").color(Color.rgb(255, 165, 0))
Text.of("Hex 颜色").color(Color.hex("FF8800"))
Text.of("反色(Inverse)").inverse()
Text.of("暗淡").dimmed()

// 嵌套文本样式
Text.of(
    Text.of("前缀 ").color(Color.CYAN),
    Text.of("高亮").color(Color.RED).bold(),
    Text.of(" 后缀").dimmed()
)

支持 16 色、256 色、RGB 真彩色,中日韩字符自动占 2 列宽度。

9 种边框样式:

┌──────┐  ╔══════╗  ╭─────╮  ┏━━━━┓
│single│  ║double║  │round│  ┃bold┃
└──────┘  ╚══════╝  ╰─────╯  ┗━━━━┛

╓────────────╖  ╒════════════╕  +-------+  ↘↓↓↓↓↓↙
║singleDouble║  │doubleSingle│  |classic|  →arrow←
╙────────────╜  ╘════════════╛  +-------+  ↗↑↑↑↑↑↖

Flexbox 布局:写起来就像 CSS

// 水平等分面板
Box.of(
    Box.of(Text.of("左侧"))
        .flexGrow(1)
        .borderStyle(BorderStyle.SINGLE),
    Box.of(Text.of("右侧"))
        .flexGrow(1)
        .borderStyle(BorderStyle.SINGLE)
).width(60).height(5);

// 垂直布局 + 弹性填充
Box.of(
    Text.of("标题").bold(),
    Spacer.create(),           // 自动撑开中间空白
    Text.of("底部提示").dimmed()
).flexDirection(FlexDirection.COLUMN).height(10);

// 内容对齐
Box.of(Text.of("X"), Text.of("Y"))
   .justifyContent(JustifyContent.SPACE_BETWEEN)
   .width(20);
// 输出:[X                  Y]

与 ink 的 API 对照

功能ink (TypeScript)jink (Java)
声明式 UIJSXBuilder API
状态管理useStateComponent.setState()
副作用useEffectonMount / onUnmount
输入处理useInputonInput(String, Key)
FlexboxYoga (C++)纯 Java 实现
颜色chalk内置 Color
边框boxen9 种 BorderStyle
最低版本Node.js 18+Java 8+

开箱即用的 Demo 库

项目自带 20+ 个 Demo,覆盖各种使用场景:

Demo说明
Counter自动递增计数器(定时器 + setState)
TopDemo类 top/htop 系统监控 TUI
MazeDemo控制台迷宫游戏(Prim 算法)
CopilotDemoGitHub Copilot CLI 界面复刻
FeatureShowcase4 个标签页综合展示
SelectInputDemo方向键列表选择
ChatDemo简单聊天输入框
JestDemo并发测试运行器模拟

一行命令运行任意 Demo:

.\scripts\run.ps1          # 交互式菜单(Windows)
./scripts/run.sh           # 交互式菜单(Linux/macOS)

快速上手

1. 添加 Maven 依赖

<dependency>
    <groupId>io.mybatis.jink</groupId>
    <artifactId>jink</artifactId>
    <version>0.5.0</version>
</dependency>

2. 写第一个组件

public class Hello {
    public static void main(String[] args) {
        Ink.renderOnce(
            Box.of(
                Text.of("Hello, World!")
                    .color(Color.GREEN).bold()
            ).borderStyle(BorderStyle.ROUND).paddingX(1),
            40, 3
        );
    }
}

3. 或者用交互式渲染

Ink.render(new MyComponent()).waitUntilExit();

项目信息

  • GitHubabel533/jink
  • License:Apache 2.0
  • Java 版本:Java 8+
  • 测试:146 个单元测试
  • 当前版本:0.5.0(稳定发布)

如果你正在用 Java 构建 CLI 工具、DevOps 脚本、监控面板,或者只是想让命令行输出酷起来,不妨试试 jink。

项目还在持续迭代,欢迎提 Issue 和 PR。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

isea533

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值