2012年8月26日日曜日

Eclipse PDT でコメント切り替えショートカットキーが効かなくなるのを直す

Eclipse 4.2 Juno にアップデートしたら、Ctrl+/によるコメントアウトの切り替えが動作しなくなることがありました。

どうやら、エディタを複数開くと2つ目以降でCtrl+/が効かなくなるものがあるようです。
調べるうちに、同じ現象での相談がフォーラムに投稿されているのを見つけました。

http://www.eclipse.org/forums/index.php/m/894630/

解決方法はPDTプラグインの中身を直接いじるというもの。jarファイルを展開、編集して再度アーカイブするように書いてあります。

展開後再アーカイブする方法を試してみましたがエラーが出るなどうまくいきませんでした。しかし、再アーカイブではなくアーカイブ中の対象ファイルのみを更新する方法でうまくいきましたのでその方法を書きます。

jar を展開する

まず、編集対象のファイルを取り出すため、対象のjarファイルを展開します。
Eclipse Pleiades All in Oneでは、
eclipse\dropins\PDT\eclipse\plugins\org.eclipse.php.ui_3.0.1.v201201110400.jar
にありました。 元のjarをバックアップした後、一時フォルダにコピーします。

その後コマンドプロンプトを起動し、一時フォルダに移動してjarを展開します。
> jar xvf org.eclipse.php.ui_3.0.1.v201201110400.jar

plugin.xmlを書き換える

展開されたファイルのうち、plugin.xmlを書き換えます。書き換える箇所は612行目付近の次の箇所です。

書き換え前:
<!-- overriding WST's Handlers with the same 'commanId' -->
<handler class="org.eclipse.php.internal.ui.actions.PHPToggleLineCommentHandler"
    commandId="org.eclipse.wst.sse.ui.toggle.comment">
    <activeWhen>
    <or>
        <reference definitionId="org.eclipse.php.ui.phpContentType.definition" />
       <with variable="activePartId">
        <equals value="org.eclipse.php.editor"/>
       </with>
    </or>
        
    </activeWhen>
    <enabledWhen>
        <reference definitionId="org.eclipse.php.ui.phpContentType.definition" />
    </enabledWhen>
</handler>
書き換え後:
<!-- overriding WST's Handlers with the same 'commanId' -->
<handler class="org.eclipse.php.internal.ui.actions.PHPToggleLineCommentHandler"
    commandId="org.eclipse.wst.sse.ui.toggle.comment">
    <activeWhen>
        <reference definitionId="org.eclipse.php.ui.phpContentType.definition" />
    </activeWhen>
    <enabledWhen>
        <reference definitionId="org.eclipse.php.ui.phpContentType.definition" />
    </enabledWhen>
</handler>

jarを更新

書き換えたplugin.xmlをjarに注入して更新します。
> jar -uf org.eclipse.php.ui_3.0.1.v201201110400.jar plugin.xml
更新したjarで元ファイルを上書きし、eclipseを-cleanオプション付きで起動します。
これでエディタを複数起動した時も2つ目以降でCtrl+/が効くようになります。

2012年8月22日水曜日

Eclipse Pleiades All in One PHP 版でタスク一覧から特定のフォルダを除外する

Eclipse Pleiades All in One PHP 版でタスク一覧から特定のフォルダを除外する方法です。
(確認したバージョンはEclipse 4.2 Juno)
  1. まず公式の「Eclipse Web 開発者ツール(Web Developer Tools)」をインストール
    メニューの「ヘルプ→新規ソフトウェアのインストール...」を選び、Eclipseのリリースサイトからインストールします。
  2. プロジェクトのプロパティーに「検証」が出現
    PHPエクスプローラでプロジェクトのルートディレクトリを右クリック→プロパティ
  3. 「検証」のバリデーター一覧のうち、PHPTaskValidatorの設定で除外したいフォルダを指定する。
    「プロジェクト固有の設定を可能にする」チェックボックスをオンにし、 PHPTaskValidatorの設定ボタンをクリックします。
    出てきたダイアログで「除外グループの追加..」ボタンをクリックし、追加された除外グループを選択して「ルールの追加...」をクリックします。
    ダイアログの指示に従い除外したいフォルダを指定します。
これでタスク一覧から指定したフォルダが除外されます。「Eclipse Web 開発者ツール」を入れないとプロジェクトのプロパティーに「検証」メニューが出てこないので注意してください。

2012年8月12日日曜日

Symfonyを使った開発で機能テストはlimeかSeleniumか

Webアプリの開発をテスト駆動で行おうとするとき、機能テストを自動化するためのテスティングフレームワークの選択は重要であると思います。

lime vs. Selenium


機能テストの自動化にSymfony付属のlimeとSeleniumのどっちを使うか、と思ってたら同じ事考えてる人がいました。

http://stackoverflow.com/questions/2777913/selenium-vs-phpunit-lime

上記リンク先では用途によって使い分けるべし、という論調でたしかにその通りなのですけれど、問題は「機能テスト目的としては両方とも使えてしまう」ことです。たしかにlimeでしかできないこと・Seleniumでしかできないことはあります。しかし機能テストのほとんどの部分はどちらでもできてしまうことなので、やっぱり選択は迷うことになります。

自分の結論:lime


で、ともかく自分でやってみようということで両方使ってみました。
結果、現在のところ自分はlimeのみ使っています。その理由は、
  • 速い
  • テストが書きやすい
です。

まず実行速度は当然といえば当然ですが圧倒的にlimeの方が速いです。これはテスト駆動開発を行う上で何度もテストを実行する必要が有ることを考えると、開発効率にかなりの影響を与えます。Seleniumではブラウザで実際にアクセスするのでどうしても時間がかかります。

また、テストファーストで開発を進めるのに、limeならPHPですから条件分岐やループなどの制御構造をテストに組み込むのも全く難なく出来ます。Seleniumでは制御構造をテストに組み込むにはプラグインを導入する必要があったり、書き方もHTMLを使った独特の文法ですので若干テストが書きづらいです。(PHPUnitと連携できるみたいですが環境構築が大変。やろうとして途中でやめました。)

Javascriptのテストはどうする?


ちなみにJavascirptの単体テストにはqUnitを使っています。limeによるテストではJavascirptの機能は反映されませんので、Javascriptに依存する機能は別途qUnitでテストを行うことになります。
逆に言うとlimeによるテストがJavascirptなしでも可能になるようにコードを書く必要があります。

現状、lime+qUnitという構成で自動テストの環境はほぼ十分です。最後はブラウザから操作して確認することが必要ですが、これは自動テストに抜け漏れがなかったかを意識するとよいと思います。

2012年8月9日木曜日

同じ点を複数回通れる場合の「パターンロック」のパターン数


Androidなどに採用されていてる、並んだ点同士を指でなぞって結ぶことにより、パスワードの代わりとする認証方法があります。正式名称は知らないのですが、とりあえずここでは「パターンロック」と呼ばせていただくことにします。

Androidのパターン数については既に計算している方がいます。
http://blog.goo.ne.jp/nihongi/e/d0cfde12d440b92c181b6afd2b7dc4cb
http://beust.com/weblog2/archives/000497.html

Androidでは一度通った点は再度通れないことになっています(上を通過するのはOK)。しかし、独自に認証を搭載したアプリで、同じ点を何回でも通れるようなパターンを設定できるものがありました。これのパターン数を知りたいという方がいましたので、数えてみました。
条件は、
  • 隣接する上下・左右・斜め方向の動きで点を結べる
  • 将棋の「桂馬」の動きのような結び方はなし
  • 一度通った点も再度通れる
  • 使える点は3x3の9個
です。

3x3の点で同じ点を複数回通れる場合の「パターンロック」のパターン数

結ぶ点の数パターン数
19
240
3200
4952
54624
622272
7107648
8519552
92509056
1012113920
1158492928
12282425344

結ぶ点の数が12個までを計算しましたが、同じ点を複数回通れるので結ぶ点の数はいくらでも増やせます。

Androidで一度通った点は再度通れないようにしているのは、UI上で通った点の軌跡を表示する都合上、同じ軌跡を2度描けないからだと思います。

私が見たアプリではUI上で通った点の軌跡を表示せず、通り方そのものを覚える方式であるため、複数回同じ軌跡を描くような通り方も設定可能になっていました。

たしかにUI上で軌跡を表示すればグラフィカルに記憶できますが、制限を外して自由にパターンを書けるようにしたほうがかえって覚えやすい場合もありますので一長一短ですね。

参考:Rubyによるプログラムのソース

以下に3x3の点がある場合のパターン数を計算するRubyスクリプトを示します。 実行時の引数に結ぶ点の数を指定するとパターン数を出力します。
#!/bin/ruby
# assume dots such as:
# a b c
# d e f
# g h i

class PatternLock
  def initialize
    @dots = {
      'a' => ['b', 'd' ,'e'],
      'b' => ['a', 'c' ,'d', 'e' ,'f'],
      'c' => ['b', 'e' ,'f'],
      'd' => ['a', 'b' ,'e', 'g' ,'h'],
      'e' => ['a', 'b' ,'c', 'd' ,'f', 'g' ,'h' ,'i'],
      'f' => ['b', 'c' ,'e', 'h' ,'i'],
      'g' => ['d', 'e' ,'h'],
      'h' => ['d', 'e' ,'f', 'g' ,'i'],
      'i' => ['e', 'f' ,'h'],
    }
  end

  protected
  def countPattern(level, dot)
    if (level <= 1) then
      return 1;
    else
      count = 0
      @dots[dot].each do |x|
        count += self.countPattern(level - 1, x)
      end
      return count
    end
  end

  public
  def getCount(length)
    count = 0
    @dots.each do |k, v|
      count += countPattern(length, k)
    end
    return count
  end
end

pl = PatternLock.new
puts pl.getCount(ARGV[0].to_i)
PatternLockクラスのインスタンス変数@dotsは、パターンに使える点をキーとし、次に結べる点の集合の配列を値に持つ連想配列です。上記例では各点にアルファベット1文字を割り当てています。@dotsを変更することで点の数が異なる場合や将棋の桂馬の動きを許可する場合なども計算できます。

2012年8月1日水曜日

yumでCentOSのバージョンをダウングレードする(6.3=>6.2)

yum update でOSごとアップデートしてしまった時、元に戻したい時はどうすればいいか試してみました。
検証用に以下のCentOS6.2のVMware用イメージを使わせて頂きました。
http://www.thoughtpolice.co.uk/vmware/#centos6.2
これをyum updateで6.3 にアップデートした状態。ここから6.2に戻してみます。

まずリポジトリの参照先を戻したいバージョンに強制します。
(参考 → http://d.hatena.ne.jp/stakizawa/20100522/t1

# cd /etc/yum.repos.d
# cp CentOS-Base.repo CentOS-Base.repo.orig
# vim CentOS-Base.repo
:%s/$releasever/6.2/g
:wq
# yum clean all

で、yum distribution-synchronization を実行。このコマンドはリポジトリ上の全てのパッケージをまとめてインストールあるいは更新し、バージョンもリポジトリと同じになるように試みます。例えばすでにインストールされているバージョンよりリポジトリ上のバージョンが古い場合はダウングレードを行います。

# yum distribution-synchronization

これですんなり成功してくれればいいですが、エラーが出ました。

Transaction Check Error:
file /usr/lib/python2.6/site-packages/system_config_keyboard/__init__.pyc from install of system-config-keyboard-1.3.1-3.el6.x86_64 conflicts with file from package system-config-keyboard-base-1.3.1-4.el6.x86_64
file /usr/lib/python2.6/site-packages/system_config_keyboard/__init__.pyo from install of system-config-keyboard-1.3.1-3.el6.x86_64 conflicts with file from package system-config-keyboard-base-1.3.1-4.el6.x86_64
file /usr/lib/python2.6/site-packages/system_config_keyboard/keyboard.pyc from install of system-config-keyboard-1.3.1-3.el6.x86_64 conflicts with file from package system-config-keyboard-base-1.3.1-4.el6.x86_64
file /usr/lib/python2.6/site-packages/system_config_keyboard/keyboard.pyo from install of system-config-keyboard-1.3.1-3.el6.x86_64 conflicts with file from package system-config-keyboard-base-1.3.1-4.el6.x86_64
file /usr/lib/python2.6/site-packages/system_config_keyboard/keyboard_models.pyc from install of system-config-keyboard-1.3.1-3.el6.x86_64 conflicts with file from package system-config-keyboard-base-1.3.1-4.el6.x86_64
file /usr/lib/python2.6/site-packages/system_config_keyboard/keyboard_models.pyo from install of system-config-keyboard-1.3.1-3.el6.x86_64 conflicts with file from package system-config-keyboard-base-1.3.1-4.el6.x86_64

エラーの発生したパッケージを削除し、作業後に依存パッケージとともに再インストールすることにします。

# yum remove system-config-keyboard

依存性のため一緒に削除されるパッケージがあるのでメモしておきます(この場合anacondaとfirstbootが一緒に削除された)

再度トライ
# yum distribution-synchronization
今度は成功。

先ほど削除したパッケージをインストールします。
# yum install system-config-keyboard anaconda firstboot

古い情報が残っていて再インストールに失敗しました。rpmコマンドで直接対象のパッケージをアンインストールします。
# rpm -e system-config-keyboard-base-1.3.1-4.el6.x86_64
再度トライ。
yum install system-config-keyboard anaconda firstboot
これでOK。

カーネルの新しいバージョンのパッケージが残っているのでyumコマンド実行時に依存パッケージ欠如で怒られますが、ダウングレードしたバージョンで起動するので特に気にならないのであればこのままでも問題ないでしょう。気になるようなら削除すればいいと思います。