読者です 読者をやめる 読者になる 読者になる

あと味

たくさん情報を食べて、たくさん発信すると、あとになって味わい深い。

MT のドキュメントを Emacs から引けるようにした

SLIME をインストールすると同時にインストールされる hyperspec-lookup コマンドのように、MT のドキュメントを検索できると良いなと思ったので、hyperspec-lookup を模倣して、パッケージにした。

mt-doc-lookup

https://github.com/taiju/mt-doc-lookup-el

インストールすると、M-x mt-doc-lookup-tags で、コマンドで指定した MT タグのドキュメントをブラウザで閲覧できるようになる。

同様に、M-x mt-doc-lookup-config-directives環境変数M-x mt-doc-lookup-modifiers でグローバル・モディファイア、M-x mt-doc-lookup で MT タグと環境変数とグローバル・モディファイアを横断的に検索し、閲覧できる。

リポジトリにも貼っている、利用時のスクリーンショットが下記。

f:id:jdg:20150517231524g:plain

スクリーンショットでは、ido + smex + ido-vertical-mode がインストールされていて、有効にしている状態での操作内容なので、それらが入っていない場合は、初期状態の Emacs の補完機能と同様、微妙な使用感になる。helm など、他の標準の補完機能を拡張するパッケージが入っているなら、その使用感で使えると思う。

mt-doc-lookup の横断検索は、リストから検索するのに対し、mt-doc-lookup-tags のように用途を絞る検索は、ハッシュから検索するので、多分、用途を絞った検索の方が速いと思う。

特に各コマンドを標準ではキーバインドはしていないので、お好みで。

標準では eww でドキュメントを開くようにした。(mt-doc-lookup-browser-function 変数で変更可能)

ドキュメントを閲覧するには eww で必要十分だし、コピペビリティも高くてオススメです。

検索の各候補は下記のワンライナーで出力したものを加工した。もしかしたら、足りてなかったりするかもしれない。

$ perl -Mojo -E 'say g($ARGV[0])->dom->find(q{a[rel="bookmark"]})->map(sub { sprintf q{("%s" "%s")}, $_->text, $_->{href} =~ s|^$ARGV[0]||er })->join("\n")' http://www.movabletype.jp/documentation/appendices/tags/

最初は Emacs lisp でがんばろうかと思ったものの、標準の道具では厳しそうだったので、やめた。

Mojolicious + Perl でのワンライナーだいぶ便利なので、代替なかなかない。

まとめ

これまでも、タグリファレンス等を eww のブックマークから開いて閲覧していたので、ドキュメントへのアクセスのステップが短くなり、今後多少なり捗る気がする。

ただ、ドキュメントがリニューアルしたら、即ゴミになるのが辛い。可能な限り追従したいとは思っている。

Emacs に衣替えした話

たぶん、Emacs に衣替えできたので、その話をします。

いつもですます調だけど、である調で書いた。

プロローグ

普段は Vim を使っているが、数年に一度くらい、Emacs を使いたい欲求がどうしても抑えきれなくなることがある。(Vimmerあるあるネタだろうか?)(多分、コイツは最近 Lisp の本を読んだ)

欲望のまま Emacs を立ち上げ、ひととおりチュートリアルをこなすと、不思議なことに抑えきれなかったはずの欲求が綺麗サッパリ消えているのだ。本当に微塵もないのだ。 そして、あの気持ちはなんだったのだろうかと我に帰り、Vim を立ち上げ、安堵する。「俺にはやっぱりコイツじゃなきゃダメなんだ」と。 そんなやりとりが、これまで何度もあった。

ところが、最近の Emacs には、Evil という悪魔が存在する。

去年も Emacs を使いたい欲求が抑えきれなくなった。(ねぇ?Land of Lisp でも読んだ??)

欲望のまま Evil をインストールした Emacs を立ち上げた。

普段であれば、すぐに退散してしまうその世界は、いつもと違い、居心地の良さを感じる。

そして、退散することなく、その世界にとどまってしまった。悪魔がそそのかしたのである。

気がついたら、Evil + Emacs を使い始めて半年を超えていたのだった。

Evil 移行期

前述のプロローグに書いたように Evil + Emacs に移行して結構な日数が経っていたが、実際に移行した実感は薄かった。

シェル操作が必要な時(基本は eshell 使いになっているが、たまに必要になる)に tmux でウィンドウを立ち上げて、vim でちょこっとファイル編集し出すと、ふと気づいた時には Emacs 使ってないみたいな状態になっていることが多々あった。

で、その状態でマシンをスリープして、翌日作業を再開したりすると、気づいたら今日 Emacs 使ってないみたいなこともよくあった。

利用時の違和感がなさすぎると、移行はスムーズだが、逆に移行した意義も見えなくなる。

なので、Emacs らしさを取り戻すために、magit や wanderlust のような大きめなアプリケーション使ってみたりして、移行した意義を再認識するようにした。

葛藤の日々

magit とか wanderlust など、ある程度の大きめなアプリケーションを使う時は、Evil 環境下でも、Emacs チックな操作系等を強いられる。

いつの間にか、ESC でモード変わらなくなって、

C-g「馬鹿め、そいつは残像だ」

・・・そして、画面上には j, k の残骸が無数に転がっていた。

みたいな感じになって辛い。

ウェブで探すと、Evil 向けのカスタマイズ例などが見つかるが、アプリケーションごとに書いていくの厳しそうだし、設定の事例自体少ない。

Emacs を使うと Emacs Lisp を書いたり、読んだりする機会が増えるわけだが、Emacs Lispデバッグをしようとして、emacs -QEmacs を立ち上げた後の自分の無力感が半端ない。

そういった事情があり、Evil を使っていると、Vim 脳と Emacs 脳の切り替えを強いられる状況が多々起こる。 その状態が半年も続くと、意図せず、ある程度 Emacsキーバインドに慣れてしまっている自分がいることに気づく。

Evil との別れの時

Evil をやめることにした。

ローマ字入力から、かな入力に移行した経験があるので、移行中はイライラ以外に得るものは何もないけれど、強制的に禁じることでちゃんと移行できる確信はあった。

Emacs でも Evil をアンインストールして、使いづらいからといって Vim にも逃げない日常生活を送ることにした。

やはり、数日は何をするにもイライラした。

C-h b (describe-bindings), C-h m (describe-mode) をひたすら叩いた。

でも、数日で慣れた。

かな入力の時より、移行期間は短かった。

まだ、たどたどしい部分はあるが、Vim を起動すると、一旦心落ち着けないと混乱する程度には Emacsキーバインドに慣れた。 たとえば、今 Vim でカーソル移動しようとすると、やたら補完される。

設定の見直しの日々

Vim 使っている時にもあまり大した設定はしていなかったし、あまりプラグインも入れてなかった。

現在の Emacs の設定もそんな感じである。

また、自分はデフォルト厨でもあるので、標準機能で事足りるならば、不便を強いられても標準機能を利用したいという指向性がある。

Emacs ビギナーあるあるだと思うが、最初はいろいろなユーザーのおすすめ設定とか、おすすめパッケージをコピペしたり、インストールしたりしていたが、実は使ってないとか、標準機能で十分ということがいろいろありそうだったので、一旦白紙にして標準機能でまかなえるものは標準機能を使うことを前提に、フルスクラッチで設定書くことにした。

例えば、helm とか auto-complete なんかは、ido で十分な気がしたので、ido + ido の拡張パッケージで済ませるようにした。

Evil 期に、いきなり Emacs の応用から入った感じになっていて、dired とか バッファリストの操作など、Emacs の基本をほとんど把握してなかったが、使ってみたら便利そうな機能もあった。 あと、eshell を常用していたが(今も常用している)、tmux + vim での作業文化を引きずっていただけということにも気づき、利用頻度は少し減った。

Emacs は標準でも普通に便利だし、今は、標準機能の理解をもっと深めようというフェーズにある。

Chromebook で使っている設定が下記で、一度すべてリセットしてスクラッチから書き直している途中。*1

内容も薄いので、起動もそれなりに速い。

Evil 期では、おすすめ設定みたいなのをウェブで拾いつつ、init-loader + 各パッケージごとの設定ファイル(ファイル名先頭が連番)みたいな構成にしていたが、各設定ファイルの記述内容が数行程度で、ファイル名の先頭に連番付けていたけど、途中で不要になったパッケージが出てきた時に、連番が飛んで辛い感じになるので、init.el だけの運用にすることにした。

init.el の中の記述についても、どの設定をどの設定の周辺に書こうか迷うのが面倒なので、パッケージ名のアルファベット順で機械的に判断して記述できるようにした。設定順に依存する依存関係が出てくると面倒なことになるかもしれないが。

また、パッケージを管理するために Cask を使っていたけど、実質的には、ただインストールするパッケージの一覧を可視化したいというだけだったので、標準機能で済ませることにした。

ちょうど、設定をスクラッチで書き直し始めるころに見つけた Emacs Startar kit の手法が良さそうだったので取り入れた格好。

init.el で指定したパッケージが未インストールだったら、標準のパッケージ関連機能でインストールするというもので、これで特に問題ない気がしている。

職種がサポートエンジニアで、普段は広く浅く技術を使うため、特定の言語(Perl は毎日使うのだけど、デバッガ+αという感じ)や技術に特化した設定とかはいらない模様。

Emacs に移行して良かったと思うこと(まとめ)

そもそも Vim を使いなしているユーザーでもなかったので、それ Vim でもできるよというツッコミはあるかもしれないけれど、その点はご容赦を。

Emacs に移行した中で、良かったと思うことは、Lisp (Lisp-1, Lisp-2) が読み書きしやすくなるということはもちろんあるけれど、Emacs のことを Emacs で把握でき、Emacs の定義を Emacs で再定義できるという点かもしれない。

例えば、新しく試すモードを理解する場合、C-h m (desribe-mode) でキーバインドを確認して、そこからコマンドの定義にジャンプできるし、コマンドの定義の中でわからない関数があれば、C-h f (describe-function) でさらに詳細を把握できる。そして、今、キーバインドに対応するコマンド名は C-h k (describe-key) で調べて追記している。

Info ドキュメントが提供されている場合は、C-h i (info) で、Info ドキュメントの閲覧ができるし、その操作もしやすい。

新しい設定を書くような場合も、C-h v (describe-variables) で変数の定義を確認して、書いた設定を C-M-x (eval-defun) すればすぐに反映される。

もっとざっくりと apropos-* で、コマンドや関数、変数を探すこともできる。

Emacs Lisp はどちらかと言えば、Common Lisp 寄りな感じなので、shiro さんの Common LispとScheme という記事で言及されている

全部Lispで完結するCL上のプロジェクトの場合、逆にとりあえず REPL起動してasdfでビルド/ロードして、aproposやタグジャンプを使って Lispの「中から」全体を把握してゆく方向になる。

という体験に近い感じかもしれない。

様々な機能が Emacs Lisp で書かれているので、Lisp の知識で読める。

必要に応じて定義を追ったり、デバッグしたり、機能書いたりできるということは、半永久的に日常で利用するツールとして、それ以上に心強いことはないと思う。(まぁ、そんなにする機会ないから詭弁かもしれないけど)

Emacs は、自分の誕生日より早く生まれているツールで、今日まで発展しているので、自分が死ぬころにも普通にあると思う。その頃には、Emacs 50 は超えているかもしれない。

ということで、新米になったところだが、今後は Vim に戻ることなく、Emacs を使い続けることになりそうという実感が、今のところある感じ。

ほなの。

*1:話は変わるが、今年から Chromebook をメインマシンにしていて、Chromebook のシェルで日本語入力できないクソみたいな問題があるので、Chromebook では、ウェブブラウジングChrome を使う以外には、基本的に Emacs ですべてのことをこなしていて Emacs 強制ギブス状態となっている。

Mac で Oracle Database 11g Express Edition (XE) の開発環境をセットアップする

MacOS X Mountain Lion)で Oracle 11g の環境を整えたいと思ってセットアップしたんですけど、そこそこ面倒だったので、同じこともう一回調べたくないし、記事にします。

古いけど OS は Mountain Lion で、ApacheMac 標準のものを使っています。

DB サーバのセットアップ

MacOracle の DB サーバ構築するのはそもそも無理ってことを知ったので、VM セットアップしないといけないのか、やだなーと思って、念のため調べてみたら、用途ぴったりの Vagrantfile 提供している人がいて、それを使わせてもらうことにしました。

DB サーバのセットアップの手順が省略できるので楽できました。

上記の README の Installation のセクションの通りにセットアップすれば、vagrant up して VM 立ち上げている間、localhost の 1521 ポートにアクセスすると、ゲスト OS の 1521 ポートに転送されるので便利です。

Instant Client のインストール

Mac 用の Instant Client が Oracle のサイトでダウンロードできるので、ダウンロードします。次工程を進めていく過程でエラーになる度、それらしいファイルをダウンロードするという手順で、結果的に Basic, SQL*Plus, SDK が必要ということになりました。

上記のサイトから 64 bit 版をそれぞれダウンロードして、アーカイブをそのまま展開すると、instantclient_11_2 ディレクトリの中に各種実行ファイル、ライブラリ、ヘッダーファイルなどが配置されるので、上記のページの Installation セクションの通りに、instantclient_11_2 ディレクトリを /opt/oracle/instantclient_11_2 に移動して、シンボリックリンクの作成と環境変数の設定をしました。

Mac 側にクライアント環境が整ったら、sqlplus で表領域や、ユーザー作れば、DB 操作ができるようになります。

DBD::Oracle のインストール

$ORACLE_HOME, $DYLD_LIBRARY_PATH, $PATH 等の環境変数が設定されていれば、インストール自体はコケることなくすんなりできました。

ただ、実際に使ってみると /ade/ 配下の意味不明なパスからライブラリを探そうとしてエラーになりました。

/opt/oracle/instantclient_11_2 配下の各バイナリがそういう設定になっているようなので、各バイナリを otool -L した時に出力されるパス通りにディレクトリ作って、各ライブラリのシンボリックリンクを置きました。

install_name_tool コマンドでライブラリのパスを変えるという方法もあるらしいのですが、パスが書き換わらないファイルがあったので、あきらめました。DBD::Oracle::Troubleshooting::Macos にもそれらしい手順が書いてあったし。

DBD::Oracle をコマンド上で使うときには、シェルに環境変数がエクスポートされていれば問題ないですが、ApacheCGI として使う時には、Apache の設定ファイルに SetEnv ORACLE_HOME /opt/oracle/instantclient_11_2 みたいな形で Apache環境変数を設定する必要があります。

oci8 のインストール

pecl で oci8 をインストールして、インストール時に出力されたガイドの通りに、php.iniextension=oci8.so を指定しても、php -m では oci8 が認識されてるのに、Apache の 公開パスに置いた PHP ファイルで phpinfo を出力しても、その結果の中には oci8 が反映されてなくて、よくわからなかったので、phpenv と、php-build で、5.4.x を --with-oci8 オプションを指定した(Apache で使うので、--with-apxs2 オプションも指定しました)状態でビルドし、インストールしたら正しく認識されました。

ただ、Apache の公開パスに oci8 を使って DB 接続するプログラムを置いたら、ORACLE_HOME が設定されてないみたいなエラーになりました。

同じプログラムをシェルで実行すると問題なかったので、Apache環境変数がエクスポートされている状態にならないといけないということを理解しました。

調べてみたところ、グローバルに環境変数を設定する場合は、/etc/launchd.conf環境変数を設定すれば良いということがわかったので、ORACLE_HOME やら、DYLD_LIBRARY_PATH やらを設定して解決しました。

利用シーンによって読み込む環境変数が違っていて、面倒な話ですが、シェル、Apache、システム全体の 3 箇所で同じような環境変数を設定する羽目になりました。

まとめ

DB サーバのセットアップが省略できたものの、思ったより面倒でした。

記憶をたどって書いてるので間違っているかもしれませんが、間違ってたらごめんなさい。

ほなの。

Chromebook (Acer C720) 買った

年末に Chromebook (Acer C720) を買いました。

いろいろ弄る中で知見を得たので、記事にすることにします。

結果的に良い買い物だったという気がしています。

購入前

今使っている Macbook Pro も数年使っていて、ハード的にも環境的にもボロボロになってきたので、買い替えを検討していました。

本当は Macbook Air が欲しかったんですけど、結婚してから自由に使えるお金が限られるようになったので、Macbook Air はヨイショと簡単に買えるような端末ではなくなってきていました。

振り返ると、家で使う個人端末では Chrome とシェルしか使ってないので、別に Macbook Air にこだわることはないのかなと思い、安い Linux ラップトップを買おうかなと思ってたんですけど、予てから興味のあった Chromebook を調べてみると、Chromebook で事足るのかなと思い始めてました。Chromebook は、貧乏人の Macbook Air だという評価も見かけましたし。

正直 Chromebook を弄りたいという欲が先行していて、同スペックのより安い Linux ラップトップがあるかどうかはろくに調べていないのですが、Windows 8.1 with Bing なラップトップと比べても、Chromebook はコスパが優れている方な気がします。

自分の日本語入力方式が JIS かな入力なので、JIS 配列のキーボードが必要だと思っていて、輸入で買う選択肢はなく、日本での JIS 配列キーボード搭載版の Chromebook の発売を待っていました。

とりあえず、日本版のすべての Chromebook のラインナップが出揃ったので、本格的に購入することを検討し、一番コスパが良さそうな Acer C720 の購入に至った次第です。

Acer C720 は現時点で日本で発売されているラインナップのうち、唯一 SSD を換装できる端末らしいのですが、SSD は 16GB のまま換装はしませんでした。(後述しますが、16GB では余裕で足らないです)

Web 開発できることが条件

Chromebook を安物買いの銭失いにするのは絶対に避けたかったのと*1、今後のメインマシンにするつもりで購入するので、Web 開発できることが絶対条件でした。

Chromebook に Ubuntu を入れる方法はすでに確立されていて、それでなんとかなるかなと思っていましたが、実際に使ってみて今のところなんとかなりそうな気配です。

Chrome OS に関しては、Virtualbox にインストールして触ってみてましたが、Chrome に毛が生えた程度なので、特に事前に触ってみる必要もなかった気もしています。

OS として起動が速い点は大変良いです。*2

Web 開発環境のセットアップ

Ubuntu は crouton でインストールしました。

他にも選択肢はあるようですが、Issue 見てもちゃんと対応しているし、複数人でメンテされていて、crouton であれば、Chrome OS の特徴を殺すこともないので、自分的には crouton しか選択肢なかった感じです。

crouton は chroot の仕組みを使って、Ubuntu をインストールする仕組みですが、chroot するディレクトリは任意に選べます。

本体の SSD の容量は 16GB で、実際使える容量はさらにそれより少なく、余裕で足らない感じだったので、USB メモリ内のディレクトリにインストールすることにしました。

幸い、Chromebook には、USB 3.0 端子があるので、高速な USB メモリが利用できます。

ネットで調べて評判も高そうだったサンディスクの 64 GB の USB メモリを買いました。

64 GB あればとりあえず当面は十分です。

IO の反応も非常に速く、リムーバブルディスク上で操作している感はありませんでした。SSD すら初体験という前提はありますが。

USB メモリを ext4 でフォーマットしようと思ったところ、USB 3.0 に対応した端末が Chromebook しかなく、詰んだかなと思ったんですけど、普通に Chromebook の Crosh ウィンドウのシェル*3で、fdisk やら、mkfs.ext4 が使えたので、事無きを得ました。

ついでに、USB のラベルも、接続直後、「USB Disk」という微妙なラベルだったので、e2labelchromebook に変更しました。(以下、USB メモリのラベルを chromebook に変更していることを前提としてパス等記述しています)

crouton のインストールオプションは下記のような感じです。

sudo sh ~/Downloads/crouton -r trusty -t xfce -p /media/removable/chromebook/crouton

t オプションに xiwi を指定して、crouton の Chrome エクステンションをインストールすると、タブ上で Ubuntu を開くことができたり、Chromebook と Ubuntu 間で、コピー・ペーストを共有したりできるらしいのですが、タブ上で Ubuntu を開くのはうまくできませんでした。

あと、cli-extra というターゲットを指定すると、X Window System のないミニマムな Ubuntu 環境をインストールできますが、後述する通り、Virtualbox 使うために X Window System が必要だったので、指定しませんでした。

インストールが終わったら Ubuntu が USB メモリに入ります。USB メモリがなければただの Chromebook で、USB メモリがあれば Ubuntu も利用できるという感じで、Chromebook はそのまま残しつつの運用ができるのでおすすめです。

p オプションをつけてインストールすると、インストール先の bin ディレクトリ(例えば上記で言えば、/media/removable/chromebook/crouton/bin)に crouton の各種スクリプトがインストールされます。

Crosh ウィンドウのシェルで、

sudo sh /media/removable/chromebook/crouton/bin/startxfce4

と入力すれば、Xfce4 の Ubuntu デスクトップ環境が起動しますし、

sudo sh /media/removable/chromebook/crouton/bin/enter-chroot

と入力すれば、Crosh ウィンドウでそのまま UbuntuCUI 環境で利用できます。

UbuntuSSH サーバー入れて、自動で起動する設定をしておいて、Secure ShellSSH ログインするという方法もありますが、sudo enter-chroot で Crosh ウィンドウからそのまま UbuntuCUI 環境使う方が 、Ubuntu デスクトップ環境を起動する必要もなく、気軽だと思います。

VirtualboxWindowsIE)を動かせるようにする

Chromebook で Web 開発するにあたって、VirtualboxWindowsIE)を動かせることも必要条件と考えていました。

インストールした Ubuntu をデスクトップ環境としてそのまま利用することは考えておらず、Virtualbox を利用するためのデスクトップ環境という感じで考えています。*4

ただ、Virtualbox のインストールは簡単ではありませんでした。

crouton リポジトリWiki を参照して、

あたりを見ながら各種設定し、modern.IE の OVA で、Windows 7IE 11 が動かせたので、この条件もクリアできました。

カーネルヘッダのビルドは手動でもやってみましたが、すごく時間がかかって大変だったので、上記の Wiki にリンクのある、下記のスクリプト使うのが良いかなと思います。自分の環境はそれで動きました。

Virtualbox のインストールは何度か躓いて、躓いた時に何が足りなかったのかイマイチわかってない状況です。Xfce4 ではなく、Unity をインストールした時に、crouton の Issue にも同例の報告があった Virtualbox で Windows 起動した時に Chromebook が強制的にリブートする問題が発生してうまくいかなかったんですけど、Xfce4 に変更した今は問題は発生していません。ネットで情報を見ながらアレコレ試行していたので、この問題がウィンドウマネージャを変更したことで解決したのかどうか、それが関係あるのかないのかも正直よくわかってません。。。少なくとも Issue にあるように Trusty を Precise に変更するという方法では解決しませんでした。

Virtualbox がインストールできたことで、他の OS を操作することができる状況も確立したし、Chrome リモートデスクトップ を使って、既存の Macbook Pro を操作できることも確認できたので、今後困ったことがあっても逃げ道ができた感じです。

あとは日本語言語パックの設定とロケールの変更、シェル環境の整備、LAMP 周りのソフトウェアとか入れて、いい感じに使えるようになりました。

とにかく Virtualbox のインストールだけが一癖あって、他のツールのインストールは特に問題は起こっていません。

各種環境を整えた後、Movable Type をセットアップして実際に操作してみましたが、IO が速いせいか、既存の Macbook Pro 上の環境と比べても速く、今のところスペックによるストレスは感じていません。

困った点と解決方法

以上のセットアップで、Chromebook で Web 開発できるような雰囲気になりましたが、いろいろと細かいところで問題があり、これからもあるかもしれません。

使ってみて発覚した各種の問題を、自分はどのように解決したか、または解決するつもりなのかということを、今後購入される方向けに残しておきます。

Crosh ウィンドウが複数開けない

Crosh ウィンドウの欠点としては、複数ウィンドウが開けない点です。

一方、Secure Shell は複数ウィンドウが開けます。

Ctrl + Alt + TChrome のタブに複数開くこともできるのですが、Chrome のタブとして開くと、Chrome のショートカットキーが優先され、一部のキー操作が奪われるという問題があります。

Secure Shell であれば、ウィンドウを複数開くことができ、かつ、それらを Chrome のタブとしてではなく、独立したウィンドウとして開く設定にしておけば、Chrome のショートカットキーにキー操作が奪われることもないので、この運用を好む方もいるかもしれません。

ただし、Secure Shell で開く場合は、Crosh ウィンドウから Ubuntu デスクトップを起動しておく必要があります。

cli-extra を入れて、sudo startcli するという方法もありますが、シェルが別画面に開くだけで、使用感は変わりませんでした。

自分は、Crosh ウィンドウ内で sudo enter-chroot して UbuntuCUI 環境で開き、複数ウィンドウ開けない問題については、tmux や screen を使うことで対応することにしました。

日本語情報が少ない

まだ、日本語情報が少ない感じです。ただ、すでに欧米では Chromebook のハックの実績が多く、知見もあるので、英語圏の情報は充実しています。

しばらくは、何か調べる際は、英語圏の情報を探すしかないです。

crouton 固有の情報は、経験的に、crouton リポジトリの Issue や Wiki から探すのが良いです。

セットアップのやり直しをするたびユーザー領域がリストアされる

個人的にもセットアップのやり直しを何度か実施したのですが、そのたびにユーザー領域がリストアされます。

設定情報等は、クラウドに保存されるようで、再セットアップの手間はそれほどではありません。

消えて困るデータは、リムーバブルメディアや Google Drive に保存するようにした方が良さそうです。

/etc/hosts の書き換えができない

Ubuntu 側は問題ありませんが、Chromebook 側の /etc/hosts の書き換えができません。*5

DNS サーバーをセットアップすることで任意のホストで Ubuntu 上のウェブサーバーのリソースにアクセスできるようにすることも可能なのかもしれませんが、自分は xip.io のようなサービス使って凌ぐことにしました。

サービス(xip.io)が終了したら、任意のドメインで同じようなことを適当にやります。

Secure Shell でも Crosh ウィンドウのシェルでも日本語入力できない

ここ重要!

Chrome で Secure Shell 使う時もこの問題があったので、予想はしてましたが、Chromebook の Crosh ウィンドウや Secure Shell であっても同じ状況です。コピペはできますが、それでは厳しいです。

Chromebook にインストールした Ubuntu デスクトップ環境を、そのまま利用する場合は、問題なく日本語入力できます。

Crosh シェルで crouton の enter-chroot コマンドで CUI 環境を利用する場合や、Secure Shell で SSH ログインして CUI 環境を利用する場合には、ウィンドウ内で日本語入力ができないので、この点が購入にあたっての大きな障害になり得ます。(Vim で開発する人とか)

自分の場合は、Chrome で Secure Shell の操作を確認した際に、SSH ログインした環境で、Emacs の入力切替ができることは確認できていたので、Vim から Evil + Emacs に移行しつつある自分的にはクリアできる問題となりました。

要するに日本語入力したければ Emacs 使いましょうという話です。

mozc.el 入れて、通常と同様に文字変換できるし、設定を変更すれば、JIS かな入力もできます。

シェル上で日本語を使いたい場合も、eshell 使えば良いので、無問題でした。

Vim を使っている時にハングアップする

よくわかりませんが、Crosh ウィンドウや、Secure Shell のウィンドウで、Vim を使っていると、突如ハングアップして、 使っていたウィンドウがどれであるかは関係なく、シェルを起動したすべてのウィンドウが軒並み動作しなくなることが何度かありました。

その状態では新しくシェルを立ち上げることもできないので、再起動するしかなくなります。

Emacs では今のところ発生していないので、基本は Emacs を使っています。

これはハード固有の問題なのか、たまたま自分の環境で起こっている問題なのか、解決策があるのかもわかっていません。

ハード固有の問題

Acer C720 では、リストア後のセットアップで WiFi に繋がらないという問題が、2回ほど発生しました。

一度接続設定をしてからは問題ないのですが、リストア後のログイン直後でそういう事象が起こりました。

1回目は何度も試行しているうちにつながり、2回目はルータを再起動したらつながりました。

多分、下記の QA と同様の事象だと思いますが、何が起こっていたのかよくわかりません。

あとは、キーボードやディスプレイ*6、タッチパッドが値段相応の品質ということです。これはどうしようもないので、慣れるしかない。

Macbook がよく出来ているということを痛感した感はあります。

まとめ

Macbook Air を購入しても財布が痛くない人は、素直に Macbook Air 買えば良いと思います。。。

自分の場合は、型が古くなっても新しい端末が買えなかったり、故障した時に新しい端末の調達がすぐにできないといった状況がストレスなので、今後そのようなことがあっても安く必要十分なマシンが調達できることが確認できて良かったです。*7

また、crouton でインストールした UbuntuCUI 環境に、Crosh ウィンドウのシェルからアクセスする運用は、Chrome OS をシャレオツな UNIX デスクトップ環境として使っている感覚で気に入りました。*8

これで今後も持たざる者(いろんな意味で)として快適に生きられそうです。

ただ、今のところ万人におすすめできるものとは思ってません。特に日本語入力できない問題が痛い。

あ、あけましておめでとうございます。

ほなの。

*1:それだとコスト削減のために Chromebook 買う意味がなくなるし。

*2:あと、バッテリーがやたら持ちます。外出ないけど。

*3:Crosh ウィンドウを開いて shell とタイプして利用できるシェル。

*4:インストールした UbuntuChromium を起動した時の敗北感たるや...

*5:調べるとやりようはあるっぽいのですが、やってません。

*6:HDMI 端子があるので、テレビに繋げるという選択肢もある。多分使わないけど。

*7:少なくとも Chromebook が発売され続ける間は。

*8:crouton ありきな危うい状況ではありますが。

MT の管理画面を開くコマンドラインランチャー作った

この記事は、Movable Type Advent Calendar 2014 の 21 日目の記事です。

最近になって、遅ればせながら peco を使い始めました。汎用的なインタラクティブフィルタリングツールなので、どんなコマンドとも組み合わせて使うことができるし、ないと困るツールになりそうな気配です。

本題ですが、MT の特定の画面をサクッと開けるランチャーを作りたいなと以前から思っていたんですけど、一から考えて作るのは厳しいのでほぼボツ案だったのですが、peco または percol を使えばそれなりに満足するものが作れそうだなと思ったので、昨日作ってみました。

MT::Tool::Launcher

$ cd $MT_HOME
$ ./tools/launcher --protocol=https --host=cms.example.com --cmd=/path/to/peco

実行例

例1) あるウェブサイトの記事作成画面を開く

https://github.com/taiju/mt-tool-launcher/raw/master/artwork/launcher1.gif

例2) すべてのブログのプラグイン設定画面を開く

https://github.com/taiju/mt-tool-launcher/raw/master/artwork/launcher1.gif

上記のような感じで使います。

所感

ローカルマシンに環境作って開発してるケース以外では使うことないと思いますが、自分はローカルマシンで開発することが多いので、あると便利かなと思っています。

一応 Windows でも動くように作ったつもりなんですけど、手元に検証に使える環境がないので動かなかったらごめんなさい。MacUbuntu では動作確認してます。

peco や percol は汎用的なツールなので、他のツールスクリプトにもいろいろ応用ききそうで、発想が広がる感じがします。

ということで 21 日目の記事でした。引き続きお楽しみに。

ほなの。

MTの管理画面でMT標準のJSテンプレートエンジンを使う

管理画面のカスタマイズをしていて、JSでDOMを弄ってHTMLを出力しようと思った時に、コードの見通しを確保するためにJSテンプレートエンジンが欲しいなと思いました。

ただ、そのためにライブラリ読み込むのも微妙だし、正規表現で頑張るかと思ったところ、管理画面でJSテンプレートエンジンが使われてたことを思い出しました。

MTの管理画面で使われている、JSテンプレートエンジンのライブラリは、/path/to/mt-static/js/common/Template.js にあって、実装を確認したところ、シンプルで汎用的に使える小さなライブラリっぽいので、下記の通り機能をまとめました。

ちなみにこのライブラリは、数年前から更新が止まっていて、Github リポジトリの当該ファイルのコミット履歴も、「Common JavaScript ライブラリをリポジトリに入れました」的なログが一つあるだけのレベルです。

メンテが止まっていて、いつ役目を終えるかわからない感じの存在感なので、その点はご留意ください。

この記事の賞味期限もそれまでです。

使い方

下記のような感じで使えます。

var tmpl = new Template('Hello, [#= name #]!');
var context = new Template.Context({ name: 'taiju' });
tmpl.process(context);
// => "Hello, taiju!"

/*
下記で使う変数tmpl_textには下記のテンプレート文字列が保存されていると仮定する
  <ul>
  [# jQuery.each(vars, function (i, v) { #]
    <li>[#|h|u v#]</li>
  [# }) #]
  </ul>
*/
tmpl.compile(tmpl_text);
context.vars = { vars: ["<script>alert('foo');</script>", "バー", "baz"] };
tmpl.process(context);
/* =>
"<ul>

  <li>&lt;script&gt;alert('foo');&lt;%2Fscript&gt;</li>

  <li>%E3%83%90%E3%83%BC</li>

  <li>baz</li>

</ul>"*/

Underscore.jsのテンプレート機能のように、普通に言語の機能がそのまま使えるタイプのシンプルなテンプレートエンジンです。この手のテンプレートは学習コストが低く、言語のパワーがそのまま使えるので、個人的に好むタイプです。

管理画面はjQueryがロードされているので、jQueryのユーティリティを組み合わせてテンプレートを書くのが良いかもしれません。

ライブラリの機能

Template.jsによって、Template, Template.Context, Template.Filterというクラスが提供されます。

Template.jsは、Core.jsに依存しているので、利用するにはCore.js等の依存ライブラリがあらかじめ読み込まれている必要があります。

主に使うのはTemplateクラスになりそうですが、先のサンプルのようにTemplateクラスのインスタンスを作って処理する他、Templateクラスのクラスメソッドを使って、JSテンプレートをビルドすることもできます。

var templates = {
  foo: '[#= foo #]'
};
var vars = {
  foo: 'FOO'
};
Template.process('foo', vars, templates);
// => "FOO"

クラスメソッドの方が手軽に使えるかもしれません。

テンプレートの記法

[#から#]で囲まれた部分が JS テンプレートの記述部分になります。

JavaScript の任意の式や文が記述でき、式の結果を出力したり、出力結果にフィルタをかけたりできます。また、Template.ContextのインスタンスをTemplateクラスのインスタンス(compile済み)の持つ、processメソッドに渡すことで、テンプレートに任意の変数を渡すことができます。

[##]というテンプレートの開始位置、終了位置を指定するための文字列は、TemplateクラスのインスタンスbeginTokenプロパティとendTokenプロパティを変更することで変更可能です。

頻繁に使うことになるのは、[# ... #] と [#= ... #] ですかね。テンプレートエンジンでよく見かける形式だと思います。

テンプレートのサンプル

[# ... #]

[# if (false) { #]
ここは出力されない
[# } #]

[#から#]で囲まれた範囲では、任意のJavaScriptの式や文を評価することができます。評価内容は出力されません。

[#-- ... --#]

[#-- 下記でゴニョゴニョする --#]
ゴニョゴニョ

[#--から--#]で囲まれた範囲はコメントになります。コメント中の式や文は実行されず、出力もされません。

[#= ... #]

[#= true ? 1 : 0 #]

[#=から#]で囲まれた範囲は、任意のJavaScriptの式を記述でき、評価された値が出力されます。

[#* ... #]

[#= foo #]
[#* return #]
[#= baz #]<!-- この変数の値は出力されない -->

[#*から#]で囲まれた範囲は、定義された特定のコマンドを記述できます。

とは言え、実際には、returnしか定義されておらず、returnコマンドを記述すると、その記述以降のテンプレートは評価されません。

[#| ... #]

[#|i "foo ${bar} baz" #]<!-- ${foo} や $foo という記述が変数展開される -->
[#|h "<script>alert(1);</script>" #]<!-- HTMLをエスケープする -->
[#|H "&lt;script&gt;alert(1);&lt;/script&gt;" #]<!-- HTMLをアンエスケープする -->
[#|u "テスト" #]<!-- URLエンコードする -->
[#|U "%E3%83%86%E3%82%B9%E3%83%88" #]<!-- URLデコードする -->
[#|lc "ABC" #]<!-- 小文字にする -->
[#|uc "abc" #]<!-- 大文字にする -->
[#|substr(0, 3) "abcdefg" #]<!-- 指定した位置から指定した位置まで文字を切り出す -->
[#|ws "   foo   " #]<!-- 前後の空白を除去する -->
[#|trim(3) "abcdefg" #]<!-- 引数で指定した文字以降を…(U+2026)で省略する -->
[#|date "2014-06-05T00:00:00+09:00" #]<!-- ISO形式の日付文字列をISO形式の年月日文字列に変換する -->
[#|localeDate "2014-06-05T00:00:00+09:00" #]<!-- ISO形式の日付文字列をロケールに合わせた表記に変換する -->
[#|rt "<script>alert(1);</script>" #]<!-- タグを削除する(内容は残す) -->
[#|rp(/foo/g,"bar") "foobarfoobar" #]<!-- 引数に指定した文字を引数に指定した文字に置換する -->

[#|から#]で囲まれた範囲は、評価された式の値に、定義されたフィルタを適用した上で値を出力します。

上記の中でも、iフィルタや、dateフィルタは、内部で使っている関数がCore.jsに依存しています。

MTのJSライブラリあまり調べたことなかったので意識していなかったんですが、結構グローバルオブジェクトを拡張してるようです。

rpフィルタはうまく動いていなかったので、PRしました。

また、フィルタはUnixのパイプのような感じで、複数組み合わせることができます。

[#|ws|rt|uc "   <span>abcd</span>  " #]<!-- 前後の空白を除去してから、タグを除去して、内容を大文字にする -->

Template.Context, Template.Filter について

Template.Contextには、いろいろメソッドが用意されていますが、Templateクラスを通して透過的に利用することがほとんどな気がしたので、紹介は割愛します。フィルタに関しても、基本はテンプレート内に記述するケースがほとんどでしょう。

Template.Contextのincludeメソッドは単体でも使うかもしれません。

var templates = {
  header: 'Header!!',
  body: '[#= context.include("header") #] Body!! [#= context.include("footer") #]',
  footer: 'Footer!!'
};
Template.process('body', {}, templates);
// => "Header!! Body!! Footer!!"

まとめ

よく使う機能に関しては、上記で紹介した通りです。あとはソース読んで確認してください。

昔はいろいろとMT標準のJSライブラリについて、ナレッジが共有されていたのかもしれませんが、今は、ググってもあまり情報が見つからない感じがします。

Template.jsに限らず汎用的に使えそうなライブラリもありそうですが、ドキュメントないし、自分のような新参者はソース読むしかない感じです。公式ドキュメントが待たれるところ。

Template.jsは、汎用的に使えるテンプレートエンジンだと思うので、MTの管理画面のカスタマイズ用途等で、特に他のライブラリを読み込む予定が他にない時は、このJSテンプレートエンジンを使おうかなと思ってます。

ほなの。

PSGI + SeleniumでMTの管理画面のテストをする

MTの管理画面は、JavaScriptに依存した部分が結構多く、PhantomJS等のヘッドレスブラウザを使ったテストが必要になるケースがあります。

CasperJSや、Seleniumなど、いろいろなツールがありますが、MTの管理画面のロジックは、Perlで書かれているので、Perlで書けるのがベストです。Perlでデータの初期化とかしたいですからね。

Perlで書ける方法でツールを絞り込むと、現状では、Selenium::Remote::Driverを使うのが良い気がしています。

ということで、下記のようなテストを書いてみました。

テストの実行には、MTのGitHubリポジトリに含まれる、tディレクトリが必要です。あと、試す場合は環境変数MT_CONFIGを書き換えずに、MT::TestでDBを初期化すると、既存データが吹っ飛ぶので、テスト用の環境は別途用意した方が良いです。

Test::TCPで、GhostDriverと、MTのPSGIの管理画面を空いてるポートで起動して、Selenium::Remote::Driverを使って、管理画面を操作する感じです。

実際書いてみると、いろいろハマりどころがあった感じですが、ハマりどころを回避しつつテストを書くことになりそうです。

テストと同時にキャプチャを撮れるので、エビデンス対策も取れてよいですね。上記のコードではダッシュボードと、記事作成後の画面をキャプチャしていて、下記のような感じのキャプチャが撮れました。JavaScriptも処理されていて、ちゃんとした見た目になってます。

f:id:jdg:20140501090135p:plain

f:id:jdg:20140501090152p:plain

もう少し便利メソッドをカジュアルに使いたい場合は、Wight を使うのも良い気がします。

他言語でもSelenium使う機会があるかもしれないので、今後の学習コスト削減のために、今のところは単純なアダプタであるSelenium::Remote::Driverを使おうと思います。

ほなの。