型安全にbashを書けるAmberを試す
これを触っていく。現在Alpha版
前提
M3Mac で試している
$ uname -m
arm64
$ sw_vers
ProductName: macOS
ProductVersion: 14.2.1
BuildVersion: 23C71
環境構築
公式ドキュメントだと以下のスクリプトで入るらしい
curl -s "https://raw.githubusercontent.com/Ph0enixKM/AmberNative/master/setup/install.sh" | bash
ただ brew にも一応あるっぽく可能な限り brew で管理された状態で入れたいので brew から入れてみる(なにか問題があれば公式Docの方でやり直す)
$ brew install amber
Windows版もちゃんとあるっぽく良い
brew にあるのは Amber Framework のものだった。のでuninstallして公式のインストールをやっていく
$ curl -s "https://raw.githubusercontent.com/Ph0enixKM/AmberNative/master/setup/install.sh" | bash
$ amber --help
Amber's compiler
Version 1.0.0
USAGE: EXAMPLE:
For evaluation:
amber [INPUT] amber foo.ab
amber -e [EXPR] amber -e "\$echo Hello World\$"
For compiling:
amber [INPUT] [OUTPUT] amber foo.ab bar.sh
🤟
VSCode Extension を入れておく
基本を抑える
拡張子は .ab
らしい
でトランスパイルすると bash スクリプトが書き出される(TS -> JS の関係)
let fruits = ["Apple", "Banana", "Orange"]
loop fruit in fruits {
echo "Fruit: {fruit}"
}
を用意して
$ amber ./sample.ab sample.sh
すると
__AMBER_ARRAY_0=("Apple" "Banana" "Orange");
__0_fruits=("${__AMBER_ARRAY_0[@]}");
for fruit in "${__0_fruits[@]}"
do
echo "Fruit: ${fruit}"
done
が書き出される
公式ドキュメントにサポートするデータ型が書かれている
連想配列に相当するデータ構造がないのでそこまで自由度は高くない
型チェックについては CLI でトランスパイルするときに怒ってくれる感じみたい
let fruits = ["Apple", "Banana", "Orange"]
loop fruit in fruits {
let x = fruit * 10
echo "Fruit: {fruit}"
}
文字列への掛け算を書いてトランスパイルさせようとしてみると
$ amber ./sample.ab sample.sh
ERROR
Multiply operation can only multiply numbers
at ./sample.ab:4:19
3| loop fruit in fruits {
4| let x = fruit * 10
5| echo "Fruit: {fruit}"
こんな感じで怒られる。エラーがわかりやすい
VSCode 拡張機能は入れたけど保存してもエラーは表示されていないのでおそらく CLI で型エラーが出るだけっぽい。ここは今後に期待したい
コマンドは $内容$
を使って実行する
$mv ./a ./b$ failed {
echo "It seems that the file.txt does not exist"
}
mv ./a ./b
__AMBER_STATUS=$?;
if [ $__AMBER_STATUS != 0 ]; then
echo "It seems that the file.txt does not exist"
fi
関数を試す
fun add(arg1: Num, arg2: Num): Num {
return arg1 + arg2
}
echo "1 + 2 = {add(1, 2)}"
シグネチャに型がかける
型チェックも同じくCLIでのみエラーが表示される
➜ amber ./sample.ab sample.sh
ERROR
Expected expression
at ./sample.ab:5:20
4|
5| echo "1 + 2 = {add('hello', 2)}"
6|
一応ファイルインポートができるらしい。main block もあるので
fun add(arg1: Num, arg2: Num): Num {
return arg1 + arg2
}
if __name__ == '__main__':
echo "1 + 2 = {add(1, 2)}"
みたいな形で書いて直接呼ばれたときはechoを実行するし、importされたときは関数だけ提供するもできるっぽい
おまじない: set -e
との相性が悪い
$set -euxo pipefail$ failed {
echo "Failed to set"
}
$mv ./test.txt ./test2.txt$ failed {
echo "Failed to move"
}
吐き出されるコードは set -e
を考慮しないのでこれを実行すると
$ amber ./sample.ab
+ __AMBER_STATUS=0
+ '[' 0 '!=' 0 ']'
+ mv ./test.txt ./test2.txt
mv: cannot stat './test.txt': No such file or directory
amber で failed に書いた処理が実行されない
なので、set -e
した上で
unsafe $set -euxo pipefail$
unsafe $mv ./test.txt ./test2.txt$
echo "next line"
みたいに unsafe で書いていくか、amber 的には failed を強制させてはくれるので
$mv ./test.txt ./test2.txt$ failed {
echo "Failed to move"
unsafe $exit 1$
}
echo "next line"
のように明示的に失敗したときの処理で exit してあげる形になりそう。amber 的にはたぶん後者なのかな。
型エラーがリアルタイムに見たい
せめて watch オプションで見れないかなと思ったけど
$ amber --help
Amber's compiler
Version 1.0.0
USAGE: EXAMPLE:
For evaluation:
amber [INPUT] amber foo.ab
amber -e [EXPR] amber -e "\$echo Hello World\$"
For compiling:
amber [INPUT] [OUTPUT] amber foo.ab bar.sh
本当に最低限でそのまま実行する or トランスパイル(+型チェック)が逐次実行でできるだけって感じ。npm-watch とかと組み合わせれば一応できそうだけど設定の手間がかかって大変
使えそうなケース
Altbash、ちょっといいなと思ったんだけど実際 bash スクリプトを置きたいのってインストールなしで実行させたいみたいなモチベーションから来てるのでそうなると使い所に悩むなーという感想だった。
インストール必要なら別に @ts-check
+ zx とか、あるいは bun, deno +zxで良いし。
.ab
ファイルと .sh
ファイルの両方をコミットすれば
- ファイルを編集するなら amber CLI が必要(開発環境)
- 実際に実行するときには sh を実行すれば良い(amber をインストールをしたくない特定の環境)
みたいな形にはできるので、便利スクリプトを書くみたいな用途ならこの形になるのかなー。
あとは OSS とかでシェルスクリプト自体とかインストールスクリプトを配布している場合とかは結構良さそう。.ab
ファイルだけをコミット対象にして一定秩序ある状態でシェルスクリプトを書きつつ、書き出されたファイルのみを配布すれば良い。
という感じで
- シェルスクリプト自体をライブラリやツールとして配布したい場合に一番マッチしそう
- リポジトリの便利スクリプトとして書くシェルスクリプトのために使うのはややアンマッチ感を感じる
- 使うなら
.ab
と.sh
の両方をコミットしておき、編集するには amber CLI が必要だが、実行だけなら依存なしで実行できるよ、みたいな形になりそう - 現状の開発体験とデータ構造的には不便なので、シェルスクリプト自体が成果物にならないなら zx + 任意のランタイム(node.js + ts-check or bun or deno, ...etc)のが better かなという感想
- node 以外のエコシステム下なら良いかもしれない
- 使うなら
まとめ
- Amber はちょうど TypeScript のように
.ab
→.sh
にトランスパイルしてくれるくん- 静的な型チェックが行える
- CLI や VSCode Extension はまだあまり機能が充実しておらず、実行前に静的に検査できる安全性が得られるくらいがメリットで開発体験にはあまり寄与しない(補完や開発中の型エラー表示は期待できない)
- シェルスクリプト自体を配布したい場合には(一定の学習コストはあるものの)結構良さそう。比較的秩序ある書き方ができる
- 便利スクリプトみたいな枠としては、連想配列がなかったりまだ拡張機能だったりが充実していないのもあって、学習コストを抜いても言語やTS(or JS + JSDoc の型チェック) + zx のほうが良いなーという感想だった
結構用途が限られるなという感想だったけど、まだ Alpha なので今後改善するかもしれない