history

まだ大きな仕様変更をよくやるのでちゃんとした changelog はとってないんですが, 大雑把な記録くらいは残してみようかなということで.
誰も見てないことをいいことに開発日記ぽくダラダラ書いてみよう.

(2006.11.29)

いまさら気付いたのですが 面白いことやってる方を発見. Scheme ネイティブなエディタを C で作ろうとされているようです. 開発に意欲が感じられるところがいいですね, 私と違って(笑)
C で直接開発というのはやはり利点が大きいと思うので期待したいところです.
私はこのところ止っているし, 今はおもいっきり別のことに力を注いでいたり するので (iアプリ作ってます(笑)), 自分の方はしばらく凍結しときます.
まあエディタの話は面白いし, またそのうち舞い戻ってくるかもしれませんが.

(2006.10.13) [考察] tabk

gtk-text-view-set-tabs や pango-tab-array-new など, tab を扱う GTK の API が Gauche-gtk ではまだ未定義のようです. うーん, こまった.
自分で stub をいじって追加したとしても, 他にもこういうのは結構あるし, 根本的な解決にはならなそうです.
Shiro さんは Gauche-gtk をメンテできる人がいたらだれかやってほしい みたいなことを Mailing List で言ってたぐらいだから, 相当忙しくてこっちは手がまわらな いのでしょうね. 自分ができればいいけどまず無理です(笑).
ちょっとまたペンディングかな...

(2006.10.11) [考察]

不完全ながら, 正規表現で色を付けてみました. しばらく気分がコードいじりから離れてたので, 色でも付いたら少しはヤル気が出るかと思いましたが, いまひとつ(笑).
数百行のファイルに単純なパターンの色を付けるだけで数秒かかっているので, やはり様々なところをもっとチューニングしないといけません. まあ暇をみてやっていきたいと思います.

あと自分用メモをいくつか.
unwind-protect は当初から放置してたスペシャルフォームのひとつなんですが, そろそろちゃんと考えないとなあ. scheme には継続があるので, body から飛び出る だけでなく飛び込んでくることがあるわけですよね. dynamic-wind はまさにそれを 指定する構文なわけです. それに対し, elisp の unwind-protect は Java の try 構文の finally 的な役目なんですよね. 後始末です. 意味が全然違うので, 無理矢理 unwind-protect に相当する構文を作るよりは, その都度適切なコードに変えるしかないのかもしれません.
ただ, 今のところ考えている継続ベースの Multiprocessing で, 途中で飛び出たら二度と 飛び入りできないようにしたいコードももしかしたらあるかもと思っているので, その場合にはちょいと考えるかもしれません. またあるいは, 特定の範囲の中では途中で割り込みを受けたくない構文なんかも. (いわゆる Java における syncronized のような, でもちょっと違うか)

(2006.04.16) [考察]

だいぶ空いてしまったけどまたコードいじりたくなってきたので, FF も終わったし(笑), ちょいと触ってみたところ, かなり重いバグに遭遇してしばらく立ち往生. ぜんぶ自分の汚いコードのせいなんですが, これだけタイトなバグだと自分の 才能の無さにしばし嫌悪感さえ抱きます.
ひとつのことを完璧にこなす小さなコード片を, という原則から離れたソースばかり になってて, こんなんじゃこの先も似たようなことが起こりそうです. うーむ.

(2006.01.15) [考察]

same-window-p ってそのまま Scheme 的に書こうとすると same-window? だけど, これでは window を引数に取りそうに見えるし誤解しやすい気がするので, reuse-same-window? のような名前にしようと思います.
same-window-regexps と same-window-buffer-names についても同様に名前を 変えるしかないですかね. こういう命名ってセンスが問われるなあ.
少しずつコードをいじってリハビリしてみます...

(2005.12.07) [独り言]

たまに, 何からやったらいいのかわからなくなったりします.
特にひさしぶりに触ると(笑). やはりちょくちょくイジってないとカンもなにも なくなりますね.
とりあえずは自分で不満に思う点からチマチマと直していくところからかな. 気張っても続かないことは目にみえているので, 日曜プログラミング程度にのんびりやっていこうかと思います.

(2005.10.28) [独り言]

手続的な記述を関数的にできるとまあちょっとは気分もいいんですが, 手続的な記述をそのまま手続的な記述に Scheme 用に直すだけってのは楽しくもなんともない わけで, でもむしろそういうものの方が大半なわけで, そんなのばっかりだとやはり気が滅入ります.

というかまた1ヶ月以上空いた...orz
半分デスマってたのが終わって暇になるんじゃなかったのかよ. 幸せは山の彼方の空遠く.

(2005.09.18) [考察] regexp

どうでもいいことですが newcomment.el の中にあった正規表現の一部
"\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(\\s<+\\|"
もうわけわからんです(笑)
これが爪楊枝症候群てやつですか(日本語環境なら円マーク症候群かな).

(2005.09.08) [考察] 続 re-search

激しく勘違いしてました. Emacs も xyzzy も non-greedy な正規表現をサポートして ますね. 参考にしてたマニュアルが古すぎました...
さて, だからというわけじゃないですがやっぱり ^ と $ の行頭行末マッチは欲しいのです. なので妥協案として, 正規表現の簡単な検査をして ということにしたいと思います. greedy と non-greedy が混ざったときには, 前回書いたような(おそらく)望んだもの ではないマッチで hit する可能性があります. つまり,
abc
abc
abc
というバッファに対して #/[^b]+[^y]+?c$/ という正規表現検索をすると
abc
abc
abc
にマッチしてしまい, 本来欲しい(と思われる)
abc
という結果にはならない, ということです. 正規表現の機構を地でいくくらいにがんばってコードを書けばこれも正しい結果に なるようにできるかもしれませんが, ちょっと今はこの部分にそこまで気合を入れてられないので, 上記のようなユルい実装としておきます.

(2005.09.03) [考察] re-search

re-search-forward をちょっと掘り下げてたらハマり気味です.
通常の正規表現であればバッファの内容をまるごと文字列にしてしまい, Gauche の rxmatch を順次適用していこうと考えてます. メモリの効率的な利用を 無視すれば(無視できないくらい重くなる可能性もありますが), それで正しい動作をする はず.
通常でない場合というのは, anchor である $ が最後についてる場合です. Gauche では $ が行末に hit しない(現時点)のですが, エディタ上で正規表現 検索をするときには, ^ と $ が行頭と行末に hit すると便利だし Emacs での扱いに 近くなるのでそうしようと思ってます. そうすると検索範囲を単純に 「現在位置と buffer 末尾」とすることはできないので, 検索範囲を拡張(縮小)しながら 検索を繰り返す必要があります.
Emacs や xyzzy では, 検索対象範囲の末尾をバッファの末尾から順に手前の行末に移動 (検索範囲を縮小)しながら 検索を繰り返すことで, hit したものを結果とすることができるのだと思います.
ここで Emacs や xyzzy と違う状況として, Gauche が non-greedy な正規表現を サポートしていることがポイントになります. non-greedy な場合, 手前から末尾に向け て移動(検索範囲を拡張)しながら繰り返さなければなりません. が, しかし.
なにが問題かというと, non-greedy なものと greedy なものが混ざった正規表現に 対してどう対処するかが, 明確に定められないのではないかと思うからです.
例として, 以下のようなバッファがあるとします.
abc
abc
abc
これに対して, #/[^x]+[^y]+?c$/ という正規表現で検索した場合, 結果はバッファ の先頭と末尾になるべきでしょう. 最初の [^x]+ で一気に最後の方まで行くので. つまり結果は
abc
abc
abc
となります.
一方, #/[^b]+[^y]+?c$/ という正規表現の場合, 結果は
abc
となるのが正しいはずです. しかしながら, 末尾から範囲を縮小させようとして最初に
abc
abc
abc
という「文字列」として検索を実施しても, これでマッチしてしまいます. $ で末尾が固定されるため, [^y]+? が non-greedy でありながらも 2文字目から最後の方までカバーできるからです. しかしながらそれは望む結果ではないので,
abc
が結果とならなければならないはずです.
つまり, non-greedy と greedy が混ざっていると, 行末範囲を末尾から縮小すればよいのか 手前から末尾に拡張していけば良いのか, 単純なアルゴリズムとして記述できないのです.

うーん, どうしよう...
ちょっぴり 「^ と $ を特別扱いしない」という逃げの思考に傾いています(笑).
というのは, 上の問題の他にも, Gauche では 「.」が改行にマッチするので, 気軽に #/a.*b/ とかやると改行をまたぎまくるわけで, やはり今までと同じような使い方 はそのままではまずいケースも多いように思うのです.
これについてはまだ迷っている感じです...

(2005.08.15) [メモ]

buffer-input-port にまつわる API は, 最初は buffer-input-port-forward-char とか buffer-input-port-current-point とかそのまま命名してましたが, 考え直して bip-forward-char , bip-current-point のように prefix をつけて 短かくしました. buffer-input-port- をつける方が正しいような気はしますが... これ使う場面は限られているとはいえ, 使うときはまとまって使うと思います. ある程度の使用頻度がある関数の名前は 20 文字以上あってはいけないと個人的 には思うのです. なんか読むの疲れるんすよ.
なんで bip- つけて短くしました. こっちの方がぜったい読みやすい.

あと途中で気付いたんですが, ドキュメントが必要ぽいです. 自分のために(笑).
前に書いたプログラムの仕様をどっかり忘れてる... re-search-forward の repeat が 失敗したときの戻り値はなんだっけ?
ドキュメントなんてある程度まともにモノが動くようになってから, と思ってましたが むしろそれがないとまともにモノができそうにないので, 真面目に考えたいと思います.

(2005.08.02) [メモ]

parse-partial-sexp を中途半端ながらも作ってみたものの, ちょっと遅いので virtual-input-port を使った buffer-input-port てのを考えて, それを使うようにしてみました.
そしたらえらい速くなったのです, というか前のが遅すぎたというか. Edwin でも buffer の内容を順ぐりに port 的に扱える関数があった ので, やっぱりこういう方法は有効なんだなと納得です.
gtk binding である gtk-text-iter- なんたら を直接使うのは速いとはいえやっぱり気持ち悪いですからね. port として抽象化できるのはなにかと役に立ちそうであります.

(2005.07.19) [メモ]

やっとの週末ひさしぶりに少し時間ができたのでコードでも書こうかと 思いきや, 前なにやろうとしてたかキレイに忘れてるし(笑).
進捗がゼロどころかマイナスですが愚痴ってないで仕切り直し!
Gauche を 0.8.5 にしたらちょっと速くなった気分. すばらしいですね.
さて, ファイル編集機能をまともにしようとしたら, まずそもそも scheme-mode がある程度まともでないとやってられないことに気付きました. 具体的にはインデントとか対応括弧移動とか.
なので, semantic のような機能をそのうち, と思ってたけどまず先にそこそこ まともな S 式用の移動を用意しなければなりません. parse-partial-sexp あたりとかを真面目に書いてみます. 少しずつ少しずつ scheme 用のエディタに近づけていかないといけません.

(2005.06.24) 0.0p6

気づけば半年以上晒してなくてこりゃいかん, 忙しさにかまけて フェードアウトしそうだ, ということで.
相変わらず人に見せられるレベルでさえありませんが, 完成してから晒すように すると永遠に出さないことになるためです. やはり実用性ゼロですのでソース見て フーンと流す程度にしてください. まあ見たい人なんていないか.
実験的なことばかりやってますがまあ存在自体が実験なのでよし.
やらねばならないことは山積してます. 時間があったときはやる気がなく, 時間がない今こそやる気満々という ありがちな状況です. やっとこさファイルの足回りを真面目にやろうと思って ますが誰か時間貯金箱くれませんか. やはりまず目指すのはメモ帳なのです. そして最低限の編集保存機能がまともになったら自分自身で自分を編集するようにすりゃ いいのです. それでやっと末尾再帰完成です. 末尾再帰したかったんです. きっと使ってるうちに不満でいっぱいになり速攻で直すことになるはず!! ああ気付けば Gauche が 0.8.4 になってるのですね 自分の環境を早くバージョンアップしなければ. っていつやるんだ.

(2005.06.06) [参照とシンボル名]

参照とシンボル名について.
グローバル変数ってわけではないですが, 例えば $b-current-directory などは トップレベルから見ると local-parameter のインスタンスです. それを参照する 変数は複数あるかもしれませんが, 公的な名前としては $b-current-directory と してあるわけなので, インスタンスの参照から $b-current-directory というシンボルを取得したいことがあります.
従来の Emacs 内部では, 具体的な参照ではなくシンボルの状態のまま変数を扱って いる場面がいくつもあるように見えます. たとえば minibuffer でファイル名を読むときに そのヒストリを保存する変数については, file-name-history のような参照としてではなく 'file-name-history という「シンボル」を渡したりするのです.
これは, そのシンボルを eval すれば参照は得られる し, シンボルそのものがもちろんシンボル名になるので公的な名前は取得できます.
具体的にはエディタのように画面に変数名を表示させる場合などで, 変数の値と名前を 出したい場面があるのです. そういった場合には, このような参照ではなく 「参照へのシンボル」を持つというのは確かに有効です.
ただし, Scheme ではやっぱり全部の値を無名のファーストクラスにする方が しっくりくるような気もするので, 特定のシンボル用のスロットを内部に暗黙で持たせて, 参照から「公的な唯一のシンボル名」を取得できるようにしようかなと思ってます. たとえば buffer local な変数の一覧などを取得するときはこうするとラクなので. ただしまだあまりよく練ってないのでまた変わるかもしれませんが.


あとまたちょっと仕事しんどいので止まるかもしれません.
でも忙しいときこそ逆に逃避願望によりいろんなアイデアが出てきたりする のでそれはそれで出てきたらメモしておきたいわけですが...

(2005.05.28) [考察] message, echo area

どうも xyzzy のように, echo area を minibuffer の領域とは分けた方がいい ような気がしてきました.
ちょっくら実験してみたのがこちら.
色のせいかもしれませんが, どうもいまひとつ. xyzzy では echo area は windows の標準的な ステータスバーの位置に溶け込んでいるので違和感ないのですけどね...
色のせいかなあ. それとも 3D ぽく枠を加工すればいいのかな.

ちょっと思いついて, echo area を minibuffer の下ではなく右にしてみたら どうかなと思って実験してみたのがこちら.
一行におさまってるのでエコ感はあるかも. やはり色が悪い(笑).

あまり固定長的な画面分割にこだわらなくて, 境界やグループをわかりやすくした方がい いのかもしれないなあ.

(2005.05.18) [考察] undo

久しぶりにエディタらしい機能(笑)の実装を, ということで undo 作ってみました. 意外にアッサリできてびっくり. もともと tree なクラスを用意していたってのもありますが.
tree 状に全ての変更を保持しているので, 通常の undo や redo では関係ない ですが, 少し undo した後(ここをA地点とします)に編集をし, 再び undo で A地点以前まで戻った後に redo をしようとしたとき, 分岐になるのでどちらの 処理を redo するかを選択できるようにします. まあ最新の分岐の操作を redo する, ってのが通常のエディタの動作だと思いますけど(Emacs を除く), 古い分岐も選べたら いいかなと思ったので. でも選択できるようにすると undo-mode みたいにしないと わかりにくくなりそう. どうしようかなあ.
ちなみに, すごい富豪的な勢いで Undo 用のオブジェクトを作るので, きっといずれ Object pooling とかで生成のコストを抑えないといけないかなと思いますが, まあ今のところ富豪的に猪突猛進なのです.

(2005.05.08) [考察] tiling or overlapping

Emacs てのはコンソールでの利用から出てきたエディタなわけで, ウィンドウの分割などは基本的にタイル式(tiling)です. 敷き詰め型なかんじ.
んで, いわゆる一般的な Windows のエディタというのは, MDI だったりタブだったり するのもあるでしょうが, 大抵はタイル型ではなくウィンドウ型と呼べると思います.
どっちが優れているかというのは難しい問題かもしれませんが, どちらが直感的かと 訊かれれば, 普通はウィンドウ型(overlapped windows)じゃないでしょうか.
でも, Edge では Emacs と同様にタイル型の分割方式をとっています.
GTK の機能を利用すればウィンドウ型にするのは容易なんですけど, やっぱりタイル型 の方が制御しやすいのと, あまり概念を大きく変えたくなかったからです.

冷静に見ると, tiling より overlapping な方式の方が高機能のような気もします. 大は小を兼ねるという考え方をすれば, overlapping な方式であれば tiling を エミュレートできるので当然そう考えられますね.
しかしながら敢えて tiling にした他の理由として, 実用上 tiling 以外の使い方はしない のではないかという変な確信があったからなのです.
Emacs 系エディタは Multi-buffer なので MDI アプリと単純な比較はできませんが, SDI や MDI のアプリで沢山のウィンドウを切り替えるとき, 2〜3個程度なら 問題ありませんが, およそ7以上の数になると管理が複雑になります. それに, overlap している部分は見えないし, 隙間はただ単に無駄なだけです. エクセルとかでも, MDI 内の複数ウィンドウは整列して使うことが多いと思います. overlap 可能なウィンドウも結局は整列して使うことがほとんどであるならば, 最初からタイル式のみとしちゃっていいんじゃないかな, と思ったわけです.
Eclipse とかでも沢山の画面構成をパースペクティブとして切り替えできますが, 全部 敷き詰め型ですよね. なので, 実用的な観点からいくと敷き詰め型に落ちつくかなと.

(2005.05.05) [考察] 続 pixel base

window-width や window-height が pixel を返すと今までとちょっと使い勝手が 違うので戸惑いそうなので, xyzzy から API 名を借用して, 文字幅を返すには window-columns を, 行数を返すのは window-lines を使うようにしようと思います. もちろん, 文字幅と行数は当該 window の default のフォントサイズで window の pixel サイズの quotient をとった整数なわけですが.
なんというか, そろそろ wiki みたいなページ作って実装ノートみたいな感じで まとめたいなあ.

(2005.05.01) [考察] pixel base

いろいろ工事してる最中に自分で自分の首を締めてるような気がしてなりませんが, window のサイズを論理文字数でなく pixel 指定を基本とするように改造しようとしてます.
もちろん GtkTextView を生成するときには pixel 指定は必要だったのですが, 当初は起動したらあとはずっと文字の大きさは変わらないことを前提としてたのです. というかまあ考えるのが面倒だっただけですが(笑).
でもやっぱりフォントを動的に変えたりはしたいので, 文字幅を固定だとする前提では あまりよくありません. するとむしろ pixel 指定が普通になり, 文字幅ベースの指定は pixel の指定を呼び出すようにするのが自然だ, という考えになります.
そういう発想はかなり最初の方で気付くべきだろと思いますが(汗), なんで今になるまでそのままにしておいたかというと... 余談なのですが, 実は一番最初は Gauche-gtk ではなく SCM の curses ライブラリの上でエディタを作ってみようとしてたのです. そのときは当然 curses なので端末とかを想定してたので, 論理文字幅だけを想定してて, 途中で Gauche-gtk の存在に気付いてそっちで作るように変えたんですね. なので pixel ベースにするのをずっと後回しにしてたのでした. というのが言い訳です(^^;)

(2005.04.20) [考察] widget

scroll bar を GTK の gtk-vscrollbar でやろうとして思わず手が止まりました. 表示領域の持ち方をもっと一般化しないとダメだ. 最初は GtkTextView しか想定してなかったので無理もないか...
最初のころに比べれば相当マシになってる気はしますが, やはりまだまだですね. またしても「進めてみないと間違ってたことに気付かない」症候群です. てなわけで再び基礎工事に着手です!!

ちと関係ありませんが, ソフトウェアの開発は建築にたとえられることがよくありますね. 曰く, 「最初の1本目の釘を打つ前に家の設計は完成していなければならない」というやつ. 確かに似ている部分はかなり多いとは思いますが, 近年はかなり相違点も浮き掘りにされ てきているのではないでしょうか. はっきりいってソフトウェアの全体像が決まる前に いきなりプログラムを書き始めることはよくありますし, Waterfall な時代でもないでしょう.
家の場合はやり直すことのコストが尋常ではないため, 最初に設計が完璧である必要 があります. 一方ソフトウェアの場合は, 「ここで設計仕様を変えると全部やり直しだ」 というラインをかなり浮動的に後ろにずらすことができます. 場合によっては無くすことさえできるかもしれません. それはソフトウェアの結合部分を疎にすることで, インターフェースの変更の影響範囲を かなり限定できるからですね.
それに, ソフトウェアなら物理的な資材が不要ってのも大きいですかね. 建築で同じことやったら, 釘を打ったり抜いたりしたグダグダの木材ばかりになります(笑).

(2005.04.13) [考察] 移動系の例外

Emacs では, たとえば forward-char は buffer の最後にくるとそれ以上進めないので End of buffer として error を投げます.
でも, これって例外投げない方がいいのでは?と思ったりします. むしろ進んだ文字の数を返すようにする方が合理的ではないかなと. 文字を進めながら様々な処理をするときには, port の操作と同じように戻り値で 結果を判断する方が何かと便利だと感じますし, 少なくとも, 例外を伝播しなければならない ような回復不能な事態ではないはずだと考えるからです.
また, Emacs ではそれを黙らせるには condition-case で捕獲するわけですが forward-char を書く場所で毎回例外捕獲をやるのは面倒な気がしてます.
例外についてはまだまだ整理しないといけないことがあるんですが, ひとまずこれらの移動系の例外についてはナシにしようかと思ってます.

(2005.04.12) [考察] recursive-edit

recursive-edit はいわゆる再帰編集ってやつですが, read-from-minibuffer の中で 使ってます. 当初はこの minibuffer の実装がよくわからず, しばらく考えてたんで すが, 「そうか, ここで継続か!」とわかったときに, 継続に対する理解が少し深まった ような気がしました. GTK の event 待ちの main loop の前の継続を保存しておいて, 再帰編集のときにはそれを呼び出してやればよいわけですね. minibuffer での 入力が終ったら飛ぶ直前に保存しておいた戻り先の継続に値を入れて呼べばよい, と. まあ継続については相変わらずわからない部分もまだあるんですが...
で, Multi-Threading をやると, ここは少し別の方法でも可能になってきます. 原理的には同じですが, 単純に現在の thread をブチッと終了してしまえばいいのです. 他の thread が残っていればそれの実行をしつつ event は gtk-main-iteration-do で拾 えるし, 他の thread が無ければ単純に main loop に戻ってまた event をひたすら待つ, ということになるからです.

(2005.04.05) [考察] screen

pseudo frame のやつ, 今までは virtual frame の意味で vframe と個人的に呼んで いたんですが frame と紛らわしいし, pseudo frame もなんかオマケみたいで可哀想 な気もしてたので, buffer や window のような一級(?)の名前を付けてあげようかな と思い, 普通に screen とすることにしました. ストレートでわかりやすいかなと.
screen local なパラメータは, たとえば $s-unread-command-events のように, $s- を接頭辞に持つようになります.

どうでもいいことですが最近は目の下にクマができてなかなか消えない...
集中力がピークに達するのが午前3時であるということが最大の問題でしょうか.

(2005.03.31) [考察] Multi-Threading 再考

おお, C-g による中断の実装できそうかもです. timed-lambda によるエンジンの実装で 継続切り替えの簡単な Multi-Threading 的な動きができました.
(defvar weight-value 0)

(defun execute-weight ()
  (let ((proc (lambda (i)
                (+ i 1))))
    (let loop ((i 0))
      (set! weight-value i)
      (if (= i 10000000)
          i
          (loop (proc i))))))
こんなような単純な繰り返しの execute-weight を定義して scratch で実行させると, 今までは weight-value が 10000000 に達するまで何もできなかったのですが, 今回試しに実装してみた C-g で中断するしくみが動いたのです. ちゃんと weight-value も 906898 みたいな途中の数字で止まってましたよ. やったー!!
画面についても, thread ごとに window 構成をいちいち作り直すのではなく単に thread local な (pseudo) frame を切り替えればよいので大丈夫そうだし.
個人的に一番ネックというか, できるかどうかよくわからない部分だったので, これで MT 化の見通しが立ったことでちょっとやる気が出てきました(笑).
まあこれで会社がヒマならもっといいんですけど...

(2005.03.27) [考察] いろいろ

ふむふむ, ちとソース見てみんとわからんなあ, ということで Kali Scheme を ダウンロードしようとしてみたら, Not Found. orz. そんなあ...
まあ仕方ないですかね. むう.

そういえば本屋で入門 xyzzy なる本を発見したのでしばし立ち読み.
知らなかったんですが, xyzzy では echo area と minibuffer の領域を明確に分けて いるんですね. echo area はいわゆるステータスバーの位置だとか.
さらに, frame という概念がやや Emacs とは異なっており, pseudo frame という感じで 管理しているのだそうで. 個人的にですがこれはすごく納得です. 自分は Emacs で windows.el というウィンドウ管理的な elisp を常用させてもらってますが, windows.el では新しい frame を作るかどうかを選べるオプションがあり, 私は frame は作らず まさに pseudo frame 的に利用しています.
相変わらずいろいろ勉強になることは多いです.

(2005.03.20) [考察] 続refactoring

だいぶ修正. meta-window の考え方を使うと再帰しまくりで妙に気持ちイイ.
というかやはりタイル式に敷き詰めるならアルゴリズムは自然と再帰になりますね.
今まで何やってたんだよと我ながら思います. やれやれ.
さて, やや関係ないですが久しぶりに google で comp.lang.scheme ざらっと読んで いたら, multi thread の話題があって, やや古いけど Kali Scheme なるものがあるとか. Kali Scheme は分散実行環境のようで, 最近はあまりメンテとかはされてなさそうな雰囲 気もあるんですが, Kali Scheme の実装に関係している Higher-Order Distributed Objects っていう paper があって勉強になりそうなので読んでみようかなと思っています.
でも風邪ひいて花粉症も重くてヘコみ中...(ー_ー)

(2005.03.08) [考察] refactoring

ずっと前から, ornament が window を継承してるのはおかしい んじゃないのかとひっかかってたんですが, そうかこれは抽象クラスが前にあれば いいんだと気付きました. というかそんなことはとっくに気付いてましたが, 考え方 がどうもまとまってなかった. ちと本腰いれて考えてみます.
ついでにもういっちょう. meta-window という概念の導入を考えてます. これは何かというと, window を分割していくときの分割具合を理論的に管理する ものです. なぜそんなものを導入するかというと, Emacs では window-configuration てのがあって, frame の中身をごそっと入れ換えることができますが, それを特定の window の内側だけでやりたいと思ったからです. こうしておくと後々いろいろ拡張 できてよさげかなと. おそらく meta-window の config の top level の場合がたまたま 現行の window-configuration である, というのが正しい姿ではないかと想像してます.

(2005.02.26) [ひとりごと] version control

あまり放置してると色んなこと忘れそうなんでまたちょっと触りつつ. 夏過ぎれば少しは暇になるはずなんですがねえ. やれやれ.
で, いろいろいじってて, ちょっと思い切って大きな修正を しようとするときにディレクトリごとコピーして実験的にいろいろやるんですが, そういう古いやりかたもどうだかなあ, というわけでそろそろバージョン管理でも してみようかなという年頃です.
普通は cvs だろうけど, subversion とかが今後の流行なんですかね. せっかくだから 試してみようかな.

(2005.02.05) [考察] vim-gtk

げ, vim-gtk がちゃんと GTK で box cursor 実装してるじゃん.
freshmeat で GTK で box cursor 実装してるエディタを探してふーん無いのかー と思ってたけど, vim に gtk の実装があったのね. アホか俺は. つーか (X)Emacs にも GTK の実装がありそうだし, もう灯台元暮しです. 灯台に住んでやる.
ちとソース読んで勉強しなおしですな.

あとまたしても仕事が忙しいのでちょっとまた止まります...

(2005.02.03) [ひとりごと] gtk bug

「text/base の色によっては更新時に変な色になる」というバグをずっと追いかけて て, どうやらこれは GTK のバグっぽいということがわかり凹.
なぜなら gedit で配色を設定して再現できたからです(黒背景に黄色など)...
これは vmware の中でやってる自分だけの現象なのか他の人の環境でも再現するのか, GTK のバージョンが上がれば解決するのか, ちょっとわからんのでしばし放置します. ざらっと bugzilla 見たけど見当たらないから, ちゃんと再現するならレポート したいんですけど, いくらなんでも gedit とか使ってる人が気付かないはずないような バグなので尚更に自分だけの環境で起きてるのではないかと思ってしまうのです. まあ GTK のバージョンが少し上がると細かく色々変わるし, 今後も再現するならレポートしようと思いますが....
GTK もまだ不完全な部分があることを念頭に置いておいたほうがよさそうですね.

全然関係ないけど 仕事で Java 使ってるんですが, なんかカスタムタグとか Struts とか tiles とか XDoclet とか Velocity とか, もうマクロをくれってかんじです.
「本来やらなくていいはずの無駄な繰り返し」であることが明白に意識できている 状態でその無駄をやらなければならないことの苦痛. やたらに沢山テンプレート的な機能の実装があるけど, どの機能も Lisp のマクロに比べたら粗悪品でしかないよ. というかやたら沢山あること自体が Java 言語の機能不足を露呈してるとしか思えない.
Lisper/Schemer の人で Java を仕方なく使ってる人って多いと思うけど, やればやるほど煩悶とした気分になっているのではないかなあ. まあ Java に限らずだろうけれども.

(2005.01.30) [ひとりごと] cursor-aspect-ratio

GtkWidget に Style Property なる概念があること, および cursor-aspect-ratio なる属性があることを発見しました.
これのデフォルトは 0.04 らしい. もしやこれに 1 とか入れれば box cursor になる のでは?と期待を胸に設定してみたところ, ... , ダメでした orz.
確かに box ぽくなるんですが, Emacs 的な box cursor とは違って文字の上ではなく あくまで間に来てしまいます. その間のカーソルが太くなっただけなので, ただ単に 見にくくなっただけ(笑). GtkTextView に child widget として float させる方法以外 に box cursor を実装できるかもと期待しただけにガックリです. まいっか.

ちなみにこういった widget の Property や Style Property の設定は普通はファイル に書くらしく, ちょっと特殊なので今回試したのをメモとして残しておきます.
(gtk-rc-parse-string
   "
style \"default\"
\{
  GtkTextView::cursor-aspect-ratio = 1
\}
widget_class \"*GtkTextView*\" style \"default\"
widget \"*GtkTextView*\" style \"default\"
class \"*GtkTextView*\" style \"default\"
"
   )
当然ですが上のような内容を書いても見にくくなるだけということになります(笑).

(2005.01.23) [考察] propertized text

プロパティ付きの text について.
text-tag の概念で propertized な text を表現するには, ひとつにはたとえば
'(tagged-text (foo-tag "foo"))
のように, タグで修飾されたテキストとして表現する方法があります.
かたや, 開始終了の範囲とタグを内部でリストにする index 的な方法もあります.
'(tagged-text "foo"
   0 3 foo-tag)
Emacs の propertize は, 引数こそタグっぽくなってますが内部的には範囲と 属性をそれぞれ持ってるっぽいですね.
(propertize "foo" 'face 'italic)
=>
#("foo" 0 3 (face italic))
インターフェースとしてタグ表現を取ることができるものがあってもいいと思いますが, 内部表現はやはり Emacs と同様, この index 的な方法にしようと思います. タグ形式で内部も持つとなると, 複数のタグの範囲が重複しているような場合はけっこう面倒な気がするのです.
たとえば, "foo and bar" というテキストの foo and を foo-tag で, and bar を bar-tag で修飾しようとすると, タグ表現では,
'(tagged-text (foo-tag "foo" (bar-tag " and")) (bar-tag " bar"))
となりますが, index 的な表現なら
'(tagged-text "foo and bar"
   0  7 foo-tag
   4 11 bar-tag)
となります. 少なくとも gtk の tag をやりとりするなら絶対 index の方がラクです. (^-^;)

(2005.01.11) [考察] 続 profile

profiler 多分動いたかも. ちょっと感動です.
まあ重要なのはこれをもとにしてネックを潰すことなんですがね.
速度が気になる所があるといったけど, 正直モッサリしすぎてチューンしないと使いもの にならない勢いなのでそのうち頑張って高速化します. そのうち...
いろいろいじってて advice の書式が二転三転. メソッドコンビネーションてのは同一の 特定度の複数補助メソッド指定はどうやるんだろう? まあいいやまた立ち読みしてきます(笑).
こういうの楽しいんだけど同時にすげー疲れるな...

(2005.01.06) [考察] profile, advice

今のところ適当にまあ動けばいいんじゃないの的に作ってるんですが, ちと速度が気にな る所があるので, 後々のことも考えてプロファイルを取れるようにしておこうかと考えて ます.
Emacs には elp(Emacs Lisp Profiler) というのが付いていて, これが実に便利であります. なのでそれを真似たのを作ってみようかなと. elp では関数セルを直接いじっている ようなんですが, まあやってることは時間測定のための再定義なわけで, これを機会 に advice の方もちょっとまとめてみようかと思います. で advice を利用して profiler を作る, と.

Scheme で Emacs における advice のような機能を実現するにはどうすりゃいいのかを前 悩んだことがあって, Shiro さんのところの WiLiKi ちょっとだけ書いてあります.
結論としては, まあこの方法でなんとかなるんですがひとつ潜在的な問題があります. それは advice 前の定義の参照がどこか別の場所で保持されている場合, advice が効か ない場面があり得るということです.
(define (foo)
  (print "foo!"))

(define bar foo)

(define-advice foo-adv foo 'after
  (print "adviced!"))

(foo)
;; => foo!
;;   adviced!

(bar)
;; => foo!
advice の細かい書式は置いておくとして, 上のような例の場合, foo に advice が適用 されたとしても, advice が適用される前の foo の参照を保持している bar に対しては 素の foo の内容しか見えません.
もっぱら関数的に利用するものの参照を別で保持するというのは頻繁にあることではない かもしれませんが, 同時にまったく無いわけでもないと思われます. Emacs Lisp が関数 呼び出しが実質は funcall であり, symbol から関数セルを見にいくという性質があるた め, この問題は Emacs Lisp にはなく Scheme で実装するときに表面化する問題です.
これは参照を置き換える方法をとる以上は避けられない問題なので, ひとつの 解決方法としては, Edge 内部で利用している defun や defcommand といった宣言マクロ で最初にダミーの参照を噛ませておき, advice しても一次の参照先が変更されないよう にして, advice 可能な関数を defun, defcommand で宣言されたものに限るという ことを思いつきます. ただこれは相当にナイーブな方法で, 安全ではあっても外部ライブ ラリに適用できないため, ちょっと狭苦しすぎる方法でしょう. 特に今回は export して ない内部用の関数もプロファイルを取りたいので, やはりこの方法は取れません.
なので少々の懸念材料はありますが参照置き換えの方法でそのまま乗せてみようかと. advice はのちのち汎用的にできるかもしれないので, あまりエディタ内部にとりこまないようにしておきます.

あと, Common Lisp 的なメソッドコンビネーションとの関係については, ちょっとどうか しらと思ってます. 本屋で立ち読み(笑)した限りでは, メソッドコンビネーションという のは generic method の特定度の高い順に各々の before, after, around 等のメソッド を定義して呼び出すことができるというものらしいです.
これはこれでとても便利だと思うんですが, ちょっと advice とは異なる点もある気がす るのです. advice での before, after, around 等の呼び出し順序はそれらが定義された 順番で実行され, プログラマが変更できます. どれかを必ず最初に呼び出したい, という場合には それをプログラマが注意深く管理する必要があり, この点は Emacs のマイナーモードで のキーマップ順位に関する問題に似ているかもしれません.
一方, メソッドコンビネーションは特定度順なのでそういう問題はなさそうです. 実際たしかに似てるのでうまく統合できたらいいなあとは思いますが, 当面は別モノとし ておき, ひとまず advice は通常の lambda に対してのみ適用できるようにしようという 考えです.

ちなみに, advice についてはマクロでごちゃごちゃ書いてます. たぶん Gauche の object-apply を利用すればもっとスッキリ書けるはずだし(実際ねるさんはそうしてる) たぶんそっちの方が速いかもと思うんですが, あえて lambda にこだわってます.
理由は, advice 後も procedure? が #t を返すようにしたいことと, arity を変えたく ないという点です.

(2004.12.30) [考察] box cursor

box cursor がうまく更新できなかった問題わかったーーーー!!!
画面の即座更新をしたいときは gdk-window-invalidate-region, gdk-window-process-updates の順に呼べばよかったのかあ. ってそんなの知るか!!
てのを gtk-widget のリファレンスで発見. いやあマニュアルはちゃんと読まないとですね.
ああ, 半年くらいノドに刺さってた魚の骨が取れたような気分です. ふう.
やっぱエディタは box cursor しかないわけですよ. bar 型なんて見えないじゃん.

(2004.12.23) [考察] 日付形式

またしても寄り道というか, dired もどきのモジュール(file-manager)を作ってみたり.
ちなみに dired って表示が ls -l っぽいですよね. 個人的にはあの ls -l の 日付形式がずっと嫌いでした.
OCT とか FEB とか英語表記の月名なんてパーサ書くときやりづらいだろうし, 数字だけでスパーンと統一した方がいいんじゃないのかよ, と思っていたのです.
そう思って, yy.mm.dd hh:mi の形式で表示してみたのが これ.
正直なところ, なんというかイマイチなのです. つーかメリハリがないっ!!
そしていつも通りというか ls -l っぽいので試してみたのが こっち. ああ, なんかしっくり来るというか マッタリ落ち着くというか, やっぱ日付形式はこっちの方が人間的なんだなと再認識 してしまったのですよ. 知らず知らずに英語表記に毒されたのかもしれませんが, こっちの方がぜんぜんいいなと思ってこっちをデフォルトにしようと思います.
もちろん Scheme なのでカスタマイズ可能ですが, デフォルトって大事ですよね.
(ちなみに Gauche の組み込み機能のみで作ってるので ls は呼んでません)

(2004.12.15) [考察] Modifier or Mode

Emacs 系のエディタをまともに使う場合, いかに Control key が押しやすい位置にある かってのが重要だと思います. 今のところ個人的に左手親指の位置がベストだと 勝手に思い込んでますが, まあ人それぞれかもしれません.
ちなみに, Emacs vs Vi(m) みたいな聖戦がよくありますが, 最近の結論は Eclipse でしょ うかね(笑). と冗談はさておき, Emacs vs Vi はいくつか側面があって, キーの入力の面 でも見ることができます. つまり「Control」か「モード」か, というやつ.
以前, Control キーなしで全部をモード的に入力したらどの程度になるだろう, もしかし て Control より打ちやすいかな, と思いたって, Emacs の keybind を Vi ライクな形式 で割り当て直してみたことがあります. ただし, コマンドモードの ESC は遠いので, あえて「,」(カンマ)を犠牲にしてそれをコマンドモード切りかえに, 入力切りかえは Vi と同様 i で, という形にしました. しばらく実験してみて, 悪くない感触でした.
一応自分なりに一番無駄のないモード入力だったと思ってるのですが, 左手親指Control (快適に Control が押せる環境) と比べるとどうかというと, Control による方法の方が 若干速いのではないかと感じました. まあこれは私が Vi よりは Emacs ばかり使ってい る偏見もあるでしょうけど, どうしても Vi 形式だとモードを意識しながらになってしま うのです. このあたり, Vi 神ユーザの操作を見てみたい気がするです.
ちなみにこの前「ヒューメイン・インターフェース」て本を読んだら, モードの概念を導入 することによるインターフェースの複雑化について論じてありました. やはり状態を持ち うるモードという概念は注意深く設計する必要があるようです.
Control の方法も, Control を押下している間だけモードを変えているという見方もできます が, キーを離せばモードが終わるのでモードを意識するということは殆どないですね.
さて, たとえ親指に Control が割り当てられても, かならずしも打ちやすい環境になら ないことがあります. たとえばノート PC とか. ノートだと Modifier 系はたぶん全滅で すね. 打ちにくいキーのノートだと快適とはほど遠い環境になってしまうかも. ノートでは Vi 系の入力形式が強いかもしれません.
てことで, 環境に左右されにくくかつ快適な入力形式ってのはなかなかないものですかね. なんてまとまりのない文章だ...

(2004.12.11) [考察] command

コマンドてのは, keymap に割当てることができて, M-x command のような形で呼べる ものです. この M-x 的な呼び方について.
M-x tab てやるとわかると思いますが, この execute-extended-command では全ての コマンドを呼ぶことができます. でそれは果たしてそれでいいのかよ, ということ.
というのは, major mode 固有のコマンドであれば, current-buffer の major mode が異なる場合にそのコマンドを呼ぶことはできないため, そもそも入力候補になっている こと自体がおかしいはずです. たとえば, dired-mark なんてのは dired 以外のバッファ ではエラーにしかなりませんが, 常に execute-extended-command で補完入力ができてしまうのです.
つまり, 補完対象を「グローバルなコマンド(常に呼び出し可能)」「major mode 固有コ マンド」「minor mode 固有コマンド」などと分類し, 補完は現在の状態に合わあせて行なわ れるとするべきではないか, と思ったのです.
これは, defcommand 時点でちょっと細工をすれば実現可能なはずなので, ちょっと実験 でやってみることにします.

(2004.12.07) [考察] default-directory, 相違点

もうこの際だから気にくわない名前を全部変えてしまおうかという勢いです.
default-directory て変数は, Emacs における各バッファの directory を意味します.
が, たぶん current-directory とするべきだったと思われます.なんか歴史あったんで しょうかねえ. まあとにかく current-directory に変えちゃいます. 正確には buffer local なパラメータに変えるので $b-current-directory です. Gauche の file.util での current-directory と非常に似た動きになるかと.
さて, いろいろ変えてるとはいえ一応 Emacs との相違点をどこかにまとめてお かないと後で自分が困るような気がしてなりません. そのうちどこかにまとめるとして, 今思いつくのをメモしてみます. まあ細かく見れば同じ ものの方が少ないかもしれませんが...

(2004.12.04) [考察] 定義

関数定義やコマンド定義にあまり考えなしに defun と defcommand を使ってるんですが, これってどうなんだろうなと漠然と考えたりします. Emacs の defun の書式と互換性が あるわけでもないですし.
エディタ以外の様々なアプリケーションを想定すると, 独自の関数定義を導入したいこと は十分あると思うし, defun とか defcommand くらい普通にカブりそうな気もするのです. たぶん Scheme 的には, define-editor-function とか define-editor-command みたいな 名前のマクロにするのが正当なのかもしれません. でもちょっと長いんですよねえ.
そういう命名で厳格になるのはわかるんですが, この発想でいろいろ命名してると なんか Java みたいな滑稽に長いパッケージと かクラス名を連想してしまい, 可読性が落ちる気がしてならないのですよ.
つーことでまあ惰性ですが defun と defcommand で進めてます. defun は Emacs のを(名前だけ)真似てそのまま使ってるだけです. コマンドは defun + interactive 指定ではなく別定義にしようと思って defcommand と してます.

(2004.12.01) [考察] 名前

なんかよく考えると, Emacs の関数名も「ん?」て思うのがあるような気がします.
たとえば find-file とか. もうファイルを開く場合はこれが基本関数となっているわけ ですが, 意味としては open-file の方がしっくりきますよね. find してると感じるのは minibuffer で補完してるときだけではないでしょうか.

あと kill も実はあまり一貫性がなかったりします.
kill-region や kill-rectangle などは, 消える部分がどこかに保存されて別利用できる というニュアンスがあります. が, kill-emacs や kill-buffer はそうではなく, 不可逆的な操作です. おそらく前者を cut とする方がよいかなと思います. でもそうすると kill-ring に相当する概念も名前を変えないといけないのか. うーむ. cut-ring はなん かイマイチ...それとも後者を quit-emacs, delete-buffer のようにするべきなんでしょ うかねえ...つーかやっぱあんまり変えないほうがよさそうかも. (笑)

(2004.11.15) [考察] overlay

text-tag による property の実装をしてて, やはり従来の overlay に相当する ものは当面ナシにしようかと考えてます.
overlay は face などの変更が主な用途ではないかと思いますが, 実装はやはり gtk-text-tag になります. すると, 範囲の途中の部分を remove できてしまい, overlay を分断することができてしまうのです. それを防ぐには明示的に overlay に属する gtk-text-tag を特別扱いする必要があり, また gtk-text-tag から overlay への逆参照も必要になります. これはあまり綺麗なものにはならなそうだなと 思ったわけです.
いずれ「やはり overlay に相当するものがあったほうがよい」と確信するようなことが ないかぎりは, text-tag による property の実装だけで当面は進めてみます.
ただ overlay には before-string や after-string みたいな特殊な用途もあったりする ので, こういうのはどうしようかなとは漠然と考えてます. まあつまりは何も考えてないということです(笑).

(2004.11.09) 0.0p5

相変わらず遅々として進んでません.

(2004.11.05) [考察] UI

さて, Emacs は導入コストが高いという説明がされることがあります.
少なくともとっつきにくさは Windows のエディタに比べると相当高いでしょう.
とっつきにくさの原因はいくつかあると思います.
たとえば, Emacs では基本的にキーボード操作で処理を行います. そのとき, どのキーを押すと何が起きるのか, という情報がわかりにくいものがあります. 自分で自在に設定したり, describe-bindings などで確認しながら操作できる, というのは既にかなりの上級者であって, 最初のころはとてもしどろもどろだったはず です.
たとえば, ある Elisp を起動して, echo エリアに
Commands: m, u, t, RET, g, k, S, D, Q; q to quit; h for help
てなかんじで表示されることも多いと思いでしょう.
この表示にどの程度ユーザビリティがあると云えるでしょうか?
q と h 以外にどれほど情報量があるのでしょう?
少なくともこれらの部分については, 良質なテキストベースのメニューが必要だと考えま す.

また, 補完やリスト選択などで画面が分割されるとき, 終われば画面構成が元に戻る とわかっているのは慣れた後だけで, 最初は操作を進めるとどうなるのかがはっきり わかりにくい場面というのは多いと思います.
これも, Windows エディタならダイアログなどでポップアップされるので, それを閉じ れば元の編集に戻るということがわかるのに対し, Emacs などでは一定の経験がなければ わからない場面というのはあるはずです. ユーザとしては window-configuration が保存 されるかどうかがわからないからです.


つまり, 高度な編集に対して, それが何を意味し, 結果遷移がどうなるのか, といった 「アフォーダンスが低い」ということが, UNIX 系エディタが Windows 系一般のエディタに対して 遅れをとっている点なのではないかと思うのです.
少なくとも, 操作が直感的でないことと, 慣れれば高度な操作ができることは, あまり関係が ないと思います. 拡張性を犠牲にしなければ使いやすいシステムにならない, などということ はないでしょう.
具体的に何をどうするのか, といったことはまだまだですが, カスタマイズ性が高いまま でも利用しやすい UI を目指すべきだ, とは思っています.

(2004.10.31) [考察]

ibuffer のソース中のコメント.
;; ah, if only we had closures.  I bet this will mysteriously
;; break later.  Don't blame me.
やっぱり Elisp といえど closure とか OO な手段とかが無いとそりゃシンドイですよねえ.
(´ー`)

(2004.10.26) [独り言]

どうもやるべきことがありすぎて全然関係ないところをちまちまいじるのが楽しかったり します.
buffer menu ぽいのを作ってみようかと思い, どうせなら高機能なやつを手本にして みようと ibuffer を真似てみようとしてみたのです.
ということで真似してみたところ...選択を失敗したかも. ibuffer 高機能すぎです.
ibuffer の作者さんはきっと相当な Lisp 好きですね. Macro を関数生成に使ってるし, なんてったって Paul Graham の Anaphoric Macro までありますよ. 4箇所でしか使われてないけど(笑).
あと cl の関数を普通に使ってたり, assert まであるし.
たかが buffer の切り変えのための Elisp なのに 3700 行あるってどうですか. いや, まあいいんですけどね...

(2004.10.23) [考察] text property

ふが.
風邪やら仕事忙しいやら PC 買い換えやらで1ヶ月近くも放置してたのか.
まあいいや.
そろそろ無視してきた text property を真面目に考えてみます.
いきなりですが text-tag という概念を導入しようかと思います. いわゆる gtk-text-tag と 1対1 に対応するものですが, gtk のオブジェクトを生で 触るのは気持悪いとか色々あるので, Gauche のオブジェクトとしてでラップしときます.
んで, face がどうのとか keymap を変えるとか, いわゆる property はこの text-tag に対してのみ作用させ, 実際の buffer 内のテキストに対してはあくまで text-tag のみ を適用させる, という感じです.

さて, そうすると, 従来の propertize のような, 装飾済みの text を表現するには どうすりゃいいのか, となります.
ストレートに思いつくのは, text-tag でタグ付けした SXML ちっくなリストを 従来の propertized なテキストと同等の扱いとし, insert とかは普通の string の他にこのタグ付きの SXML も扱えるようにする, という方法が思いつきます.
まあこんな具合でなんとかなるでしょう.

尚, 従来の Emacs では buffer-substring とかではデフォルトで property も付いて きましたが, Edge ではデフォルトでは string のみとしようかなと考えてます. text-tag も一緒に必要な場面では能動的に -with-text-tag とかでやる. たぶん通常の用途では tag が不要な場面の方が多いと思うので, リソースの節約 にもなるかなと.

なんかこの text-tag の方式でつきつめてくと overlay との関係がどうなるか微妙なん ですが, まだ頭の中でまとまってないのでちゃんと整理しないといけません.
つーか仕事忙しすぎ...

(2004.09.29) [考察]

動的変数のカラミで面白い現象発見.
completing-read にて, tab 押したときの補完関数を決められるように, それを動的パラ メータに持たせるということをやっていたのです.
んで, completing-read の最初に補完関数を指定する変数に特定の関数 を入れてから呼び出し, 戻ってきたら元に戻す, と. 再帰編集をしても大丈夫なようにしよ うとしてたのです. が, これが動かない.
要するにグローバル変数を fluid-let でくるむのと同じなのですが, fluid-let はふつうは dynamic-bind でくるんだマクロとして展開されます. この dynamic-bind がよ くなかったのです. なんでかというと, completing-read が呼び出す本体は read-from-minibuffer であり, これは一種の再帰編集です. つまり初っ端から継続が飛ぶ!!
(fluid-let ((var x))
  (read-from-minibuffer ...))
イメージとしてはこんな感じに近いのですが, read-from-minibuffer を呼び出した瞬間に dynamic-bind が発動し, var には x ではなく元々の値が格納されます.
で read-from-minibuffer から戻ってくるとまた x に束縛し, すぐ終わるのでまた元に 戻る. つまり fluid-let はさっぱり働いてないのです(笑).
read-from-minibuffer の中でエラーになったりあさっての継続に飛びっぱなしになって も別に var の指定は戻ってなくていいと思ったので(正確に順ぐりに複数の再帰から戻ると きだけ重要), ここは dynamic-bind を使わない fluid なマクロにすればいいかなと.

(2004.09.26) [メモ]

自分用メモ.
coding-system-for-read は動的パラメータとはせず, insert-file-contents にエンコー ディングを指定する引数を追加する方向にする. 極力関数的に.
ちなみに, -unix だとか -dos とかを coding-system の末尾に付ける Emacs の習慣はや めようかなと思います. character encoding と eol type を別々に管理した方がストレー トでいいかなと. 表示も xyzzy のように [euc-jp,lf] みたく mode-line に併記とか.
まあ逆に character encoding と eol type を一度に表現するものが無くなるのはそれは それで面倒な場面もあるので, ちょっとこれは考えないといけないかな...

(2004.09.22) [独り言]

はあ.
なんかさすがに1万行越えてきたのでテストとか書かないとわけわかんなくなってきた.
はたして私にはこれを完遂できる能力があるのか?
相当アヤシイとところですがまあ行けるとこまで行って力尽きてみます.

最初に手をつけたとき, きっと途中で Elisp のパターンとかを一般化できて, 自動で Scheme のコードに変換できるスクリプトとか書けるようになるだろかと期待してました.
で, そろそろ悟りを開いたりしてるかというと ... ぜんぜんダメっぽいです ( ´∀`)
やっぱり動的スコープは面倒ですよー.
まあ, while ループと無駄な let 宣言を高階関数で短く書けたときのささやかな快感 も捨てがたいものがありますよねと負け惜しみをしてみる秋の夜長です...

(2004.09.14) [独り言]

スクリプトの中でいくらか階層が深くなったところに
(if (memq system-type '(vax-vms windows-nt))
    ...)
みたいな記述がポツンと出てくるとやる気萎えるのは私だけではないですよね...

ちと忙しいのでしばし止まるかもしれません.

(2004.09.08) [考察] interactive-p

前から, interactive-p ってどーすりゃいいんだと途方に暮れてたんですが, コマンド定義のしくみに一段かましてやればできるかもと気付きました.
原理的にはもう引数に interactive? みたいなのを追加するしかないと思います.
(defcommand forward-char ((count <integer> (i/a 'p)))
  ...)
こんな定義をしたら, ↓のような具合の定義になるイメージです.
(defun %forward-char ((interactive? <boolean>)
                      (count        <integer> (i/a 'p)))
  ...)

(defun forward-char ((count <integer> (i/a 'p)))
  (%forward-char #f count))
こうすることで, interactive? という暗黙の変数を関数内で参照できるようにしようか と. んで, call-interactively から forward-char を呼ぶときは (%forward-char #t) で呼ぶと. 簡単にテストした限りではこれでうまくいきそうです.

ちなみに i/a は interactive の構文に近いものを私が勝手に定義したものです. Emacs の interactive の構文がやや変態的だったのを改善しようとして作りました. i/a は単に入出力をしばしば伴いつつ値を返す関数に過ぎませんが, コマンド定義にデフォルト引数の位置に書くようにして使うと楽なようになってます. interactive が長くて略したかったのと, 意味的にも字面的にも i/o に似ていると考え i/a としました. これもちゃんとドキュメント化しないといけませんね.
にしてもドキュメントなんていつ書けるようになるんだろう...

(2004.09.03) [考察] Multi-Threading の問題

色々考えていておそらく重要だと思う問題点に気付きました.
current-buffer が返す値は thread local になるべきでしょう. では window や frame の状態は thread local になるべきか? ということです.
というのは, たとえば window-configuration が thread local になるとすると, 継続を切り替えるたびに window 構成も入れ替えるわけで, とてもじゃないけど実用的な 速度にはならなかろうという想像が容易にできます. 最低でも裏スレッドの場合は描画をしない, ということをやらないといけないでしょう けれど, それでもかなりの負荷になりそうな気がします.
一方で thread local にならないとすると, ちょっと予測できない問題が起きる可能性が あるのです. もし裏で別スレッドが走っててその裏スレッド内で window を切り換えたり window-configuration を復元したりという操作をすると, ユーザが表で操作してていきなり 別の window に切り替わることになり, 一貫性のないスレッド処理になってしまいます.

完全な別解として, thread と frame を 1:1 に対応させてしまい, ある thread が実行 中ならばその frame を選択することはできないようにする, みたいな方法もあるかもし れません. そしてその場合は, 新しい thread を作成することは新しい frame を作るこ とと同一になります. ひょっとしてこういう形の方が感覚としてはわかりやすいかもしれ ません.

この問題についてはまだうまく考えがまとまっていないので, ちょっと保留にしておきます...

(2004.09.01) [考察] Fair Threads

スレッドまわりのお勉強を少し.
Scheme Fair Threads
Fair Threads
call/cc での協調スレッドは適当に round-robin で回せばいいかなとは考えてたんですが, そういえばスレッド間で同期とりたいときどうすりゃいんだろうと思ってました. そのあたりをきっちり, というか preemptive なのと cooperative なスレッドの融合と して Fair Threads てのを論じているのが上のリンクです. で signal や broadcast. わかりやすいかも.
Scheme Fair Threads のほうは bigloo にその API も入ってるそうです. つか著者が bigloo の Fair Threads の実装も担当してるっぽい. それにしても bigloo は色々なラ イブラリがあってすごいですね. ついでにソース DL して解凍したら 60MB もあってサイズもすごい.
さて, Fair Threads てのは preemptive + cooperative な具合で, user threads と service threads という風に役割を分担しています. user が cooperative, service が preemptive. このあたり, 一般的なスレッドの boss/worker 型に少し似てるのかも(いや あんま似てないか). そうい や master/slave て云っちゃいけなくなったのかな?まあいいや.
ちなみに割り込みは lambda の置きかえによる実装でやろうとしているので, まあ プラットフォームが pthreads やらをサポートしてなくてもよいと. それにしてもそんな ことができるのは lisp 系言語にマクロがあるからですよね. こればっかりはマクロが無けれ ばどうにもならない気がするです.
む, まてよ. Wiliki 読んでたら気付いたけど, トップレベルの構文をdefine-syntaxで置き換えた場合の振る舞いはR5RS的には未定義なのか. うーん, どうしようかなあ...粒度を考えると lambda や define の再定義がいいけど ...defun だけでも一度実験してみようかな.

(2004.08.30) [考察] local hook とか

local のやつはクロージャでもよかったんだけど Gauche の object-apply で書きました.
たぶんクロージャで書くとちょっと面倒な気がしたので. てっとり早く書けるという意味 では object-apply はとても便利ですね.
さて, 今度は local hook の概念. Emacs では run-hooks するときに, 対象となる hook が local hook を持っている場合に は global な中身を実行すると同時に local hook の中身も一緒に走らせるという機構 になってます.
Edge ではこれは普通に, 「local な hook があればそれを実行する」という処理を行う関数を 通常の hook に追加すればよいと考えました. get-local-hook-applier と make-local-hook という関数を定義し, たとえば以下のように書きます.
(defvar change-major-mode-hook (make-hook))
(defvar $b-change-major-mode-hook (make-local-hook))
(add-hook! change-major-mode-hook
           (get-local-hook-applier $b-change-major-mode-hook))
こうすることで, (run-hook change-major-mode-hook) をしたときに, それを実行した buffer 内で $b-change-major-mode-hook が中身がのある hook であればそれも実行する, というようにしようかと. 複雑度はあまり変わってないかもしれないですが(というか上がったかも), local な hook を適用できるタイミングやそれを外すという自由度がプログラマに委ねら れているのはまあアリかなと.
ややわかりにくい部分だと思うのできっちりドキュメントに書かないといけない内容でしょうね...

(2004.08.21) [考察] local

Emacs では make-local-variable や make-variable-buffer-local と指定すると自動的 に buffer local として扱われる変数を指定できます.
でも Scheme ではやはり束縛は静的に決定されるべきですから, Emacs と同じ方法は取れませんね. Edwin はどうやってんのかなと見たところ, local な変数へのアクセスは専用の 関数を利用していたので, 最初は方法としてはそれに倣ってみていました.
当初はひとまず buffer に対する property のような形で, (local-ref buffer 'buffer-file-coding-system) といった風に利用するようにしていました. シンボルに対する plist のような感覚です.
ただしここへ来てこれを変更しようと思っていて, gauche.parameter を拡張したよう なものを考えています.

Multi-Threading として協調スレッド的なものを考えていますが, そこでも parameter 同様に thread local な値が必要になります. で, そういったものと同様の書式で buffer local な値も扱える方が統一的であると感じるようになりました. つまり, thread local な値は make-parameter で作成されたクロージャであるのに, buffer local な値は属性リスト的なアクセスというのはイケてないなと思ったのです.
なので buffer local であってもクロージャにしてしまおうというわけ. つまりそれが呼 ばれた瞬間の current-buffer に対する値を返すことで buffer local 的な動きをするこ とになります. それらの parameterize 的な構文も必要でしょう.
さて, そうするとまた別の問題があります. 処理内容によってはクロージャ呼び出しの嵐 になりますから, それが buffer local なのか thread local なのかそれ以外なのか, と いうのがソース上の初見で判断できなくなってしまうのです.
なので, 少々泥臭いのですが, buffer local なら $b- を, thread local なら $t- を接 頭辞として変数名の頭に付けるような習慣にし, ($b-buffer-file-coding-system) のような呼 び出しにして見わけることができるようにしようと考えてます. 記号を使うのは Perl 的 であまり好きではないし, たぶんちょっと顔をしかめる人も居そうなくらいですけど, むしろこういった特殊性を視覚的に訴えるくらいにしてお かないと後で苦しみそうな気がするのです. なぜならば今が既に, Elisp のソースの中でど れが buffer-local であるのかが簡単に判断できない上に, 普通の名前でクロージャに した場合 Scheme ではクロージャと関数の区別がつかないので, Elisp 以上に判別が難 しくなります.
たとえば以下のような式があったとして, 普通の名前だと
(buffer-file-truename
  (file-truename (buffer-file-name)))
こうなりますが, $b- を付けると
($b-buffer-file-truename
  ($b-file-truename (buffer-file-name)))
こうなります. buffer-file-name が通常の関数で, それ以外が buffer local な値を返 す/設定する クロージャである, ということが, 前者の例では非常にわかりにくいと思います.

(2004.08.18) [考察] 手続き的な書式

fluid-let と同様に, Elisp の特徴として手続き的な書き方が非常に多いということがあ ります. 正直かなり滅入るんですが, こればっかりはどうしようもないのかもしれません.
冷静に考えると, エディタ上の操作ってのはほとんどが破壊的な操作なわけです. そう するとどうしても順序を意識しながら上から下に progn 的につながる関数が多くなって しまうのかもしれません. で, それはまあしゃあないとしても, ちょっと「長すぎねえか」 というくらい長大な関数が多いのですよ. もう少し細切れにできないもんかと. 私は Emacs の画面で上下 40 行くらいの高さで作業してますが, エディタ上の一画面に 収まらない規模の関数はちょっとなあ, と思います.
関係ないけど, どっかで Haskell で Emacs 作るみたいな話があったような...純粋な関 数型言語でエディタをどう実装するのか興味あったんですが, どうなったんだろう.

ちなみにいろいろ煩悶しながら作ってると, ジレンマみたいのが出てきたりします.
「理想的なコーディングにしよう」とすると「必要な作業が多すぎて先に力尽きる」という可 能性が高くなり,
「ひとまず泥臭くとも quick hack しておこう」とすると「後で進退窮まってどうにもな らなくなる」という可能性が出てくる(特にMT周り),
といった具合です. まあ, 一発で綺麗なコーディングに全部乗せ換えることができるくら いのセンスと体力とがあれば一番いいんでしょうけど.

オリンピック観ててより一層手が止まってます...

(2004.08.11) [考察] preemptive

今は GTK のハンドラに Scheme のコマンド起動を引っ掛けてるだけなので, C-g で中断が出 来ないことになります. ということで中断やるにはどうするの, と.

MT 化とのからみもあってまだ勉強中ですが, gauche.threads のいわゆる pthreads を使 うというのがひとつ. ただこれはスレッドサポートを有効にして Gauche がコンパイルさ れている必要があるし, プラットフォームがサポートしてなかったら厳しいですね.

もしくは call/cc による軽量スレッドを自前でやりくりするか. call/cc による軽量スレッドてのがどんなのかよくわからなかったのですが, ケント本に あるエンジンのことですよね. 読み直してみてふむふむ. 面白いかもしれません.
それぞれのエンジンごとに燃料となる ticks を可変にすれば, スレッドの優先度を変更 するような, プロセスにおける renice みたいなこともできるかな?
さて問題はタイマーの設定ですかね. ケント本によれば, プリミティブのタイマー割り込 みを使わないならば timed-lambda のようなマクロで既存の lambda を置き換える必要がある, とあります.
かなり粒度が荒くなるけど, defun の中でタイマー消費もやってしまうのもありか. ただ そうするとエディタ以外の関数を実行している間にタイマー消費ができないため, 最悪の 場合は暴走しても止められない可能性もありそう.
やや反則気味だけどエディタ実行時に最初に lambda を timed-lambda に置き換えてしま う方が現実的かもしれません.Gauche にもシステム的割り込みがあるかもと思われますが, Scheme だけで実装ってのもなんだか雅でよいかも.

さて, ひとつ懸念事項があります. dynamic-wind を使っている関数は大丈夫だろうか.
というのは, この継続ベースの Multiprocessing を利用して関数をスライスするとき, もし関数内で dynamic-wind を使っているとその before と after の thunk がすごい勢 いで呼ばれまくるからです. 本来はこういった風に, before も after も複数回呼ばれる ことが意識されていればよいのですが, Java における try/catch/finally のような感覚で使わ れているとズっこける可能性が高い. Shiro さんの文章の なんでもλ においても, 脚注で

「正確には、dynamic-windはtry/catchなどの メカニズムよりも一段低い構成要素であり、 例15のように例外時に ファイルを閉じる目的で使うのは邪道ではある。」

とあります. というか私も今までこの邪道な方法が普通だと思ってました(笑).
まあ, それはそれで邪道なコーディングを直す機会だと思って, この方法で preemptive な処理の実装をしてみようかなと思っているのでした.

(2004.08.10) 0.0p4

ぜんぜん進んでないけど自戒のため. あいかわらず file 系の実装で手間取ってるのでエディタと呼べる機能は遥か先で す... (-_-;)

(2004.08.08) [考察] fluid-let

Elisp を Gauche のコードに移植してる途中, よく fluid-let 的な使われを方している コードに出会います. その度に, もし変数そのものを無くせるなら廃止したり, そうでな いなら parameter にして parameterize でくるんだり, まあいろいろ頭かかえながら進 めてます.
あまりにも多いので, fluid-let を恐れずに多用するべきかなあとか, local な値も同様 に使えるマクロを定義しようかなとか考えてみてます.
本質的には, こういったグローバル変数を関数的な手段に置き換えることができればベス トなわけですね. 中にはそういう方法が使えるのもあるんですが, fluid-let 的な方法でな いと逆に複雑になってしまう部分もあるっぽいです. fluid-let 的なのは Multi-Threading を考えると破綻しやすいと思うので極力は関数的にしたいのですがこれ がまたなかなか...けっこう深いところにこのグローバル変数は入り込んでいるのです...ぐう.

(2004.08.05) [考察] いろんな変数

buffer-file-number て file の i-node の番号らしいんですが, これ一体いつ使うんだ ろう. /lisp 下での調査ではまったく重要そうな利用方法なし. 要らないかな. i-node 番号がもし必要になったらその都度 file-stat で取得すればいいと思うし.
あと, find-file-run-dired てのがあるのを知りました. find-file で directory を指定した ら dired で開けるようにするかどうかというフラグ. というかそれが当然だと思ってい たのでフラグになってることさえ知らなかったんだけど, はて. あってもいいと思います が, なんとなくもっと一般的な方法でまとめられそうな気がするのです. file-name-handler-alist みたいなしくみで包括的にできないかなあ. あー頭いてー.

(2004.07.27) [考察] coding-system

coding-system は実質的に Gauche の ces 名になると思っています. ただし, Emacs においては euc-jp に対して euc-jp-dos, euc-jp-mac, euc-jp-unix のように 改行コードを明示した表記もあり, 扱い方はもちろん変える必要があります (明示してないのは base-coding-system と呼ばれ, 改行は適宜推測される).
一応 Emacs のソースの coding.h の coding_system の構造体を見ると怪しいフラグとか pre,post な関数用のスロットとか見えるしその用途まではまだ追いきれてないのでもし かすると coding-system はクラスにした方がいいのかしらと不安にもなるのですが, 直 観的には Gauche の ces を大体はそのままの形で使えるはずと考えてます.
どうでもいいけど Unicode には改行コードが8種類もあるのですかね? ここ とか. CR と LF 以外の改行コードは面倒な気がするなあ. 見なかったことにしよう...
そいえば utf-8 で CRLF を強制するには utf-8-dos ってなるんでしょうかね. なんか間抜けだ.

(2004.07.23) [考察] write-region-annotate-functions

エディタを作ってみようとする前はある程度 Emacs のことはわかってたつもりだったの ですが, いざ手をつけるともう知らない機能があるわあるわ. オマエは一体何をわかった 気になってたのかという感じです.
んで, まあ多機能なのは当然なのですが, 中には移植する必要があるのかどうか怪しい機能もあるわけです.
たとえば write-region-annotate-functions とか. これはファイルへ書き込むテキストに対する注記の形でテキスト属性を符号化するため にある abnormal hook らしいのですが, そんなん使うのかよ, と思ってしまうわけです.
でこういう場合, 私はよく Emacs のソースの lisp/ の下で grep をかけるというのをよ くやります. ここには沢山の標準的 elisp コードがありますし, calendar や gnus といっ たある程度高度なアプリもあるので, これらがある lisp/ の下で grep をかけてあまり hit しない ようであればそれは重要度も利用頻度も低い, というまあ一種の市場調査みたいなことができる かなと思っています.
んで write-region-annotate-functions の結果はというと, dos-w32.el がプリンタ出力 用に使っているだけ. はっきりいって実装する必要なしでしょう. まあ Emacs にある以 上は何らかの歴史的理由があったのかもしれないし, 後になって実は必要だったとかになれば実装する かもしれませんけど(最初スっとばしてて後でああそういうことかみたいなことは結構あります), まあ最初は愚直に「要らないじゃん」と思った機能はスルーするようにしてます.

あー, file 関係の処理はめんどくさいな〜.

(2004.07.19) [独り言]

明らかに自分が使わない機能っていうのは, かなり実装しててモチベーション下がりますよね. マウスでウィンドウの枠をつかんでドラッグすればリサイズできる, ってのはアプリの常 識だろうし, リサイズできないエディタは控えめに云ってもまあおかしいでしょう.
でも, もし Emacs like なエディタを使いはじめてのち常用段階に入ったら, 使用中にフレームの大きさを変える 人なんてほとんど居ないと思うのですよ. 私は自宅と会社で Emacs 使ってますが, ディスプレイ の解像度を変えたりしない限り, 設定してある起動位置とサイズはまず変えません. そう考えると, 自分が使わないリサイズ機能を実装しようとしてもモチベーションが 下がってしまうのです. もうこれはいっそのことリサイズ不可を前面に出すくらいの仕様にしてしまおうか と真面目に考えてしまいました. それに起動後のサイズが不変であるという前提があると, コードを書く側の人間にとってはとても都合がよいのですよ. window-configuration を 変えたときに元のフレームサイズから変化しているかどうか調べる必要が無いし, 余計な コードを書かなくて済むのですっきりするし.
まあさすがにそうもいかないだろうとは思いますよ. 自分が使わない機能は実装しない, なんてことしたら, 「リサイズ不可」 「マウスサポートなし」という狂った仕様のエディタになってしまいます. それはそれで アリな気もしますが(笑).
てなわけで一応まともな機能になるようコツコツ書いていこうとしてますが, いつか甘い誘惑に 負けて寝返るかもしれませんね.

(2004.07.15) [debug]

リサイズ問題わかったーー!!
gtk-widget-size-allocate を top level window に適用すればよかったのかあ.
くそーどれだけこれで悩んでたんだよもう. まあいいや. とにかくスッキリしました.

どうでもいいけどこのごろは時間が全然ないっす...
こういう開発は学生のときにやりたかったなあ.

(2004.07.09) [考察] 関数名

関数名は最初から悩みまくりなんですがまあ大抵は Emacs と同じにしてあります.
だったらどこに悩む余地があるんだよと云われそうですが, それはインタプリタ(Gauche)の API との整合性みたいなものです.
たとえば, Emacs には file-modes と set-file-modes という関数がありますが, それら は Gauche では file-mode と sys-chmod に相当すると思います.
なら新たに関数など作る必要はなくて全部 Gauche の API で書けばいいじゃないか, と 思うかもしれません. というか私も最初はそのつもりでした.
が, Elisp を Gauche のスクリプトに落とす場合にはコピペしてちょろっと修正する, と いう作業が大半です. 正直, 既存の Elisp とあまり離れた名前の関数を使うのは修正も 面倒だし, 上の例では file-modes と set-file-modes の方が綺麗なようにも見えるのです.
ならばそれらの名前で関数を定義し, 実体は file-mode と sys-chmod を呼ぶというブリッ ジをかませばいい, という発想になります.
しかしここでまた問題があるのです. もしそうするならば, 一体どこまでブリッジをかますべきか? という問題です. たとえば Emacs の file-exists-p は Gauche では file-exists? に相当します. Scheme の慣習を考えれば, これは新規で関数を定義せず そのまま file-exists? を使うべきでしょう.
では file-writable-p はどうでしょう? Gauche では file-is-writable? に相当します. ブリッジ的な考えなら file-writable? かもしれません. でもそのまま file-is-writable? で問題ないとも思えます. というか英語的にもこっちでしょう.
こういった, 関数であったりエイリアスであったりという API 群になると, エディタ側の API なのかインタプリタ本来の API なのかがわかりにくくなっ てしまうのです. 別にそれはそれでいいのかもしれませんが...うーん...

(2004.07.01) [考察] semantic

semantic をもう少し調べてみると, 大雑把には以下の機能があります これが全部 Elisp で作られてるっていうんだから, 改めてスゴいとしか云いようがないです.
もしこれと同等な機能を実装した場合, たぶん という利点があるのではないかと思われます. 構文木をそのまま持ってしまうわけですか らね. エディタとしてはこれ以上に都合のよい地図はありません. semantic は昔 JDEE を少し使ったことがあるのでたぶんそのとき利用したのだと 思うのですが, それほど遅いとは感じませんでした. まあちょっともっさりした感じはあっ たように記憶はしてますけど.
で, こういった機能はとても面白そうだし, 時間があったら是非実装したいと思うのです.
でもかなり高度な機能だし, 最初からこれを乗せることを前提としていると手間どりそう なので(特に私にとっては), 落ち着いたときにじっくりといじってみたいなという題材です.
ちなみにオリジナルの LL parser を semantic bovinator て作者さんは呼んでいるんだけど, bovine て「牛のようにのっそりと」という意味なんですね. たぶん LL な parser を brute force 的にしかも Elisp で実装したからやや自虐的な意味でそう呼んでいるのかな?
他になんか意味があるのかなあ.

(2004.06.25) [考察] overlay と text property

Emacs において, text property と overlay というのはかなり似ています. どちらも特定のテキスト部分をカバーし, face を変更できたり keymap を設定できます.
ではどこが違うのかというと, 最大の違いは text property はテキストの変更に該当し, コピペすれば他の場所にでも適用されるし, undo でも復元対象となる, といったところ でしょうか.
Emacs の text property の実装の特徴として, 「text property は範囲ではない」とい うことが Emacs lisp reference manual に説明されています. 最初, これを読んでちょっ と意味がわからなかったのは私だけでしょうか? 範囲ではないと云っても API としての put-text-property などは「開始」と「終了」という範囲を引数として取るからです. 要は, 「範囲ではない」というのは実装の話であってユーザから見れば違いはあまりわか らないのではないかと. 気にするのはきっとエディタを作ろうとしてる人くらいでしょう.
overlay を gtk-text-tag を使って書いてみたんですが, たぶんこれの扱いを少し換えれ ば text property と同じ振舞いができるはず, と考えています. いっそのこと text property をなくして, overlay の属性に何か追加することで text property のように動 作するようにしてみようかな, とか色々.

(2004.06.22) [考察] Multi-Threading

Emacs devel では Multi-Threading について 2003年の 11 月から 12 月あたりにかけて 長いやりとりがあったようですね. まあ定期的に出ている話題なんじゃないかなとは思うけど. 要点としては(といってもさわりをナナメ読みしただけだが),
  1. Emacs の MT 化はけっこう大変
  2. 多くの elisp は MT safe でないので書き直し
  3. 動的スコープのことも忘れるな
  4. Guile Emacs になっても状況はあまり変わらない
  5. MT 化するの何が嬉しいの? gnus とか.
てことで, MT 化するなら「最初からやっておけ」というのが結論ですかね(本当かよ).
一応, Thread ごとになりそうなやつは make-parameter しているつもりだけど, いずれ ちゃんと詰めなければならないでしょうね. gauche.threads を使えばヨユー, ってもんで もないでしょう. buffer の排他制御は mutex? reader/writer?

感覚的には, 「巨大ファイル内で置換を実行」→「やべ, 時間かかりそう」 →「新スレッド立ち上げて別のことやる」 みたいなことがスムーズにできるのが理想な のでしょうね. スマートに実装できるのかどうかはちょっとまだわかりません.

(2004.06.20) [考察] minor mode

そろそろ minor mode の実装をぼーっと考えてみます.
local な環境が buffer, window, frame とあると考えているので, 従来の minor mode は実質は buffer minor mode なわけで, 理屈の上では window minor mode, frame minor mode みたいのもありえるように思います. が, 現実にそういうものがどれだけあるだろう? わからない. window minor mode や frame minor mode のような概念で素直に実装できる ものがあるかもしれない. 無いかもしれない.
あまり考えると頭が痛くなってくるのでとりあえず従来通りの minor mode を実装してみ て, 途中で拡張するかもしれない, という程度にしておこうと思います.
このあたりでも, 最適な実装というものは「実装してみないとわからない」っていうこと を実感してしまうのです. まあ自分の先見性のなさでもありますが...

(2004.06.17) [考察] defcustome の group

defcustome の group について迷っています.
モジュールと非常に近い概念だとは思うのですが, 微妙に違いがあるような気がするので.
また継承関係も考えると, class にしてしまうべきなのかもしれません.

(2004.06.17) [考察] defun の引数クラス指定

defun の書式は, おそらく現在の形で確定だと思っています.
元々は define-method を複数生成するマクロのためにクラス指定を入れていた(つまり苦 肉の策)のですが, Shiro さんに let-optionals* が使えるとのアドバイスを頂いて改良したので, 原理的にはクラス 指定は不要です. そして let との対称性を考えるとクラス指定は無い方がよいのではないか と散々悩んだのですが, let とは 2点ほど違いがあると思い, 結局クラス指定は残す方 向で考えがまとまりました.

違いの 1点目は, 仮引数のスコープの長さと可読性の関係です.
通常の let では束縛するスコープをできるだけ短くするのが普通で, それが非常に短い場合は簡単 な変数名で充分です. しかし変数が生きるスコープが長くなると, より分り易い名前にす べきであると誰もが思うはずです.
そこへきて, 仮引数というのは関数定義内で最長のスコープを生きる変数ですので , 分り易い変数名をつけるのと同時に, 最初に束縛される時点での型(クラス)が明示さ れていることは可読性の向上に直結する, と考えました.

2点目は, エラーチェックです.
通常の let は処理内容も変数束縛もそれを書くプログラマだけが関知するものです.
それに対して, 関数は他のプログラマやユーザが利用し, どんな値を入れるかがわかりま せん. 必然的に, 値のエラーチェックをすることになるでしょう. 厳密に範囲やとり得る 値のチェックなどは各プログラマが書くべきかもしれませんが, 型が合っているかどうか というチェックを自動化するだけでも大分違うのではないかと思いました.
短期間に極めて多数回呼ばれるような関数ではエラーチェックがネックになる可能性はありま すが, そういう場合は型指定ナシで宣言するとかネック部分を内部 define するとか色々 できますからね.

(2004.06.17) [考察] Syntax table

Syntax table は当初からずっと放置してます. なかなか考えがまとまらないのです. あんま無闇に Emacs と違う仕様にはした くないんですが, Emacs の Syntax table はコメントのフラグ指定が破綻していると思う ので(3文字以上のデリミタのコメントを扱えない), やはりそこは変更が必要かなと.
Syntax Table は結局構文の要素を定めるものなので, 必然的に parser ぽいことをやる 関数が利用するわけですが, Emacs には semanticていうかなりの力作な parser まであります. でもこういうのは力作すぎかなと.
いろいろ考えていくと, 究極的には BNF を入力すればそれで構文を規定してソース内を 移動できるような関数を生成できればベストなのかな, とすれば既に幾つかあるパーサジェネレータ を利用できるのではないかな, とか考えるんですが, シンプルな方法が思いつかないし, いきなり飛躍するよりは やっぱり Emacs の Syntax Table に近いものを実装してまずはそれでやってみるのが一 番かなと思っています.

(2004.06.11) 0.0p3

なんか, elisp を移植しようとするとゴテゴテしてて気持悪い...
単なる let じゃなくて fluid-let 的なのが多すぎ...
パっと見て変数が buffer-local なのかそうじゃないのか分からなすぎ...
手続き的な書き方が多すぎ(これはしょうがないのか)...
ちと疲れてきたです...

(2004.05.10) 0.0p2

その他いろいろ追加修正.
営団地下鉄の S マーク欲しかったなぁ.

(2004.04.10) 0.0p1

ひっそりと野に放ってみる.











役に立たないので戻る