Loading [Contrib]/a11y/accessibility-menu.js

Shellyを使ってCommon LispファイルをExecutableにする

コマンドラインからCommon Lispの関数を実行できる Shellyを使ってCommon Lispファイルを実行形式にしてみました。Shellyは

$ shly + 1 2
3

みたいに関数を実行できます。

モチベーションとしては、 Shellyの作者深町さんがTwitterで「Shellyでloadを使うとスクリプトみたいに実行できる」と発言していたのがきっかけで、Shebangを無視できればUNIX系ではExecutableにできるのでは?と思いついてやってみました。

readしてevalして…とか考えてましたが、loadstreamを渡せるようなので案外簡単にできました。

(in-package :shelly)
(export (defvar *argv* nil))
(in-package :cl-user)
(defun script (file argv)
"Execute a file as script ignoring shebang"
(setf shelly:*argv* argv)
(let* ((in (open file :if-does-not-exist :error))
(first-char (read-char in))
(second-char (read-char in)))
(cond
((and (char= first-char #\#) (char= second-char #\!))
(read-line in))
(t (unread-char second-char in)
(unread-char first-char in)))
(load in)
(values)))
view raw script.lisp hosted with ❤ by GitHub

コマンドライン引数を受け取るために*argv*という変数を用意してます。

こんなことを~/.shelly/Shellyfileに書いておき、Lispの初期化ファイルに

#+shelly
(load "~/.shelly/Shellyfile")

と書いてます。この~/.shelly/ShellyfileにはShelly向けの関数を溜め込んでいく予定です。

あとは

1
2
3
4
5
#!shly script

(defun hello ()
 (format t "Hello ~a~%" (first shelly:*argv*)))
(hello)

foo.lispに書き込めば

$ chmod u+x foo.lisp
$./foo.lisp κeen
Hello κeen

と実行できます。勿論、

$shly script foo.lisp κeen

としても同じです。一部の処理系ではこのようなことが出来ますが、コマンドライン引数の渡し方とかも処理系依存なのでポータブルに書くなら一つ試してみてはいかがでしょうか。

Written by κeen