Emacs Lispで、ファイルから入力する処理をCommonLispのノリで書こうとしたら・・・
>(require 'cl)
>(with-open-file (in "hoge.txt" :direction :input)
(with-open-file (out "fuga.txt" :direction :output)
(princ (read in) out)))
Debugger entered--Lisp error: (void-function with-open-file)
あれ?
>(open "hoge.txt")
Debugger entered--Lisp error: (void-function open)
・・・あれ?
ELispってファイルオープンしてストリームを作ることができないのか・・・。
調べて見たところ、streamとして使えるのは以下のとおりらしい。
- 入力
- buffer
- marker (バッファ内のマーカの位置)
- string
- function (2種類の呼び出し方を扱えるもの)
- t (ミニバッファ)
- nil (standard-input)
- symbol (関数定義)
- 出力
- buffer
- marker (バッファ内のマーカの位置)
- function (1つの文字を引数にして呼ばれる)
- t (エコー領域)
- nil (standard-output)
- symbol (関数定義)
つまりはバッファを介さないとファイル入出力ができないっぽい。
なので、open/closeでストリームを扱っているつもりになれる関数を書いてみた。
(require 'cl)
(setf *opening-stream-buffers*
(make-hash-table))
(defmacro with-default-values (binds &rest body)
`(progn
,@(mapcar
(lambda (bind)
`(unless ,(first bind)
(setf ,(first bind) ,(second bind))))
binds)
,@body))
(defun open (filename &optional direction)
(with-default-values
((direction :input))
(let ((buf (create-file-buffer filename)))
(when (eq direction :input)
(with-current-buffer buf
(insert-file-contents filename)))
(setf (gethash buf *opening-stream-buffers*) (list direction filename))
buf)))
(defun close (buf)
(when (eq (first (gethash buf *opening-stream-buffers*))
:output)
(with-current-buffer buf
(write-region
(point-min) (point-max)
(second (gethash buf *opening-stream-buffers*))))
(kill-buffer buf)))
0 件のコメント:
コメントを投稿