fixedpoint.jp - Trac から howm へ




Trac から howm へ

2007/12/10 に Remember The Milk から howm へインポートするためのコードを書きましたが、換骨奪胎により Trac のチケットの RSS フィードから howm へインポートするプログラムになりました。

基本的なアイディアは前回と同じですが、

という点が異なっていました。

出力例:

= [sample] #15: example <http://example.com/trac/sample/ticket/15>
= [sample] #16: メモリリークを直す <http://example.com/trac/sample/ticket/16>
= [sample] #20: 設定を変更する <http://example.com/trac/sample/ticket/20>
= [sample] #21: test1 <http://example.com/trac/sample/ticket/21>
= [sample] #23: test2 <http://example.com/trac/sample/ticket/23>
= [sample] #25: test3 <http://example.com/trac/sample/ticket/25>
...

XML を howm の書式に変換するプログラム:

trac2howm.scm
#!/usr/bin/env gosh

(use gauche.charconv)
(use srfi-1)
(use sxml.ssax)
(use sxml.sxpath)

(define *trac-output-encoding* "EUC-JP")
(define *trac-namespace* '())

(define entry->title (compose second fourth))
(define entry->link (compose second second))

(define (entry->memo project entry oport)
  (define (f str . params)
    (apply format oport (string-append str "\n") params))
  (let ((title (entry->title entry))
        (link (entry->link entry)))
    (f "= [~a] ~a <~a>" project title link)
    ))

(define (xml->howm iport oport project)
  (let* ((proc (sxpath '(// item)))
         (tree (ssax:xml->sxml iport *trac-namespace*))
         (entries (proc tree)))
    (for-each (cut entry->memo project <> oport) entries)
    ))

(define (main args)
  (call-with-input-conversion (current-input-port)
    (lambda (iport)
      (call-with-output-conversion (current-output-port)
        (lambda (oport)
          (xml->howm iport oport (cadr args)))
        :encoding *trac-output-encoding*))
    :encoding "*JP")
  0)

Emacs でのコマンドの定義:

trac.el
(require 'w3m)

(defvar trac-url-prefix "http://example.com/trac/")
(defvar trac-login-url-suffix "/login")
(defvar trac-feed-url-suffix "/query")
(defvar trac-feed-query-parameter '((status . new) (status . assigned) (status . reopened) (format . rss) (order . priority)))
(defun trac-login-url (project)
  "URL for trac's login."
  (concat trac-url-prefix project trac-login-url-suffix))
(defun trac-feed-url (project)
  "URL for trac's RSS feed."
  (concat trac-url-prefix
          project
          trac-feed-url-suffix
          "?"
          (mapconcat (lambda (pair) (concat (symbol-name (car pair)) "=" (symbol-name (cdr pair)))) trac-feed-query-parameter "&")
          ))
(defvar trac-feed-content-type "application/rss+xml")
(defvar trac-temporary-file-prefix "/tmp/trac")
(defvar trac-convert-program "/home/tabe/bin/trac2howm.scm")

(defun trac-retrieve (project)
  (interactive "sProject: ")
  (catch 'failed
    (let ((use-cookies w3m-use-cookies)
          (temp-file (make-temp-file trac-temporary-file-prefix)))
      (unwind-protect
          (progn
            (setq w3m-use-cookies t)
            (with-temp-buffer
              (w3m-retrieve (w3m-retrieve (trac-login-url project))))
            (set-file-modes temp-file ?\600)
            (with-temp-file temp-file
              (let ((content-type (w3m-retrieve (trac-feed-url project) nil t)))
                (unless (equal trac-feed-content-type content-type)
                  (throw 'failed (message "failed. (%s)" (or content-type "nil"))))
                )
              )
            (call-process trac-convert-program temp-file t t project))
        (delete-file temp-file)
        (setq w3m-use-cookies use-cookies)
      ))))

動かすには:


© 2006,2007 Takeshi Abe