さくらんぼのlambda日記

lambdaちっくなことからゲーム開発までいろいろ書きます。

複数行のコマンドの実行結果を文字列に設定する

これですが、とりあえず深く考えないで実装してみることにします。
前回までと同様リードマクロを使えば出来そうですよね。

まずは、前回までで分かっている道具をちゃんと関数にしておきます。外部プログラムを実行し、その結果を文字列として返す関数を定義します。

(defun exec-command (command)
  (with-output-to-string (out)
    (sb-ext:run-program command nil :search "/bin" :output out)))

:searchにプログラムを探しに行くパスを指定できるのですが
SBCLにてユーザの$PATHを取得する方法が分からないので
"/bin"を指定しています。

あとは、各行の文字に対してexec-commandを実行するものに変更すればOKのはずです。
リーダマクロとして#`を定義してみます。

(defun |#`-reader| (stream sub-char numarg)
  (declare (ignore sub-car numarg))
  (let (chars)
    (do ((curr (read-char stream)
               (read-char stream)))
        ((char= #\newline curr))
      (push curr chars))
    (let* ((pattern (coerce (nreverse chars) 'string))
           (pointer pattern)
           (output))
      (do ((curr (read-line stream)
                 (read-line stream)))
          ((null curr))
        (if (string= pattern (string-left-trim '(#\Newline #\Tab #\Space) curr))
            (return))
        (setq output (concatenate 'string output (exec-command curr) (make-string 1 :initial-element #\newline))))
      (string-right-trim '(#\Newline) output )
      )))

(set-dispatch-macro-character
 #\# #\` #'|#`-reader|)

どっこらしょ。

CL-USER> #`END
ls
date
 END
"_darcs
clbuild
clbuild-bash-completion.sh
clbuild.conf.default
clbuild.lisp
dependencies
doc
implementations
my-projects
projects
sharp-less.lisp
sharp-less.lisp~
sharp-less2.lisp
sharp-less2.lisp~
source
systems
target
test.lisp
test.lisp~
wnpp-projects

2010年  1月 21日 木曜日 13:35:52 JST"

できたー。

でも結構制限事項が多いです。誰か教えてー。