← 返回首页

Command Manager

一个用 JavaFX 写的命令行管理与插件化运行工具 —— 把常用命令变成带图形参数面板的条目,底层挂一个常驻 shell 会话。

语言Java 21 界面JavaFX 21 构建Gradle 分发单文件 jar(约 11 MB) 许可GNU General Public License v3.0

它解决什么

命令行很强,但参数难记、手册要翻、同一串命令得反复敲。Command Manager 把这些收敛成「条目」:每个条目就是一个插件,用一份 manifest.json 声明它需要哪些参数(文本 / 数字 / 下拉 / 文件 / 开关),运行时按声明动态渲染出表单,点执行就把拼好的命令送进底下的 shell。

既保留手敲命令的自由,又不用再记参数 —— 这是它和普通终端模拟器的区别。

核心特性

插件化架构

一份 manifest.json 就是一个插件,丢进 cmmgr/plugins/ 即可被扫描到。声明 id、名称、可执行文件和参数列表,不用改一行程序代码。

参数面板自动生成

支持 text / number / select / file / checkbox / flag 六种控件,按类型渲染对应输入组件。必填项留空会在执行前被拦下并列出缺哪个,而不是静默传个空值。

常驻 shell 会话

不是 cmd /c 那种跑完就退。命令写进 shell 的 stdin、输出从 stdout 读回,cd 和环境变量跨命令保留。

单文件分发

./gradlew fatJar 打出约 11 MB 的可执行 jar,JavaFX 原生库和 Jackson 一并打进去,java -jar 直接能跑,不需要配 --module-path。

编码自适应

PowerShell 7 走 UTF-8、Windows PowerShell 5.1 走 GBK。默认 shell 是 pwsh 7 时自动选 UTF-8;编码和 shell 对不上会明确提醒,而不是让你对着乱码猜。

配置持久化与迁移

设置存在 cmmgr/config/config.json,损坏或缺失时用默认值启动。旧布局(plugins/ 与 .command-manager/)在启动时自动搬迁,逐个文件移动、失败不丢数据。

插件长什么样

以自带的 ffmpeg 转码插件为例,整份声明如下:

{
  "id": "ffmpeg.transcode",
  "version": "0.1.0",
  "name": "FFmpeg 转码",
  "description": "用 ffmpeg 把视频转码 / 缩放。",
  "type": "shell",
  "executable": "powershell.exe -ExecutionPolicy Bypass -NoProfile -File \"cmmgr/plugins/ffmpeg/run.ps1\"",
  "isExecutable": true,
  "parameters": [
    { "name": "input",      "label": "输入文件", "type": "file",   "required": true },
    { "name": "output",     "label": "输出文件", "type": "text",   "required": true },
    { "name": "resolution", "label": "分辨率",   "type": "select", "required": false,
      "options": ["original", "1920:-1", "1280:-1", "854:-1", "640:-1"] },
    { "name": "quality",    "label": "画质",     "type": "select", "required": false,
      "options": ["high", "medium", "low", "tiny"] }
  ]
}

程序按 parameters 渲染出表单,执行时拼成命令行写进 shell。含空格的值会自动加引号。

界面结构

主页

快捷入口。

终端

左侧插件列表、右侧参数面板、底部输出区与命令输入框。插件执行和手敲命令走同一条 shell。

插件

已加载插件列表,可移除条目、打开插件目录。

设置

shell 路径与启动参数、工作目录、输出编码、终端字号、回滚行数上限。

页面切换带方向动画:每个页面有一个数字 id,比较 id 大小决定滑入方向,缓动为 ease-out。

项目结构

command-manager/
├── build.gradle.kts              构建 + Shadow fat jar
├── cmmgr/                        运行期数据
│   ├── config/config.json        设置
│   └── plugins/ffmpeg/           插件(含 run.ps1 包装脚本)
└── src/
    ├── main/java/org/passerbya/
    │   ├── Main.java             入口
    │   ├── core/                 CommandManager · PluginManager · AppSettings · AppPaths
    │   ├── tools/                manifest 数据模型与加载器
    │   ├── debug/                DebugLogger
    │   └── ui/                   MainGUI · PageId · pages/ · components/
    └── test/java/                31 个单元测试

几个踩过的坑

JavaFX 的 CSS 变量会静默失效

把 CSS 变量赋给 -fx-border-radius 时,JavaFX 会先把值转成 Double 再强转 Size,抛 ClassCastException —— 圆角悄悄不生效,只刷一屏警告。最后改成写字面值。

同一仓库里 BOM 规则是相反的

Java 源文件带 BOM 会直接编译失败(非法字符: '\ufeff');而 PowerShell 5.1 读无 BOM 的 .ps1 会按 GBK 解码,把中文读乱、连带破坏语法解析。所以 .java 一律无 BOM,.ps1 一律有。

命令拼装模型没法在值前面插 flag

拼装方式是「executable + 按顺序的值」。像 ffmpeg 这种需要 -i / -vf / -crf 交错参数的,得套一层包装脚本,把 flag 编排收进脚本里,manifest 只声明「值」。

fat jar 里的 JavaFX 能直接跑

原生库(glass.dll、prism_d3d.dll 等)本就在 javafx-graphics-*-win.jar 内部,运行时 JavaFX 自己解压到临时目录再加载。所以 fat jar 不需要额外处理原生库。

截图

终端页 —— 左侧插件列表,右侧参数面板
设置页 —— shell 路径与编码
插件执行输出

(截图待补 —— 把图片放进 assets/ 后替换上面三个占位块即可。)

构建与运行

  1. 准备 JDK 21
  2. 克隆仓库并进入目录
  3. 运行下面任意一条命令
./gradlew run       # 直接运行
./gradlew test      # 单元测试(31 个)
./gradlew fatJar    # 打包成单文件可执行 jar

java -jar build/libs/command-manager-1.0-SNAPSHOT-all.jar

程序的工作目录就是启动时的当前目录,运行期数据都收在它下面的 cmmgr/ 里。