ヴァル研究所 Advent Calendar 2016、18日目はATOK Sparkから駅すぱあとWeb APIを使ってみる例を紹介しようと思います。
ATOK Sparkとは
ATOK Sparkは定型フレーズの展開機能を提供するソフトウェアです。例えばエディタ上でgijiroku:<ENTER>
といった入力に対し、あらかじめ登録しておいたフレーズに展開することができます。
ソースコードを記述する際のスニペットや議事録のテンプレートを展開するデモが紹介されています。また、Windows,Macの両方で利用できるという利点もあります。
以下のスライドでATOK Sparkの機能が紹介されています。
ATOK Spark プラグインから駅すぱあとWeb APIを利用する
さて、このATOK Sparkですが、展開したいフレーズをXMLファイルで登録しておく他に、プラグインも作成できます。フレーズの展開をプラグインの形で行う場合は、動的に変化するパラメータを展開用フレーズに含めることが可能になります。
5日目の記事ではRubyスクリプトから駅すぱあと for web URL生成の機能を利用する例を紹介していました。今回はこの処理をATOK Sparkのプラグインの形で再実装してみます。
プラグインのプロトコル
先のスライドで解説されていますが、プラグインとATOK Sparkは標準入出力でやりとりするようです。プロトコルとしてやりとりできるコマンドはいくつか用意されていますが、最低限CHECK
とGETTEXT
を実装すればよさそうです。
プラグインのソースコードは以下のようになります。単に5日目の記事で紹介したRubyスクリプトをCHECK
とGETTEXT
プロトコルに対応させただけです...。
#!/usr/bin/env ruby
# coding: utf-8
require 'net/http'
require 'uri'
require 'erb'
include ERB::Util
require 'json'
# URLリクエストを投げる
def request(url_str)
url = URI.parse(url_str)
req = Net::HTTP::Get.new(url.request_uri)
if ENV['http_proxy'] != nil
ENV['http_proxy'] =~ /http:\/\/(.*?):(.*?)\//
proxy = Net::HTTP::Proxy($1, $2)
res = proxy.start(url.host, url.port) {|http|
http.request(req)
}
else
Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
end
end
# アクセスキー
key = ENV['EKISPERT_ACCESS_KEY']
# ATOK Sparkと接続するための識別文字列を返却します
puts "HELLO ATOK Spark/0.0"
# dataversionを取得する
url_str = "http://api.ekispert.jp/v1/json/station/light?key=#{key}&name=#{url_encode(ARGV[0])}"
engine_version = JSON.parse(request(url_str).body)["ResultSet"]["engineVersion"]
result_url = ''
loop do
line = gets.chomp
next if line == nil
if line =~ /CHECK \/search\/course\/light:(.*?):(.*?):/
keyword = $1
# 出発駅の駅コードを得る
url_str = "http://api.ekispert.jp/v1/json/station/light?key=#{key}&name=#{url_encode($1)}"
from_code = JSON.parse(request(url_str).body)["ResultSet"]["Point"][0]["Station"]["code"]
# 到着駅の駅コードを得る
url_str = "http://api.ekispert.jp/v1/json/station/light?key=#{key}&name=#{url_encode($2)}"
to_code = JSON.parse(request(url_str).body)["ResultSet"]["Point"][0]["Station"]["code"]
# 探索結果を駅すぱあと for webのURLとして取得する
url_str = "http://api.ekispert.jp/v1/json/search/course/light?key=#{key}&from=#{from_code}&to=#{to_code}"
result_url = JSON.parse(request(url_str).body)["ResultSet"]["ResourceURI"]
puts "REPLACE 0"
elsif line =~ /GETTEXT 0$/
puts "TEXT #{result_url}"
end
if line =~ /QUIT/
break
end
end
CHECK /search/course/light:東京:高円寺:
のようなコマンドを入力すると、駅すぱあと for web URL生成を呼び出し、探索結果のURLを取得します。CHECK
コマンドの引数の形で入力された文字が渡されてくるようで、入力文字の一部をコマンド名と出発・到着駅として解釈することで、動的に変化するパラメータを処理することができます。レスポンスとしてREPLACE 0
を返していますが、これはプラグインの中でマッチしたフレーズのインデックスになります。今回はCHECK /search/course/light:<出発駅>:<到着駅>:
の探索結果に対応するURLを1つだけ返す動作なので、インデックス0
を返しています。
GETTEXT
コマンドはATOK Sparkがプラグイン内でマッチしたフレーズを取得します。なので単に探索結果URLをTEXT <探索結果URL>
の形で返します。
実際に試してみる
さっそく実際にプラグインの動作を試してみます。が、実際にエディタからCHECK /search/course/light:東京:高円寺:
をうまく展開させられていないので、コマンドラインからの動作確認となります...。
(他のプラグインのドキュメントを見ると、plugin.lst
に作成したプラグインの実行パスを記述すれば良いらしいのですが...)
実行例としては以下のようになります。標準入出力でプロトコルのコマンドを入力することで動作確認としています。
$ ./plugin/ekispert_webapi_sample/search_course_light.rb
HELLO ATOK Spark/0.0
CHECK /search/course/light:東京:高円寺:
REPLACE 0
GETTEXT 0
TEXT http://roote.ekispert.net/result?arr=%E9%AB%98%E5%86%86%E5%AF%BA&arr_code=22671&connect=true&dep=%E6%9D%B1%E4%BA%AC&dep_code=22828&highway=true&hour&limitedExpress=true&liner=true&local=true&minute&plane=true&shinkansen=true&ship=true&sleep=false&sort=time&surcharge=3&type=dep&via1=&via1_code=&via2=&via2_code=
ちなみに、(当たり前といえばそうですが)ATOK Sparkにサンプルとして登録されているフレーズもCHECK
コマンドで展開できます。
(なのでATOK Spark自体には接続できているようです)
CHECK main:
int main( int argc, char* argv[] )
{
// パラメータ解析
std::map<std::string,std::string> xMap;
if( argc == 1 ){
// 引数なし
}else{
// 引数あり
xMap = parse( argc, argv);
}
★ここにメインの処理を記載します
return 0;
}
まとめ
ATOK Sparkのプラグインから駅すぱあとWeb APIを呼び出してみました。今回は探索結果URLをフレーズとして展開しただけですが、経路探索結果をテキストで表示したり、時刻表情報を展開できるようにする等の応用例がありそうです。
(エディタからプラグインのフレーズ展開を呼び出す方法を調べ切れていないのが難ですが...)