シェルスクリプトじゃなくてシェル。 前回の記事でGNU bison/flexのことを書いたのはこれの副産物だったのであった。 なぜ作っているかというと面白そうだからという理由以外ないのだけど、きっかけはxonshというPython-powerdなシェルがあることを知って「PythonがあるならRubyもほしい」と思ったのであった。
reddish-shell
シェルの名前は reddish-shell
としている。
reddishは赤みを帯びたという意味らしく、Rubyも赤っぽいし、shで終わっているし*1でこれにした。
もしかしたら、そのうち変えるかもしれないし変えないかもしれない。
コンセプト
ただ普通にシェルを実装しても面白くないし実用性もないので、ある程度コンセプトを考えている。 まず、大前提として前述したとおりRuby-powerdにしたい。 Rubyの構文が使えるようにしたいと思っている。
そして、bashとの互換をある程度保ちたい。
これは、私がbashに慣れているという理由が大きいのだけど、例えば環境変数にアクセスするのに ENV['PATH']
とかするのは流石にめんどくさいし、 echo PATH
としたときにPATHが文字列なのか変数なのかわからないのである程度仕方ない部分もあるかもしれない。
ただ、前述のRubyの構文とのバッティングがあるので、どのように調整するかは悩んでいる…ので作りながら調整する。
最後に、簡単で便利にする。 fish-shellを普段使っているので、私の中のベースがそれになっているので便利にしたいなぁという感じ。
実装した機能
reddish-0.1.0としてぎっはぶにリリースした。
…が、ほとんど機能はないです!!!
コマンドが実行できる、文字列を正しく扱える(ダブルクォートやシングルクォートが使える)、 $ENV
で環境変数に置換できる、&&
や ||
が使える程度。
reddish> uname -r 5.4.0-31-generic reddish> echo hoge hoge reddish> echo $TERM xterm-256color reddish> echo cmd1 && echo cmd2 cmd1 cmd2 reddish> echo cmd1 && false || echo cmd3 cmd1 cmd3 reddish> false || echo cmd2 cmd2
Syntax Errorを起こすとプロセスが終了するというおまけつき*2。
❯ ./reddish reddish> echo "hoge Reddish::ParserError: unterminated string
そんな感じで、普段遣いとしては機能不足すぎるけど、新しい機能が実装できるとめちゃくちゃ楽しいので継続して開発していきたい。 なお、バイナリをアップロードしてあるけど、私の手元環境(Ubuntu 20.04)以外では全く動作確認していないので、動かなくてもあしからず…。
工夫したところ
工夫したところといっても、まだ作り始めでほとんどないけど、あえてあげるとするとRubyではなくてmrubyを使っている。 ワンバイナリで提供したほうがポータビルティが高いし、あわよくば組み込み環境でもつかえるのでは?と妄想している。 というか、今の所のRuby要素はmrubyくらいしかない…。
基本的にはRubyで書くようにしていて、パーサー部分だけCで書いている。 最初は字句解析もCで書いていたが、Cで文字列処理するのがとてもつらい気持ちになったのとbisonのアクションをよしなにCで処理するのがめちゃつらだったのでRubyで実装している…。 ここまで来たらパーサーもRubyで書けばいいのでは?っと思われるかもしれないが、そこに注力したいわけではないので「使えるものはなんでも使え」という某大団長理論で作っている。 Rubyでかけるのはとても楽なのだが、実行速度とかメモリの使用量とか大丈夫かなという心配はあるが、まぁそこまで最適化する必要もなかろうということでいまは気にせずに作っている。
参考にした本
mrubyを使うにあたり「入門mruby Cからmruby APIを使いこなす」がめちゃくちゃ手助けになった。 ネット上に情報はあるものの古かったり、網羅的ではなかったりしたのでこの本はめちゃくちゃありがたかった 🙏 リファレンスとして使いたいので電書でも出していただけると助かります(チラチラ