アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

隙があればlispを詰め込んで行きたい (9)

こんにちは、chibaです!
隙があればlispを詰め込んで行く日々ですが、古めのウェブページの累計カウンター的な物を月に一回更新するという作業が発生しました。
sedで一発かなと思いましたが、sedで一発と思ったらCLで書くことにしているので、CLで書いてみます。
具体的な内容ですが、index.htmlの中に、カウンター的なものがあり、数字はそれぞれ1枚のGIF画像になっているのを、毎月集計された数字に更新というところです。
サーバーとは、SSHで通信できます。
折角なので、リモートのファイルをローカルのファイルと同じ感覚で編集できるようなマクロを作成してみました。
といってもリモートからscpしてきて編集するだけのものです。
これと、以前に定義したオレオレsedを組み合わせて任務は完了です。

(exec:define-executable scp)

(defmacro with-output-to-remote-file ((stream path) &body body)
  (let ((temp-file-name (string (gensym "/tmp/with-output-to-remote-file-"))))
    `(unwind-protect (progn
                       (with-open-file (,stream ,temp-file-name :direction :output)
                         ,@body)
                       (scp ,temp-file-name ,path)
                       nil)
       (when (cl-fad:file-exists-p ,temp-file-name)
         (delete-file ,temp-file-name)))))

(defmacro with-input-from-remote-file ((stream path) &body body)
  (let ((temp-file-name (string (gensym "/tmp/with-input-from-remote-file-"))))
    `(unwind-protect (progn
                       (scp ,path ,temp-file-name)
                       (with-open-file (,stream ,temp-file-name)
                         ,@body)
                       nil)
       (when (cl-fad:file-exists-p ,temp-file-name)
         (delete-file ,temp-file-name)))))

(defun カウンター (num)
  (fare-utils:join-strings
   (list
    "<!-- カウンター -->"
    "<div id=\"count\">"
    "<table id=\"counter\">"
    "<tr>"
    "<td>"
    (format nil
            "~{<img src=\"./images/count_~a.gif\" alt=\"\" />~%~}"
            (map 'list #'values (write-to-string num)))
    "</td>"
    "<td> <img src=\"./images/count_ken.gif\" alt=\"\" width=\"18\" height=\"17\" /></td>"
    "</tr>"
    "</table>"
    "</div>"
    "<!-- /カウンター -->")
   :separator #\Newline))
;; 実行例
(with-output-to-remote-file (out "example:public_html/index.html")
  (with-input-from-remote-file (in "example:public_html/index.html")
    (sed "<!-- カウンター -->"
         "<!-- /カウンター -->"
         (カウンター 12345)
         :IN IN
         :OUT OUT)))