alias-exeについて
Rustで作成したシングルバイナリのCUIコマンドで、Windowsにalias相当の機能を提供します。
こちらが基本操作
# 1 hello aliasを作成
> alias edit hello
# 2. 開いたエディタで内容を編集
echo hello $(echo $1)
# 3. 実行
> hello world
hello world
GitHubは wordijp/alias-exe
マニュアルとして README.md と、詳しい仕様についてのドキュメントサイトを用意しています。
バイナリを用意していますが、 scoop.sh 対応ですのでこちらの方がインストールや更新追従も手軽です、aliasはlist
ディレクトリに作成されますが、こちらのPATHも自動で設定してくれます。
> scoop bucket add wordijp https://github.com/wordijp/scoop-bucket
> scoop install wordijp/alias-exe
機能としては、aliasの登録/更新/削除などの管理機能、実行時に引数処理用の変数($0
、$1
、"$@"
、etc)、コマンドのネスト($( ... )
)の基本に加え、Bash functionのように複数コマンドの実行や、cmd/Bashから欲しい機能を盛り込み、グルーコードとしてmrubyに対応したりなどの結果、魔改造めいたものとなりました。
mrubyは単体では機能が乏しかったため、欲しい機能をRust側で実装して対応しています1。
作った経緯
Windowsでalias相当の事をしようとしたらdoskey
コマンドでマクロを登録し、癖が強い2batファイルで頑張るくらいしかありませんでした。
ターミナル環境ではパスや実行環境の差異に悩まされるのでいまいち踏み切れず、そしてつい先月の環境変数のPATHが長すぎてWSL2が突然動かなくなるという一波乱が引き金となり、PATHを短くする為にもalias-exeの作成に踏み切りました。
サンプルコード
aliasとしては冒頭の使い方で十分なのですが、紹介用に他の機能を網羅したコードを記載します、ドキュメントの機能一覧コードそのままですが、以下のような事が出来ます。
まずoverview aliasを作成し
> alias edit overview
内容の編集、この時にVimかnotepadエディタが開きます。
# overview.txt
# command
echo command
# nested command
echo nested $(echo command)
# arguments
echo argc=$# args="$@"
# built-in commands
@set ENV=builtin_set_environment
echo %ENV%
CD
@pushd ..
CD
@popd
CD
# mruby as glue code
```ruby
# this is mruby comment
puts "mruby code"
def add(a, b)
a + b
end
``` DUMMY
# ↑Qiitaのスタイル崩れ防止のDUMMY、取り除いてください
# nested mruby
echo 2 + 3 = <%= add(2, 3) %>
実行
> overview hoge foo "hello world"
command
nested command
argc=3 args=hoge foo "hello world"
builtin_set_environment
C:\path\to
C:\path
C:\path\to
mruby code
2 + 3 = 5
FizzBuzzを実装してみる
これだけだとなんなので、機能紹介も兼ねて色んな方法でFizzBuzzを実装してみようかと思います。
どれも> fizzbuzz 1 100
で実行し、同じ結果になります。
mrubyでオーソドックスにFizzBuzz
# fizzbuzz.txt
```ruby
for i in $1..$2 do
if i % 15 == 0
puts 'FizzBuzz'
elsif i % 3 == 0
puts 'Fizz'
elsif i % 5 == 0
puts 'Buzz'
else
puts i
end
end
``` DUMMY
内部用aliasはprivateスコープの意味合いとして _ 始まりにしています。
複数aliasを組み合わせてFizzBuzz
# _rng.txt
```ruby
for i in $1..$2 do
puts i
end
``` DUMMY
# _fizzbuzz.txt
```ruby
while s = STDIN.gets
n = s.to_i
if n > 0 && n % 15 == 0
puts "FizzBuzz"
else
puts s.chomp
end
end
``` DUMMY
# _fizz.txt
```ruby
while s = STDIN.gets
n = s.to_i
if n > 0 && n % 3 == 0
puts "Fizz"
else
puts s.chomp
end
end
``` DUMMY
# _buzz.txt
```ruby
while s = STDIN.gets
n = s.to_i
if n > 0 && n % 5 == 0
puts "Buzz"
else
puts s.chomp
end
end
``` DUMMY
# fizzbuzz.txt
_rng $1 $2 | _fizzbuzz | _fizz | _buzz
良く分からないコードになった
ネストしまくったFizzBuzz
# _args.txt
```ruby
def add(a, b)
a + b
end
def ary(a, b)
(a..b).to_a
end
``` DUMMY
# 1から100までのruby配列を作成
```ruby
a = [].from_cmd %q( <%= ($(echo $1)..$(echo <%= add($#, 3) %>0)).to_a.to_cmd %> <%= ary(51,$2).to_cmd %> )
``` DUMMY
echo <%= a.to_cmd %>
# _fizzbuzz_args.txt
```ruby
Buzz = 'Buzz'
``` DUMMY
```ruby
for x in ARGV
x = x.to_i
s = ((x%3==0)?'$(echo Fizz)':'')+((x%5==0)?<%= Bu$(echo zz)%>:'')
puts (s!="") ? s : x
end
``` DUMMY
# fizzbuzz.txt
_fizzbuzz_args $(_args $1 $2)
おわりに
alias作成先へのPATHは先頭に追加して優先度を上げた方が使いやすいかとは思いますが、既存コマンドとの名前被りの時に思いもよらないハマりを引き起こしてしまうかもしれません、僕はそれを回避するためにalias名を]hoge
と ] 始まりの名前にしています、ほんとは @ 始まりにしたかったのですが実行時に無視されてしまう為、他の押しやすく被らない接頭語を探した結果 ] 始まりとなりました。