--- title: candidate-transformerを用いたanythingのsourceづくり author: kazu634 date: 2009-10-16 url: /2009/10/16/_1352/ wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4835;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - Emacs ---

取得した候補の文字列から、「anythingの候補として表示させる部分」と「選択後にコマンドによって実行される部分」とを分断することができます。その処理を行う関数を行うのが、 candidate-transformer ということになる…らしい:

candidate-transformer (オプション)
source から補完リストが作成された際に引数を一つとって呼び出される関数である。その引数は source から取得された候補のリストである。実際の補完に用いられる変換済み候補のリストを返さなければならない。
この要素は候補のリストからアイテムを変更したり、取り除いたりするために用いることができる。
この関数は「(表示文字列 . 実際の文字列)」という対のリストを返すことで、候補を修正することができる。この場合、「表示文字列」は Anything バッファーで表示されるが、「実際の文字列」は候補が選択されたときの action の引数に用いられる。このことによって、例えば候補があまりに長ければより読みやすくすることができるし、他の候補と共通の部分があり表示のために短縮した文字列に安全に置換できるようになる。
注意: 仮に「(表示文字列 . 実際の文字列)」という形式が用いられた場合、パターンマッチは表示文字列で行われ、実際の値では実施されない。

2009-10-12 – 武蔵の日記

というわけで、実際に使ってみました。

使用する外部スクリプト

前回と同じようにflickrから情報を引き出すスクリプトを用いますが、ブログに投稿できるようなサイズの画像へのリンクも一緒に取得させています。

ちなみにこのスクリプトを使用する際には、flickrからapi_keyを取得し、「xxx」の部分を取得したapi_keyに変更してください。

# === Libraries ===
use strict;
use warnings;
use Perl6::Say;
use YAML;
use utf8;
use Encode;
use WebService::Simple;
use XML::Simple;
use YAML::Syck;
# === Main part ===
my $flickr = WebService::Simple->new(
base_url => "http://api.flickr.com/services/rest/?",
param    => {
api_key => 'xxx',
method => 'flickr.photos.search',
machine_tag_mode => 'any',
}
);
my $response = $flickr->get( { user_id => '42332031@N02', } );
# (1) 取得したXMLの表示
# say YAML::Syck::Dump( XMLin ($response->content));
my $temp = XMLin($response->content);
foreach my $i (sort keys %{$temp->{photos}->{photo}}) {
my $title = encode('utf8', $temp->{photos}->{photo}->{$i}->{title});
print "$title\t";
say 'http://farm' . $temp->{photos}->{photo}->{$i}->{farm} .
'.static.flickr.com/' . $temp->{photos}->{photo}->{$i}->{server} .
'/' . $i . '_' . $temp->{photos}->{photo}->{$i}->{secret} .'.jpg';
}

実行結果

~/bin on kazu634 [504] $: perl flickr.pl 
Latex Installation      http://farm4.static.flickr.com/3519/3910763253_f21d0a92f4.jpg
牛タン  http://farm3.static.flickr.com/2491/3926830661_31876f9021.jpg
夕飯    http://farm3.static.flickr.com/2652/3933158369_dbecc6cb8c.jpg
一ノ関の夕暮れ  http://farm4.static.flickr.com/3516/3933159353_c18fbb1b1d.jpg
324-todo-flow   http://farm3.static.flickr.com/2552/3940382629_a0ca185977.jpg
326-rsvp-flow   http://farm4.static.flickr.com/3422/3940382747_7debe2c8e8.jpg
323-flow-template       http://farm3.static.flickr.com/2564/3941161952_9c1e689cce.jpg
325-login-flow  http://farm4.static.flickr.com/3444/3941162050_d5288b1b06.jpg
厳美渓の農道    http://farm4.static.flickr.com/3495/3944022597_d1010fda01.jpg
温泉    http://farm4.static.flickr.com/3430/3944023685_465f5bcf4a.jpg
フレンチ        http://farm3.static.flickr.com/2558/3944024177_69112cd66e.jpg
一関ハーフ当日  http://farm3.static.flickr.com/2667/3944801484_0445c243b1.jpg
温泉    http://farm3.static.flickr.com/2553/3944802592_68ec2fb316.jpg
Fastfinga       http://farm3.static.flickr.com/2472/3946789592_126226025a.jpg
Evernote        http://farm3.static.flickr.com/2658/3950568038_b053d2bbf9.jpg
Evernote        http://farm3.static.flickr.com/2590/3950568530_4f659bcde4.jpg
同窓会  http://farm4.static.flickr.com/3471/3955756606_8e90852e93.jpg
20090929_lunch  http://farm4.static.flickr.com/3167/3965082006_0b157ee2e3.jpg
ハロウィン      http://farm4.static.flickr.com/3430/3976527917_9aaef1f53e.jpg
たぬき  http://farm3.static.flickr.com/2558/3976528247_7d88f7f418.jpg
下北沢  http://farm4.static.flickr.com/3531/3977289848_4c327672af.jpg
下北沢  http://farm3.static.flickr.com/2540/3977290184_749e4e923b.jpg
下北沢  http://farm3.static.flickr.com/2445/3977291276_d8d485bbd5.jpg
夕飯    http://farm3.static.flickr.com/2499/3977291658_ff606260a6.jpg
Stationary Hacks        http://farm4.static.flickr.com/3282/3991212701_f45092560b.jpg
anythingのサンプル2     http://farm4.static.flickr.com/3492/4006542967_5d62d0c82c.jpg
anythingのサンプル1     http://farm3.static.flickr.com/2630/4007300814_5ba6ffb8f3.jpg
anything-flickr http://farm3.static.flickr.com/2557/4010787675_1a0d784227.jpg

candidate-transformerを用いる前

前回と同じままだと

;; anything-test
(defun my-anything ()
(interactive)
(anything
(list
tmp-c-source)))
(setq tmp-c-source
'((name . "Example")
(candidates . (lambda ()
(delete ""
(split-string
(shell-command-to-string "perl ~/bin/flickr.pl")
"\n"))))
(action . (("Insert" . insert)))))

こんな画面が表示されます。

candidate-transformer を用いると

ここで candidate-transformer を用いてみます。

(setq tmp-c-source
'((name . "Example")
(candidates . (lambda ()
(delete ""
(split-string
(shell-command-to-string "perl ~/bin/flickr.pl")
"\n"))))
;; ここで (表示文字列 . 実際の文字列) の形式に変換している
(candidate-transformer . (lambda (candidates)
(mapcar
(function (lambda(arg)
(apply 'cons (split-string arg "\t"))))
candidates)))
(action . (("Insert" . insert)))))

すると、このようにタイトルのみが表示されています(この例だと「c」で絞り込んでいるので表示されている数が少ないですね。。。)

候補を選択すると、次のようにURLが挿入されます。

イディオム

外部コマンドの標準出力への出力を取り込む場合、最後の改行が問題になるから、こう書くのがイディオムみたい:

(delete ""
(split-string
(shell-command-to-string "perl ~/bin/flickr.pl")
"\n"))