2008年10月15日水曜日

[xyzzy]外部コマンドの結果を文字列として出力する

command-substitutionという関数があります。けっこう便利。

上の関数を、バッファを介せずにCLの標準関数だけで作れないかなーと 思ってこんなものを書いてみた。まだまだ処理系依存。

やっていることは以下の3点

  1. 外部コマンドを呼び出して、結果をファイルに保存
  2. 保存したファイルの中身を文字列ストリームに流す
  3. ついでに右端の空白文字を取り除く
(defun cat (file &optional stream)
  "print file contents."
  (with-open-file (fp file)
    (do ((ch (read-char fp nil nil)
             (read-char fp nil nil)))
        ((null ch))
      (princ ch stream))))

(defun shell-command-to-string (command)
  "Execute shell command COMMAND and return its output as a string."
  (let ((outfile (make-temp-file-name "xyzzycmd-")))
    (unwind-protect
        (with-output-to-string (stream)
          (call-process command :output outfile
                        :show :minimize :wait t)
          (cat outfile stream))
      (delete-file outfile))))

(defun command-substitution (command)
  (string-right-trim '(#\SPC #\TAB #\LFD)
    (shell-command-to-string command)))
結果:
(command-substitution
 (format nil "ls -1 ~A"
        (merge-pathnames "*.exe" (user-homedir-pathname))))
=>
"C:/home/xyzzy/xyzzy.exe
C:/home/xyzzy/xyzzycli.exe
C:/home/xyzzy/xyzzyenv.exe"

(command-substitution "echo 舌足らずなブログ") => "舌足らずなブログ"

意図してなかったが日本語も通るようだ。

ちなみにshell-command-to-stringという関数名はEmacsから

後は

  • 一時ファイルを作成する関数 (make-temp-file-name)
  • 外部プロセスを処理する関数 (call-process)
がCLにあれば尚良いんだけど…

0 件のコメント:

コメントを投稿