Clipboard API

wasavi からクリップボードを操作する場合、vim と同様レジスタ “* を使って y/d/p する。Chrome と Firefox はエクステンションがクリップボードにアクセスする API を提供しているので、問題ない。

問題は Opera なのだ。例によって。

一方、Opera は 12.50 で Clipboard API をサポートするという。これは何かといえば、ユーザがブラウザの提供するカット、コピー、ペースト機能を呼び出した時に、その本来の働きが行われる前にイベントとして取れるようにする、またそのイベントハンドラの中でクリップボードにアクセスできるようにする、その辺の仕様を規定したものだ。

重要なことに、これはカット、コピー、ペースト機能自体をスクリプタブルにするものではない。そういうことはできないと仕様に明示してある。ユーザが ctrl-c を押した時にセレクションの内容にかかわらずクリップボードには “ほげほげ” とコピーする的ないたずらはできるが、ユーザの知らないところでクリップボードを読み書きすることはできない。そういうあくどいことはともかく、たとえばブログでよくあるコードサンプルでの「ボタンを押すとコードをコピー」的なものもできない。

というわけで、Composition Events 同様迂回策を考える必要があるのだが……。まずクリップボードへの書き込みに関しては、かつては Flash を経由してできたかもしれないが、今は無理。読み出しに関しては、input モードで ctrl+v が押されたことを前述の Clipboard API を通じてキャッチし、デフォルトの動作をキャンセルした上で wasavi の動作として貼り付けることはできると思う。使い勝手は端末から vim を使ってる時に input モードで端末の機能を使ってペーストする感じに似ている。

ctrl+v はもちろん wasavi では vim 同様の特殊な文字入力のプリフィクスなので、やはり vim 同様 ctrl+q もプリフィクスとして認めるようにして ctrl+v は開けておく必要がある。

しかしこうしてみるとととても中途半端なものにしかならないなあ。ダメだなこれは。はやく Opera もエクステンションでクリップボードの読み書きできるようにしてください。

wasavi, come here

wasavi を呼び出すのに、textarea 内で特定のショートカットを押す。このときの手法は、コンテントスクリプトで document に capture フェーズの keydown イベントハンドラを引っ掛けるという極々ふつーのものだ。ふつー過ぎて、ページによっては時々この keydown イベントの監視による wasavi の起動がなされないことがある。

コンテントスクリプトはページ自体が持つスクリプトよりも早い段階で実行され、keydown イベントハンドラの登録もページスクリプトより先だ。イベントハンドラの呼び出しは登録順なので、つまりキー入力に対して wasavi の起動監視が最も早く行われるはずなのだが、なんで起動がなされないのかちょっと不思議。いろいろ追いかけてみる必要がある。あるのだけど、とりあえずのワークアラウンドとして textarea 上のコンテキストメニューに「Run wasavi」的なものを追加して、そこからも起動できるようにした。Opera にも 12.10 からエクステンションによるコンテキストメニューのアクセスが可能なのだ。ってすごい最近ですね。

ちなみにエクステンションによっては、hotkey 的な API を提供しているものもある。たぶんそっちを使ったほうが強力なのだろう。でもざっと各エクステンションの仕様を見る限り Chrome の commands API では動的にキーバインドを定義できない? manifest に記述してそれだけなんだよね。というわけでまだそういうものは使っていない。Opera にそういう API ないし。

Opera と言えば、こうやって wasavi で書いてる間もなんか起動したりしなかったりする。これはどうも wasavi の問題ではなくて Opera のキャッシュがぶっ壊れている(iframe に読み込んだ http://wasavi.appsweets.net/ に対して、その injected script である wasavi.js が実行されない、ときがある)っぽいのが困る。設定からキャッシュを全削除して Opera を再起動すると直る。直らなかったりする。やめてよねそういうの!

wasavi 0.5.280 released

リリースした。

変更点
  • キー入力がバッファリングされた後再生されなかったのを修正
  • 入力した行が textwidth を超えてしまうことがあるのを修正
  • 実行中に上書きした設定がページリロード後に再生される機能を実装
  • Opera で実験的・擬似的に Composition Events が動くようにした
  • 入力モード中のパフォーマンスを修正
  • J コマンドが失敗するのはカーソル行が最下行にあるときのみにした
  • Google 日本語入力使用時、不要なコントロールコードが入力されることがあるのに対処
  • Firefox 18 で ctrl+[a-z] を押下した時のキーコードが変更されているようなので対処
ダウンロード

 * * *

Chrome、Opera、Firefox の各エクステンションのリポジトリに更新を申請した。

Spring is approaching

ぼちぼち Opera でも安定して input モードが動作する頃になってきたような気がする。そろそろ公開するかな。ただ *nix で Composition Events のエミュレーション自体が不可能なのは対処のしようがないのが残念。*nix と書いたのはたぶん BSD とかでも同じだろうということで(試してはいない)。

ただまだ undo ログが不正になる時があるんだよなー。それを直したら公開しよう。

undo はほんとうに難しい。もしかしたら根本的に書きなおさないとダメかもしれない。

Similarity and Edit distance

ページのリロード後も設定を持ち越す、という動作を実装する。先に書いたとおり、難しいのはリロード前に wasavi を起動させ設定を追加した textarea が、リロード後に必ずしも同じノードパスとは限らない、という点だ。これは、ノードパスを文字列化したもののレーベンシュタイン距離をとり、適当な閾値以内かどうか、で判断すれば良いと思う。

一方、ページのリロードではなくフォームの送信のように URL が変化する場合もある。また、URL のパスは同一でも、クエリ文字列やフラグメントが微妙に変化する場合もある。つまり URL についても類似性を見る必要があるかもしれない。例えば example.com/?foo=bar 上の textarea に対する設定は、example.com/?foo=baz をブラウズしたときも同様に再現されてほしい。ただしこれは微妙かもしれない。クエリ文字列やフラグメントが 1 文字変化しただけでまったく異なる内容を提供される場合もないとは言えないからだ。しかし、類似性を見て得る情報はしょせんエディタの設定だ。間違えたところで、今のところはそんなに危険というわけでもないので、まあいいだろう。

URL については構成部品ごとに分けて考える必要があると思う。パス部分は曖昧な類似性は関係ない。同じか否かで見る。一方クエリ文字列は難しい。& で連結される key=value の部分は順不同だからだ。?foo=1&bar=2&baz=3 と ?baz=3&foo=1&bar=2 は実質同じクエリ文字列だが、レーベンシュタイン距離は結構な値になる。そうすると、クエリ文字列の類似性はレーベンシュタイン距離ではなく、trigram による similarity measure を見たほうがいいかもしれない。

 * * *

そんな感じで組んでみた。覚えておく URL は直近の 30 件、類似性の閾値は 0.8 とした。

Opera is bad #7

いろいろ弄っているのでまた wasavi で取り留めのないことを書いてみよう。

テレビ、具体的には公共放送の相撲中継を見ていて気になるのだが、解説の親方はじめ、あまりテレビ慣れしていないと思われる方々はなぜかインタビューされると「そうですね、」というのを最初に付けすぎだと思う。なんなんだ、イエスマン症候群か。

それ系のことに注意してテレビのインタビューを見ていると、能動態と受動態の混乱とか、「~だし、~だし、~だし、……」という「『し』の行進」とか、「○○は、××が△△という○○」みたいな口語ならぎりぎり許されるレベルのへんてこな文構造とか、「~なんですけどー」(けど、何?)という定型的な語尾とか、いろいろ気になり始めるのである。

しかしまあ、気にしたら負けなのだろう。たぶん。

 * * *

ちなみにここまで wasavi on opera で書いてみて、なんか笑っちゃうほど buggy なので結構がっかりしているところである。ああ……。

一応 Opera の名誉のために書いておくと buggy なのは Chrome/Opera/Firefox で同じような動作をさせようとしている wasavi のコードであって、Opera は悪いか悪くないかといえばとりあえず悪くはない。しかし根本的な原因をさかのぼれば、いろいろと回りくどい動作を強いる Opera が悪いのは言うまでもない。

Opera is bad #6

ぼちぼち、Google 日本語入力でも安定して入力できるようになってきた。とはいえまだびみょーにあれ? という点がある。それを洗い出すためにとりとめのないことでも書いてみよう。

今使っているキーボードは Thinkpad USB Keyboard with trackpoint というやつなのだが、最近になってというか昨日のことなのだが「=」キーの効きが悪くなった。押下して、感覚的に入力されるかな? というタイミングで入力されない。そこでキートップを外してみた。

キートップを外すのは割と簡単だ。パンタグラフの四隅が、キートップの裏のそれぞれのかみ合わせに引っかかるようになっている。そこでマイナスドライバーをまずキーの下側の真ん中に差し込み、くるっと回す。同様に上側からもドライバーを差し込み回す。回すのはゆっくりではなく素早くやったほうが良いようだ。

ちなみに tab キーを始めとする横に長めのキーは四隅というにはちょっと中心部分に寄ったところがかみ合わせになっているので、ドライバーでくるっ、も 4 回に分けたほうが無難だ。

というわけで外してみたところ、細い毛がラバーカップの上に乗っていた。こんな微妙な原因でキータッチの感覚が変わってしまうのかー。

などと書いていて早速気づいたが、変換した時に出てくる候補のポップアップが仮入力文字列の上にかぶさっていてとても見にくい。うーんテストページではちゃんと表示されるんだけどな。カーソルの要素が position:fixed なのが問題なのかしらん? とりあえずいろいろ調べて見ることにしよう。

 * * *

どうも Opera のバグのようだ。wasavi の iframe に box-shadow をかけて、さらにその iframe が position:fixed か position:absolute だったとき、おそらく内部的には原点が影の分だけ左上に移動するのだろうが、変換候補ポップアップについてはそれを考慮した補正を忘れている。とそんな感じだと思う。Chrome や Firefox ではそういった現象は起こらない。また、これが起こるのは Windows だけのようだ。

ということでバグレポした。DSK-380712。

Opera が悪い。

Opera is bad #5

勘違いだった。Google 日本語入力でも、イベントの発生の仕方は同じだった。wasavi 側の対応をちょっと修正。input モード時はカーソルを消去しないようにした。

ちなみに、キーボードの入力のテストは http://appsweets.net/wasavi/keytest/index.html で行うことができる。手元には Windows+ATOK とか、Mac OS X の環境がないので確認できない。それらの環境で、compositionstart、compositionupdate、compositionend イベントが Chrome や Firefox と異なる振る舞いをしていたら教えてください。

Ubuntu でも試してみた。iBus+Anthy、iBus+mozc の両方で、仮入力中はなぜか keydown イベントが発生しない。input や keyup イベントは発生する。うーんどういうことなのか。keydown イベントが発生しないとそもそも composition events のエミュレーションを開始すること自体ができないのだけど。これはどうすることもできないかもしれない。

いやー本当に、Opera は、ダメなブラウザだ。Opera が悪い。

Thinkpad bluetooth keyboard with trackpoint

むむっ。

【CES 2013レポート】Lenovoがテーブル型PCやフルHD 11.6型着脱式ThinkPadを公開
http://pc.watch.impress.co.jp/docs/news/event/20130107_580789.html

Thinkpad USB keyboard with trackpoint の後継モデルが出るようだ。欲しい。

いくらくらいになるのかなー……?

 * * *

などと唐突に wasavi と何の関係もないエントリ。とりあえず安定して、Opera でも IME を通した入力ができるようになった。

 * * *

Google 日本語入力でも試してみた。うーん微妙にイベントの発生の仕方が違う。暗黙的変換時の input イベントの発生回数が違う? これは要調査。

Opera is bad #4

wasavi の設定は、基本的には exrc、つまりエクステンションが保持する localstorage の項目に書いておく。しかしこれだけだといろいろと煩雑だ。また、wasavi を使用するのは何かを送信するフォーム内の textarea というケースが最も多いと思うが、ajax を駆使したフォームでもない限り送信することでページが更新されるので、送信前の wasavi でテンポラリ的に :set なんちゃらした値は送信と共に失われてしまう。

これをなんとかしたい。つまり、wasavi の実行中に動的に変更したオプションを、ページの更新を超えて自動的に再現したい。

ここで難しいのは、ページ更新前に与えた wasavi の設定が、更新後の html 内のどの textarea に対応するか、という判定だと思う。たとえば textarea に id が振られていれば、それを判断の材料にできる。しかし id に頼るのは危険かもしれない。論理的には更新前後で同じ textarea だったとしても、サーバ側の都合で異なる id を振られている場合が考えられるからだ。

id ではなく、たとえば html のルート要素から textarea へ至るパスを頼るのはどうか。つまり html->body->div->textarea みたいな感じの文字列をキーにしたハッシュを保持して、それに設定を書いておく。実際は、html(1)->body(1)->div(3)->textarea(1) みたいに要素のインデックスも必要かも。

この構造が更新ごとにダイナミック、あるいは微妙に変化する html ページってあるかなあ。たとえば更新ごとに div 内の最初に textarea が配置されたり最後に配置されたりするページ。ないとは言えないか。そうすると、ノード名を単語とみなした sentence similarity measure を測ったりする必要があるかもしれない。めんどうだなー。

 * * *

よく考えたらこの話題は別に Opera に文句をつけるものではなかった。まあいいか! Opera が悪いのは事実だし!