短期集中連載 速報!Ubiquityのポテンシャルを探れ

第3回Ubiquityでオリジナルコマンドを作ろう(応用編)

今回は、前回に引き続き、実際に自分のコマンドを作ってみます。サンプルとしてgotoコマンドを例に挙げ、応用して利用する方法について紹介します。

gotoコマンド - シンプル版

開きたいサイトが明確にわかっている場合、ブックマークやポータルサイト、ソーシャルブックマークは操作性が遅い場合があります。ブックマークツールバーに登録しておいてボタン1つで飛ぶようにしておいても、対象が増えてくるとスクロール操作が必要になるなど煩雑です。コマンドとキーワードで特定のサイトにジャンプできるようになると便利です。

ここでは、Ubiquityを使ってキーワードから特定のURLにジャンプするコマンド「goto」を作成しながら、Ubiquityコマンドの作成方法や、より実用的な実装方法を説明します。

リスト1 gotoコマンド - シンプル版
CmdUtils.CreateCommand({
  name: "goto",
  takes: { "argv": noun_arb_text },

  author: { name: "Daichi GOTO" },
  license: "BSD",

  execute: function( argv ) {
    var href = "";

    switch ( argv.text ) {
      case "reader":
        href = "http://www.google.com/reader/";
        break;
      case "mixi":
        href = "http://mixi.jp/";
        break;
      case "twitter":
        href = "http://twitter.com/home";
        break;
      case "calendar":
        href = "http://www.google.com/calendar/";
        break;
      case "gmail":
        href = "https://mail.google.com/mail/";
        break;
      case "home":
        href = "http://www.google.com/ig";
        break;
      default:
        href = "http://www.google.com/ig";
        break;
    }

    displayMessage( "going to " + href );
    Utils.openUrlInBrowser( href );
  },
});

引数に任意の文字列を指定し、execute: function()で引数をチェックします。特定のキーワードに一致した場合はdisplayMessage()でメッセージを出力してから、対応するURLをUtils.openUrlInBrowser()で開きます。

たとえば「goto reader」でGoogle Readerにジャンプし、⁠goto mixi」でMixiにジャンプします。最低限の機能としてはこれで十分であるため、あとはキーワードとURLを追加していくことでより多くのサイトにジャンプできるようになります。

gotoコマンド - カスタム名詞型で補完入力

Ubiquityのコマンド入力を効率的に実施するには補完機能の活用が欠かせません。先ほど作成したgotoコマンドに、静的なカスタム名詞型を使って入力補完機能を実施してみます。任意の文字列名詞型(noun_arb_text)だったところをカスタム名詞型で置き換えます。

リスト2 gotoコマンド - カスタム名詞型で入力補完機能を有効化
noun_type_sitekey = new CmdUtils.NounType(
  "sitekey",
  [ "reader", "mixi", "twitter", "calendar", "gmail", "home" ]
);

CmdUtils.CreateCommand({
  name: "goto",
  takes: { "argv": noun_type_sitekey },

  author: { name: "Daichi GOTO" },
  license: "BSD",

  execute: function( argv ) {
    var href = "";

    switch ( argv.text ) {
      case "reader":
        href = "http://www.google.com/reader/";
        break;
      case "mixi":
        href = "http://mixi.jp/";
        break;
      case "twitter":
        href = "http://twitter.com/home";
        break;
      case "calendar":
        href = "http://www.google.com/calendar/";
        break;
      case "gmail":
        href = "https://mail.google.com/mail/";
        break;
      case "home":
        href = "http://www.google.com/ig";
        break;
    }

    displayMessage( "going to " + href );
    Utils.openUrlInBrowser( href );
  },
});
図1 入力候補が表示される
図1 入力候補が表示される

これでキーワードの入力補完が有効になります。またカスタム名詞型に含まれていないキーワードが指定された場合には、gotoコマンドで処理する内容ではないとしてデフォルトの検索エンジンを使った検索へ処理が切り替わります。

gotoコマンド - 動的カスタム名詞型で補完入力

入力補完は有効になりましたが、先ほどの方法では名詞型とexecute: function()の両方にキーワードを入力する必要があり煩雑です。できればキーワードとURLの対応データは1ヵ所で記述し、名詞型はキーワードから自動的に作成できた方が便利です。このほうがソースコードの管理が簡単になりますし、名詞型と処理の両方にキーワードを追加する場合に片方だけ追加を忘れるというミスも防げます。

リスト3 gotoコマンド - 動的なカスタム名詞型で入力補完機能を有効化
var Sites = {
  'reader' : 'http://www.google.com/reader/',
  'mixi' : 'http://mixi.jp/',
  'twitter' : 'http://twitter.com/home',
  'calendar' : 'http://www.google.com/calendar/',
  'gmail' : 'https://mail.google.com/mail/',
  'home' : 'http://www.google.com/ig',
};

var noun_type_sitekey = {
  _name: "site keyword",

  suggest: function( text, html ) {
    var suggestions = [];

    for ( var keyword in Sites ) {
      if ( keyword.match( "^" + text ) ) {
        suggestions.push( CmdUtils.makeSugg( keyword ) );
      }
    }

    return suggestions;
  }
};

CmdUtils.CreateCommand({
  name: "goto",
  takes: { "argv": noun_type_sitekey },

  author: { name: "Daichi GOTO" },
  license: "BSD",

  execute: function( argv ) {
    displayMessage( "going to " + Sites[argv.text] );
    Utils.openUrlInBrowser( Sites[argv.text] );
  },
});

上記のようにすれば、キーワードとURLを1ヵ所で管理しつつ、1つ前のように補完処理も機能させることができます。特に次の部分に注目してください。これが静的に名詞型を作成していたところを動的に作成するように変えた部分です。

リスト4 名詞型の定義 - _unameとsuggest: function()が必要
var noun_type_sitekey = {
  _name: "site keyword",

  suggest: function( text, html ) {
    var suggestions = [];

    for ( var keyword in Sites ) {
      if ( keyword.match( "^" + text ) ) {
        suggestions.push( CmdUtils.makeSugg( keyword ) );
      }
    }

    return suggestions;
  }
};

名称として_nameを、補完候補を返す関数としてsuggest: function()を作成します。名詞型の正体がこれです。キーワードの入力に対して逐次suggest: function()が実行され、返ってくる候補一覧を使って補完対象を表示したり、対象のコマンドに一致する引数であるかどうかをチェックしているわけです。suggest: function()から空データが返ってくるとその名詞型ではないとして、別のコマンドの処理対象となります。

上記の場合、入力されたキーワードがサイト一覧データにあるか頭からチェックし、一致している場合には補完候補として返しています。補完候補にする段階でCmdUtils.makeSugg( keyword )のようにCmdUtils.makeSugg()を使っているところもポイントです。この関数を通じて補完候補データに変更しています。

開発向けドキュメント

UbiquityはすぐれたチュートリアルLabs/Ubiquity/Ubiquity 0.1 Author Tutoriaを提供していますが、APIドキュメントは提供されていません。今後の開発でAPIが変更される可能性も高いことから、APIドキュメントはある程度APIが固まってきてからの提供になると見られます。

今のところUbiquityの提供しているAPIを調べる最良の方法はUbiquityのソースコードを閲覧することにあります。Firefoxのユーザデータ領域にあるextensions/ubiquity@labs.mozilla.com/chrome/content/以下にメインのソースコードがインストールされていますので、開発の際の参考にしてください。

また、おもに次の3つのソースコードがUbiquityを使った開発で参考ソースコードとして活用できます。

名詞型の概念さえ掴んでおけば、あとはとくに困ることはないでしょう。JavaScriptのテクニックやjQuery APIを活用した開発が可能です。

Ubiquityコマンドの配布とアップデート

作成したUbiquityコマンドは次のような要素で指定しておけばFirefoxでページを閲覧した段階でコマンドのインストールへとつなげることができます。Ubiquityコマンドの配布については今後配布向けのサービスや信用できるかどうかのチェック機構などが用意されることになると見られます。

リスト5 Ubiquityコマンドファイルの配布用要素の書き方例
<link rel="commands" href="http://スクリプトへのパス" name="=スクリプトのタイトル" />

Ubiquityでは最終的に、一度インストールしたコマンドは現在のエクステンションのようにアップデートできるものにしようと考えているようで、どのように安全性を確保するかが注目されることになりそうです。

Ubiquityでコントロールを取り戻せ

まだ実験的な取り組みとして公開されているUbiquity 0.1.1ですが、すでにかなり興味深い機能拡張が可能なプロダクトに仕上がっています。とくにJavaScriptのプログラミング経験が豊富であれば、Ubiquityの提供している仕組みは実に簡単で興味深いものと言えます。

今回紹介した内容はUbiquityの初期段階にすぎず、今後さらに機能拡張や実装が予定されていることが楽しみといえます。あまり実用的とはいえそうもないのですが、日本語文章を解析するコードの鱗片がすでにUbiquityに追加されており、今後日本語への対応も進むのではないかとみられます。Ubiquityの今後の発展に注目です。

おすすめ記事

記事・ニュース一覧