elispのshebang

# shebang
これを elisp ファイルの先頭に記述する。

```
:;exec emacs -Q --batch -l "$0" -- "$@"
```

# サンプルプログラム1 (simple.el)
```elisp:simple.el
:;exec emacs -Q --batch -l "$0" -- "$@"
(princ "hello\n")
```

```shell-session:実行結果
$ ./simple.el
hello
```

なお、この場合、引数を使っていないので、`-- "$@"` は省略可能。

# サンプルプログラム2 (shebang.el)

```elisp:shebang.el
:;exec emacs -Q --batch -l "$0" -- "$@"

(prin1 command-line-args)      (princ "\n")
(prin1 command-line-args-left) (princ "\n")

(while (setq line (ignore-errors (read-string ""))) (princ (concat line "\n")))
```

```plaintext:data.txt
1
2

4
```

```shell-session:実行結果
$ cat data.txt | ./shebang.el hello 'w o r l d'
("emacs" "-l" "./shebang.el" "--" "hello" "w o r l d")
("--" "hello" "w o r l d")
1
2

4
```

# 解説
### シェルの動作

```
$ ./shbang.el
```

によりシェルが起動し、シェルは shebang.el の1行目を読み込む:

```
:;exec emacs -Q --batch -l "$0" -- "$@"
```

これはシェルにより、`;`  で区切られた2つのコマンドと解釈される。すなわち:

```
:
exec emacs -Q --batch -l "$0" -- "$@"
```

ここで、`:` (=NOP) は何もしないコマンドである。

emacs のオプション `-Q` は site startup file 等の読み込みと X (GUI) 関連の処理をスキップする。

```plaintext:man_emacs
-Q, --quick
    Similar to "-q --no-site-file --no-splash".  Also, avoid processing X resource
-q, --no-init-file
    Do not load an init file.
```

オプション `--batch -l` は指定した elisp ファイルを実行する。

```plaintext:man_emacs
--batch
    Edit  in  batch mode.  The editor will send messages to stderr.  You must use -l and -f options to specify files to execute and functions to call.
-l file, --load file
    Load the lisp code in the file file.
-f function, --funcall function
    Execute the lisp function function.

```

ここでは elisp ファイルとして `"$0"` (=`shebang.el`) を指定している。
つまり、ここで emacs が起動し、`shebang.el` を実行する。

また、`exec emacs` としているため、シェルのプロセスが emacs に置き換わる。
つまり、emacs の処理が終わるとこのプロセスは終了するため、これより後のコードをシェルが読むことはない。
そのため、シェルはもはや `(prin1 ...)` 以降の行を一切読まないため、シェルが elisp コードでエラーを吐くこともない。

emacs のオプション `--` は、それ以降の引数をオプションとみなさないオプションである。
"$@" で、シェルに渡された引数をそのまま emacs に渡している。

### emacs の動作

ここからは呼び出された emacs の処理に話を進める。
emacs は `shebang.el` の1行目を読み込む:

```
:;exec emacs -Q --batch -l "$0" -- "$@"
```

`;` 以降はコメントと見なされるため、この行は唯一のシンボル `:` と解釈される。
`:` は定数 `:` として評価される。
つまり、この行では何も行われない。
そして emacs は `(prin1 ...)` 以降の処理を続行する。
おわり。

#### : の解説

`:` については深く考える必要はないが、一応解説をすると、
名前が `:` から始まるシンボルはそれ自身という定数として評価される。
 
[Symbol Type](https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Type.html)

> A symbol whose name starts with a colon (‘:’) is called a keyword symbol. These symbols automatically act as constants, and are normally used only by comparing an unknown symbol with a few specific alternatives. See Constant Variables.

nil が nil、t が t  という定数として評価されるのと同じで、:aaa は :aaa という定数として評価される。

[Variables that Never Change](https://www.gnu.org/software/emacs/manual/html_node/elisp/Constant-Variables.html#Constant-Variables)
> In Emacs Lisp, certain symbols normally evaluate to themselves. These include nil and t, as well as any symbol whose name starts with ‘:’ (these are called keywords).

`:` の使い所は、関数定義時に `&key` とともに利用することで、Keyword Parameter を実現することである。
[Functions](https://gigamonkeys.com/book/functions.html#keyword-parameters) の Keyword Parameters 節が非常に参考になった。
以下抜粋

> (defun foo (&key a b c) (list a b c))
> (foo)                ==> (NIL NIL NIL)
> (foo :a 1)           ==> (1 NIL NIL)
> (foo :b 1)           ==> (NIL 1 NIL)
> (foo :c 1)           ==> (NIL NIL 1)
> (foo :a 1 :c 3)      ==> (1 NIL 3)
> (foo :a 1 :b 2 :c 3) ==> (1 2 3)
> (foo :a 1 :c 3 :b 2) ==> (1 2 3)