| 2005/07 | ||||||
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 | ||||||
| 2005/08 | ||||||
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 | |||
| 2005/09 | ||||||
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | |
top > かいはつにっき 2005 Q3
いろいろ励ましをいただいてしまいました。。。ありがとうございます。とりあえず生きてます。
最小化がおかしいのを修正。
App.RegisterProperty() というものを作ってみました。簡単に言うとこれでプロパティを登録すると、それが萌ディタの知らないものでも環境設定画面に出るようになる。。。というもの。
App.RegisterProperty(PROP_BOOLEAN, 'indent-on-newline', '改行入力時のインデント', '');
なんてしておくと

というふうに「その他」タブに出てきます。
ファンクションキーのラベルとか。ファンクションのラベルというのは、プロパティ funckey-normal などにカンマ区切りの文字列で指定します。これに対してファンクションキーの動作というのは、他のキーと同様に onKeyF1 とかに定義します。
で、スクリプトで F1 だけの動作を差し替えたいなーとなったとき、
/* ラベルを書き換える。
* カンマ区切りを配列にして該当の要素だけ書き換えてまたカンマ区切りにする
* めんどうでとりとめのないコード */
var a = App.Prop('textfile', 'funckey-normal').split(',');
a.length = 12;
a[0] = 'ほげほげ';
App.Prop('textfile', 'funckey-normal') = a.join(',');
delete a;
/* イベントハンドラ上書き */
class_textfile.prototype.onKeyF1 = function (arg, classname, methodname) {
:
:
}
な感じで、ラベルを書き換えるのが大変めんどうです。というか、コード自体は別にめんどうではないのですが。。。なんというかファンクションキーにまつわる定義が 1 箇所に固まってないのがなんとも居心地が悪いような。
例えば
class_textfile.prototype.onKeyF1 = function (arg, classname, methodname) {
// ラベルを求められていればそれを返す
if (arg & KEYMASK_DESCRIPTION) {
return 'ヘルプ';
}
// そうでなければ通常の動作を記述
else {
:
:
}
}
な感じで、arg の特定のビットが立ってたら本来の動作ではなく、ラベルを返す。。。なんて仕様にするとどうか。
この仕組みは、やりようによってはファンクションキーに限らず、すべてのイベントハンドラに概要を持たせることができそうですね。「ヘルプ」モードに入ってなにかキーを押すと、動作の代わりに概要を表示するとか。なんかどこかから訴えられそうな機能ですが。。。
まあ実際にそうすると、すべてのキー入力系イベントハンドラで、概要を求められているかどうかの判定をしなくちゃいけないのがめどいので、やりませんが。。。
とりあえずファンクションキーに関しては上記のような仕様にしてみました。したがって、以下のプロパティは削除。
それにしても仕事というのはなかなか見つからないものです。
もう、めんどうだから、首吊って、死ぬか!
いろいろ妄想:
ファンクションキーのラベルというものがあります。今は、これを 1 つのプロパティで F1 から F12 までまとめて、カンマ区切りの文字列で指定しているのですが、これだとあるラベル 1 つだけ変更したい、というときめんどうです。
ファンクションキーのラベルのリクエストを受けるイベントがあればいいのかもしれません。あるいは、onKeyF* イベントハンドラで、特定の引数の場合はラベルを返すような仕様にするか。
オートインデントというものがあって、萌ディタの場合その動作は完全にスクリプト側に任されています。この動作を on/off したい場合、
ということになると思います。前者は特に書くことはないのですが後者の場合、こんなふうに萌ディタの知らないプロパティを追加した場合、環境設定画面には表示されません。これはちょっと使いにくい。
すでにこういうプロパティはいくつか定義されていて、srcfile.javascript.txt の
なんかがそうです。萌ディタ側に、プロパティの型・説明を教えてあげる仕組みがあればいいのかも。
矩形選択の Undo まわりにバグがいるようなので、それを直したら nightly build 出しますねぇ。

作ってみました。
まずこの機能自体の on/off をプロパティ indent-paragraph で指定します。
それから以前考えたように、段落最初の行の空白があまりに長すぎる場合、後続する行のインデントを単純に合わせてもみ難いので、プロパティ indent-paragraph-limit というのを 0.0 〜 0.75 くらいで指定するようにして、空白文字列が折り返し幅に対してその幅以内の割合ならインデントする、というような感じにしてみます。
空白文字列というのは、タブか Unicode のプロパティが Zs な文字ということなのですが。これに追加の文字列を指定できるようにしたら便利といえば便利かな。
◎箇条書きみたいな感じに表示する
ことができます。
のように空白列 + 任意の 1 文字までをインデント量とみなす感じ。必要でしょうか?
字句解析のパフォーマンス。まず Lex.AddKeywords() で追加するキーワードの探査です。
このキーワードの探査は、
そいで、今現在だとこのキーワードの探査というものを 2 分探索でやっています。そもそもこれが十分に速いのかどうか?
ためしにこれをハッシュで持つようにしたら、割と効果があるようです。と思ったらAlpha がすでに同じような経過を辿っていたみたいです。
ところで、いくらパフォーマンスをあげても、1 段落が例えば 10KB とか 100KB あったりすると解析に相当な時間がかかるわけで、適当な閾値と、それを越えたら解析中断、とかのオプションが必要かもしれません。
スクロールで描画がずれるのを修正。。。? 原因はだいたい分かったのですが、うちで出ないバグというのはやっかいです。
世代つきバックアップに失敗するのを修正。
前に書きましたが、バックアップのパス名で '%' で始まるマクロがあるのですが。環境変数の展開をさせようとするとかち合うので、'$' で始まるようにしようと思います。
同様に、バックアップファイル名やウィンドウのキャプションにも '%' で始まるマクロがあります。こっちは環境変数を展開するわけではありませんが、いちおうマクロは '$' に合わせてみます。
してみました。よさそうですが、プロパティから取得したバックアップパスを丸ごと ExpandEnvironmentStringsW に渡すと、'%〜%' という文字列そのものとか、'%' 自身を含むパスを指定することができないような。結局自前でパスを走査して、'%〜%' を切り出す必要がありそうです。
ということで、そうしてみました。
ぼちぼち nightly build を出してみようかな。
表示まわりのボトルネックをまとめると、
ということみたいです。
字句解析まわりがボトルネックではないとはいえ、極端にキーワードが多い場合や *return* 遷移は重くなることが分かっています。次は字句解析まわりを洗ってみます。
そんなわけで、nightly build です。
ものすごく後ろ向きな高速化(というか、低負荷化)ですが、キーリピート中は再表示を 2 回に 1 回間引くようにしてみました。すごく動きが微妙です、かくかく〜て感じ。プロパティ lazy-repaint で指定し、true のとき間引くようになります。デフォルトは false です。

実になんの意味もありませんが、アクティブなタブにグラデーションをかけてみました。
ウィンドウのサイズを変更したときにできるだけ表示が乱れないようにしてみました。
補完を確定するとき shift を押している場合はキャレットの右側を補完の対象としないようにしてみました。
CrystalMark でうちのマシンのベンチとってみました。えー、登録 35312 件中の 33420 位、GDI だと 29221 位。。。
マジか。
ということで、そうしてみました。
一応合成自体は最大で 1 割ほど速くなった。。。みたいだけどぜんぜん体感できないや。
だめじゃん。
うちのマシンのように Blt 自体がそれほど速くないとなると、そもそもオフスクリーンバッファを使ってることがネックになってしまいますね。。。壁紙がなければオフスクリーンバッファなしで行くんですけども。
どうでもいいですけど、オフスクリーンバッファを使わずスクリーンだけで表示を完結させたい場合って、たいてい WM_ERASEBKGND が邪魔なので DefWindowProc を呼ばずにリターンさせるのですが、このメッセージの存在意義がよく分からないなあ。
ちなみに、背景色とのαブレンドをするように設定した場合は、合成領域の幅の最適化とかしようがないので、常にビュー全体を AlphaBlend() します。なので、遅いままです。
テーマ周りの小バグを直してて気付きましたが、壁紙を表示している状態というのはオフスクリーンは 8bpp なのです(壁紙なしなら 15bpp)。なので、設定した色をそのまま使うわけではなく、256 色の論理パレットから一番近そうな色を選んで、それに置き換えられます。
ある表示要素に対応するパレットインデックスは固定して、適宜パレットの中身を書き換えるようにすれば置き換えは発生しませんが。。。使用色が256を越えられないとかいう変な制限がつくことになってしまいます。字句解析器のスタイルをどうするのかとか、選択範囲を反転させたとき見難くなるかもとかということを考え始めると話が複雑になりすぎるので、これはまあ仕様ということで。。。
壁紙との合成から考えてみます。
この合成というのは、Windows2000 から実装された TransparentBlt() という API を呼んでいるだけだったりします。これは、転送元のデバイスコンテキストうち透明とみなす色を渡すことで、その色以外だけ転送ということができる。
この API ですが、そんなに速くないっぽい。カーソルキーを押しっぱなしにしてスクロールさせたりすると、CPU 使用率が簡単に 80 とか 100% いってしまいます。なんか CPU だけで処理しているような感じ(少なくともうちのマシンでは)。試しに Delphi で同じようなことをするコード(転送元矩形に対して、透明色以外なら転送)を書いてみても、あまり速度が変わらなかったりします。
どうでもいいですが、この TransparentBlt() とか AlphaBlend() って、msimg32.dll に入ってることになってますが、Windows2000 だと本体は gdi32.dll にあるっぽいような。msimg32.dll はたぶん Win9x 系でも使えるようにするためのラッパということなのかな。
で、これをどうやって速くするかなのですが。。。
速度を計ってみると、ビューのサイズが 764×440 のとき、合成がだいたい 6msec、合成後のスクリーンへの転送(BitBlt())が 7msec くらいかかってるみたいです。
うーんこんなものなのかな。なんか後者が、アクセラレータが効いてないっぽい感じがしますが。。。TBitmap で作った実体が、スクリーンにコンパチブルな DC やビットマップとみなされないからかなあ? と思って、TBitmap ではなく CreateCompatibleDC()/CreateCompatibleBitmap() で作った生のビットマップを使うようにしてみましたが。。。変わらない。
オフスクリーンバッファを DDB で作るようにしてみたりしましたが、変化なし(かえって遅くなる)。なんかスクリーンへの転送自体はこんなものっぽいのかな。ちょっと納得いかないけどな。。。
ということで、合成処理側を速くしたほうがよさそうです。
とりあえず壁紙を 32bpp や 24bpp で持つよりは、15bpp で持ったほうが気持ち速いので、これはすでにそうなっています。
TransparentBlt() を使わないやりかただと、モノクロのビットマップを用意して転送先に AND して転送元を OR する、という昔ながらの方法か、MaskBlt() ということになると思います。でも転送元となるオフスクリーンバッファの背景色が常に rgb(0,0,0) というわけでもないのでちょっと面倒だし、BitBlt() の速度から考えるに現状から劇的に速くなることはなさそうです。
あるいは DirectX に行っちゃうとかかな。。。
TransparentBlt() の対象となる幅はビューの横幅なのですが、上のように表示していたとき、折り返し幅を超えて描画されることはありえないのに、透過転送する必要のない領域まで透過判定しつつ転送しているわけで、無駄です。これを最小の幅で合成するようにしたらそこそこ速くならないかな。
ついでにいうと上の「<td>22</td>」なんかは相当短いので、こういう行を有効に利用できないか。つまり 1 回でどばっと TransparentBlt() するのではなくて、行ごとに必要な幅の分だけ TransparentBlt() を繰り返す感じ。
もしかしたら 2 週間ほど更新できなくなるかもしれません。
読んでも何の意味もありません。
バッファに対する変更が、画面に反映されるまでの流れを、忘れないように記しておきます。
バッファに対する操作をするオブジェクトとして、TkfCaret というものがあります。TkfCaret は TkfView に参照され、同時に TkfBuffer を参照している。で、TkfCaret のメソッドを通してバッファを操作するわけです。
これらのメソッドは、最初と最後に BeginUpdate() と EndUpdate() を呼んでいます。前者は
後者は
あたりのことをします。これらは呼び出し回数を記録していて、メソッドの呼び出しを入れ子にしても TkfView への通知は必ず 1 度だけ行います。
次に通知を受けた側の TkfView の処理ですが。前者は必要な変数の初期化くらいしかしませんが、後者が面倒です。
まずキャレットを通したバッファの操作というのにレベル付けがあります。
基本的にはこれらのバッファ操作レベルと、更新前のキャレットの情報を TkfView 内へコピーして、更新が必要であるフラグを立てて Invalidate() するわけですが。連続して更新を行った場合、バッファ操作のレベルを上げることはすれ、下げないようにします。つまり最初の更新で cuFullRepaint、次の更新で cuMoveHorz が来ても、全体のレベルとしては一番強いもののままにしておかなければいけないので、cuMoveHorz は無視する、みたいな感じです。
そんなこんなで Invalidate() した結果 WM_PAINT が来て、再描画フラグが立っているのでオフスクリーンバッファを書き直します。まずバッファ操作レベルで振り分けて、
というようなことをして、最後に壁紙との合成やらをしつつスクリーンに転送して表示が終了します。
差分再描画というのは、TkfView は TkfBuffer をどのように更新したかということは知らされないので、前回オフスクリーンバッファを描画したときの描画の状態を覚えておいて、それと異なる行だけ描画しなおすということです。
そんなわけで再描画自体はだいたい無駄なく行ってるはずなのに、いまいち軽いわけではないのは、字句解析と壁紙との合成が重いのから、のようです。
それを軽くしてみようかなーと。
0.6.1 です。どんなもんなんでしょうか。
拡張子クラスを書く際の変更点をまとめると、
Lex.DefaultColor()、Lex.DefaultBackgroundColor() は obsolete になりました。代替として、Lex.DefaultStyle() を使用してスタイルを指定します。
Lex.Add() で指定するスタイルに、exstyle 句を新設しました。
'@' で始まるテーマカラーは削除されました。
スタイルには直接 color:white とか書いてもかまいませんが、その場合テーマの表・裏の影響を受けません。新しく拡張子クラスを書く場合はできるだけ exstyle 句を使用するようお願いします。
そんなわけで、スクリプトを exstyle を使うように書き換えてみました。
さて、従来からプロパティの中に色を指定するものが存在しています。alt-space-color とか。ところがテーマ側の機能がいろいろ詰まってきたので、プロパティに対する指定はあまり意味がなくなってきました。逆に、プロパティ側ではテーマの裏表を指定できないので融通が利かないことになってしまった。
ということで、削除します。色については一括してテーマに頼ることになります。
Microsoft Visual C# 2005 Express Edition Beta というものを入れてみたり。
へー。
とりあえずすべての拡張子クラス(の字句解析器)に適当に色を割り当ててみました。
どうでもいいけど php のファイルとか開いてみると字句解析に体感で分かる間が出てきて使い物にならないなあ。どうでもよくない。
これは php の字句解析器の場合、登録するキーワードの数が群を抜いて多いのと、字句解析で *return* 遷移が発生したときの戻り先の取得に時間がかかるからですね。。。これはいずれ修正する必要があります。
自分で書いておいてなんですが、というか書いた記憶がないのですが、bmp ファイルや jpg ファイルを explorer から萌ディタへドロップすると壁紙に設定する。。。そうです。へー。
でもドロップは javascript へ一度イベントとして投げたほうがよいような気もしますね。html なバッファへドロップしたら img タグに展開、とかのほうが使いではありそうです。ないか。
なんで突然ファイルのドロップの話かというと、ふと explorer から「フォルダ」をドロップしたらどうなるのかな、と思ってやってみたわけです。そいで、そんなケースを想定していなかったので、とりあえずフォルダだったら何もしないように修正しました。
これ、例えばフォルダをドロップされたら「開く」ダイアログを表示。。。とかでもいいんですけども。複数のフォルダを落としたらどうなるの? というのを考えると何もしないのが無難な気がします。explorer からドロップするってことは、そっちでファイルを選択したほうが早いし。
ちなみに、他のエディタの場合でも、フォルダをドロップしたときの挙動は想定外なのか、落としたフォルダの数だけエラーダイアログを表示したりするものがけっこうありました。それはいいのですが、中には落ちてしまうのもあったので(WZ とか)、落ちるのは直したほうがいいんじゃないのかな。。。と思った。
コピーと貼り付けは、めどいのでやめました。
メニューからテーマの裏・表を切り替えられるようにしてみました。壁紙のフィルタが「明るく」か「暗く」であった場合、連動するようにしました。
だいたい萌ディタ側は動いてきたような。次はスクリプトをいろいろ直さなければいけません。。。
なんかむらむらと、スクリプトエンジンを別スレッドで動かしたくなってきました。
デフォルトスタイルの解析部分を書いた。編集用のテーマクラスに必要なプロパティやメソッドをいろいろ書いた。デバッグ用にテーマの内部情報のダンプ処理を書いた。編集用のテーマをエディタ側のテーマに assign するところを書いた。スタイルの内部情報を外部に公開する形式に変換する処理を書いた。
次はテーマの更新に応答して、各字句解析器内に保持しているスタイル情報を更新する処理を書きます。
書きました。とりあえず設定したものが反映するようになった。
次は ini ファイルへの保存。
書きました。
次はコピーと貼り付け。
こんな感じに。
メニューにしたので、昨日言っていた中間のダイアログというのは、なし。それにしてもメニューをオーナードローするのはめんどいなあ。しかも rtl な環境のことを無視して描画してたりします。あと、XP だとどうなるんだろう。
そんなことよりも、色をコンテキストメニューから選ぶという UI はどうなんでしょうか。。。とりあえず手持ちのエディタでは、そういうのはないです。
グリッドの各行のヘッダは、実際にスタイルを適用させて描画するとわかりやすいかも?
あとはデフォルトスタイルの解析部分と実際のテーマへの反映と一時的な反映とスタイルのコピー/貼り付けと ini ファイルへの保存を書くだけ。。。

とりあえず、こんな風になっています。
個々のセルの値をどうやって変えさせようか。こういう、グリッド的なコントロールだと、クリックでセルを選択、ダブルクリックで値の変更というのが多いと思います(Excel とか)。環境設定画面もそんな感じになっています。
まず色を表示しているセルから考えます。これをダブルクリックしたとしてどうなるといいんでしょう? 色選択のコモンダイアログでもいいのですが、基本の 16 色とか、システムカラーとかはアレからは選べないのでなにか中間に自前のダイアログをかます必要がありそうです。
でもそうするとしても、任意の色を作成するには結局コモンダイアログを呼ぶことになるのですが、ダイアログだらけになってしまうのが煩わしい感じがしないでもありません。
次にチェックボックスですが。これはいかにもクリックで値が変わってくれそうな雰囲気をかもしだしているので、ダブルクリックで値を変える仕様にすると違和感があります。True/False での表示のほうがいいのかな。でもチェックボックスのほうが見た目にははるかにわかりやすい感じがします。困った。
装飾は。。。これは 4 つの選択肢があります。ダブルクリックでサイクリックにする?
正規表現の '|' の動作がおかしいのを修正。
ビューを最初に表示したとき一部しか表示されないのを修正。
プレビューがあるといいな。
「適用」ボタンの代わりに「テスト」ボタンにして、実際のビューに反映させられるようにしてみようかな(適用と違うのは、「キャンセル」ボタンを押すと反映されたものが元に戻る)。

半分ほど適当に作ってみましたが、字句解析器で色の設定とスタイルの設定が分かれているのが微妙かも。
これはつまり、
lex.DefaultColor(0) = '@foobar';
と
lex.Add('', '/[0-9]+/', 'exstyle:barbaz');
と色、あるいはスタイルを指定する個所が 2 つあることに対応しているのですが。前者も、色ではなくスタイルを指定するようにすればいいのかな。
ということで、そうしてみました。従来の Lex.DefaultColor() と Lex.DefaultBackgroundColor() は obsolete ということで。とりあえず残しておきますが、何もしないようになっています。
で、そのかわり、Lex.DefaultStyle() というのが増えてて、
lex.DefaultStyle('1..4') = 'exstyle:コメント背景';
とか
lex.DefaultStyle(0) = 'color:blue; decoration:underline';
とかになります。
次に、色設定がどういうインターフェースだと使いやすいかということなのですが。
わりと色設定でありがちなのは、個々の項目に対してボタンが並べてあって(ボタンの表面が選択した色で塗りつぶされていることも多い)、それを押すと色選択のコモンダイアログが開いて。。。という感じのもの。
あるいは、リストボックスに項目が並んでいて、適当に項目を選んで色選択ボタンを押すと、同様にコモンダイアログが。。。という感じのもの。
前者の場合、複数の項目に同じ色を設定するのがすごくめんどいです。その割に項目の数がやたらあったりして、なんか賽の河原で苦行をしているような気持ちになります。
後者の場合であっても、複数の項目の選択・設定を許しているエディタはそれほど多くないように思えます。こちらはこちらで、じゃあリストボックスを使っている意味って? となってしまう。
なかなかむずかしい。
字句解析器のテーマに対する設定の場合、bold とか italic とかのスタイルの設定も行える必要があるのですが。他のエディタをみてみると、リストボックスに表示された項目を選ぶと、リストボックスの隣に置いてあるチェックボックスが項目の状態に応じて変更されるというのが多いと思います。
これもまた、わかりにくいような。項目を選ばない限りその状態を知ることができないです。またしても、リストボックスを使って一覧させている意味って? となります。
どうせ一覧で表示するなら、スタイルも一緒に表示してしまえばよさそうです。
GUI。色設定の GUI に必要なものは、
の 2 つです。
というか、まずこの GUI を新しいダイアログとするか、環境設定画面のページの 1 つとするかというところから考えてみます。
まあどっちでもいいんですけども。たとえばツールバーの設定をするダイアログは独立しているわけですが、なぜ独立しているかというとツールバーのダブルクリックで呼び出せる以外に、環境設定画面で toolbar プロパティをいじるときからも呼び出せるからです。
toolbar プロパティは、環境設定画面ではエディットコントロールを通していじることしかできませんが、「...」ボタンを押すことで専用の GUI がでてくる。つまりいじるものは同じで、いじり方に差異がある場合に別の GUI にしています。マクロの管理も同様。
これがもし、環境設定画面の左のツリーからたどれる別ページにツールバー設定とかがあったりすると、遷移上のつじつまが合わないどころか、ユーザから見てツールバーをいじる個所というのが複数あるように見えるのでとてもあいまいで、気持ちが悪いです。
というのを踏まえて、色の設定はどうなるべきなのかというと。。。color-theme プロパティというのはクラスドメインのテーマとしてどの ini ファイルを参照するか、というものなので、つまり上記の要件 1 に関連しているわけですが。でもイコールじゃないんですよね。。。color-theme はいわば、ポインタに何を指させるかであって、ポインタが指す中身をいじるわけではない。
ということで、独立したダイアログの GUI として作る(とりあえず、環境設定画面からの遷移もしない)というのが妥当な気のせいがしてきました。
字句解析器に設定した色の情報が実際に表示されるまでの流れ。
まず字句解析器にテーマを関連付けます。とりあえず [萌ディタをインストールしたディレクトリ]\theme\lex\ + 字句解析器名 + '.ini' というファイルがあればそれを参照、ない場合はデフォルトのテーマを参照します。
次に、字句解析器に対してデフォルトの色を設定したり、ルールを設定したりします。
lex.DefaultColor = '@foo';
lex.Add('', '1/bar/i', 'exstyle:baz');
まず 1 行めですが。字句解析器内のデフォルト色テーブルは、テーマの表裏で 2 セット持つようになったわけです。'@' 付きの指定をした場合は、それぞれの定義を ini ファイルの [light-bg-palette]、[dark-bg-palette] セクションから読み込みます。従来はこのテーマカラーというものは、すでに決まっている名前しか使えなかったのですが、ini ファイルごとに好きな名前をつけて構いません。GUI を作ったらこの名前が出てくるのでわかりやすく日本語でも構いません。
逆に、従来のテーマカラーを使っているスクリプトは、ini ファイルに定義していない限り不当な色とみなされてしまいます(エラーになるわけではない)。
2 行めは、'exstyle' というキーワードで ini ファイルに指定したスタイルを指定しています。こちらは [light-bg-style]、[dark-bg-style] セクションから読み込みます。
[light-bg-style] baz=color:#000000; decoration:underline [dark-bg-style] baz=color:#ffffff; decoration:underline
のような感じです(なんか毎日書いてる気が)。そいで、表示の際プロパティ theme-side を参照して、どちらかの定義を適宜使用するわけです。同じテーマでも外部スタイルに定義できるのは、color、background-color、decoration、font の見た目に関わるスタイル指定子だけです。
というわけで、だいたいできてきた。
GUI がめどー。
といいつついろいろいじったので、とりあえずあげときます。
わりと重要な変更をしてたりします。
従来、オートメーションオブジェクトの CLSID やら TypeLib やらをレジストリに登録していました。これは萌ディタをオートメーションのアウトプロセスサーバにしてみようかなということなのですが。
あまり役に立ちそうな使い方が思いつかないので、それはやめました。オートメーションオブジェクトはすべて内部だけの生成・使用にしたので、つまりレジストリにはまったく触らないようになりました。
たぶん。
ファイル名を表示するところ(C:\〜 [html, eucjp, lf] とかのあれ)上のコンテキストメニューを、すべてタブのそれに移動しました。
環境設定画面でのプロパティの表示順を、種別でソートするようにしました。プロパティの名称を生のままにするか、日本語で表示するかを ini ファイルに保存するようにしました。
バッファの内容が変わったことによる再描画で、スクロールしなかった場合の最適化をしてみました。なのでそのへんにバグが入っているかも。
ということです。テーマ周りをいじるのはさらに大きな変更(拡張子クラスの定義スクリプトも変更する必要が出てくるかも)になります。
実際にどうなるかというと、まず字句解析器に属するテーマに対する ini ファイルが
[palette] foo=#ffffff bar=#000000 : : [light-bg-style] string-literal=color:olive; : : [dark-bg-style] string-literal=color:yellow; : :
な感じで、従来スクリプトで定義していたスタイルを ini ファイルに追い出します。字句解析器に定義する背景色・前景色のために palette セクションもあります。それから、スクリプトで字句解析器を定義するところのうち、スタイルの指定に関わるところが、ini ファイルのエントリを参照するような表記に変わる(transit や state はそのまま)。
lex.DefaultColor(0) = '@foo'; lex.Add( 'literal', '1/L?"([^"]|\\\\")*"/', 'style:string-literal');
というような感じ。と思ってソースをいじろうとしたらテーマやパレット周りをどう組んだかまったく覚えていないわけですよ。
まとめると、
というような感じです。あと、いいかげんカラーテーマを編集する GUI が欲しいところ。
で、これで何がよくなるかというと色の再定義が楽になるわけです。
悪くなるところは、すべての拡張子クラスを通して、明るい背景か暗い背景かのどっちかで統一されてしまうこと。
壁紙の表示をαブレンドだけにすればもうちょっとシンプルになるんだけどなあ。GDI の AlphaBlend() は微妙に遅いのです。CPU だけでごりごりやってるのかな。
なんかとつぜん ADSL 回線が繋がらなくなってしまったとか。
とりあえず G.dmt 固定にしたら安定したけどすごく遅くなってしまったよ。。。
とかやってたら雷で瞬電したり停電したり。
もう、今日は、寝る。
色とか。
萌ディタでの色の指定というのは、背景色・前景色を始めとして、だいたいの要素に設定できます。これは全然ふつうです。
次に、カラーテーマという仕組みがあって、色の指定を即値ではなく ini ファイルの定義を間接的に参照するような特別な値で指定をすることもできる。そうすると参照する ini ファイルにより、テーマに沿った色合いを動的に選択できるわけです。カラーテーマはプロパティで指定するので、クラスごとに異なるテーマを割り当てられます。
これは、これで、いいのですが。
字句解析器のルールとして指定する色についてつじつまの合わない部分がある。
といった問題があると思います。
1 は、例えば
lex.Add('state1', '1/<\\/?/', 'color:@altforeground1; state:2');
などというルール。このルールはタグの開始記号 < に対するものですが、色をテーマカラーである @altforeground1 に割り当てている。このとき、カラーテーマ側ではなにに対する色か、という情報は省略されて総称的な色名になってしまうので、カラーテーマの ini ファイルを覗いたときどれを変えたら色分けのどの要素が影響を受けるのかがまったく解らない。
2 はそのままの意味です。
ということで、つじつまを合わせる必要がある。
なぜこうなるのかというと、まずカラーテーマというものが拡張子クラスが持つ情報なのに対し、色分けに使用する字句解析器は拡張子クラスが保持しているわけではないためだと思います。それを統合しているので無理が出てくるのではないか。
字句解析器ごとにテーマを参照するようにすればいいのかな。つまり、行番号の色とか、ガイドの色とかを定義するクラスドメインのカラーテーマと、色分けだけの定義を行う字句解析器ドメインのテーマ。。。という感じに。
ただそうすると、標準でデフォルトのテーマと「黒背景」のテーマというものを付けているわけですが。。。こんな感じでテーマを階層化すると、切り替えるのがめんどうそうです。
テーマの色の選択というのは当然、背景色に対して見やすいものというのが大前提の条件になると思いますが、特に背景に壁紙を表示している場合、壁紙(あるいはフィルタ)を切り替えることでその大前提となるものを簡単に変えられてしまう。
例えば明るめの壁紙から暗めのものに切り替えた場合、現状なら「黒背景」のテーマを選択するだけで済むのが、字句解析器ごとの定義をすべて更新しなければいけません。これは面倒にもほどがあるので、何か連動する仕組みがあればよいのかも。
いっそのこと、1 つのカラーテーマ内に明るい背景向けのもの、暗い背景向けのもの。。。と 2 種類定義するようにしようかな。表テーマと裏テーマみたいな感じで。
とりあえずそんな風にしてみようと思います。
たぶん読んでもまったく面白くありません。
ええと、もうひとつの解りにくさに、拡張子クラス間の継承関係があると思います。自分で作っておいてなんですが、解りにくい。。。というか GUI との相性があまりよくない。この継承関係というのは 2 つあって、
前者は、実際に使う上でそれほど問題にはならないかもしれないですが(スクリプトをいじり始める段階になるまではユーザが意識することはないでしょうから)。後者、例えば linenumber-width というプロパティがあって、これは行番号領域の幅を保持しているのですが。で、ルーラ上のマーカーをドラッグした場合にこのプロパティを更新するのですが、標準のスクリプトではクラスローカルにしていないのでテキストファイルだろうがソースファイルだろうが変更の影響を受けます(プロパティの実体を定義している拡張子クラスについて、変更が行われるため)。
これをユーザが「なんで XX のソースだけ変更できるようにならねーんだボユゲ」と思ったとき。。。
のどれかの手順を踏めば、解決するわけですが。
はたしてこの作業を、ついさっき萌ディタを落としてきたばかりのユーザが行えるかどうか。きっと無理でしょう。少なくとも「プロパティの値がクラス間で継承される」「継承を切って独自の値を与えることができる」という知識が必要です。
とまあ根幹の部分に複雑さを抱えているわけです。ドキュメントを整備するとかの方法でこの問題をフォローしたことになるのか、あるいはプロパティの継承という仕様自体を変えるべきなのか。
仮に継承というものをなくしてしまうと、それぞれの拡張子クラスの初期化時にだらだらとプロパティに値を入れるコードを書くことになってしまうし、新しいプロパティを付け足したらすべてのスクリプトを更新しなくてはいけません。つまりプロパティの継承という仕様はスクリプトで環境設定を行うという仕様と深く関係しているということです。
設定をスクリプトで行うプログラムというのは、どこか unix の香りがするというか、どうしてもユーザにある程度の知識を要求することになるので、それを単純に GUI に持ってくるととでどうしても逃れられない不自然さがつくことになるようです。
といいつつ、変更するとあまりに影響が及びすぎるので、若干の懸念を残しつつ、このまま。
いい機会なので、復習を兼ねて萌ディタというエディタを俯瞰してみます。
世の中にはテキストエディタというのはシンプルなものから超高機能なものまで様々なものがあるわけですが、萌ディタの立ち位置というのは以前マイナーテキストエディタ愛好会に書いたとおり:
691 名前:名無しさん@お腹いっぱい。 :03/12/22 01:36 ID:Ak6I121n sage ちなみに653はこれまでどんなエディタ使ってきたの? ○○を使っていたが、××なところがどうしても不満で自分で作るとか、 別プラットフォームの○○というエディタが好きでWinでパクりたいとか、 結局何っぽいエディタ作ってるの? 694 名前:653 :03/12/22 02:15 ID:rtKOuSFK sage >>691 常用してるのはWZ、サクラ、メモ帳くらいです。そのほかにも いろいろつまみ食いしてみましたが、 ・機能盛りだくさんなエディタを使いこなせない ずらーっと並ぶメニューとか、目的の設定項目まで何重も ダイアログをとおらなければならないエディタは、自分には つかいこなせない。。。 ・かといって、シンプルさを売りにしているエディタは本当に シンプルなので、物足りない というふうに感じました。 で、これらの中間〜シンプル系寄りに位置するような、基本的には シンプル指向なんですけど、そこから頭一つ出た程度の機能(スクリプト による拡張性であるとか、Unicode への対応であるとかあるとか)を もったエディタが欲しいなあということで、まあ探せばあるのかも しれませんが、とりあえず作っているわけです。
ということで、それは今でも変わってないです。なので、萌ディタを紹介していただいているサイトで「高機能な〜」とか、「拡張性高い〜」といった枕詞がつくのは、個人的には持ち上げられすぎという感じです。
上記のような枕詞は、
という仕様にかかっているのだと思います(あるいは編集の履歴とか、色分けあたり?)。キーバインドを再割り当てできるエディタの多くは 1 つのキー入力に対して 1 つの機能、という感じが多いと思うのですが、この部分がプログラマブルになっているのは確かに自由度は高いです。が、極端に言うと javascript 側でやることは萌ディタが提供する機能のどれを呼ぶか、ということでしかなくて、機能の質・量は結局萌ディタ側に依存するので、一概に高機能とも言えない。
もちろんテキストの編集を考えたときに明らかに有用な機能は逐次追加していくことになるのですが、例えば javascript 側でなんとかしてアウトラインのツリーコントロールを出す、といった大技はいまのところできないわけです。萌ディタ側でアウトライン専用の、あるいはもっと低レベルな、コントロールを生成して操作する汎用的なインターフェースを用意するかしないとならない。
そういった複雑な機能というのは、当然大前提であるシンプルなエディタというスタンスに反するので実装するのは相当に慎重になります。このへんのバランス取りがむずかしいのが課題の 1 つです。
それから、「設定するのが複雑すぎ」という評価も受けるのですが。。。これはまったくそのとおりで、要するに javascript が絡むところ:
あたりが複雑とみなされるのだと思います。
でもコアとなる仕様が javascript に強く依存している以上、「設定の仕方解りません」という要件には「解らない? 解れ」としか言えないんですよね。。。まあまとまったドキュメントがないというのもあるんですが。
個別に見ていくと、1 と 2 はいまのところ、これ以上簡単にはしにくい。3 もアレはああいうものなので、「よし! がんばれ!」としか言いようがないです。
5 は、メニューの定義を GUI で行えるようにすれば割と扱いやすくなると思うんですけども。いずれにせよ最終的には javascript のコードに落とすことになるので、それをどうするか。
メニュー定義専用のスクリプトファイルみたいなのを設けて、GUI で設定したらそのファイルに対して有無を言わさず上書き、みたいな感じにすればいいのかな。。。でも、スクリプトを直接メニューアイテムに引っ掛けるようなパターンは GUI でやるよりコードを直接編集したほうが楽そうです。というか、メニューはそうそういじるわけでもないし、メニュー設定のコードは別に複雑なわけでもないし、GUI 化したとして使うかな。。。ちょっと微妙。
4 は、明日。
久しぶりにソースを見てみたら、すっかり忘れてるような覚えてるような。
ぽけーとソースを流し読みしてたら地震がきてしっこ漏れそうになった。
とりあえずいろいろ修正。nightly build
えーと何を作ってたんだっけ。。。
ああ、段落の字下げでした。そうそう。
それはそれとして、色の指定がものすごくやりにくいのでこの辺の仕組みをちょっと考え直そうかな。。。
あと、バックアップ先のパス指定で環境変数を展開したいのですが、萌ディタ側で認識する %f、%b、%e といったマクロとかち合ってしまうので、これを例えば $ で始めるようにするかもしれません。