標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

Windows ユーザは cmd.exe で生きるべきかもしれないが、俺は nyagos でやってきた

たぶん、自分が nyagos を積極的にアピールするのはこれが最後だろう。今後、多少のバージョンアップをするとは思うが、基本、保守にだけ徹してゆくことになると思う。だから、せいぜい暇なときにでも読んでもらえたら幸いだ。

nyagos は cmd.exe 同様、Windows の秩序の中で動いているコマンドラインシェルである

  • Cygwin や msys、WSL と違い、Windowsファイルシステムの普通のパス表現をそのまま使用する。ドライブレター、UNCパス、どんとこい
  • cmd.exe のバッチファイルをそのまま利用することができる。環境変数設定バッチもそのまま利用でき、環境変数変更結果をちゃんと取り込むことができる

nyagos は他の何かに依存しない

  • Go言語による static-link された実行ファイルなので、外部にランタイムは DLL を必要としない
    • かつては lua53.dll を必要としていたが、今は Lua もGo製ライブラリを使用している
  • USBメモリに入れて持ち歩くこともできれば、scoop や Chocolatey でインストールできる
  • レジストリを汚すようなことも行わない

nyagos は Unicodeで動いている

  • GitHub の☆をくれてる人の半分とまではいかないが、かなり外国の人がいることが多国語対応がほぼ完全にできている裏付けになっている
  • かつて、フランス語のキーボードに対応できていないというissue が起案されて、対応したこともある(Linux 対応の際、キーボード入力の方式を改めた後、さらにもう一回 issue 立てられてしまうこともあった)
  • 故に %USERPROFILE%\.nyagos は UTF8 で書かねばならぬ。

環境変数のオーバーフロー防止にも対応できる

%USERPROFILE%\.nyagos にて、nyagos の中でだけ有効な %PATH% の追加ができる。

nyagos.envadd("PATH",
    "C:\\go\\bin",
    "C:\\TDM-GCC-64\\bin",
    "%ProgramFiles%\\Git\\bin")

nyagos.envadd は重複しないよう環境変数ディレクトリを追加する Lua 関数だ。 もちろん、ここまで高機能なことをせず、単純な環境変数操作も

nyagos.env.path = nyagos.env.path .. ";C:\\go\\bin"

と風に書ける。一方、nyagos の中で使いそうもないディレクトリを %PATH% から除くこともできる。

nyagos.envdel("PATH",
    "Oracle",
    "Lenovo",
    "Skype",
    "chocolatey",
    "TypeScript",
    "WindowsApps")

nyagos.envdel は環境変数の中から、指定したキーワードを含むディレクトリを除く関数だ。正確にディレクトリ名が一致する必要はない。このように環境変数に許された文字数を節約するのも簡単だ。

起動時に外部の環境変数設定バッチを呼び出すのも、これだけだ。

nyagos.exec("foo.bat")

内部的には

cmd.exe /s /c ""foo.bat" & set > テンポラリファイル1 & cd > テンポラリファイル2"

と大層なことをやっているが、ユーザはそういう水面下の動きに気づくことはないだろう。

エイリアス

オーソドックスに

nyagos.alias.ps1="powershell -ExecutionPolicy RemoteSigned -file"

といったシンプルな定義もできるし(無論、$* とか $1 のマクロも使える)

nyagos.alias["print"] = function(args)
    for _,s in ipairs(args) do
        assert(loadstring("print("..s..")"))()
    end
end

といった Lua 関数を使った定義もできる

他の追随を許さない補完

  • bash に準じた補完。1回目のタブキーで可能な範囲でも文字列の補完、2回目で候補の一覧表示
  • デフォルトでは、カーソル位置によって、コマンド名補完・ファイル名補完を行う
  • C:\Programなどのように空白を含むパスを補完すると、"C:\Program Files\ と先頭に二重引用符がちゃんと付加される
  • cdpushd ならディレクトリ名だけを補完、which の場合は引数であってもコマンド名補完など、コマンドに応じた補完を行う
  • ユーザが補完をカスタマイズすることも可能。.nyagosuse "git.lua" を追加すると git branch の後でブランチ名の補完、git checkout の後のコミットハッシュ・ブランチ名の補完、git add の後の更新ファイル名だけの補完などが拡張される。このロジックは Lua で実装されている。

コードの依存性管理の徹底によって実現した極めて高い移植性

  • 誰も使わないが、Linux バイナリも存在する
  • かつて lua53.dll ベースで行っていた Lua 言語サポートも、GopherLua ベースに切り替えることにも成功した

そして

  • Emacsキーバインド
  • キーアサインの変更(例:nyagos.key.c_u = "KILL_WHOLE_LINE")
  • カーソルを動かしてのファイル名の選択入力(Ctrl-O)なんてこともできる。HJKL でカーソルが動くのだ

f:id:zetamatta:20200720232255p:plain


結局、ただの多機能自慢になってしまった。本当はもっと本質的なことを理路整然と書ければと思っていたのだが。

nyagos の前身であった nyaos の 0.1 がリリースされたのは今から22年ほど前。当時は OS/2 の cmd.exe に一行エディターをラッピングした簡単な C++ シェルだった。その後、DOS/Windows 上で実装しなおし(2.x)、Lua を内蔵し(3.x)、Go言語で再び実装し直した(4.x)。fork できないのを goroutine でエミュレートし、内蔵コマンド・外部コマンドの区別なくパラレルで動作する本当のシェルを作り上げることができた。やれることは、もうみんなやった。DOS/Windows/OS2/Linux いろいろ対応した。非才な人間にしては本当に上出来だ。

nyagos は多くの人には受け入れらることはなかったが、ごく少数の方々ではあるが貴重な issue やプルリクエストなど支援いただけた。おかげで自分はいっぱしのプログラマ気分を味わうことができ、とても幸せな日々を過ごせたと思う。ユーザ各位には本当に感謝したい。