2010/09/01

選択テキストをWeb検索するHotstrokes定義

選択中の文字列をパラメータにして検索サイトのURLを開くなど、エディタやブラウザでの選択文字列に対して処理を行いたいことはよくあります。

NILScriptでは、「Window」ユニットの「Edit」クラスに用意されている「selection」プロパティで選択文字列の読み書きを行なえますが、エディットコントロール側がエディタ関連のウィンドウメッセージに応答するように作られている必要があり、全ての選択テキストに対して有効なわけではありません。
エディタ関連メッセージに未対応のテキストエディタやブラウザなどからは、別の方法で選択テキストを取得しなければなりません。
一番汎用的だと思われるのは、Ctrl+Cなどを送信してコピーを実行し、クリップボードにコピーされたテキストを取得する方法でしょう。

下記に挙げるのが、エディタ関連メッセージに対応したコントロールではselection、それ以外のコントロールではクリップボードを使用して選択テキストを取得しGoogle検索するという機能をHotstrokesに割り当てるスクリプトです。
Main.createNotifyIcon();
var {Clipboard}=require('Clipboard');
var {Hotstrokes}=require('Hotstrokes');
var {Edit}=require('Window');
Hotstrokes.defineConditions({
 'Editor':function()(['Edit','TEditorX'].contains(this.focusedWindow.className)),
}).map({
 'Win+G':{
  'Editor':function(){
   this.cancel();
   exec('http://www.google.com/search?q='+encodeURIComponent(Edit.focused.selection));
  },
  '':function(){
   this.cancel();
   Thread.create(function(){
    var bk=Clipboard.text;
    Hotstrokes.send("Ctrl+C");
    sleep(100);
    exec('http://www.google.com/search?q='+encodeURIComponent(Clipboard.text));
    if(bk){
     Clipboard.text=bk;
    }
   });
  },
 },
}).register();
最初のdefineConditions()では、「Editor」という条件名にエディタ関連メッセージに対応したコントロールのクラス名を条件とする関数を定義しています。
「contains()」は、引数で指定した値を要素として持つかどうかを返す配列の拡張メソッド、「this.focusedWindow.className」は、ストロークが受理された時にフォーカスを持っているコントロールのクラス名を得る式です。
上記の例では、メモ帳などで使われる基本的なテキスト編集欄であるEditや、VxEditorで使われているTEditorXを対象として定義しています。

map()では、Windowsキー+Gに対して、条件に応じた動作を割り当てています。
「this.cancel()」というのは、Gキーの押し下げストロークの本来の動作を無効化するという動作です。これがないと、「g」という文字が入力されて選択テキストが上書きされてしまうでしょう。

Editorの場合の動作では「Edit.focused.selection」でフォーカスのあるエディタの選択テキストを取得しています。「Edit.forused」は、フォーカスのあるコントロールをEditクラスのインスタンスとして取得するというEditクラスのプロパティです。
exec()は、システムの関連付けに従ってファイルやURLを開く関数、encodeURIComponent()はURLのパラメータとして使えるように文字列をエンコードするJavaScript標準の関数です。


他の条件に一致しなかった時に参照されるデフォルト動作である「''」に対する割り当てでは、this.cancel()以外を「Thread.create()」によって新規スレッドで実行しています。
sleep()などを含み時間がかかる処理は、そのまま実行すると動作が不安定になってしまう場合があるので、このようにして新規スレッドで実行させるように習慣づけておくとよいでしょう。
スレッド内では、クリップボードのテキストを変数にバックアップし、Ctrl+Cを送信し、コピー処理が完了するのをsleep()で待って、検索結果のURLを開き、バックアップしたテキストがあれば書き戻すという処理を行っています。

0 件のコメント:

コメントを投稿