2012年9月1日

Emacs 24 の Emacs Lisp スクリプトで shebang を書いても Lexical Scope を有効にする方法がわからない(解決)

概要

Emacs Lisp は Emacs 24 から Lexical Scope が利用できるので、コマンドラインスクリプトが書き易くなった。
Emacs 使いはこの際、スクリプトを Emacs Lisp で書けば良いのぢゃないかと思った。
でも、shebang を書いて実行すると Lexical Scopeが有効にならないみたい。

普通にスクリプトとして実行

Emacs では Emacs Lisp をスクリプトとして実行できる。

;; -*- coding: utf-8; lexical-binding: t -*-
(message "hello world")
以下で実行する。
emacs --script sample.el

shebangを利用できるか

「emacs --script」で起動するのでなく普通にスクリプトとして起動したい。

chmod 755 sample.el
./sample.el

でも、「shebang」(シバン or シェバン)(!#) を書くと Lexical Scope が有効にならない。

#!/usr/bin/env emacs --script # -*- coding: utf-8; lexical-binding: t -*-
;; これは正常に動作しない。 2番目の # 以降が無視される。
;; 2番目の # を先頭にすると shebang が無視される。
;; 2番目の # を ;;; とかに変更すると文法エラーになる。

以下のように書いても Lexical Scope が有効にならない。

:;exec emacs -batch -l "$0" "$@" --no-site-file -q  # -*- coding: utf-8; lexical-binding: t -*-

知りたいこと

ソースまで調べていないので、shebangの利用をしながら Lexical Scope が有効にできるか不明。
「emacs --script」で起動すれば良いので、困るわけではないが、なんか方法があるなら知りたい。

補足:Emacs Lisp でコマンドラインスクリプトを作成する

Emacs Lisp でコマンドラインスクリプトを作成したい方は、「スクリプト言語としてのEmacs Lisp」を参照するとわかりやすい。

追記

2012年09月01日深夜追記

cvmat@twitterからの指摘。
GNU Emacs Lisp Reference Manual 11.9.4 Using Lexical Binding」に「Note that unlike other such variables, this one must be set in the first line of a file. 」の記述があり、1行目にしか書けない。
1行目に書くパターンでも shebang を書いた状態で認識させる方法が無いみたい。
現在の仕様では無理みたい。

2012年09月01日深夜さらに追記

cvmat@twitterから「exec」で「/dev/stdin」を使う方法を教わりましたので以下みたいにしたら動作しました。
安全かどうかとか、これが綺麗な書き方かとかはまだ詳細に考えていませんが動かす方法があることはわかりました。ありがとうございます。

:;exec emacs --script /dev/stdin <<EOF
;; -*- coding: utf-8; lexical-binding: t -*-
(setq x 1)
(defvar y 2)

(defun one ()
  (message "one: x = %d, y = %d" x y)  ;; x = 1, y = 5
  (+ x y))

(defun two ()
  (message "two: x = %d, y = %d" x y)  ;; x = 1, y = 2
  (let ((x 3)
        (y 5))
    (one)))

(message "%d" (two))  ;; 6 が表示される(x = 1, y = 5の加算)
;:EOF
blog comments powered by Disqus