組み込みサブコマンドによる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コンパイラに3つの重要なアーキテクチャ上の変更を加えました:
1. バイナリへの組み込み(Embedding)
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. 引数のマスキング(Masking)
最後のパズルのピースは、スクリプト自身に対する「錯覚」を維持することでした。build-apk.coniスクリプトは、フラグ(-p cameraなど)を読み取るためにcli/parse-optsを使用します。引数を盲目的に評価器(エバリュエーター)に渡すと、先頭のandroidやbuild-apkといったトークンによってスクリプトが混乱してしまいます。
これを解決するために、Goのルーターは舞台裏でグローバルなos.Argsスライスを書き換えます:
os.Args = append([]string{os.Args[0], embeddedPath}, os.Args[3:]...)
スクリプト側から見れば、直接呼び出されたと思い込むわけです!
結果
その結果、超高速でシームレスなCLI体験が実現しました。すべてのツールとヘルパースクリプトはConiバイナリ内に有機的に組み込まれて出荷され、自然でネイティブ感のあるサブコマンドを通じて瞬時にアクセスできます。
追加のダウンロードも、パスの設定も不要です。ただ、純粋で邪魔のない生産性があるのみです!