CodeMirror 上で wasavi を起動できるようにした。また、ace でも同じように特別な対応を施すようにした。
ただ、若干もったいない話ではある。CodeMirror も ace も、それ自体が高機能なエディタなのだ。また、両者とも vi っぽいキーバインドにすることができる(ex コマンドっぽいものはない)。
CodeMirror 上で wasavi を起動できるようにした。また、ace でも同じように特別な対応を施すようにした。
ただ、若干もったいない話ではある。CodeMirror も ace も、それ自体が高機能なエディタなのだ。また、両者とも vi っぽいキーバインドにすることができる(ex コマンドっぽいものはない)。
github 上の issue についていくつか。
#18
sqlfiddle というサイトで wasavi がうまく起動しないというもの。このサイトでは、ページ上に CodeMirror を置いている。
CodeMirror 自体が javascript と DOM と css からなる複雑な要素で構築されたテキストエディタである。一方で wasavi はシンプルな textarea に対して起動する。したがって両者の相性はそもそも良くない。CodeMirror の実行中に ctrl+enter を押すと一応 wasavi が起動するが、これはたまたま現在の CodeMirror がキーボード入力を受け付けるために隠された textarea 要素を抱えているだけの話だ。起動しても、編集中のテキストが正しく wasavi に転送されるわけでもあるいは逆に書き出せるわけでもない。
なので、単にサポート外ですと言ってもいいのだけど、なんとかならないものなのだろうか?
CodeMirror を構成するオブジェクトとしては、
がある。wasavi の content script/injected script から、最後の CodeMirror インスタンスにアクセスできればなんとかなる。
実はこのインスタンスは div.CodeMirror 要素から参照できる。なのでページ上の javascript からは、
document.querySelector("div.CodeMirror").CodeMirror.getValue()
などとすれば CodeMirror が保持するテキスト全体を得ることはできる。しかし content script からは、参照している window が別だったりラップされていたりするのでこの方法は使えない(Opera ではできるが、inject script のコンテキストからページ上のスクリプトが生成したオブジェクトを直接呼び出すのは怖いのでやりたくない)。
wasavi が置き換える対象となる要素に対して内容を読み出したり書き込んだりする機構を汎用化してページのスクリプトのコンテキストを通すようにすればいいかもしれない。
ニュースというものは、「いつ」「誰が何をした」ということが、伝えられるべき最重要な事柄だということは言うまでもない。
というのも、IT にまつわる何かをググって IT 系ニュースサイトの記事が引っかかった時、それがいつ書かれたものか、記事の末尾にちんまりとしか載せられていないものがあって困るのだ。読み進めて「ふーん…」「うん…?」「これって、いつの記事なんだ?」……「2005 年じゃねーか!」とかなる。時間の無駄である。大見出しの直下にいつの記事なのか書かれてしかるべきものだと思う。それが統一されていないサイトが少なくない。
また、「誰が書いた記事か」というのも重要だ。かつて ZDNet Japan というサイトがあったのだけど、その中の単発のコラムかアンカーデスク的なものか忘れたが(憶えておく価値もないのだが)Dan なんとかという奴(憶えておく価値もないのだが)が「おまえは何を言っているんだ?」という全く的はずれな文章をよく載せていた。このサイトも、記名は文章の最後尾だったので、「ふーん…」「はぁ…?」「なんでそうなるの…?」……「Dan、またお前かよ!」とよくなったものなのだ。ページの頭に誰が書いたのかが書いてあれば、このような無駄なことをする必要もなかったのだ。
このような不誠実なことが起こらないために、ニュースサイトには「いつ」「誰が書いた」記事なのかをページの最初にはっきり書いて欲しいのである。
impress.co.jp、あなたのことを言っています。
wasavi を起動し、dropbox や gdrive にすでにディレクトリとして保存されているパスに対して :write した場合、エラーになってもらわないと困る。もしも保存したパスがディレクトリで、なおかつそのディレクトリの下に多数のファイルが保持されている時、有無を言わさずそれらがすべて消去され指定のパスが同名の単なるファイルにすり替えられるとしたら、これは絶対に避けなければならないケースだ。
google drive の場合、ファイルを上書きするには先んじてそのファイルの ID を得なければならない。これはこれで面倒な作業ではあるけれど、しかしその過程でファイルの mime タイプが application/vnd.google-apps.folder かどうかを判断するチャンスがアプリケーション側に与えられるので問題ない(それを一つのトランザクションとして見なした場合、そんなゆるゆるなチェック体制でいいのか? とは思うけど)。
dropbox の場合、ファイルを更新するにはそのパスと内容を同時にアップロードするだけだ。dropbox で上記のクリティカルなケースがどうなるか試してみたところ、どうもサブディレクトリの下にファイルがある場合はエラーになり、完全に空のディレクトリの場合は単なるファイルへの上書きが成功するようだ。
それはそれで賢い振る舞いなのかもしれない。また、この辺の振る舞いは別に wasavi 側で規定できるわけでもない。
ということで、そういう動きを受け入れることにする。
Presto Opera のエクステンションにおいて、エクステンション内のファイルを xhr なりなんなりで読み出した場合、先んじて /locales/[現在のロケール]/[指定されたファイル] というパスが検査され、そこにファイルがあれば優先して使用されるようになっている。この仕組みをもって、i18n に対応してます! と Opera は嘯いている。
このとき、[現在のロケール] とは具体的には何なのか。たとえば Opera の設定で UI のロケールを変更しても、エクステンションの上記の仕組みには影響しないようだ。
コンピュータにログインした状態では、だいたい
みたいな階層構造でロケールが定義されると思う。Presto Opera のエクステンションでは、どうも最後の UI ロケールは見ていないような気がする。このように、エクステンションのロケールを気軽に切り替えられないのは特にテストの時に不便だ。というのは、テストは en-us ロケールで実行するのが前提だからだ。Chrome はコマンドラインのオプションでロケールを指定できる、あるいは Firefox はプロファイルに設定したロケールが Add on SDK のロケールモジュールにも正しく影響するので問題ないのだけど、Opera だけがポンコツだ。
というわけで、Opera ネイティブの i18n システムをそのまま利用するのではなく、navigator の browserLanguage/language/userLanguage あたりを見て自前でロケールを決定するようにした。
つまり結局のところ Opera ネイティブの i18n システムは利用しないことになった。用意されてる機能がポンコツ過ぎて役に立たないというのは、まあ Opera においてはよくある話なのであります。
普段 Windows 上で作業しているといっても、実際は cygwin の端末の中でちくちくしているわけだ。
一方で、Windows 向けの PHP をインストールもしている。そうすると cygwin の中から PHP スクリプトを呼び出したくなる時もある。どうすればいいだろうか。
純 Windows 環境側の path 環境変数で、すでに php.exe にはパスを通してある。また cygwin は起動時にその path を継承するので、とりあえず cygwin 上で
$ php -f C:\path\to\script
というのはできる。次に shebang を通して実行させたい。つまり #!/usr/bin/php
と 1 行目に書いた php スクリプトを実行させたい。
うちの環境では、cygwin 上の php.exe の位置は [cci]/cygdrive/c/Program Files (x86)/php/current/php.exe[/cci] だ。そこでまず、コマンドプロンプトで > cd C:\cygwin\bin
などとしてみた: 失敗。Windows では実行形式を指すシンボリックリンクを実行したとき、argv[0] が真の実行形式ファイルを差さないようだ。それはシンボリックファイルを指したままだ。だから、実行形式を指すシンボリックリンクを実行した場合、実行形式の存在するディレクトリを起点にして設定ファイルを読み込んだりする処理はことごとく失敗する。うちの環境の php の場合、php.exe の隣においてある php.ini が読み込まれない。
> mklink php.exe "C:\Program Files (x86)\php\current\php.exe"
そういうわけで /usr/bin/php として
#!/bin/sh
exec "/cygdrive/c/Program Files (x86)/php/current/php.exe" "$@"
てな感じのシェルスクリプトを置くと動く。
また、php スクリプト側を
#!/usr/bin/env php
としてもいい。あんまりこの env のトリック好きじゃないけど、実質的にはいちばん楽かなー。
仮想環境の Ubuntu 内でビルドとテストが行えるようにした。とりあえず chrome でテストが実行できることを確認したけど、なんか、仮想環境というのを差し引いてもちょっと遅い。全テストに 110 分くらいかかる。その他いろいろ微妙にテスト時の chromium の動きが Windows 上の chrome と違う部分がなくもない。
ついでに javascript の minifier として UglifyJS2 を使ってみた。
以前書いた通り、wasavi をテストする Selenium の構成は
といった感じで、それぞれの jar あるいは exe を必要とする。テストを java で書くのは wasavi のビルドを ant に頼っていて、また ant から junit のテストを呼び出すのが簡単だからだ。
chrome
chrome の場合は chromedriver.exe というものが chrome と Selenium の間に立つブリッジになる。これを最新のもので更新したところ、いきなり動かなくなった。というのは、テスト用に立ち上げた chrome に wasavi が読み込まれないのである。この場合の wasavi は、開発者モードとして読み込まれる必要がある。これはつまりエクステンションのアーカイブではなく、ファイルシステム上のソースをそのまま参照してねモードだ。このモードを指定するには、chrome の起動時のコマンドラインオプションで [cci]–load-extension=C:/path/to/extension[/cci] てな感じのを追加する。
で、それがどうやら効いていないようなのだ。テスト用に立ち上げた chrome で chrome://version を開いてコマンドラインを参照してみると、wasavi 以外に selenium とのやりとりのためのエクステンションが指定されている。どうやらこれと競合しているらしい。–load-extension って複数指定できないんだっけ。
というわけで、テスト用 chrome に対してプロファイルディレクトリを明示して指定するようにして([cci]–user-data-dir=C:/path/to/profile[/cci])、そのプロファイルに対して予め開発者モードの wasavi を登録しておくようにした。
その他は特に問題なし。
opera
opera の場合、operadriver.jar が opera と Selenium の間を取り持つ。operadriver.jar は Selenium client に付属しているので、基本的には別途取得する必要はない、のだけど。たとえば Selenium 2.35.0 に付属の operadriver-1.4.jar だと、うまく opera 12.16 が起動してくれない。数日前にリリースされた operadriver-1.5.jar を代わりに使う必要がある。
このように、Selenium とブラウザと付随するライブラリのそれぞれのバージョンによって動いたり動かなかったり、一部の機能が動かなかったりすることがけっこう多い。これは困ったものです。特に最近のブラウザはえらい勢いでバージョンが上がるので、なおのことその危険性は高い。
ブラウザのオートメーションというものは、このようになんだかずいぶん脆弱な仕組みの上にかろうじて成り立っているように思える。この辺りの動作こそブラウザベンダ同士が協働して仕様やプロトコルをきっちり決めたらいいんじゃなかろうか。
ちなみに opera の場合もプロファイルを明示して、そのプロファイルに対して開発者モードの wasavi を登録しておく必要がある。
firefox
firefox については特別な jar ファイルとかは必要ないのだけど、その代わりなんか動作が変だ。たとえば shift キーとかのモディファイアを指定したキーストロークを送出することができない。wasavi は起動するためにデフォルトで ctrl+enter のショートカットを使うので、これはなかなか致命傷なのである。
あと、全体的に遅い。chrome で全テストを終えるのにだいたい 1 時間かかるのだけど、firefox で行うとだいたい 1.5 倍くらいの時間がかかる。
また、firefox にはエクステンションを開発者モードで読み込む的な機能がない(知らないだけであるのかもしれないが)ので、テスト前に一旦アーカイブをビルドする必要があるのが地味に面倒くさい。
* * *
というわけで一応 3 ブラウザでテストを行えるようにはなりつつあるのだけど、実行時間が問題だ。先に chrome でさえテストに 1 時間かかると書いたが、これはすべてのテストをシーケンシャルに行っているからだ。テスト自体は編集のテストとか、ex コマンドのテストとか機能毎に独立したソースになっているので、すべてを並列にとは言わないが、せめて同時に 3 枚くらいウィンドウ出して並行して行えばスピードアップできるのである。そんな機能ないのかなー。
また特に firefox の場合、テスト用に立ち上がる firefox が必ずフォアグラウンドな状態じゃないとテストが失敗するという意味の分からない動作をする。つまりテストの間 pc はそれに専念する専用マシンと化してしまうのだ。
なに、それ。テスト専用 pc を複数用意しろというのか。
Firefox 版の wasavi を AMO にフルレビューしてくれと提出してもう 2 ヶ月くらい経つのだが、キャンセルした。というのはあまりにレビューが遅いからではなくて、なんとびっくりすることに Firefox 版の 0.5.329 では http://wasavi.appsweets.net/ を開いた時に自動的に wasavi が起動する機能がバグってて動かなかったのだ。
これはかなり恥ずかしい。wasavi をリリースする前準備として、Selenium を通した機能テストを行っている。666 項目のテストをパスしてからリリースするのである。といっても、実を言うと、そのテストは Chrome だけでしか通していないのであった。Opera と Firefox は通していない。
これは、wasavi の仕組みのせいなのか、Selenium の制限なのか、Selenium と Opera/Firefox をつなげるブリッジ部分のドライバの制限なのかよく分からないが、とにかく Opera と Firefox で動かすと wasavi をそもそも自動起動させられなかったり、キー入力が無視されたりしてテストにならなかったのだ。Chrome だけが素直にテストが通る。
しかしそういうわけにもいかない。3 ブラウザで完全にテストを通すようにしないといけない。そういうわけで Selenium のテストを見直すことにしよう。
vim 7.4 がリリースされた。たぶん Cygwin 版もすでに更新されてるんじゃないかなと思い、Cygwin のセットアップを公式へ取りに行った。
すると今まで単に setup.exe として提供されていたインストーラが x86 版と x64 版にわかれているじゃないか。あれ? そういえば Cygwin って 32bit アプリケーションだったっけ? とタスクマネージャを見ると確かに *32 が付いている。
x64 版への移行ってどうするんだろ?
* * *
とりあえず x86 版のセットアップを動かしてみたら vim は 7.3 のままだった。がぼーん。
ということで、単に Cygwin だけを更新した。