エンドユーザ向けアプリケーションを書くときに必要になる、フォーム入力、メニ ュ、テキストといったユーザ・インタフェースを作って、多くのタスクを組み立て るのは、なかなか手のかかる作業ですが、「Unix」を生んだ「AT&T Bell Laboratories」で開発され「AT&T」内部で長年に渡って数多くのプロジェクトに使 われてきた「Easel」(End-User Application System Encoding Language) と呼ば れるエンド・ユーザ向けアプリケーション開発言語が、一般の書籍
Ed. Balachander Krishnammurthy,- Practical Reusable UNIX Software (John Wiley & Sons, Inc.) ISBN 0-471-05807-6)にも紹介され、そのソースコードも
http://www.research.att.com/sw/tools/reuse/で公開されました。
一般に、対話型エンド・ユーザ・システムは、ユーザ・インタフェース(フォーム、 メニュ、テキスト)とシステム構造(タスクとサブ・タスク)からなる「デザイン・ プログラミング」(Design Programming) の部分と、計算機能とデータ構造からな るアプリケーション固有の「計算プログラミング」(Computation Programming)の 二つから構成されますが、問題の本質とは関係ない割に手のかかる前者がアプリケ ーションとは独立であることに着眼して、専用の言語(Easel Language)とそのコン パイラ、インタプリータ、開発ツールを実現したもので、従来のやりかたと比べて、 ざっと 1/10 の手間で済むことが実証されたそうです。
この言語の感覚は、前記の書籍が例にあげている電子メイルのシステム
1) メニュからメイルの相手先を選択し、 2) フォーム入力によりメイルを作成し、 3) mail コマンドで発送するの Easel による記述例を見ると良くわかると思います。
{frame email ~call users > ~users ~call select ~users > ~to ~call mform ~to > ~to ~subj ~mesg (~to!=~null && ~mesg!=~null): ~call msend ~to ~subj ~mesg }f「{frame .. }f」はハイレベルのタスクで、Easel では「フレイム」(frame) と呼 んでいます。先頭が「~」で始まる名前は Easel のコマンドや変数で、このフレイ ムでは、「users」というフレイムを呼び出して、その出力を「~users」という変 数に格納します。後でわかりますが、これがメイルの宛先のリストになっています。 「}f」等の「}」の後ろの文字はコンパイラが無視しますが、対応が明確になるよう に、習慣として付けられています。
次に、「select」というフレイムにその結果を渡して、その処理結果を「~to」に 受け取りますが、これがユーザがメニュによって選択したメイルの宛先になります。
その後、「mform」というフレイムにメイルの宛先を渡して、メイルの宛先、表題、 本文をフォーム入力し、最後に宛先と本文の両方が記入されているかどうかをチェ ックしてから、「msend」フレイムに宛先、表題、本文を渡して、メイルを発送しま す。
最後の「~call」の前の「:」式は、全体あるいは部分として省略可能な
[実行条件 : 終了条件]というもので、Easel のほとんどのコマンドはループ構造になっていて、
if (実行条件) while (終了条件) コマンドを実行という方式で実行されますから、この条件式を省略すると、「真」の条件を指定 したと見なされますから、二つ共省略すると、そのコマンドは一度だけ実行され ることになります。上記のフレイムの最初の3行はこの両方が省略された場合で す。
{frame users {process "/bin/sh" > ~logins ~!"ShIsDone\n","echo ShIsDone\n" ~$ cat /etc/passwd | cut -d: -f1 | sort -u | xargs }p ~return ~logins }f「users」フレイムでは /etc/passwd ファイルの最初のフィールドを切り出して、 そのホストを利用するユーザのリストを作っています。「process」ブロックは 入力と出力の2つのパイプを作って、指定されたコマンド(ここでは /bin/sh)の 標準入力と標準出力を Easel に接続し、「cat /etc/passwd」以下のコマンドを 実行させ、最後に「~!」で指定した「echo ShIsDone\n」コマンドを実行させ、 「~!」で指定した「ShIsDone\n」というレスポンスを待ちます。つまり、「~!」 は指定されたコマンドが持ち返る文字列の最後の識別に使われ、その直前までの 文字列が「~login」変数に代入されて、それを「email」フレイムに返します。
「~$ [変数]」はこの間ディスプレイに何を表示するかの指定で、この場合は表示 変数がありませんので、画面はそれまでのままになります。
{frame select ~list {menu :(~pers == ~null) ~pers .window( x=5, xlen=50, y=0, ylen=10 ) Mail To: ~to {option ~list " \t\n" ~to = ~to * ~pers * " " }o }m ~return ~to }f「select」フレイムは宛先のリストを受け取って選択メニュを作ります。 「{option .. }o」がメニュ項目とユーザが何か選択したときのアクションになり ます。ここでは、ユーザが選択した宛先をリストにまとめていますが、これは同一 のメイルを複数のユーザに送ることを考慮した結果です。ユーザは選択の終了を 「Ctrl-E」というキー入力で指示します。ここで何も選択せずに終了しても、次の フォーム入力で任意の宛先を入力することができます。
{frame mform ~To {context .form( c=2, a=p, To: <_____________________ $ ~To Subj: <___________________________ $ ~Subj Mesg: <___________________________ $ ~Mesg ) Mail Form {descript Some HELP for the form }d {question ~To To: }q {question ~Subj Subj: }q {question ~Mesg .field( r=10 ) Mesg: }q }c ~return ~To ~Subj ~Mesg }f「mform」フレイムでは宛先(To:)、表題(Subj:)、本文(Mesg) を記入するための フォームを作って、ユーザが自由に記入できるようにしています。ユーザが
{frame msend ~To ~Subj ~Mesg ~getenv ~LOGNAME {process "/bin/sh" ~!"ShIsDone\n","echo ShIsDone\n" ~$ mail ~To < 「msend」フレイムは mail コマンドにフォーム入力された、宛先、表題、本文 を渡してメイルの発送を行いますが、最後に「Thanks! 発信者の名前」という行 を自動的に追加するために、「LOGNAME」環境変数を使っています。
easel の使いかた
Easel のソース・ファイルは普通「.f」のサフィクスを付けておきます。全てを 一つのファイルにまとめても、フレイム毎に別のファイルにしてもかまいません。 例えば、上記のファイルを「email.f」にした場合は、「efc」というコンパイラ で、
efc email.fを実行すると、email.p, users.p, select.p, mform.p, msend.p というオブジェ クト・ファイルができますので、エラーがなければ、「efm」というインタプリー タを使って、efm -semail等で実際に実行することになります。Easel が扱うデータは文字列だけですが、それが数値として解釈できる場合は、 数学関数を含めた数値計算も可能ですし、文字列や正規表現の処理もできるように なっています。メニュやフォーム等の画面の細かな制御もできますが、ほとんどの 場合、デフォルトの動作で間に合うように、うまく設計されています。詳細は、ソ ースに付属する詳細なドキュメント「EASEL Programmer's Manual」を見てくださ い。140 ページほどですが、groff でフォーマットする場合は、mm マクロを最新 のもの(ftp://ftp.efd.lth.se/pub/mm*.tar.gz)で置き換える必要があります。古 いバージョンでは「.FG」「.TB」のバグがあって、表の一部がうまく印刷できませ ん。
「Figure.1」だけは、ベル研の新しい roff のプリプロセサがないと処理できませ んが、これは前記の書籍の「Figure 4.5」(pp 151)と同じもので、私が pic で書 いたものを、下記に付けておきます。
.PS R: ellipse "Requirements" width 1.5 height 0.3 at 0,2.1 U: ellipse "User Interface" "Frames" width 1.5 height 0.5 at -1.2,1.4 C: ellipse "Computations" "Data" width 1.5 height 0.5 at 1.2,1.4 P: ellipse "Prototype" width 1.2 height 0.3 at 0,0.6 UT: ellipse "User Test" width 1.2 height 0.3 at -1.1,0 Rl: ellipse "Releases" width 1.2 height 0.3 at 1.1,0 arrow from 1/2to U.ne arrow from 1/2 to C.nw arrow from U.se to P.nw arrow from C.sw to P.ne arrow from P.sw to UT.ne arrow from P.se to Rl.nw spline -> from UT.nw to (-2.3,1.8) then to R.sw spline -> from Rl.ne to (2.3,1.8) then to R.se .PE Easel には「efb」(EASEL Frame Builder)と呼ばれる Easel のプログラムを対話 的に作成するツールがありますが、これは Easel で書かれています。
コンパイル
上記のサイトから「easel.src.unix.README」と「easel.src.unix.cpio.Z」を取 ってきてから、次の操作を行うとコンパイルできます。
1) /usr/local/easel 等のデュレクトリでソースを展開 zcat easel.src.unix.cpio.Z | cpio -icdmv」でソースを展開 2) インストール・スクリプトの実行 ./Install いくつかの質問がでますが、gcc を使う場合は cc のオプションで 「-traditional」か「-fwriteable-strings」を指定してください。 ソースの中に文字列定数を書き換えるところがあります。また、 「Multi-byte」文字を指定します。その他はデフォルトでコンパイルは「Install」スクリプトで「Mk-efs」スクリプトを作成し、 「Mk-efs」をバックグラウンドで起動して、経過の記録「mk.out」に取る仕組にな っています。ライブラリの一部のオブジェクトを消し忘れていますので、後から消 すか、Makefile を書き換えてください。移植やデバッグを行うときは、やりかた を替えないとたいへんです。だ け押してください。 多くのシステムでは簡単にコンパイルできますが、最近の BSD 系ではマクロ名の 衝突等があって、かなりの書き換えが必要でした。また、Sun の SparcServer1000 (マルチ・プロセッサ)では efm が起動されたとたんに core を吐いて死んでしま うものですから、それに対応した変更が必要というのが私の経験です。
Easel のソースには次のライブラリが含まれていて、標準の「stdio」ライブラリ や「curses」ライブラリは使われていません。バグが多くて使いものにならず、 新しいライブラリから作るしかなかったのだそうです。メニュやエディタ等の機能 も新しい「screen」(curses) ライブラリ内部で実現されています。
screen library - Easel の足場になっている高機能「curses」ライブラリ sfio - 高速で安全でモダンな stdio ライブラリ dict - 辞書操作を行うためのライブラリこれらはすべて src/lib ディレクトリに入っていて、ドキュメントは doc/lib にありますが、screen ライブラリのドキュメントは wmenu() 関数等で一部実物と 一致しないところがあります。screen ライブラリの名前は「curses」が商標権 問題で使用できなかったためということですが、非常に高機能なもので、 SystemV に含まれるものから、さらに拡張されていて、Termcap と Terminfo の いずれでも使えるようになっています。sfio は従来の stdio に比べて、かなり モダンな設計です。日本語化
Easel そのものは、「Multi-byte Asian characters」に対応した「screen」 (curses)ライブラリを使っていますので、もともと EUC の半角カナに対応してい ますし、メッセージをそれぞれの国の言語に簡単に書き換えられるように、一つの ファイルにまとめてあるといった配慮が行われていますが、2バイトの漢字には対 応していませんので、かなりの書き換えが必要です。
以前、このソースを入手して実際に試してみて、ぜひ日本語化したいと思ったので すが、なにしろライブラリを含めて、10 万行を越える大きさですから、なかなか 時間がとれなくて、2年後の1998年の正月休みにやっと読み始め、1998年 の1月から社内でテストを始めました。
とりあえずは、X11 の kterm+kinput2 や、Solaris のシステム・レベルの日本語 入力機能で使えるようにした段階ですが、テスト版のパッチを公開しておきます。 バグや改善提案は下記に御連絡ください。
日本語化パッチ
平林 浩一