タイムラインコマンドの自作 (xyttr Advent Calendar 14日目)

この記事はxyttr Advent Calendar 2011の記事です。

11日目の記事の最後でチラっと紹介しましたが、今回はxyttr::define-tl-commandマクロの紹介。

リファレンスに今日追加した部分より抜粋

- *macro* define-tl-command (name params &key interactive buffer-name api-func api-params auto-reload hook)

    タイムラインコマンドを定義します。
    
    * name -- コマンド関数名
    * params -- コマンドパラメータ
    * interactive -- パラメータの受け取り方を指定するinteractive-string (paramsがnilの場合は不要)
    * buffer-name -- タイムラインバッファ名
    * api-func -- ツイートデータを取得するためのtimeline系api関数
    * api-params -- api-funcに渡す基本パラメータ
    * auto-reload -- 自動リロード間隔(秒) 省略時は`xyttr:*auto-reload*`の値
    * hook -- タイムライン用バッファ生成後に実行するhook関数(シンボル)

    api-funcは非同期版の関数を指定します。
    api関数を自作する場合はキーワード引数onsuccessとonfailureで
    コールバックを受け取るように定義してください。

xyttrで使えるtimeline系apiについては、public-timeline以外は全て対応するコマンドが定義済みです。

という事で最初の例はpublic-timelineを表示するコマンドを。

(in-package :xyttr)

(define-tl-command xyttr-public ()
  :buffer-name "*tw: public*"
  :api-func #'api-public-timeline-async)

M-x xyttr-public でパブリック・タイムラインが表示されます。

ちなみに説明を見ると分かるんですが、public-timeline APIでは指定ID以降のツイートの取得や指定ID以前のツイートの取得といった機能はサポートされていません。
リロード時や次ページ取得時に取得されるツイートの時系列がおかしい場合があるかもしれないのでご注意を。

次に、api関数を自作してオリジナルタイムラインコマンドを作ってみます。

(in-package :xyttr)

;; ツイートデータ生成関数
(defun make-tweet (status-id name text)
  `(("id" . ,status-id)
    ("user" ("screen_name" . ,name))
    ("text" . ,text)
    ("created_at" . ,(format-date-string "%a %b %d %H:%M:%S %Z %Y"))))

;; fizzbuzz API
(defun api-fizzbuzz (&key since_id max_id onsuccess onfailure)
  (if max_id
      (funcall onsuccess nil)
    (flet ((fb (n) (case (gcd n 15)
		     (15 "FizzBuzz") (5 "Buzz") (3 "Fizz")
		     (t (format nil "~D" n)))))
      (funcall onsuccess
	       (nreverse
		(loop repeat 10
		  for i from (1+ (or since_id 0))
		  collect (make-tweet i "FizzBuzz" (fb i)))))))
  ; xhr::xhr-cancel-ticket以外の非nil値を返すとこけるのでnil
  nil)

(define-tl-command xyttr-fizzbuzz ()
  :buffer-name "*fizzbuzz*"
  :api-func #'api-fizzbuzz)

リロードする度に10件ずつfizzbuzzが表示されます。
http://gyazo.com/64b81302dbbe26cd4d472209f7950cf3.png


define-tl-commandマクロのapi-funcに指定する関数は、以下のキーワード引数を受け取れるように定義して下さい。

  • since_id -- リロード時に渡される、取得済みの一番新しいツイートのID
  • max_id -- 次ページ取得時に渡される、取得済みの一番古いツイートのID
  • oncomplete -- リクエスト成功時に実行する、ツイートのリストを引数に取るコールバック関数
  • onfailure -- リクエスト失敗時に実行する、レスポンス(文字列)、HTTPステータスコード、HTTPレスポンスヘッダ(alist)を引数に取るコールバック関数

この4つのパラメータに加えてapi-paramsに指定した基本パラメータがapi-funcに指定した関数に渡されます。
ちなみにコールバック関数の呼び出しはFizzBuzzの例の通り同期的になっていてもOKです。

この例は全く役に立たない物ですが、readitlaterなどからデータを取って来るAPI関数を用意してコマンドを作ったりすると面白いかもしれません。



以上、define-tl-commandマクロの紹介でした。