blog/content/post/1970/01/01/1970-01-01-00000027.md

163 lines
14 KiB
Markdown

---
title: 非同期プロセスを anything の source で活用する
author: kazu634
date: 1969-12-31
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:4973;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- Emacs
---
<div class="section">
<p>
<a href="http://d.hatena.ne.jp/sirocco634/20091129/1259505469" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091129/1259505469', ' Emacs内でのプロセス制御について &#8211; 武蔵の日記');" target="_blank"> Emacs内でのプロセス制御について &#8211; 武蔵の日記</a>」でも書きましたが、Emacsのプロセスには同期と非同期の二種類があります。これまでは同期プロセスを用いて候補を取得していましたが、非同期プロセスを用いて候補を取得してみます。
</p>
<h4>
candidatesの説明
</h4>
<p>
こんな風に書いてありました:
</p>
<blockquote title="武蔵の日記" cite="http://d.hatena.ne.jp/sirocco634/20091012/1255336649">
<dl>
<dt>
candidates (candidates-in-buffer 要素を指定しなかった場合、必須)
</dt>
<dd>
source から候補を取得するための方法を指定する。この要素に指定できるのは、変数、引数なしの関数、あるいは実際の候補のリストである。リストは文字列のリストでなければならず、そのため必要であれば候補を文字列に変換するのは source の責任である。仮に候補が非同期で取得されなければならない場合(例えばコマンド終了までに時間がかかる外部コマンドで取得するような場合)には、その関数は外部コマンドを非同期で実行し、 the associated process object を戻す必要がある。Anything はそのプロセスを管理する(そのプロセスから出力を受け取り、必要であればそのプロセスを停止する、など)。プロセスは現在のパターンにマッチする候補を返さなければならない(anything-pattern を参照すること)。注意: 非同期の source からの結果は anything-sources 中の位置に関係なく、 anything のバッファーの最後に表示される。
</dd>
</dl>
<p>
<cite><a href="http://d.hatena.ne.jp/sirocco634/20091012/1255336649" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091012/1255336649', ' anything の source の設定値について &#8211; 武蔵の日記');" target="_blank"> anything の source の設定値について &#8211; 武蔵の日記</a></cite>
</p>
</blockquote>
<p>
</p>
<h4>
非同期プロセスで source を取得する際の動作
</h4>
<p>
candidateで指定した関数を、パターンが入力されるたびに呼び出します。そのため呼び出す外部スクリプトは引数を受け取れるようにし、そこで絞り込む必要があります。
</p>
<h4>
実行する外部スクリプト
</h4>
<p>
<a href="http://d.hatena.ne.jp/sirocco634/20091016#1255698987" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091016#1255698987', '2009-10-16 &#8211; 武蔵の日記');" target="_blank">2009-10-16 &#8211; 武蔵の日記</a>」で用いた flickr に登録した画像の一覧取得スクリプトを再利用します。ただし前述の引数を受け取る処理を追加します:
</p>
<pre class="syntax-highlight">
<span class="synPreProc">#!/usr/bin/env perl</span>
<span class="synComment"># === Libraries ===</span>
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">use </span>Perl6::Say;
<span class="synStatement">use </span>YAML;
<span class="synStatement">use utf8</span>;
<span class="synStatement">use </span>Encode;
<span class="synStatement">use </span>WebService::Simple;
<span class="synStatement">use </span>XML::Simple;
<span class="synStatement">use </span>YAML::Syck;
<span class="synComment"># === Main part ===</span>
<span class="synStatement">my</span> <span class="synIdentifier">$arg</span> = <span class="synStatement">shift</span> || <span class="synConstant">&#34;.&#34;</span>;
<span class="synStatement">my</span> <span class="synIdentifier">$flickr</span> = WebService::Simple-&#62;<span class="synStatement">new</span>(
<span class="synConstant">base_url </span>=&#62; <span class="synConstant">&#34;http://api.flickr.com/services/rest/?&#34;</span>,
<span class="synConstant">param </span>=&#62; {
<span class="synConstant">api_key </span>=&#62; <span class="synConstant">'f94ab2327e72d52859d7fe28520d482f'</span>,
<span class="synConstant">method </span>=&#62; <span class="synConstant">'flickr.photos.search'</span>,
<span class="synConstant">machine_tag_mode </span>=&#62; <span class="synConstant">'any'</span>,
}
);
<span class="synStatement">my</span> <span class="synIdentifier">$response</span> = <span class="synIdentifier">$flickr</span>-&#62;get( { <span class="synConstant">user_id </span>=&#62; <span class="synConstant">'42332031@N02'</span>, } );
<span class="synComment"># (1) 取得したXMLの表示</span>
<span class="synComment"># say YAML::Syck::Dump( XMLin ($response-&#62;content));</span>
<span class="synStatement">my</span> <span class="synIdentifier">$temp</span> = XMLin(<span class="synIdentifier">$response</span>-&#62;content);
<span class="synStatement">foreach</span> <span class="synStatement">my</span> <span class="synIdentifier">$i</span> (<span class="synStatement">sort</span> {<span class="synIdentifier">$b</span> &#60;=&#62; <span class="synIdentifier">$a</span>} <span class="synStatement">keys</span> %{<span class="synIdentifier">$temp</span>-&#62;{photos}-&#62;{photo}}) {
<span class="synStatement">my</span> <span class="synIdentifier">$title</span> = encode(<span class="synConstant">'utf8'</span>, <span class="synIdentifier">$temp</span>-&#62;{photos}-&#62;{photo}-&#62;{<span class="synIdentifier">$i</span>}-&#62;{title});
<span class="synStatement">my</span> <span class="synIdentifier">$farm</span> = <span class="synIdentifier">$temp</span>-&#62;{photos}-&#62;{photo}-&#62;{<span class="synIdentifier">$i</span>}-&#62;{farm};
<span class="synStatement">my</span> <span class="synIdentifier">$server</span> = <span class="synIdentifier">$temp</span>-&#62;{photos}-&#62;{photo}-&#62;{<span class="synIdentifier">$i</span>}-&#62;{server};
<span class="synStatement">my</span> <span class="synIdentifier">$secret</span> = <span class="synIdentifier">$temp</span>-&#62;{photos}-&#62;{photo}-&#62;{<span class="synIdentifier">$i</span>}-&#62;{secret};
<span class="synStatement">if</span> (<span class="synIdentifier">$title</span> =~<span class="synStatement"> /</span><span class="synIdentifier">$arg</span><span class="synStatement">/i</span>) {
<span class="synStatement">print</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$title</span><span class="synSpecial">\t</span><span class="synConstant">&#34;</span>;
say <span class="synConstant">&#34;&#60;a title=</span><span class="synSpecial">\&#34;</span><span class="synIdentifier">$title</span><span class="synSpecial">\&#34;</span><span class="synConstant"> href=</span><span class="synSpecial">\&#34;</span><span class="synConstant">http://flickr.com/photos/42332031</span><span class="synSpecial">\@</span><span class="synConstant">N02/</span><span class="synIdentifier">$i</span><span class="synConstant">/</span><span class="synSpecial">\&#34;</span><span class="synConstant">&#62;&#60;img src=</span><span class="synSpecial">\&#34;</span><span class="synConstant">http://farm</span><span class="synIdentifier">$farm</span><span class="synConstant">.static.flickr.com/</span><span class="synIdentifier">$server</span><span class="synConstant">/</span><span class="synIdentifier">$i</span><span class="synSpecial">\_</span><span class="synIdentifier">$secret</span><span class="synConstant">.jpg</span><span class="synSpecial">\&#34;</span><span class="synConstant"> /&#62;&#60;/a&#62;&#34;</span>;
}
}
</pre>
<h4>
anything の source
</h4>
<p>
そして次のような source を設定します。ここで注意すべきは、 candidate の部分で start-process を使用しているところです:
</p>
<pre class="syntax-highlight">
<span class="synSpecial">(</span><span class="synStatement">defvar</span> anything-c-source-flickr
<span class="synSpecial">'((</span>name . <span class="synConstant">&#34;Flickr Photos&#34;</span><span class="synSpecial">)</span>
<span class="synSpecial">(</span>candidates . <span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">()</span>
<span class="synSpecial">(</span>start-process <span class="synConstant">&#34;Flickr&#34;</span> <span class="synStatement">nil</span>
<span class="synConstant">&#34;flickr&#34;</span>
anything-pattern<span class="synSpecial">)))</span>
<span class="synSpecial">(</span>candidate-transformer . <span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">(</span>candidates<span class="synSpecial">)</span>
<span class="synSpecial">(</span><span class="synStatement">mapcar</span>
<span class="synSpecial">(</span><span class="synStatement">function</span> <span class="synSpecial">(</span><span class="synStatement">lambda</span><span class="synSpecial">(</span>arg<span class="synSpecial">)</span>
<span class="synSpecial">(</span><span class="synStatement">apply</span> '<span class="synStatement">cons</span> <span class="synSpecial">(</span>split-string arg <span class="synConstant">&#34;\t&#34;</span><span class="synSpecial">))))</span>
candidates<span class="synSpecial">)))</span>
<span class="synSpecial">(</span>action . <span class="synSpecial">((</span><span class="synConstant">&#34;Insert&#34;</span> . <span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">(</span>candidate<span class="synSpecial">)</span>
<span class="synSpecial">(</span>insert <span class="synConstant">&#34;&#60;center&#62;\n&#34;</span><span class="synSpecial">)</span>
<span class="synSpecial">(</span>insert
<span class="synSpecial">(</span><span class="synStatement">format</span> <span class="synConstant">&#34;%s\n&#34;</span> candidate<span class="synSpecial">))</span>
<span class="synSpecial">(</span>insert <span class="synConstant">&#34;&#60;/center&#62;\n&#34;</span><span class="synSpecial">)))))))</span>
</pre>
<p>
ちなみに同期プロセスを使用する場合は、「<a href="http://d.hatena.ne.jp/sirocco634/20091016#1255698987" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091016#1255698987', '2009-10-16 &#8211; 武蔵の日記');" target="_blank">2009-10-16 &#8211; 武蔵の日記</a>」で紹介したようにこんな感じです:
</p>
<pre class="syntax-highlight">
<span class="synSpecial">(</span><span class="synStatement">setq</span> anything-c-source-flickr
<span class="synSpecial">'((</span>name . <span class="synConstant">&#34;Flickr&#34;</span><span class="synSpecial">)</span>
<span class="synSpecial">(</span>candidates . <span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">()</span>
<span class="synSpecial">(</span><span class="synStatement">delete</span> <span class="synConstant">&#34;&#34;</span>
<span class="synSpecial">(</span>split-string
<span class="synSpecial">(</span>shell-command-to-string <span class="synConstant">&#34;flickr&#34;</span><span class="synSpecial">)</span>
<span class="synConstant">&#34;\n&#34;</span><span class="synSpecial">))))</span>
<span class="synSpecial">(</span>candidate-transformer . <span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">(</span>candidates<span class="synSpecial">)</span>
<span class="synSpecial">(</span><span class="synStatement">mapcar</span>
<span class="synSpecial">(</span><span class="synStatement">function</span> <span class="synSpecial">(</span><span class="synStatement">lambda</span><span class="synSpecial">(</span>arg<span class="synSpecial">)</span>
<span class="synSpecial">(</span><span class="synStatement">apply</span> '<span class="synStatement">cons</span> <span class="synSpecial">(</span>split-string arg <span class="synConstant">&#34;\t&#34;</span><span class="synSpecial">))))</span>
candidates<span class="synSpecial">)))</span>
<span class="synSpecial">(</span>action . <span class="synSpecial">((</span><span class="synConstant">&#34;Insert&#34;</span> . insert<span class="synSpecial">)))))</span>
</pre>
<h4>
「anything」に関連する最近のエントリ
</h4>
<ul>
<li>
<a href="http://d.hatena.ne.jp/sirocco634/20091118/1258549834" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091118/1258549834', ' グルメサイトを横断検索した結果を出力するスクリプト &#8211; 武蔵の日記');" target="_blank"> グルメサイトを横断検索した結果を出力するスクリプト &#8211; 武蔵の日記</a>
</li>
<li>
<a href="http://d.hatena.ne.jp/sirocco634/20091112/1258032660" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091112/1258032660', ' リストの n 番目を取り出す &#8211; 武蔵の日記');" target="_blank"> リストの n 番目を取り出す &#8211; 武蔵の日記</a>
</li>
<li>
<a href="http://d.hatena.ne.jp/sirocco634/20091101/1257084590" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091101/1257084590', ' dummy の使い方 &#8211; 武蔵の日記');" target="_blank"> dummy の使い方 &#8211; 武蔵の日記</a>
</li>
<li>
<a href="http://d.hatena.ne.jp/sirocco634/20091029/1256826524" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20091029/1256826524', ' 書き捨てのソース &#8211; 武蔵の日記');" target="_blank"> 書き捨てのソース &#8211; 武蔵の日記</a>
</li>
</ul>
</div>