使用嵌入式子命令为Coni CLI提供超级加速
Coni语言最大的优势之一是其便携性。我们的设计使得核心解释器和标准库作为单一的静态二进制文件发布。您不需要臃肿的安装过程;只需下载可执行文件即可开始使用。
然而,随着生态系统的不断发展(例如添加了我们的Android构建流水线),我们发现工作流中出现了一个小烦恼。要调用Android APK构建器,您必须通过其绝对路径运行脚本:
coni libs/android/bin/build-apk.coni ./my-app
虽然它能用,但感觉不够原生。我们希望提供一种极致的开发者体验,让开发者可以简单地运行:
coni android build-apk ./my-app
今天,我们非常高兴地宣布,我们通过实现由Go的 embed 文件系统驱动的动态子命令路由 (Dynamic Subcommand Routing),成功填补了这一空白!
它是如何工作的
我们对Go编译器进行了三个关键的架构级修改:
1. 嵌入二进制文件
我们扩展了Go编译器内部的 //go:embed 指令,以自动打包所有模块中的所有 bin/ 目录:
//go:embed libs/*/src libs/*/bin
var embeddedLibs embed.FS
这个简单的改变保证了辅助脚本(如 build-apk.coni)被永久地“烧录”到可执行文件中。
2. 子命令拦截器
我们在CLI参数解析逻辑中引入了一个巧妙的拦截器。现在,如果您运行一个无法识别的命令,比如 coni android build-apk,解析器会拦截它并动态构建一个路径查询:libs/android/bin/build-apk.coni。
它会检查嵌入的文件系统,如果该脚本存在,它会动态地将执行直接重新路由到嵌入的有效载荷!
3. 参数掩码屏蔽
最后一个拼图是保持脚本自身的“错觉”。build-apk.coni 脚本使用 cli/parse-opts 来读取标志(如 -p camera)。如果我们盲目地将参数传递给评估器,脚本会被前面的 android 和 build-apk 令牌搞糊涂。
为了解决这个问题,Go路由器在幕后重写了全局的 os.Args 切片:
os.Args = append([]string{os.Args[0], embeddedPath}, os.Args[3:]...)
从脚本的角度来看,它认为自己是被直接调用的!
结果
其结果就是获得了闪电般快速、无缝的CLI体验。所有的工具和辅助脚本都有机地打包在Coni二进制文件中,通过自然、感觉像原生的子命令即可瞬间访问。
没有额外的下载,没有路径配置。只有纯粹、不受干扰的生产力!