e2wmについて考えたこと(調査や要件定義など)
ツールを作るのも好き。昔からツールを作って満足して、そもそもの目的が達成できないタイプ。
はじめに
この記事では、e2wm.elがなんでこんなUIになっているかを説明します。UIにはストーリーが重要だと思っていて、e2wm.elについて考えたことをまとめたいと思います。また、e2wm.elやこの記事をきっかけに、Emacsに限らず、今後のIDEの開発の貢献に役立てるといいなと思っています。
あんまりうまく使い分けできていませんが、名称について。
- e2wm 仕組みや仕様を指すとき
- e2wm.el 今回の実装を指すとき
あらすじ
- 図の一覧@Cacoo (2010/07/03追記)
Emacsと画面のサイズの変化
きっかけは画面サイズ(ワイド画面)の変化でした。
以前のXGA:1024x768 (X61, X31, それ以前)のとき
自分はあまりEmacsのウインドウ分割はしない方でした。バッファ切り替えよりは必要なバッファを表示したフレームを用意しておいて、OSのウインドウ切り替え(WindowsならAlt+TAB)で表示したいバッファを切り替えていました。また、ウインドウも最大化せずに縦いっぱいの画面の幅2/3ぐらいにしておいて、隙間から下のウインドウの内容が把握できたり、何回Alt+TABを押せばいいのか分かるようにしていました。
今から思えば、バッファの行き来がEmacsのバッファ選択よりはOSのウインドウ選択の方が操作が速くて、しかも画面に切り替え先のバッファが表示されているため、視覚的にも分かりやすかったということがあるのかなと思います。
また、Emacsがpop-to-bufferなどで自動的に行うウインドウ分割にも、特に疑問や違和感を感じたことはありませんでした。おそらく1フレーム1ウインドウというのがEmacsの基本的な使い方ではないかと思いますが、このようにウインドウ分割がほとんど無い場合は pop-to-buffer(というよりはdisplay-buffer)が、空気を読んだ賢いウインドウ分割してくれます。必要なときに出るべき場所に出て、必要ないときには自動的に引っ込んでくれます。そのため、display-bufferの実装は、表示のカスタマイズや「空気を読む」ための条件分岐の連続になっています。
ただ、ウインドウ切り替えでは、複数のバッファを同時に見ることが出来ないため、時に神経衰弱のようなストレスを感じることがありました。さっとウインドウ分割をしてバッファを並べればいいのですが、「最大化 → C-x 3 → C-x o → バッファ切り替え」というコマンドを毎回入力するのもしんどいので、あまり使う気にはなれませんでした。
一方で、Eclipseなどの一般的なIDEはXGAだと画面(特に幅)が狭くて使いづらいと感じていました。いつも新しいワークスペースを作るたびに、両サイドや画面下の「ビュー」や、ツールバーを適切にカスタマイズして、画面を広く使えるようにしていました。ちょうどその頃、Macがワイド画面になり、これならEclipseは便利そうだと感じたのを覚えています。
画面が広くなった
昨年、1920x1080のディスプレイを使い始め、また今年に入って 1440x900 の X201s にメインマシンを変えてから状況が変わりました。デスクトップの画面が広くなると、今までの1フレーム1ウインドウでは逆に不便に感じてきました。
まず、ウインドウを左側から隙間無く詰めていくと、モニターの左側ばかりを見ることが多くなり、特に23インチワイドモニターでは首が痛いです。最大化して左右2分割してもあまり状況は変わりません。
次に、画面中央の見やすい位置に持ってきて使うと、ちょうど目の前にコードが表示されて悪くはないのですが、画面の半分近くを無駄に使っています。
そこで、Emacs最大化をしてEclipseみたいにウインドウ分割をしてみるのですが、ちょっと複雑なウインドウ分割を行うと、今度はEmacsの「空気を読む」ウインドウ分割がうまく働かず、意図した位置にバッファが出てこなかったり、ウインドウ分割が壊れてしまったりしてうまくいきません。
また、Emacsのウインドウ分割を毎回行うのも大変です。分割の切り替えを行うことが出来るツールはElscreenやwindows.elを始めたくさんあります。また、中には分割状態の保存を行うことも出来るものもあります。しかしながら、分割の仕方は常に一定というわけではなく、同じバッファといえども作業に応じて分割方法を切り替えたいため、これらのツールはコーディング作業ではあまり役に立ちませんでした。一方で、howm、Wanderlust、SkypeではElscreenを便利に使っています。おそらくやりたい作業とElscreenの機能がうまく合っているのだと思います。
最後に、Emacsのバッファ切り替えも不便に思っていました。以前はOSのウインドウ切り替え(Alt+TAB)で切り替えていたため不便に思わなかったのですが、Emacsでバッファ切り替えを行おうとすると、編集対象でないバッファも候補に挙がるため、「2,3のバッファを頻繁に行き来する」ような開発で良くある使い方が便利に出来ません。ついさっき表示していたバッファをもう一度表示するのにswitch-bufferやanythingを使うのも面倒です。Eclipseではブラウザのhistory.backのようなコマンドがあり、また編集対象のファイルしか選択しないため、このあたりはEmacsに比べて便利に感じていました。
逆に、画面が広くなるとEclipseやVSのようなIDEがすごく便利に感じてきました。狭い画面だとごちゃごちゃして窮屈な画面だったのが、モニターが広くなると画面の中央にコード領域がちょうどいい大きさで表示され、コード領域の周辺にプロジェクト情報やアウトライン、ツールバーなどの機能や情報が見やすく使いやすい形で並んでいます。しかもキーバインドを適切に設定してそのIDE流の操作に慣れれば、ほとんどの作業はマウス無しで快適に使えるようになります。Emacsもこういう感じで使えるべきだとはっきり認識しました。
ただ、Eclipseを使う仕事で忙しかったため、どうにかしたいのだけども具体的にどうしたらいいのかはっきりしないまま、しばらく悶々とした日々を過ごしていました。
Window分割のライブラリの開発
今年に入って仕事の区切りが出来たので、skype.elの改良を行っていました。1年以上使ってきて、いろいろ改良のアイデアがたまっています。特にウインドウのレイアウトを使いやすく配置したいと思っていたので、これまでの pop-to-buffer や split-window を適当に使っていたのを何とかしようと、他のEmacsアプリがウインドウ分割をどうやっているのか調べてみました。3ペインを実現しているWanderlustと、IDEっぽい画面になるECBを読んでみると、ウインドウレイアウト周りは整理されておらず、結構普通にレイアウトのコードがかかれていました。
そこで、まずはウインドウレイアウトを抽象化できそうなライブラリが欲しいなということで、出来たものが window-layout.el です。複雑なレイアウトでも構成をDSL的に書いて楽に指定できたり、特定のウインドウの表示をトグルするなど、ウインドウ関係で必要な機能やAPIを一通りそろえてみました。
出来たコードでいろいろ実験しているうちに、Emacs上のウインドウマネージャーのアイデアが出てきました。ウインドウ分割や表示の制御については、このライブラリと適当な関数のフックで何とかなりそうです。あとはこれに履歴管理や、周辺の領域を便利に使えるビュー機能があれば必要な機能が整いそうだと思いました。
調査、研究
ということで、Emacs上のウインドウマネージャーを自作しようかなと思い立ったわけですが、大抵似たような実装がどこかにあったりするので、まずは前例や参考になりそうな実装を探してみました。
elispの実装
Emacsを使っていて同じことで困っている人はいるのではないかと期待してみましたが、自分が期待していたもの(ウインドウ分割のレイアウト制御、Emacsのウインドウ管理)は見つけることが出来ませんでした。
- xwem
- http://www.emacswiki.org/emacs/XWindowEmacsManager
- タイル系のXのwm。探してるものとは違う。
- Window管理系
- window.el(標準添付)
- pop-to-buffer, display-buffer などの実装がかかれている
- プリミティブな関数が多い
- winner.el(標準添付)
- current-window-configurationとポイント位置の履歴を管理
- 2つに割って、また元のレイアウトに戻すなどの制御が出来る
- 戻るだけでなく、redoで進めるところが便利
- 履歴やフレームの扱い方を参考
- elscreen, windows.el など
- http://www.bookshelf.jp/soft/meadow_30.html あたり
- 分割、切り替え、保存が出来る
- 分割は人間がする。汎用的過ぎる感じ。
- ECB
- http://ecb.sourceforge.net/
- やりたいことは見た目的には一致している
- Emacsの柔軟さが純粋になくなって、他のIDEより明らかに不便になっているように感じた
- レイアウトの変更は大変そうで、コードも大きくて自分がやりたい形に持って行くには大変そう
- JDE並にインストールが大変
- ewm.el
- http://osdir.com/ml/gnu-emacs-sources-gnu/2010-05/msg00026.html
- 2010/05/20 gnu-emacs-sources のMLにポスト
- こちらのリリース準備中だったので、名前の変更に躊躇した
- window管理
- レイアウトの構築
- バッファと表示位置(ウインドウ)の結びつけ
- 軽くて求めたものに近い
- もっと前からあれば実装は参考にしていた!!
- window.el(標準添付)
自分の知らないところで他にもあるのかもしれませんが、ewm.el 以外はプリミティブな実装以外は誰もやってなさそうだということが分かりました。
ということで、「広い画面でEmacsを有効に活用するためのアプリ」を作るため、仕様をいちから考えることにしました。
お手本を調べる
まずは、Emacsに限らず、他のアプリがどのように画面を使っているのかを調べてみました。
Eclipseに限らず、NetBeans、IntelliJ、Visual Studio などのIDEは同様のレイアウトになっています。
典型的なIDEの画面構成を表してみると以下のようになると思います。
重要なことは、このレイアウトはデフォルトの配置であって、開発者がかなり自由に表示内容やレイアウトを変更できます。これはIDEっぽい画面にするだけではだめで、細かい画面レイアウトのカスタマイズが出来なければ、広く受け入れられないと言うことだと思っています。
また、Eclipseのパースペクティブのように、開発環境全体で画面の状態を持っていて、状態ごとに画面のレイアウトが変化するのも共通しています。やはりユーザーが何をしたいのかという場面を切り替えて、それぞれ使いやすく画面をレイアウトする機能が必要そうです。
IDE・開発環境の未来の形についても少し見ておきたいと思います。開発環境の研究では、UIだけでなくプログラミング言語などの研究と合わさって、かなり広い分野で多様な試みが行われているようです。典型的なIDEっぽい分野に絞ると、コードや設計の可視化・ナビゲーション、プログラマの思考の支援などが見つかります。tenjin.webでid:brazilに教えてもらった最近のIDEの研究をいくつかあげてみます。
どちらも必要なコードをひとつの空間に並べていって、関係のあるコードを近所に置いていくというアイデアです(CodeBubbleはまだ論文が見れない?)。ひとつのプロジェクトでも、大体関連のあるまとまりというのはあると思いますし、またいくつかのファイルを行ったり来たりすることは多いと思います。また、空間的な配置がそのまま大まかな設計にもなると思います。
現在広く使われている「弁当箱」のような画面配置のIDEでは、画面を切り替えることに疲れてきて全体を把握する能力に限界がくるだろうということで、ユーザーのマシンのモニター解像度とグラフィックスパフォーマンスの向上から、積極的にコードを柔軟にレイアウトして開発者の思考を補助しようということが動機になっているようです。検索結果やコールスタックをウインドウに表示するんではなくて、コードの上にレイヤーとしてかぶせるとか、ビジターパターンなどのサブクラスを横に並べて実装を比較するなど、なかなかしびれる機能が満載です。
CodeCanvasには「マルチキャンバス」と呼ばれる作業状態をいくつも作っておく仕組みが備わっています。作業状況に応じて見方の違うキャンバスに切り替えたり、ユーザー思考を永続化しておいて、またすぐに思考が復帰できるような仕組みのようです。パースペクティブはこのマルチキャンバスが少し固定化したものであると考えることが出来ますが、マルチキャンバスのようにもう一歩進んでパースペクティブの状態を永続化してそれらを切り替えたりするというアイデアはいいかもしれません。
これらの研究などからも、積極的に広い画面を有効活用する方法の模索が続いていくものと思われます。一般の開発現場に適用されるのはかなり先にはなると思いますが、おそらく将来のIDEはCUIの延長ではなく、グラフィックの性能をフルに活用したものになるのではないかと思われます。Emacsもやっと自由に画像やフォントを操作できるようになったので、今後の開発環境の発展の方向として非常に参考になると思います。
一方で、今後もキーボードでの入力が中心になるような開発スタイルでは、マウスを多用するようなIDEは果たして使いやすいのかどうか疑問にも思います。少なくとも、自分がまだ乗り換えたいと思うような開発環境はまだ見たことはないですし、今後もEmacsで頑張っていくつもりです。まずはこれらの先端研究の問題意識やアイデアだけ借りようと思います。
IDEとしてだけではなく、広くなった画面を有効に使うアイデアを調べるために、他のUIも調べてみました。
- Windows Vista / 7
- ガジェットを左右に置く
- IDEと同様、中央がメインで左右は補助的な情報
- 常に出ていているがあまり気にならない、視線移動だけで見える
- Aeroスナップ
- ウインドウをかんたんに最大化したり左右に並べる機能が便利
- XPでも機能自体はあったが使いづらかった
- ガジェットを左右に置く
やはり、ワイド画面の左右の空間をうまく扱ったり、左右に広くなった画面を便利にする機能があります。左右に並べる機能は個人的にもよく使いますし、Emacsでもコードを比較したい場面は良くあります。機能があるだけではなく、思った瞬間にすぐ使える操作感というのがポイントだと思います。
- Mac OSX
- Expose
- ちょっと混乱してきたときに便利
- 面白い
- ダッシュボード
- 必要なときに見たいもの
- ちょっとした割り込み作業
- Expose
Macはウインドウの最大化が微妙なのですが、見た目やアニメーションなどの完成度が非常にいいです。Alt+TABでアプリを切り替えている人もいれば、Exposeで切り替えている人も少なくありません。
シンタックスハイライトやソースの形からバッファが判別できることも多いので、EmacsでもExposeのようにバッファを縮小して一覧にしてみるとおもしろいのではないかと思いました。また、ダッシュボードというアイデアというか、割り込み作業や開発とは関係ないEmacsのバッファを表示するのもおもしろそうだと思いました。
メジャーなアプリもワイド画面を有効に使えるように画面の構成が変えられるものが増えてきています。
以前のこれらのアプリは、画面の上に一覧、その下に詳細を表示するような、いわゆる「3ペイン」の分割していたのですが、横に広く画面を使って、一覧の情報量を増やすことに成功していると思います。
Emacsでもウインドウの幅が一定以上あれば、上下分割ではなくて左右分割を使うようになっています。Anythingなど、一覧を表示する機能では、横幅が十分あれば縦に長い方が一覧をたくさん表示できるので便利になります。
他にもいろいろと参考になるUIがあると思いますが、いくつかe2wmの仕様に参考になったUIをあげてみました。以上の調査を元にして、e2wmの仕様を考えてみました。
Workflow / プログラマの業務分析
Emacsに限らず、開発環境やエディタはプログラマのためのUIです。UIを設計するためにはユーザーの業務を出来るだけ詳しく知る必要があります。また、ユーザーは大抵自分の業務を説明できるほど知らないことが多いです。ということで、まずはプログラマの業務を知りたいと思いました。
エディタやIDEは、昔から開発し尽くされてしかもドッグフードも食べまくっているため、どこかにそういう文献や資料がないかなと思って探してみました。安易に「プログラマ、エディタ、業務(ワークフロー)」で探すと、「(ビジネス上の)業務フローエディタ」という意味になってしまい、UMLとかBPMNのエディタしか出てきません。たぶん探し方が悪いのだと思います。論文のリファレンスをたどればいいのかもしれませんが、大学所属でないと自由に論文が読めないのですぐあきらめました。
仕方がないので自分の普段Emacs上で行っている業務の分析を行うことにしました。箇条書きでまとめてみると以下のようでした。
- コードを書く
- 通常ファイル1つを編集
- 出来るだけ上下に長く、ひとつのコードに集中したい
- ソース内、ソース間のナビゲーションが重要
- コードを読む
- 定義を追っていく→戻りたい
- 比較する
- →左右に並べたい(画面次第で上下)
- コードの整理
- リファクタリング
- コードの移動→これも並べたい
- コードを書くのに必要な情報を参照
- うろ覚えなのでちょっと見たい
- help、APIドキュメント
- →いつも決まった場所にちょっと出て、終わったら消したい
- なんだか良く分からないのでがっつり読みたい
- info,webとか
- →画面いっぱいで読みたい
- うろ覚えなのでちょっと見たい
- コンパイルや、REPL、外部プロセスを実行
- デバッグ
- 考える、設計する
- 俯瞰する、全体を見渡す(設計のメモ)
- メモする(紙、野良テキストファイル、howm)
- 絵を描く(紙、cacoo)
- ソース管理
- 現状、ほとんどの作業はシェルや亀(TortoiseSVN)でやっている
- 変更状況の確認
- コミットログを書く
- →変更状況やdiffを見る
- リポジトリの履歴やディレクトリを眺めたい(亀のリポジトリビューアーのようなもの)
- コミュニケーション
大体、予想通りの結果にはなりましたが、1つのコードを表示する画面と左右2分割の画面を行ったり来たりしたいという要望は以前からぼんやりあったのですが、この分析作業によって形になり、もやもやが取れてすっきりしました。
また、業務の中で、Emacs以外のツールで満足しているものもあります。すべてをEmacsでカバーするのではなく、手持ちのツールの組み合わせでトータルな効率が上がればいいので、要件定義の際に優先度を考えることにしました。
ちなみに、これは自分の普段のプログラミング周辺の作業を洗い出したものなので、もしかしたら他の人の作業の仕方とは違っているかもしれません。また、作業が違うということがひとつのカスタマイズの切り口になるのだと思います。これについては後で書きます。
結局ほしいもの
以上から、ユーザーである自分の要件が見えてきたので、e2wmの初回のゴールを定義したいと思います。
図にすると以下のような形です。
WindowManagerとしての機能
まずは、大枠の機能を以下のように定義しました。
- 決まった位置に、ポップアップや指定したバッファを表示させたい
- 典型的IDEの画面構成を実現したい(真ん中にコード、左右にビュー、下にポップアップ)
- window-layout.el とウインドウ管理関数を丸ごと乗っ取りで実現
- ウインドウの分割や位置、サイズは各自が細かくカスタマイズしたい
- なるべく簡単にカスタマイズできるようにしたい
- 設定のわかりやすさとドキュメントをがんばる
- パースペクティブのように、作業に対して最適なウインドウレイアウトになってほしい
- ビューをたくさん用意したり、ユーザーが簡単に作れるしくみを用意したい
- プラグインの仕組みをつくる。また、実際にいくつか作ってみる。
- 編集バッファの履歴管理
- コード編集やコードリーディングで良くあるナビゲーションが楽になるように
いきなりフレームワーク的な要件になってしまいました。作ったこともない領域でフレームワークは作れないので、まずはフレームワークのことは全く考えずにベタに書いて、それからまとめていくという方針で行くことにしました。
パースペクティブ
上の業務分析から、まず用意したいパースペクティブを考えてみました。
- コード書く
- 典型的IDEの形、コードは1つのみを出来るだけ大きく表示する
- 画面の左右にビューを配置して、コードを画面の真ん中に持ってくる
- 比較、参照
- 左右2分割してコードを2つ大きく表示する
- 履歴の情報をうまく使って、左右のバッファ選択を楽にする
- ドキュメント参照
- follow-modeでひとつのドキュメントやコードをマルチカラムで表示する
- がっつりドキュメントやコードを読めるように
- バッファ一覧
- コードを縮小して俯瞰して眺める
- ダッシュボード
- 割り込み的な作業を処理
以上が初回リリース時に実装してみようと思ったパースペクティブです。バッファ一覧やダッシュボードは実験的なものですが、e2wmの可能性を確かめてみる上で必要だと考えました。
以下のパースペクティブも必要だと思いますが、具体的な形がまだ見えてなかったり、別のツール(シェルやWebブラウザや専用アプリ)であまり困ってないため、後で考えることにしました。
プラグイン(ビュー)
次に、e2wmに用意するべきプラグイン(Eclipseでいう「ビュー」)を考えました。基本的には「典型的IDE」の画面を構成するビューを用意すればいいかなと思っていますので、以下のものを用意しようと考えました。
- バッファ一覧(履歴)
- 編集するバッファだけに限定。表示中のバッファの位置を表示。
- ファイル一覧
- 現在編集のディレクトリのファイル一覧
- アウトライン
- Imenuを使って、ジャンプしたりと現在地を表示したり
- 時計
- ガジェット的なもの
ファイル一覧については既存の実装のdiredやspeedbarを使ってもいいかなと思ったのですが、自分がEclipseのプロジェクトツリーをあまり便利に使ったことがない(AnythingみたいにCtrl+Shift+Rで開いてしまう)ので、もうちょっと自分がこれだったら便利だと思うものを作ってみようと考えて自作することにしました。
また、これらのビューはユーザーが簡単に作れた方がいいかなと思っていますので、出来るだけ簡単に実装できるようなフレームワークを考えようと思いました。
e2wmで軽減されるもの、ゴール
以上の具体的な形をイメージしながら、e2wmが達成すべきゴールを再度確認しました。
- お好みのウインドウ分割を実現
- 情報は決まった場所に表示
- 視線の移動を自然に
- ポップアップなどでレイアウトも壊れない
- パースペクティブ切り替えるだけでやりたいことがほぼ実現
- 情報は決まった場所に表示
- バッファ切り替えのストレスの低減
いろいろ風呂敷を広げてきましたが、実際にe2wmが目指す目標はこれだけです。
あとは既存のEmacsの機能や実装をうまく生かして、それぞれのユーザーが構築しているEmacs環境を壊さずに、ウインドウの使い勝手を伸ばすものに仕上がればベストかなと思いました。
対象とするユーザー
e2wmが対象とするユーザーは以下のような人です。カスタマイズや導入スキルなどの前提になります。
- Emacs22,23に対応
- CarbonEmacsやMeadow、またコンソール上(-nw)でも使えるように。
- 設定で使うようなelisp(setqやクオートやシンボル)が分かる人
- 広いディスプレイで作業していて、Emacsのウインドウ分割に違和感を感じている人
- 自分好みのウインドウ分割しているという時点で、ある程度のEmacsユーザーであるはず
デフォルトやおすすめ設定をある程度使いやすくしておいて、いちいち細かくカスタマイズしなくてもある程度使えるようにしようということも目指したいと思いました。
結果だけでなく過程がおもしろいかも
以上がe2wm.elを開発するときに調べたり、考えたりしたことのまとめです。
時に、何かを作る過程で得た知見というのは結果よりもおもしろかったりします。毎回いろいろ作って発見の連続なのですが、今回のe2wm.elもおもしろかったです。似たようなことをやっている人の参考になればと思っています。
自分が必要なものを開発していると、自分で満足したところで終わってしまうので、なかなか資料をそろえてリリースしてみたり、その開発で得た知見などをまとめたりする気力がなかったりします。今回は頑張ってみました。
続いて、e2wm.elの拡張をサポートするための実装の簡単な解説を書こうと思います。