言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

ぼくが作った Wiki とワークスペースの歴史

ふと同じようなプログラムを何度も作っている事を思い出し。ちょっと振り返ってみる事にする。

Scamper Workspace

Scamper Workspace は Squeak で書かれた Web ブラウザで、普通のウェブサイトに書かれた Smalltalk ソースコードを簡単な操作で実行出来るようにした物。

最初のきっかけはこれだった。よく Squeak コード入りの日記なんか書くでしょう。そうするとそれをつい実行したくなってくる。ただそれをコピペして実行するだけでたいした手間では無いのだけど、おや待てよ?Squeak には最初からしょぼいながらも Web ブラウザ「Scamper」が付いてくる。何でわざわざ他にブラウザが居るのだ?しかし使ってみるとよく分かる違和感。Scamper が単純なテキストと画像しか表示出来ないのは我慢出来るとしても、それでもなぜわざわざコピペがいるのだ?

Squeak の理念は「アプリケーションなんて要らない」という事だ。Squeak の中のすべての部品は有機的につながっていて、例えばソースコードの中でワープロのようなキーバインドハイパーリンクが使えるし、文字をうてる所ならどこでもそこから Smalltalk コマンドを実行出来る。Scamper もまたそういった環境の一部であるべきだ。つまり例えば日記の中に面白い Squeakソースコードを書いたら、そのまま選択して実行出来るというのが自然なんじゃないか。というわけで Scamper に数行足して作ったのが Scamper Workspace。

必要な機能は最初から Squeak に備わっていたので、実現は非常に簡単だった。しかしその結果は我ながら思った以上に面白い物になったと思う。山本さんが沢山 Scamper Workspace 向けのコンテンツを作ってどんどん可能性を探求してくれた。

話の流れに沿ってコードを間に挿み、ユーザが順に実行していくという形態は、アイデアを伝えるのにとても効果的だと分かった。特に、そのページに画像が全く無くて文字列とコードだけで構成されている場合に特徴がはっきりした。最初ユーザがページを開いた時には単調な文字列しか現れないんだけど、コードを実行するにつれてそこから画像やアニメーションがどんどん出てくる。どんどんリッチになってゆくウェブ環境への強烈なアンチテーゼになるのでは無いかと僕は思った。なんしか目前の画面には文字しか無いまるで 1995 年のホームページなのに、ここまで面白い物になるとは驚きだった。

StackWiki

StackWiki は Squeak で書かれた画像付き文書作成ソフトで、文書はウェブサーバーに独自フォーマットで保存する。

StackWiki は Zest and Marmalade に触発されて作った。Zest はローカルで動く Wiki のような物で、簡単な操作で新しいページやハイパーリンクが作れる他、ページの内容は Squeak オブジェクトなのでスクリプトを使ったダイナミックなページを作る事が出来る。StackWiki はこれに加えてさらに HyperCardWiki の特徴をさらに強く出した物だ。

StackWiki は複数のページをまとめた一つのプロジェクトから成る。普通ウェブでは、ページ間の関係はリンクだけで表現されて、ページ間に主従関係や階層関係、前後順などは無い。ウェブサイトによっては URL やリンクを工夫して仮想的にこのような構造をユーザに見せている。

ページ間に構造を持たせる事で表示されているコンテンツの全体からの位置が分かりやすくなる一方で UI は煩雑になる。つまり、過去の閲覧履歴に移動する前後ボタンの他、ページ構成に対しての前後移動が必要になる。階層関係のあるサイトではされに親要素、子要素にアクセスさせるため、計三次元的なナビゲーションが必要になる。StackWiki では HyperCard を踏襲し、階層の無い前後だけの構造を持たせた。

バックグラウンドによって、複数ページにわたる同じような構造を一つにまとめる事が出来る。HyperCard では一つのスタックにつき複数のバックグラウンドを作る事が出来たが、StackWiki ではバックグラウンドを一つだけ許した。バックグラウンドは特殊なバックグラウンドページとして実装されていて、そのページに何かを足すと、すべてのページの同じ位置に同じ物が現れる。ここにも高機能さと分かりやすさのトレードオフがある。似た構造が二カ所以上ある時、共通部分をくくりだして一カ所で表現した物をマクロと呼ぶ。マクロを使うと、データに冗長性が無くなり、簡潔でメンテナンス性が良くなる一方で、マクロを使ってマクロを定義なんかすると、だんだん抽象的になってきて扱いが難しくなる。一枚だけのバックグラウンドはマクロの大胆な一般化と言える。

StackWiki のデータはページごとにバイナリ形式で Swiki サーバに保存される。Swiki 自体が Web アプリケーションだが、ここでは Swiki のファイルアップロード機能だけを使っている。サーバーとの通信に HTTP を使う以外完全な独自方式で、Web スタンダードに従っていない。他の web アプリケーションとの連携が不可能だが、Squeak の独自機能を活用し三日で実装した。

Tinlizzie Wiki

Tinlizzie Wiki とは。Tweak で作った Wiki で、ファイル形式に OpenDocument Format (ODF) を採用し、サーバに WebDAV を用いた物。

StackWiki のデータファイルは完全に独自形式だったが、Tinlizzie Wiki ではちょっと工夫して、出来る限り既存の形式を使う事にした。データ形式に ODF を使った理由は、Tweak のシリアライザが極めて不完全であった他、将来 eToys で作られたコンテンツを移植する際に利用可能なプラットフォームに寄らないデータ形式を調査するという目的もあった。フォーマット選定の基準は、テキストをベースとする事、画像の埋め込みが可能な事、独自要素の埋め込みが可能な事、リンクが可能な事があった。ODF は複数のフォーマットから成るが、特に Presentaion フォーマットが必要な形式に近かった。

ODF は XML を zip で固めただけの単純な形式で、画像などのマルチメディアデータも同じ zip 内に埋め込む事が出来るので、例えば作品から画像だけを取り出すというような事が簡単に出来る。他のプロジェクトへのリンクも画像の埋め込みも URL を使った統一的な手法で扱う事が出来るのも利点だ。また、独自のデータを埋め込めるので、Tinlizzie Wiki ではスクリプトを使ったダイナミックなページを作成し、Open Office Org でも静的ながら閲覧出来るという事も出来る。

出来るだけ自然な形で Tweak オブジェクトを ODF に書き出すために、データの保存には注意を払った。Tweak オブジェクトの最も単純な保存形式は、オブジェクトをシリアライズした物を独自形式で xml に埋め込むという方法だが、例えば、ブックオブジェクトをフレーム内のプレゼンテーションにするなど、他のアプリケーションからも自然に見えるようにした。

ここでの問題は、オブジェクトの状態をどこまで正確に保存するかという点だ。例えば編集中のテキストを保存する場合、テキストの内容だけを保存するのか(シリアライザ)、編集中のカーソル位置を含めてすべて保存するのかという選択肢がある。実装の観点から言うと、指定された変数以外すべて保存するか、指定された変数だけを保存するかという違いになる。Tinlizzie Wiki では後者を採用した。

これには二つのデメリットがある。まず Tweak ではユーザが勝手気ままに既存のウィジェットを組み合わせる事が出来るので、出来るだけすべての状態を保存する事を期待されている点。そして新しいウィジェットを開発するたびに保存ルーチンを書かなくてはならない点。しかしすべてをデフォルトで保存するという戦略は互換性に乏しい。例えばインスタンス変数名はある時点の実装に依存するので、それを元にシリアライズを行うと新しいバージョンのアプリケーションで読み込めない問題が起こる。特にインターネットでデータを共有する場合に頻繁に発生しやすい問題なので、単純なシリアライズは現実的ではないと考えた。作った当時は百年後でも読めるようなメディアを作ろうと思っていた。

サーバーには WebDAV を使った。StackWiki、Tinlizzie Wiki ともほとんどの機能をクライアントで実現し、サーバーはデータの保存だけしてりゃいいけど、WebDAV という共通基盤を利用する事で、サーバー側に Subversion を利用する事でバージョン管理機能を簡単に追加出来る。

Javascript Workspace

Javascript Workspace はクライアントに通常のウェブブラウザ、サーバに Ruby CGI スクリプトを使ったプレインテキストだけで構成される Wiki だ。

ある日アランさんが、アドビがスクリプトエンジンを Mozilla に寄付したらしいとメールしたのがきっかけで、このプロジェクトは始まった。とにかく Javascrit を覚えなきゃと思ったんだけど、何年も Web の世界から離れていていわゆる AJAX とか言うのにも縁がなく、Squeak の安楽な世界に浸っていたのでまず最初にすべき事は Javascript 上に Squeak の楽ちん環境を構築する事だった。

ここで再度 Smalltalk の Workspace 機能について確認する。Workspace は単純なテキストエディタで、普通のテキスト編集機能に加えて二つのコマンド "do it" と "print it" がある。do it は選択されているテキストを Smalltalk 文として解釈して実行し、"print it" 文は実行結果をカーソル位置に出力する。機能的にはスクリプト言語における REPL 機能と同じだけど、使われ方は結構違う。Workspace の典型的な使われ方としては、あるライブラリの作者がドキュメントとともに利用例を Workspace の中に書いて、ユーザがそれを読みながら実行するという物だ。つまり、REPL が機械とユーザ間との二者対話なのに対して、Workspace はプログラムの著者、ユーザ、機械という三者間での対話となる。

Workspace は Smalltalk にとって欠かせない機能だが、決して Smalltalk の専用機能だという訳ではない。Javascript が使える Workspace があっても良いじゃないかという事で作ったのが Javascript Workspce だった。そしてブラウザの機能ではファイルを保存出来ないから、作ったプログラムを Wiki のように保存するというのは自然な発想だった。

しかし制作の途中で、また余計な事を思いついた。Javascript Workspace を使っていると、Javascript だけでいかに多くの事を表現出来るかに気がついた。例えば Javascript の location を変更する事で他のページに移動出来るなら HTML のハイパーリンクは必要ない。ページの保存に必要な最低限の UI さえあれば、ただテキストボックスがひとつあれば良いだけだ。これは Scamper Workspace にも通じる発想だ。ページの最初のみかけが単純でも、そこからどれだけ豊かな物でも生まれ得る。

この「画面にテキストボックスが一つだけ」という構成は、また隠れている物が一つも無いというラディカルな発想に繋がる。普通のウェブサイトは、表面に見えている情報以外に多くの隠された情報がある。例えばリンク先の URL なんかはマウスを上に置かないと分からない。しかし Javascript Workspace では目に見える物だけが全てだ。do it した結果何が起こるかは、プログラムという形式で目の前に示されている。どんなプログラムでも実行出来るという一見危険なシステムながら、実は何も隠れていないという最も安全なシステムが出来上がる。

Javascript Workspace は単純ながら極めて使いやすいので、そのアイデアは Ometa/JS の UI として採用された。

TileScript

TileScript は GUI ライブラリとして Scriptaculous を利用し、サーバーに WebDAV を利用したタイルスクリプトが使える Wiki だ。データフォーマットは独自 JSON 使用。

一つの TileScript 文書は複数の段落からなり、段落は Javascript 文かタイルスクリプトか HTML 文だ。タイルスクリプトとは、数字や関数と言った Javascipt の文法要素を示すタイルをドラッグアンドドロップして、文法エラーに苦しまずにプログラムを書くツールだ。好きな HTML 文を書けるので、リッチテキストを使ったドキュメントの間に Javascript コードを埋め込んで、文書を読みながらプログラムを実行してゆくという事を想定している。

TileScript の最初の動機は、eToys を完全に Web 上に再現出来ないだろうかという事だった。その実験はまずタイルスクリプトの Web ブラウザでの実現から始まった。最初 Lively Kernel (SVG) の利用も考えたが、結局ドロップアンドドロップ機能を Scriptaculous で実現し、タイル自体は Table 要素を使う事で HTML DOM だけによるタイルの動作自体は出来た。

次に eToys 環境自体の移植という事になるが、すぐに大変そうだと分かった。見た目上のウェブの特性としては、ユーザのブラウズ環境によって文書のレイアウトが動的に変化するフローレイアウトという事がある。著者は文書要素の具体的な位置を指定せず、文書構造に注目する。結果文書要素は動的に配置され、画面からはみ出た部分は縦スクロールだけでアクセス出来る。

一方 eToys が前提とするのはページレイアウトだ。文書要素の縦横の配置が固定されていて、ある特定の画面解像度を前提としている。これは現実の紙の文書に近く、eToys のようなグラフィカルな制作環境にマッチする反面、画面がはみ出た場合左右スクロールかズームという煩雑な操作が必要になる。

TileScript の目的は単なる eToys の移植ではなく、Web ならではの新しい方向を模索する事だったのでフローレイアウトを採用した。フローレイアウトを使っても埋め込み画像の形式で絶対座標を使ったコンテンツを埋め込む事が出来る。eToys と同じくある時点の変数の内容をリアルタイムで表示する変数ビューワを提供したが、そういったウィジェットもフローレイアウトに沿って配置した。

その後

TileScript で想定したコンテンツがちょっと大人向きの物だったので、実はタイルなんか要らずに、普通に Javascript だけで良いじゃないかという事になった。今作っているのは簡単に言うと Javascript Workspace にリッチテキストが使えるようにした物だ。また、方向としてはイアンのやつを使った全然 Web とは関係ない仕組みも作る予定なのだが、Web アプリは継続して行こうと思っている。その理由はフィードバックだ。ここにあげたプロジェクトはほとんど全て内部的なデモの為に作られた物で、まったく外部への公開を意図していないにも関わらずどこから嗅ぎ付けるのかそれなりのフィードバックが得られる。内製ツールだけを使ってシコシコ誰も見ないプログラムを書くのとは全然やる気が違ってくるわけ。ウェブはすばらしい。