HOME xyzzy download 書き込む

ファイルアップロード用スクリプト


1. はじめに

xyzzy で HTML を書いている人のためのファイルアップロード用スクリプトです。 ファイルをサーバーにアップロードします。

ファイルをアップロードする部分は Python で書いて py2exe を使って実行ファイルにしました。 xyzzy-lisp にも ftp 用の関数がありますが、ftp がハングアップすると、xyzzy 全体が ハングアップして悲惨なことになります。 そこで、リスクの高い部分は外注し、そこでトラブルが起きても xyzzy 本体は巻き込まれないようにしています。

このスクリプトでできることは、

  1. 現在のバッファをアップロードする。
  2. ファイル選択ダイアログからファイルを選択してアップロードする(複数選択可)。
  3. index.html と log.html を半自動で書き換えてアップロードする。
です。

2. インストール

以下の手順でインストールして下さい。
  1. xyzzy-upload.lzh を解凍して生成するフォルダ 'ftp-upload' を丸ごと xyzzy をインストールしたディレクトリにコピーします。
  2. upload.l, upload.lcsite-lisp にコピーします。
  3. .xyzzy または siteinit.l に以下の行を加えます。
    (add-hook '*ed::html+-mode-hook* #'(lambda () (require "upload")))
    (setq ed::*html-ftp-server* "your.ftp.server")
    (setq ed::*html-ftp-user* "your_user_accout")
    (setq ed::*html-ftp-pass* "your_password")
    (setq ed::*local-home-dir* "C:/MyHomePage/")
    
    まず1行目で、html+-mode が呼び出されるとき upload もついでに呼ばれるようにします。 それから、以下の4つの変数をあなたの環境にあわせて設定してください。

    ed::*html-ftp-server* あなたのホームページがあるサーバーの IP address です。
    ed::*html-ftp-user* そのサーバーのあなたのユーザー名です。
    ed::*html-ftp-pass* そのユーザー名のパスワードです。
    ed::*local-home-dir* ホームページを自分の PC で作るときのディレクトリです。

3. 使い方

3.1. html-upload-current-buffer

現在のバッファをアップロードします。*local-home-dir* とそのファイルがあるディレクトリを比べて、 サーバー上のしかるべきディレクトリにアップロードします。デフォルトでは S-F10 に割り振られています。
注意: ローカルでのディレクトリ構造と、サーバー上でのディレクトリ構造が一致している必要があります。

3.2. html-upload-other-files

画像ファイルや圧縮ファイルなどをアップロードします。 ファイル名を聞くダイアログが開くのでそこから選択します。 複数のファイルが選択できます。 デフォルトでは F6 にバインドされています。

3.3. html-upload-index-log

紫藤は、index.html と log.html に更新内容を書いているので、 それを半自動化するための関数です。 多分お使いになることはないと思いますが、興味のある方は自分の環境に合わせて書き直してください。 デフォルトでは F11 にバインドされています。

3.4. html-show-upload-log

アップロードがちゃんとされたか確認するための関数です。メッセージボックスに、いつどのファイルがアップロード されたかを示します。FTP がうまくいってなければその旨が表示されます。 デフォルトでは S-F6 にバインドされています。

このスクリプトは call-process を使って、後の処理を upload.exe に丸投げするので、 エコー欄にはうまくいってもいかなくても "hand over to ftp" としか表示されません。 そのため、うまくいったか知りたいときは後で html-show-upload-log を呼ぶ必要があります。

4. プログラムについて

4.1. 方針

xyzzy の方では、必要な情報(サーバー名、ユーザー名、パスワード、サブフォルダー名、アップロードするファイルのリスト) を書いたファイル upload.inp を環境変数 TEMP (または TMP、両方なければ C:) で指定されたディレクトリに作成します。 その後アップロードするプログラム upload.exe を呼び出します。upload.exe については ここを見てください。 upload.exe は upload.inp を読んでファイルを転送し、転送の結果を upload.log に書きます。 転送が失敗したらどこでエラーが起きたか記録されます。 upload.inp は読み終わった時点で消去されます。

4.2. ソースコード

ソースを以下に示します。
 01:     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 02:     ;;;             upload.l                    ;;;
 03:     ;;;            by T.Shido                   ;;;
 04:     ;;;          on July 19, 2005               ;;;
 05:     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 06:     
 07:     (provide "upload")
 08:     (in-package "editor")
 09:     
 10:     ;;; variables
 11:     (defvar *html-ftp-server* "your.ftp.server")
 12:     (defvar *html-ftp-user* "your_user_name")
 13:     (defvar *html-ftp-pass* "******")
 14:     (defvar *local-home-dir* "C:/MyHomePage")
 15:     (defvar *upload-inp* (merge-pathnames "upload.inp" (or (si:getenv "TEMP") (si:getenv "TMP") "C:")))
 16:     (defvar *upload-log* (merge-pathnames "upload.log" (or (si:getenv "TEMP") (si:getenv "TMP") "C:")))
 17:     (defvar *html-ftp* (merge-pathnames "ftp-upload/upload.exe" (si:system-root)))
 18:     
 19:     ;;; upload current buffer
 20:     (defun html-upload-current-buffer ()
 21:       (interactive)
 22:       (if (buffer-modified-p)
 23:           (save-buffer))
 24:       (html-upload-files (list (get-buffer-file-name))))
 25:     
 26:     
 27:     ;;; upload files
 28:     (defun html-upload-files (fnames)
 29:       (with-open-file (f  *upload-inp* :direction :output
 30:                                        :if-exists :overwrite
 31:                                        :if-does-not-exist :create)
 32:         (format f "(~S, ~S, ~S, ~S, \\\n(\\\n"
 33:                 *html-ftp-server*
 34:                 *html-ftp-user*
 35:                 *html-ftp-pass*
 36:                 (html-get-subdir-name (directory-namestring (car fnames))))
 37:                                                                             
 38:         (dolist (fname fnames)
 39:           (format f "~S, \\~%" fname))
 40:         (format f "))\n"))
 41:       (message "hand over to ftp")
 42:       (call-process *html-ftp* :show :hide))  
 43:     
 44:     
 45:     (defun html-get-subdir-name (fdir)
 46:       (if (string= fdir *local-home-dir*)
 47:           "HOME"
 48:         (subseq fdir (length *local-home-dir*) (1- (length fdir)))))
 49:     
 50:     
 51:     ;;; insert str after tag in the fname
 52:     (defun html-insert-new (fname tag str)
 53:       (copy-file fname (concat fname ".bak") :if-exists :overwrite)
 54:       (let ((buff (find-file-internal fname)))
 55:         (set-buffer buff)
 56:         (scan-buffer tag)
 57:         (goto-bol)
 58:         (insert str)
 59:         (save-buffer)
 60:         (delete-buffer buff)))
 61:     
 62:     ;;; upload index and log
 63:     (defun html-upload-index-log ()
 64:       (interactive)
 65:       (let ((url (read-string "URL: "))
 66:             (name (read-string "NAME: "))
 67:             (findex (concat *local-home-dir* "index.html"))
 68:             (flog (concat *local-home-dir* "log.html"))
 69:             (option (if (= 1 (read-integer "1, 作成; 2, 更新: ")) "作成" "更新"))
 70:             (date (format-date-string "%B %d, %Y")))
 71:         (html-insert-new flog
 72:                          "<dt>"
 73:                          (format nil "<dt><b>[~A]</b></dt>~%<dd><ul>~%<li><a href=\'~A\'>~A</a>を~A。~%</ul></dd>~%~%"
 74:                                  date url name option))
 75:         (html-insert-new findex
 76:                          "<li>"
 77:                          (format nil "<li><a href=\'~A\'>~A</a>を~A。[~A]~%" url name option date))
 78:         (html-upload-files (list findex flog))))
 79:     
 80:     
 81:     ;;; upload other files
 82:     (defun html-upload-other-files ()
 83:       (interactive)
 84:       (let ((files (file-name-dialog :title "Files to upload"
 85:                                      :multiple t
 86:                                      :filter '(("all (*.*)" . "*.*")
 87:                                                ("image (*.png, *.gif, *.jpg)" . "*.png;*.gif;*.jpg")
 88:                                                ("text (*.txt, *.html, *.htm, *.css)" . "*.txt;*.html;*.htm;*.css")
 89:                                                ("archive (*.lzh, *.zip. *.gzip)" . "*.lzh;*.zip;*.gzip"))
 90:                                      :initial-directory  *local-home-dir*)))
 91:         (if files
 92:             (html-upload-files files))))
 93:     
 94:     (defun html-show-upload-log ()
 95:       (interactive)
 96:       (message-box
 97:        (if (file-exist-p *upload-log*)
 98:            (let ((buff (create-new-buffer "*temp*")))
 99:              (set-buffer buff)
100:              (insert-file-contents *upload-log*)
101:              (prog1 (buffer-substring (point-min) (point-max))
102:                (delete-buffer buff)))
103:          "upload.log has not been created yet.\n try it later again.")))
104:     
105:     
106:     
107:     ;;; example of key bind
108:     (eval-when (:load-toplevel :execute)
109:       (define-key *html+-mode-map* #\F11    'html-upload-index-log)
110:       (define-key *html+-mode-map* #\F6     'html-upload-other-files)
111:       (define-key *html+-mode-map* #\S-F6   'html-show-upload-log)
112:       (define-key *html+-mode-map* #\S-F10  'html-upload-current-buffer))

簡単な説明