ぶていのログでぶログ

思い出したが吉日

シェルを作っている

シェルスクリプトじゃなくてシェル。 前回の記事で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としてぎっはぶにリリースした。

github.com

…が、ほとんど機能はないです!!! コマンドが実行できる、文字列を正しく扱える(ダブルクォートやシングルクォートが使える)、 $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を使いこなす」がめちゃくちゃ手助けになった。 ネット上に情報はあるものの古かったり、網羅的ではなかったりしたのでこの本はめちゃくちゃありがたかった 🙏 リファレンスとして使いたいので電書でも出していただけると助かります(チラチラ

booth.pm

*1:シェルの名前はshで終わらせたいという謎のこだわりがあるw

*2:ブログのネタとして残していた