PHP in cygwin

普段 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
> mklink php.exe "C:\Program Files (x86)\php\current\php.exe"
などとしてみた: 失敗。Windows では実行形式を指すシンボリックリンクを実行したとき、argv[0] が真の実行形式ファイルを差さないようだ。それはシンボリックファイルを指したままだ。だから、実行形式を指すシンボリックリンクを実行した場合、実行形式の存在するディレクトリを起点にして設定ファイルを読み込んだりする処理はことごとく失敗する。うちの環境の php の場合、php.exe の隣においてある php.ini が読み込まれない。

そういうわけで /usr/bin/php として

#!/bin/sh
exec "/cygdrive/c/Program Files (x86)/php/current/php.exe" "$@"

てな感じのシェルスクリプトを置くと動く。

また、php スクリプト側を

#!/usr/bin/env php


としてもいい。あんまりこの env のトリック好きじゃないけど、実質的にはいちばん楽かなー。

Selenium revised #3

仮想環境の Ubuntu 内でビルドとテストが行えるようにした。とりあえず chrome でテストが実行できることを確認したけど、なんか、仮想環境というのを差し引いてもちょっと遅い。全テストに 110 分くらいかかる。その他いろいろ微妙にテスト時の chromium の動きが Windows 上の chrome と違う部分がなくもない。

ついでに javascript の minifier として UglifyJS2 を使ってみた。

Selenium revised #2

以前書いた通り、wasavi をテストする Selenium の構成は

  • Selenium server
  • Selenium client (java)
  • junit
  • chromedriver
  • operadriver

といった感じで、それぞれの 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 を複数用意しろというのか。

Selenium revised

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 and cygwin

vim 7.4 がリリースされた。たぶん Cygwin 版もすでに更新されてるんじゃないかなと思い、Cygwin のセットアップを公式へ取りに行った。

すると今まで単に setup.exe として提供されていたインストーラが x86 版と x64 版にわかれているじゃないか。あれ? そういえば Cygwin って 32bit アプリケーションだったっけ? とタスクマネージャを見ると確かに *32 が付いている。

x64 版への移行ってどうするんだろ?

 * * *

とりあえず x86 版のセットアップを動かしてみたら vim は 7.3 のままだった。がぼーん。

ということで、単に Cygwin だけを更新した。

repository updated

Chrome、Opera、Firefox のそれぞれのエクステンションの公式リポジトリに提出してある wasavi を 0.5.359 に更新した。

Opera 版はまだ審査されていないので最新にはなっていない。明日か明後日くらいには更新されるだろう。Firefox 版は、例によってフルレビューがさっぱり進んでいないので、安定版は 0.5.281 とかその辺りにとどまっている。他のバージョンを見る というリンクから今回上げた最新版を参照できる。Firefox 版のみ、最新版は beta 版扱いになっているが、内容は他ブラウザと同じ。

clipboard access #4

vim にあって vi にはない、insert/overwrite モード、および ex コマンド入力時の特殊なショートカットして、^R をプリフィクスとしてレジスタの内容を貼り付ける機能がある。それを作る。

タイトルの通り、これにはクリップボードレジスタ “*” も含まれる。クリップボードを指定された場合は非同期的にそれを読みだしつつよきに計らう仕組みにする必要がある。それから、paste イベントのハンドラはクリップボード以外のレジスタを指定された場合にも実際に貼り付けを行う窓口として流用できる(文字列中の改行を調整したり、特定の文字を予めエスケープしておく処理は共通なので)。

そのためには、paste イベントハンドラを機械的に発生させられる必要がある。これは W3C の Clipboard API では、window.ClipboardEvent コンストラクタを使用することで可能だ。従来は、この手の定石は document.createEvent() でイベントオブジェクトを生成し、initEvent() とか initUIEvent() とかその他もろもろで初期化し、任意のノードで dispatchEvent() という手順だったのだが、deprecated みたい。コンストラクタでイベントオブジェクトを生成する場合はパラメータをディクショナリで指定したりするところがナウいと思う。
var pasteEvent = new ClipboardEvent('paste', { bubbles: true, cancelable: true, dataType: 'text/plain', data: 'My string' } );
document.dispatchEvent(pasteEvent);

さて、この ClipboardEvent をブラウザが備えてないと困るわけだけど…… Opera と Firefox は備えている。意外なことに Chrome が備えていない。paste イベントは認識するのに ClipboardEvent も WebKitClipboardEvent もない。どういうことなのかな。webkit のソースを見るとそれっぽいものはあるようなので単に安定版 Chrome にはまだ来ていないということなのか?

too strict review

AMO へ wasavi 0.5.329 をレビューに出してかれこれ 2 ヶ月くらい経っているのだが、音沙汰がない。レビューに出している間に何度かメールでのやり取りをしているのだが、dropbox に対しての読み書きについてテストの手順を教えてくれとのリクエストに 7 月 30 日に返事して以来音沙汰がない。キューの位置は 10 of 145 である。よほど巨大なアドオンが前に詰まっているのか?

あまりに時間がかかるので、AMO へ提出する Firefox 版は当分ベータバージョンにするかもしれない。つまり 0.5.351beta のようになる。

ctrl-v

vim から拝借してきた機能の一つにプリフィクス付きの文字入力というものがある。

insert/overwrite モード、あるいは ex コマンド入力中に ^V を押すと、次に入力する文字がその文字そのものとして入力される(ただし insert/overwrite モードで ^M、^J を入力した場合のみは enter を入力した場合と同様に改行が行われる)。これはおもにコントロールコードの入力に使用されるのだが、wasavi では ^V に続けて数字、または o/O/x/X/u/U を押した場合はさらに特殊な状態に遷移する。

  • 数字: 最大 3 桁まで入力でき、10 進文字列として評価した値をコードポイントとしてみなした時の対応する文字に変換される
  • o/O: 最大 3 桁まで入力でき、8 進文字列として評価した値をコードポイントとしてみなした時の対応する文字に変換される
  • x/X: 最大 2 桁まで入力でき、16 進文字列として評価した値をコードポイントとしてみなした時の対応する文字に変換される
  • u: 最大 4 桁まで入力でき、16 進文字列として評価した値をコードポイントとしてみなした時の対応する文字に変換される
  • U: 最大 6 桁まで入力でき、16 進文字列として評価した値をコードポイントとしてみなした時の対応する文字に変換される

^VU でのコードポイント入力は Unicode の BMP を超えた先も対応していて、その場合はサロゲートペアが生成される。