ふと思いたって、 gmnlisp を nyagos のコマンドラインに埋め込むアドオンを書いてみました。
gmnlisp_.lua
if not nyagos then print("This is a script for nyagos not lua.exe") os.exit() end share.org_filter_for_gmnlisp = nyagos.filter nyagos.filter = function(cmdline) cmdline = string.gsub(cmdline,'$%b()', function(code) code = string.sub(code,2) code = string.gsub(code,'"','\\"') code = string.format('gmnlisp -e "(format t \\\"~a\\\" %s)"', code) return nyagos.eval(code) end) if share.org_filter_for_gmnlisp then local cmdline_ = share.org_filter_for_gmnlisp(cmdline) if cmdline_ then cmdline = cmdline_ end end return cmdline end
使用方法&使用例
スクリプトの内容を ~/.nyagos
内にペーストするか、lua_f
コマンドで読み込みます。 使う時は最も外側の括弧の前に $
をつけます。
$ lua_f gmnlisp_.lua $ echo $(+ 1 2 (* 3 4)) 15 $ echo $(cons 1 2) (1 . 2)
追記
~/.nyagos
の中から ~/Share/etc/gmnlisp_.lua などというパスでスクリプトをロードする場合は
local gmnlisp_lua = nyagos.pathjoin(nyagos.env.userprofile,"Share\\etc\\gmnlisp_.lua") local fd=io.open(gmnlisp_lua) if fd then fd:close() print("loadfile " .. gmnlisp_lua) assert(loadfile(gmnlisp_lua))() end
などと書いてもよいでしょう。
解説
if not nyagos then
は nyagos ではなく、誤って lua.exe などで実行した時でも、誤動作させずにエラー終了させる文です。nyagos.filter
はコマンドラインフィルターというものです。これが定義されいた場合、nyagos は、コマンドラインの内容をその関数に与え、戻り値の内容をコマンドラインに置換します。このコマンドラインフィルターは多重に定義できるようにするため、関数を設定する時、以前に設定されていた関数を内部から呼ぶようにするのが作法です。- gmnlisp が標準出力へ出す内容は、
nyagos.eval
にて引用できます。 - gmnlisp は ISLisp のサブセットですが、ところどころ CommonLisp の文法が残っています。
(format)
文は ISLisp どおりですが、t
が標準出力を差すと解釈する点は CommonLisp と同じです。フォーマット文字列の~a
は AS IS の a ですね(ありのまま出す)。S式として出す場合は~s
とします。 - Lua の Pattern は簡易正規表現というべきものですが、
%b()
という一つ便利な表現があります。これは括弧などの対応付けをきちんと考慮してマッチングしてくれるというもので、Lisp のように内側に無数に括弧があってもおおよそ期待どおり機能してくれます。
この仕組みを利用すれば、ユーザは任意のコマンドラインフィルターを作成できるでしょう。
動機
マインクラフトのオーバーワールド→ネザーの座標を計算するのに、毎回
$ lua_e "print(100/8.0,200/8.0)"
とかかくの、うざいなー。 せや、Lisp をそのまま引用したら、ええんちゃいか?
$ echo $(/ 100 8.0) $(/ 200 8.0) 12.500000 25.000000
うーん、あんまりかわらんかなー