/ 最近 .rdf 追記 設定 本棚

脳log[SakuraEditor: 2010-06-20~]



2010年06月20日 (日) ASR @ COM Meets Rubyがアップデートされてる。

最終更新: 2016-11-30T10:20+0900

[SakuraEditor] 行削除って便利。

標準では Ctrl+Shift+E。俺は Ctrl+Deleteに割り当てた。

で、使ってるとスクロール位置がずれるのが気になってくる。深いディレクトリで GREPすると表示される結果の大部分が定型のパスだけになるから、違いを見分けるためにはパス末尾のファイル名とマッチした行が見えるように右にスクロールする必要がある。そして、目当てのものではない行を Ctrl+Deleteで削除していくんだが、行削除後にキャレットの行頭からの桁位置は保たれてるんだけどスクロール位置がずれる。画面の真ん中にいたと思ったマリオが次の瞬間背景とともに右端に移動していたようなもんだ。これがうっとうしい。

削除前に一瞬、行全体が選択されるように見えるので、このときにスクロール位置が変わってしまうのかと思って「行選択->選択範囲削除」の流れを変えて、範囲選択に依存しない削除方法を採用したのがこれ>improve_delete_line.patch(5.2KiB)

実際は削除に使っている ReplaceData_CEditView()というコマンドがキャレットの位置調整を行っていたのが原因だったから、削除方法は選択範囲の削除のままでもよかったかも。ともあれ、行全体を選択する操作がちらつくのとスクロール位置がずれるのがなくなった。(ReplaceData_CEditView()がやっているように再描画の必要な範囲を求めたりせずビュー全体を再描画してるから環境によっては画面全体がちらつく可能性がなきにしもあらず。「画面キャッシュを使う」とか DWMがなんとかしてくれることに期待。どうせ 1画面50行のうち削除された行より下は元からすべて再描画対象だしー)


 @2010-06-21 タブやタイトルバーに変更フラグが表示されるように修正した(rev1.1)。

improve_delete_line.rev1_1.patch(5.5KiB)

フラグ自体は立ってたけど描画が行われていなかったというミス。


2010年06月10日 (木) iPadがインターネットごしに DLNAクライアントになれたら迷わず買う。(これって買わない宣言?) 読書端末の本命 Sony Readerの年内発売を待っている。

最終更新: 2012-10-27T00:23+0900

[SakuraEditor] サクラエディタの正規表現キーワードを SHJS相当にしたい。(その二)

その一(20090808p03)がだらだら長くなったのでいったん切って、ここに続ける。

 @2010-06-10 バグ発見。

ひどい。「/*」を入力して後ろの行がコメント色一色になったとする。つづけて「*/」を入力しても後ろの行がコメント色のまま。たぶんこれが関係する。

行をまたぐ色分けに問題があって、たとえば一画面に収まらない長大な複数行文字列があったとして、何度も上下にスクロールしたり改行を入力したりするだけで色分けが変わってしまっていた

本当にそうなら、泥縄式バグ潰し無間地獄へ突入ですな。消火行為が点火に直結した効率のいいマッチポンプだもん。


まさしく > たぶんこれが関係する。

そのときの変更にこんなコメントが添えられているのを発見した。「IsInsideKeyword()から呼ばれたときは精算したらダメっぽいのでコメントアウトして様子を見る。」様子見の結果はダメでした。さあ、どうしよう。


別の場所で不必要にキャッシュを無効化している部分を厳密に処理したら直ったっぽい。キャッシュの有無で結果が変わるはずないんだけど……。(さらなる追求が必要。でもそれは問題が見つかってからにする)


 @2010-06-13「キャッシュの有無で結果が変わるはずないんだけど……」

変わりうる。一行の色分けは一時(いちどき)に、他の行の色分けを挟んだりせずに終わらせなければいけない。正規表現キーワードは各行の行頭がどういう状態か(コメントの中か?とか)を覚えているキャッシュの他に、ある行を中間まで処理したマッチング結果を持っており、先ほどはこれをキャッシュと呼んでいた。そいつは、次の IsStartOfKeyword()呼び出しを待っている宙ぶらりんな状態。期待していた呼び出しがくる前にクリアされたら結果がおかしくなる。マッチングを中間で止めざるをえないのは、他の色分けに先食いされた文字をマッチに利用してしまわないように。


2010年06月09日 (水) メインメニューを整理しているときに「移動履歴: 次へ」「移動履歴: 前へ」を見つけた。これまで、戻ってきたい場所へはブックマークをセットしていたが、ちょっと行って戻るだけなら移動履歴の方が解除の手間がないぶんいい。Alt+←(戻る)と Alt+→(進む)は「(矩形選択)カーソル左移動」などに使われていたので Ctrl+Shift+Zと Ctrl+Shift+Yに割り当てた。

最終更新: 2011-01-02T16:45+0900

[SakuraEditor] サクラエディタ。温故知新。

SAKURA Development BBS (ANSI)のログが 10ページ分しか閲覧できなくて、残念な思いをしていた。検索対象のリストに古い年月が存在していたり個別リンクが機能していたりするんだから、古いログが保存されているのは間違いないんだけど。Cyclamen(掲示板CGI)に関して言えば、記法のヘルプを見つけることもソースを見て記法を確認することもできない。ま、それはおいといて、

過去ログを見つけた。>http://groups.yahoo.co.jp/group/sakura-editor/files/User/bbs-log/

Subversionが最初からあった世代には考えられない開発スタイルがそこに!差分や変更したファイルを共有エリアに置いて掲示板で報告。大きな変更をした人が他の人の小さな変更をマージして最新版を管理したり。ともあれ、お宝ざくざくなので日曜日から喜々として読み進めている次第。(ログが 2007年9月で切れてるのが残念)

S:27,*,01/02/11,10:49,,
T:横スクロール時の動作
N:げんた
M:
現在のこのエディタはWM_HSCROLLが来たら横スクロール量を決定して画面全体を書き直す動作を行います。もし、画面全体を書き直す代わりに新規部分のみを書き直せば高速化すると思われるかも知れませんがそうはいきません。

なぜなら、このエディタは色分け情報をメモリ上に保持していないため、描画の都度行の先頭から調べて色を決定しているからです。その際キーワードの検索も行います。たぶん、これがかなりの処理を必要としているのだと思います。

横スクロール速度を劇的に改善しようと思ったら色分けを予め行ってその情報をメモリに保持するようにしないと難しいのではないでしょうか。

gdippを使っていると無視できないほどに強調されるので横スクロールが遅いことには気付いていた。これが書かれた当時のサクラエディタ(という名前ではまだないが)の遅さは今の PCスペックでは再現できないかもしれないけど、根は昔から存在していたよう。

S:114,*,01/03/02, 2:32,,
T:コントロールプロセスの起動方法
N:げんた
E:genta@i.am
M:
外部エディタを監視するプログラムからテキストエディタを使うとき、エディタが常駐していないと起動したプロセスは管理プロセスとなってエディタ画面は別プロセスで動作するため、編集終了の検出が正しく行えない場合があります。

自分が管理プロセスになるのではなく管理プロセスを別に起動して起動完了まで待機するような作りにできればこの問題が解決できるなぁと思いました。

タブモード(実装者は別の人)であっても 1ドキュメント 1プロセスだから Subversionのコミットメッセージをサクラエディタで編集できるんだけど、そもそもこういうことが考慮されていたからこそできるのだと確認。

S:1446,1440,02/02/01,22:27,,
T:Re2:正規表現置換の振舞い
N:げんた
M:
>..*\n$ でやってみたら削除できましたけど…???
よく見たら自分で何気なく変えたところだった.
本当に申し訳ない.
今は普通に動いています.

ただ,BREGEXPのせいなのか,^.*$ には先頭から改行コード \r\n の\rの部分までがヒットして\nが残ります.
^.*\n$ だと行全体にヒット.

「改行(.と$の動作に影響する)」= LF(0x0A)の指摘がこのとき既に。セルフリンク>20090922p01

S:1475,1474,02/02/05, 0:47,,
T:Re4: タイプ別設定に外部ヘルプと外部HTMLヘルプ新設パッチ
N:げんた
M:
ちょっと考え直してみました.

▼初期の私のアイディア
・CShareDataの役割=単にDLL Sharedを得るためのクラス.

・タイプ別設定を共有メモリから追い出す.
そのために,タイプ別設定のアクセスをCEditDoc::GetDocumentAttributeに集約.
追い出した後の実装はCEditDoc,またはCEditDocに含まれる新規クラスで行うつもりだった.

共有メモリからタイプ別設定を追い出したい理由は以下の通り.
* タイプ別設定が足りなくなり,既に2回最大値を拡張している.
* タイプ別設定の領域を予め共有メモリに確保しなくてはならないので,上限の撤廃ができない.
* 初回起動時に使うかわからない領域全てを初期化するのは無駄ではないか.

追い出しのアイディア
* タイプ別設定はそれぞれ外部ファイルに用意する.
* 設定ファイルは必要に応じて読み込まれる.
* 変更は現状通りダイアログボックスで行う.
* 変更されたらすぐにファイルに保存し,設定変更Broadcastメッセージを投げる.
* Broadcastを受け取ったら該当タイプを使用しているか確認.
* 使用していたらファイルから再読込し,設定を更新する.

>各種設定が共通設定だろうが、タイプ別設定だろうが、気にせずとりあえずCSettingMediatorに問い合わせたり、設定を依頼するだけでよくなったら便利だなぁと思っています。
なるほど.これは良いと思います.最終的には設定情報がどこに格納されているのかも意識する必要が無くなるので,これは私のアイディアと矛盾しません.CEditDoc::GetDocumentAttributeで取得するのをDLLSHAREからCSettingMediator経由に変更すればタイプ別設定のカプセル化の場所が移動します.

私の初期アイディアと組み合わせると,追い出した後の実装というのをCSettingMediatorに依頼することになるでしょう.タイプ一覧の設定,指定タイプの取得,更新などファイルへの書き出し・読み込みタイミングもCSettingMediatorが管理すれば良いような気がします.

上記内容を納得した上で私が確認した限りでは特に問題はないように思います.

---
実装に入る前に設計に対する議論を行うことは有意義だと思います.これまでは議論する相手がいなかったので...(;_;)

タイプ別設定を共有メモリから追い出すアイディアが既に出ていた。

設定の場所を隠蔽するクラスも構想されている。それのメリットとして自分が考えているのは、

  1. 実行ファイルに埋め込まれたデフォルトのタイプ別設定
  2. 基本設定
  3. 拡張子に応じたタイプ別設定

の 3を、2との差分とすることで基本的な設定の共通化(基本設定による)を図りつつ、設定の読み出しを一本化できること。

S:1606,*,02/02/16, 2:26,,
T:ssrc_2002-02-11_p1
N:hor
M:
ssrc_2002-02-11 からの変更箇所です。ご参考まで。
(省略)
□その他のその他
    ・[Ctrl+Home]or[Ctrl+End]後に[Down]or[Up]したときの挙動を見直し・・・以下変更個所
       1.矩形選択中に[Ctrl+Home]or[Ctrl+End]して[Down]or[Up]したとき以外は普通にカーソル移動
       2.選択を解除したあとは普通にカーソル移動
(省略)

ファイルの先頭へ移動するコマンド(Ctrl+Home)が「通常は、(0, 0)へ移動。ボックス選択中は、(GetCaret().GetCaretLayoutPos().GetX2(), 0)へ移動」というコメント付きで故意におかしな動作をするのはこのへんが理由だったのか。(細かいことを言うと、このときの実装は Ctrl+Homeで 0行0桁に移動した後、↓で 1行(Ctrl+Home前の)X桁に移動する、というもので、いまの実装はすこし後にでてくる)。ファイルの先頭に移動という一つの名前に異なる機能を実装するのはやめて欲しい。利用者視点の「使える」動作なんだろうけど、自分なら Alt+Ctrl+Homeを「(矩形選択)ファイルの先頭に移動(※未実装)」に割り当てるなどして対処する。

S:1759,*,02/03/23,11:01,,
T:バックアップごみ箱問題
N:みく
M:
ネットワークドライブまたはリムーバブルドライブのファイルを
ごみ箱に放り込むとOSの仕様により消滅してしまいます。
バックアップしたつもりがされてないという現象を避けるため、
これらのドライブの場合はごみ箱に放り込まないようにしました。

次回版にでも取り込んでください。


どうしてもごみ箱に放り込みたい場合は、
「指定のフォルダに作成する」でフォルダにローカルドライブのフォルダを
指定し、さらに「バックアップをごみ箱に放り込む」を指定してください。
(指定のフォルダにごみ箱を直接指定することはできません)

最近見かけたリムーバブルメディア上のファイルのバックアップをゴミ箱に放り込めない問題が 2002年に指摘されている。

自分はバックアップは Ctrl+Sに割り当てた JScriptマクロで Subversionに保存してる。差分バックアップでありながら過去の版を ViewVCで簡単に見られるのが利点。マクロでやってることのエッセンスは以下の通り。

>Editor.FileSave();
>svn up "working copy"
>copy /Y /B "filepath" "working copy/filename" );
>svn add "working copy/filename"
>svn commit "working copy/filename" -m "filepath" --force-log --non-interactive'

たかだかテキストファイルなので動画より小さく、ワーキングコピーもリポジトリも数百MiBにおさまってる。NTFSの圧縮属性を付けたらさらに三分の一にもなるし。

S:1980,*,02/04/30, 1:41,,
T:半角スペース表示
N:KK
M:
KKです。
一般掲示板の方で要望のあった
「半角スペースの表示を追加する」
パッチを書いてみました。04-27版へのパッチです。
DispSpc04-27.zip
(省略)
S:1982,1980,02/04/30, 2:12,,
T:Re:半角スペース表示
N:げんた
M:
小文字のoの下半分だけを使うという発想が何とも独創的 (^^)

いまの Unicode版も同じ実装。気付かなかった (^^) ちなみに、デフォルトの色は灰色だけど、これをテキストと同じ色にすると周りと同じ色で描画されます(コメント中の空白とかが)。

空白記号類は特に明示指定した部分以外はなるべく周辺の指定に合わせるようにしてみた // 2009.05.30 ryoji

ソースを見てないと気づかなかった。

S:2237,*,02/07/03,12:22,,
T:クラス、インターフェイスの整理
N:ボロぞうきん
M:
(省略)
1&2 1行の文字数が3万文字を超えてくると極端に遅くなるので、
行バッファを簡易gapped buffer方式に変更したかったけど、
内部のポインタを書き換え目的に使っている場所があり、
単純にconst化出来なかった。
(省略)

でました。gapped buffer

S:2278,*,02/08/23,20:29,,
T:正規表現ライブラリ
N:みく
M:
比較的新しそうな正規表現ライブラリとして、
こんなのもあるみたいです。

http://www.fides.dti.ne.jp/~oka-t/libraries.html
S:2959,*,03/07/21, 3:35,,
T:正規表現ライブラリの不具合
N:げんた
M:
http://www.fides.dti.ne.jp/~oka-t/history-2001.html
でPerlの正規表現の不具合について触れられていた.

試してみると確かに
::1234::5678901234567890::::1234567890::
888:
に対して
^([0-9]+|::)*$
で検索するとフリーズする.(よい子は真似をしないでください)

Perl 5.8ではフリーズしなかった.

リンク先が同じ。なんちゃってではなく真っ当な雰囲気がするなあ、と思いながらそのサイトをうろうろしていたら、未訪問のはずのリンクが何カ所も閲覧済みの色になっていることに気付いた。良いものは埋もれてしまわないのだ(忘れられるのは読み手(俺)の問題)。

S:2562,2559,03/02/11, 1:19,,
T:Re: マルチユーザモード(案)
N:もか
M:
▼ みくさん
>実行ファイル名を sakuram.exe とかに改名するとマルチユーザモードになり、
実行ファイル名を 任意の文字列1.exe などにすると文字コードがその数字の文字コード(この場合EUC-JPに)固定されるという機能があるから
(省略)

なんぞそれ>「実行ファイル名を 任意の文字列1.exe などにすると」

S:3140,*,03/09/15,11:53,,
T:色分けHTML出力
N:wmlhq
M:
強調キーワードなどを使って色分けしたソースコードをsakuraでもHTML/XMLで出力できたら、便利だろうな。「形式を指定してコピー(special copy)」で実装するとか。

<font size=10><pre>//<nobr>comment</nobr>
<font color="#576447">int</font> func();
</pre></font>

これは面白そう。もちろんフォーマットは

<style>
/*<![CDATA[*/
  .comment { color: green; background-color: white; font-style: oblique; }
/*]]>*/
</style>
<span class="comment">//コメント</span>

にするけど。HTML直打ちに近いブログに投稿する以外に、正規表現キーワードによる色分けのデバッグにも使える。(思い通りの結果にならないときに、見た目では判断できない違いが classによって区別できる)

それにしてもこの wmlhq(自称)という人は……。掲示板の閲覧者はする~かが試されている(笑) 関わりたくはないけど知識とエネルギーは無視できないものがある。うまく操縦できる人がいればいいのかな。上から目線で仕切屋でイラッとする年寄り言葉を使ったりでこの人に指導される新人に同情するものの、悔しいかな、メッセージの国際化の手段に STRINGTABLE, MESSAGETABLE, gettextの三つを挙げたり、入力補完の高速化に bsearch, ハッシュ, dartsの三つを挙げたり、できないもんねえ。ちょっと前に WEB+DB PRESSで dartsっぽいのは見かけてたけども、わからなくて検索したし。

S:3300,3299,03/11/07,21:31,,
T:BREGEXP.DLL
N:かろと
E:karoto@infoseek.jp
M:
▼ もかさん
> Perl Artistic License
> "Freely Available" 内の  2.「バグ修正」か「移植」のための修正
> に該当しそうですが、どうでしょうか?

オリジナルのPerlの関数には、行頭から文字列を渡せるようになっていて、
BMatchEx()で、その引数にも値を渡せるようにしただけなので、
変更そのものは簡単なことで、「移植」なんて言うのもおこがましい程度です。


> 微妙に気になるのは、V1.0(VB未対応)で、Exportしてる関数が少ないのと、for SAKURA になってる... 

V1.0とV1.1の違いって、VB対応だったんですね・・知りませんでした。
Linux版のソースをもってきた関係上、VB対応部分は入ってませんでした。
というわけで、ExportしているVB用関数もありません。
Linuxソースなので、リソース関連のファイルは同梱されてなかったので、適当に作り、
本家のBREGEXPと異なることがわかりやすいように、「for SAKURA」ってのを入れました。(笑)
まずいでしょうか?

> #いい感じだと欲が出てくるもので、
> #ついでに改行コード周りもDLL側でやってくれないかなぁ(実はやってる?)

実は、同じ事を考えて、内部の以前Perlの関数眺めたのですが、改行は1文字(\n)だと
決めて処理している箇所があり、難しそうだなぁと思いました。

> #UTF-16にも対応してくれないかなぁ

ははは・・・さすがに対応済みのDLLを持ってきた方が早いかと・・

「改行は1文字(\n)」が「改行は1文字(\rの後ろではない\n, \r)」になるだけでも十分ではないのかなあ。

  • lf_and_cr_as_eol.rev2.patch(2.4KiB)
  • sakura(r1764_without_bregexp_trick).zip(497KiB, dllの違いをテストするために、検索パターンの置き換えトリックを行わないように変更したもの)
  • $が行文字列末尾にもマッチする関係ですべて置換が置換しすぎる(上の zipファイル内の sakrua.exeに限った話)。BREGEXPは正しい処理をしているので、sakura.exeでの対処はやはり必要になる。($ が行文字列末尾にマッチしたのは無視すべきだが、空パターン (?:) が改行文字の後ろにマッチしたのは無視すべきでない。果たして両者を区別できるのか?)
  • 調子に乗って hitEnd()に相当する機能を付けたら、複数行検索も

    1. 基本的に一行検索
    2. 改行文字の後ろまでマッチが続いていたり、hitEnd()が真ならバッファを確保して複数行検索モード

    みたいにしてできるかも。複数行検索モードの実装が面倒くさい上に BREGEXP for SAKURA限定機能なので C/Pは悪い。

  • BREGEXP for SAKURAのマッチ仕様変更はこんなんで検出できる。

    bool dot_matches_cr() // falseになっていることを確認する。テストは sフラグOFFで行われる。
    {
    	BREGEXP* rxp = NULL;
    	const char* const szCR = "\r";
    	char szErrorMsg[80] = "";
    	const bool retval = 0 < BMatch("/./", szCR, szCR + 1, &rxp, szErrorMsg);
    	if(rxp != NULL) {
    		BRegfree(rxp);
    	}
    	return retval;
    }
    bool dollar_matches_before_cr() // trueになっていることを確認する。テストは mフラグONで行われる。
    {
    	BREGEXP* rxp = NULL;
    	const char* const szCR = "\r";
    	char szErrorMsg[80] = "";
    	const bool retval = 0 < BMatch("/$/m", szCR, szCR + 1, &rxp, szErrorMsg) && rxp->startp[0] == szCR;
    	if(rxp != NULL) {
    		BRegfree(rxp);
    	}
    	return retval;
    }

正規表現に関連して、ログからこんな URLも見つけ出してきた。

「COOLなURLは変わらない」ということを、リンク切れを発見するたびに思い出す。この二つの URLはもちろん今も有効。

S:3521,*,04/04/03, 0:28,,
T:有効なカーソル位置の謎
N:もか
M:
あと、有効なカーソル位置ってどの範囲なのか、いまいちわかりません。
私が認識している動作は、フリーカーソルモードか、矩形選択中・終了後の位置としてEOFにまつわる位置だけに絞っても、
1. [EOF]だけの行(データの終端は改行)は行頭以外却下。
2. [EOF]だけのレイアウト行(データの終端は普通の文字)は行頭以外却下。
 不思議なのは、レイアウト折り返し時はインデントされないし、カーソル座標表示も変かも。。
3. 普通の文字の後ろについた[EOF]より後ろ(正確には右側かつウィンドウ折り返し線より左側)は有効。
で次の行(EOFマークの次の行だから存在していない行)は不正。

あと、矩形選択で、折り返し位置にカーソルを移動しようとしても、行頭に飛ばされてしまって、最後の1文字が選択できません。
ただし、EOFの表示のみ折り返される場合は、選択できてしまいます。
選択できるようにすると、今度は、論理座標との双方向変換の1対1対応が保証されなくなるので、たぶんこまります。

後半はこれ(20091026p01)関連。なんかもう、ほとんどの問題は既出だという気がしてきた。その都度解決できていれば出てこないはずなのに……。

S:3752,*,04/09/27,17:34,,
T:改行コードが食い違う
N:もか
M:
上書き保存したファイルとエディタが保持しているデータで、改行コードが異なることがあります。

1. 名前をつけて保存で、改行コードを変換する指定で保存
2. リロードされた後、入力改行コード指定により、1.で指定した改行コード以外を選択
3. 改行を入力
4. 上書き保存。このとき、2.で指定された改行コードで保存される
この時点でリロードされないので、保存したファイルと、エディタ上のデータで食い違いが発生します。

同様に、Shift_JIS以外では、ファイルとエディタ上のデータで、実際には異なる(=リロードするとデータが変わる)ことがありますが、
こちらは下手にリロードすると、保存時に文字化けした場合は修正するチャンスを失うことになります。
S:3753,3752,04/10/02,12:21,,
T:Re: 改行コードが食い違う
N:げんた
M:
現象を確認しました.
要するに名前を付けて保存で指定したコード指定がその後の上書き保存でも生きているのが問題というわけですよね.そもそも保存時のコード指定がメンバ変数としてずっと保持されているのが不思議な気がします.
でも改行コードなんか気にしないで,他の文書からコピーしたものを保存したときに常にコードが統一されて欲しいという人もいるかもしれない.かといって保存の都度reloadするのは無駄ですし.

・保存時のコード指定は保存しない
・毎回コードを指定して上書きしたい人はマクロで対応してもらう
というのでいいように思います.

これなんかも、すでに自分で遭遇してる現象なんだけど、ずっと前に確認されていたってわけだ。

他にも、「アウトライン解析のプラグイン化」という語がログのごく初期に登場していたり、正規表現ライブラリが最初は jre32.dllであって、BREGEXP.DLLへは GPL化を目指したときに移行した*のだとか、sakura_core.dll(なにそれ?)だとか、正規表現のパターン区切りとして //k が入力必須で面倒だったり、//k を自動付加するようにしてみたけどまだ \ にエスケープが必要だから @% などパターン中に使われていない文字をセパレータにしてみたらどうか、とか(いつ 0xFFに決まったんだろう?)、意外な発見(とどこかで見たような問題が)がざっくざく。

* BREGEXPの Bは BASP21の Bと同じ BABAの Bのはずで、BASP21は WSHから利用できるオートメーションオブジェクトとして、JScript(最初に出会った記念すべきコンピュータ言語)をいじり始めた当時から有名だった(「それ、BASP21でできるよ」)から、BREGEXP"以前"が存在するとは思ってもいなかった。

本日のツッコミ(全2件) ツッコミを入れる

FILEここにもありますよ。 http://sakura.qp.land.to/?OtherDoc%2FIncmLogsto..

ds14050おおっ、2008年4月まである。楽しみが増えました。情報ありがとうございます。


2010年01月29日 (金) コアレスケ に一致する日本語のページ 1 件中 1 - 1 件目 (0.05 秒)」 1件! 書いたのは俺だけど最初に検索したのは誰?

最終更新: 2011-01-12T18:23+0900

[SakuraEditor] SendMessage()はささります。

CShareData::IsPathOpened()が、起動している他のエディタプロセスに対して SendMessage()でメッセージを投げる。ファイルを重複してオープンする代わりにすでに開いているプロセスを前面に出すという処理で使われているのだが、一つでもビジーだったりハングアップしてるプロセスがあると SendMessage()が返らないので、せっかくプロセスが分かれているのに新しくファイルを開くことができない。

長々と色分けをしてるのがビジーの原因なんだけどね。

SendMessage()の怖さを語っていたのはたしか『[大型本] Raymond Chen【Windowsプログラミングの極意 歴史から学ぶ実践的Windowsプログラミング!】 アスキー』。対象が絞れてないのか玉石混淆という印象だけど、侮れない知識も埋もれている。任意のウィンドウを左右に並べる方法とか。あ、これはどうでもいい方の知識か。ダイアログプロシージャが戻り値を返す方法とかは……、いまどき Win32 SDKプログラミングもないか。古参ユーザーのためのあるあるネタがいっぱいです。


2009年11月26日 (木) 無性に DR-Z400Sに乗りたい。

最終更新: 2011-01-02T16:57+0900

[SakuraEditor] CViewCommander::Command_SEARCH_PREV()

	/* 現在位置より前の位置を検索する */
	bool found = false;
	CLogicRange matchLogicRange = CLogicRange( CLogicPoint( -1, -1 ), CLogicPoint( -1, -1 ) );
	CLayoutRange matchLayoutRange = CLayoutRange( CLayoutPoint( -1, -1 ), CLayoutPoint( -1, -1 ) );
	const SearchPos originalSearchPos = searchPos;
	if( pLayout ) {
		bool retried = false; ///< 末尾から再検索したかどうか。
		for(;;) {
			found = 0 != GetDocument()->m_cLayoutMgr.SearchWord(
				searchPos.y, searchPos.x, // 検索開始位置
				m_pCommanderView->m_szCurSrchKey,							// 検索条件
				SEARCH_BACKWARD,						// 0==前方検索 1==後方検索
				m_pCommanderView->m_sCurSearchOption,						// 検索オプション
				&matchLayoutRange,								// マッチレイアウト範囲
				&m_pCommanderView->m_CurRegexp							// 正規表現コンパイルデータ
			);
			if( retried ) {
				break;
			}
			if( ! found && GetDllShareData().m_Common.m_sSearch.m_bSearchAll ) {
				// From Here 2002.01.26 hor 見つからなかったので末尾から再検索する。
				searchPos.y = GetDocument()->m_cLayoutMgr.GetLineCount() - 1;
				searchPos.x = static_cast<Int>( MAXLINEKETAS ); // とにかく大きければよい。
				retried = true;
				continue;
			}
			if( found ) {
				this->GetDocument()->m_cLayoutMgr.LayoutToLogic( matchLayoutRange, &matchLogicRange );

				// 検索開始位置での幅0マッチはなかったことにして一つ前から探す。
				if( matchLayoutRange.GetFrom() == matchLayoutRange.GetTo()
				   && matchLayoutRange.GetFrom().GetY2() == originalSearchPos.y
				   && matchLogicRange.GetFrom().GetX2() == originalSearchPos.x
				  ) {
					searchPos.x -= 1;
					found = false;
					continue;
				}
			}
			break;
		}
	}

20090808p03の @2009-10-19に書いた*結果の一部が上のコード。@2009-10-20でちらりと書いた、現在の選択範囲が幅0かどうかで検索のその場足踏み対策を行っていたのは不十分だということがわかったので、対処するために CViewCommander::Command_SEARCH_NEXT()を同じように書き換えられたら楽だけど、テストがないからそれは(私家版でしか)できないんだよね。

gotoを使っていたり、bRedoや bFlag1という名前の変数があるコードをいじるのは嫌だなあ。(だからこそ Command_SEARCH_PREV()は全面書き直しになった)

まあ、bRedoはわからなくもない。いや、使われている部分を確認しないとわからないのだが、retriedだって他人にとっては似たり寄ったりかもしれないので許容しよう(ただし、スコープが狭まったことで使用部分の確認がしやすいのは明らかに前進している)。書き換えたっていうけど、ループだって単に飼い馴らされた gotoじゃないかと言われるかもしれない。しかも上の例では繰り返しを前提としていない(一回で抜けるのが通常パスだ)から意図が不明確になったおそれもある。でもこの関数で使われていたもう一つの gotoのように、変数が初期化されない云々のエラーが出るために変数宣言を関数の頭に置くことを要求してしまう、そんな使い方はできないことが担保されている。(goto end_of_func; のことですよ)

あ、上のコード、キャレットが行頭にあるときのことを考慮してない(searchPos.x -= 1; の部分)。一応、問題なく機能してるみたいだけど。


 @2009-12-01

もうひとつ問題が見つかって、現状が問題ありありならばとザックリ Command_SEARCH_PREV()と Command_SEARCH_NEXT()を書き直した。どうせ問題続出するんだろうなあ、とこっそりアップロード。

CViewSelectの修正がないと、マッチの始点と選択開始点が重なったとき(選択範囲が空になるとき)に選択ロックが外れてしまう。


 @2009-12-02

 差分のバグ修正1: 対象が幅0の置換が一つ飛ばしになる件。

範囲選択中でないときは幅0マッチなどによる検索のやり直しをしないようにした。範囲選択中かどうかというのは条件として不十分なんだけど、すくなくとも検索前と後で状態が変わるということはいえる。Command_REPLACE()が事前に選択をキャンセルしてくれているので、とりあえずは置換が一つ飛ばしになることがなくなる。

 差分のバグ修正2: 検索の再試行位置が元と異なっていた件。

「aaaaaaa...」というテキストを、F6による選択ロックを利用して上方向に選択中に「aaa」を下検索する。3文字ずつ選択範囲が縮小していくはずのところが、1文字ずつしか縮んでいなかったのを元通りにした。

 日記のバグ修正

誤) SEARCH_PREV, SEARCH_NEXT

正) Command_SEARCH_PREV, Command_SEARCH_NEXT


 @2009-12-03

 差分のバグ修正3: すべて置換が無限に続く件。

すべて置換の無限置換対策として「m_pCommanderView->GetDrawSwitch() // 全て置換の実行中じゃない」という条件(見落としていた)を元のソースからコピってきた。

 差分のバグ修正4: マウスクリックで「0文字選択された」という旨のメッセージが表示される件。

CViewSelectの変更がステータスバーメッセージの不要な表示につながっていた。メッセージ表示部にそういうチェックをさせて、カーソル位置による選択範囲変更で幅0選択を可能にする(昨日の修正)部分は残したいけど、影響範囲を延々たたいていくようなことになったらいやなので CViewSelectの変更は取り消し。

F6でロックしてキャレットを動かしまた元の位置にもどす。この状態でダイアログを出して検索をすると選択範囲の拡大縮小ではなく、マッチ結果が選択されてしまう。こんなことが起こるならやはり昨日の修正を温存したくなる。不思議なのは ANSI版も同じ挙動だったのだが、UNICODE版ではきちんと選択範囲の拡大縮小になっていたこと。<<< どうやら「カーソル位置の単語文字列をデフォルトの検索文字列にする」の設定が違っていただけみたい。

CViewSelect.IsTextSelected()には、0文字選択を含むのか含まないのかはっきりしてほしい。定義からは 0文字選択を含んでいるが、IsTextSelecting()というものの存在からは、意図としては 0文字選択を含まないようにもとれる。なんにせよ CViewSelect.ChangeSelectAreaByCurrentCursorTEST()が幅0選択を特別扱いして選択解除するのは意図がわからないし、仮に目的があったとしても不適切、あるいは不完全な処置だろうと思う。問題は選択解除によって IsTextSelected()が trueから falseに変わることで、IsTextSelected()は本当にあちこちから呼ばれているので ChangeSelectAreaByCurrentCursorTEST()の変更は影響範囲が広すぎる。(ステータスバーメッセージもそのひとつ)

そもそも、keepCurrentSelectionの条件に CViewSelect.IsTextSelected()は不要に思えるのでこれを外すことで対処。元のソースをできるだけ尊重するつもりでこうしてあったんだけど。

 差分のバグ修正5: 「末尾から再検索しました」が表示されない件。

「末尾から再検索しました」が表示されないのは、条件が「先頭から再検索しました」と同じになっていたからでした。(不等号が逆向き)

 その他

「CViewSelect.cppの修正は、幅0なら何もしないのではなく、 (略)」 else節で「pSelect->Set(ptCaretPos);」と同じことをしていたつもりです。また「m_nLastSelectedByteLen = 0; // 前回選択時の選択バイト数」の扱い方がわかっていないのですが、選択解除もしていないのに「前回選択時の~」というのはあたらないのではないかと。

コメントで指摘されて rev2で導入した sel.IsTextSelected()を sel.IsTextSelecting()に変更したのは、CViewSelectの変更を取り消したことによって、検索結果による選択範囲の拡大(縮小)の結果が幅0になったときに sel.IsTextSelected()が falseになってしまうことへの対策。(選択開始点から先へ検索が進まなくなってしまうので)


本の虫: シンタックスシュガーとしてのlambdaの解説

ifの条件文に && や || が 3つも 4つも連なってくると 1つの Predicateにまとめてしまって名前を付けたくもなる。でも struct{ bool operator()() const {...} } IsHoge; と書くだけでも面倒なのに、スコープが断絶してしまうために、判断に必要な変数にアクセスするためにはコンストラクタで参照を受け取ってメンバ変数に保存しなければならない。コンストラクタを書くために型名も付けなければならない。もうね、やってられない。どうせコンパイラの最適化で消えてしまうコードを長々と書くのは無駄。消えなければもっと無駄。はやく lambdaを。


 @2010-03-31: 応急パッチ

http://sakura-editor.svn.sourceforge.net/viewvc/sakura-editor?view=rev&revision=1724

とにかく無限ループで強制終了しかできなくなるのは良くない。

* 「# 幅0の上検索がいつまでもその場足踏みしてないで上へ進むように修正。 # キャレットより前の、幅0の行頭マッチがハイライトできていなかったのを修正。(あんまりやりにくいので CViewCommander::Command_SEARCH_PREV()から gotoを取り除いて、不必要に選択範囲を保存するのをやめた)」

 CViewSelect.IsTextSelected() -> return CLayoutRange m_sSelect.IsValid() -> return CLayoutPoint m_ptFrom.BothNatural() && CLayoutPoint m_ptTo.BothNatural()。BothNaturalという名前だけど、実際は xと yが共に 0以上かどうかをテストしている。選択範囲の始点と終点の X,Y座標がすべて 0以上のとき CViewSelect.IsTextSelected()は trueを返す。

本日のツッコミ(全8件) ツッコミを入れる

ななしfix_searchword_selection_with_selectinglock_on 置換前:$ 置換後:..

ななしてけとー。 CViewCommander.cpp 【追加】 3116: const bool wasSelected..

ななしや、 3158: (sel.IsTextSelected() && matchLayoutRange.GetF..

ななしrev2 「先頭(末尾)から再検索する」をONにしているのに、 末尾から再検索しても「▲末尾から再検索しました」 が..

ななし「選択幅ゼロ」は自明なので一切表示しなくていいと思います。

ななしCViewSelect.cppの修正は、 幅0なら何もしないのではなく、 以下のようにしたほうが良くないですか? ..

ななしrev2です。 abc というテキストで、 置換前:abc 置換後:xyz 先頭(末尾)から再検索する:ON 置換対..

ななし※同じく、置換後を abcxyz、置換対象を[選択文字(0)]としても起きた


2009年11月20日 (金) DDセイバーオルタはやばい。限定販売でよかったね。

最終更新: 2010-04-08T22:28+0900

[SHJS][SakuraEditor] 色分けにこんな機能があると便利。

参照(説明の丸投げ)> 萌ディタの Lex 周り - miau's blog?

SHJSと萌ディタ、共通の泣き所。そもそも論を言えば、入力に対応した stateを一つ一つ定義していけば対応できなくもないし、Rubyの括弧を使った %記法、%r(pattern)flag のようなものでは括弧に分類される文字種が 4つしかなかったために実際そうしたのだが、非英数1バイト文字や識別子が使えるとなると状態数があっという間にふくれあがってしまう。

SHJSの場合は、JavaScriptであることと eval()で評価されることを利用して、ネイティブの RegExpオブジェクトの代わりに execメソッドと lastIndexプロパティを定義したオブジェクトを登録することで抜け道を用意できるように感じたが、どんな形で特定のキャプチャを参照するのか決めかねた。

今日試しにダウンロードしてみた K2Editorではヒアドキュメントの色分けが可能なようだ。配布パッケージに含まれる Ruby.txtと K2Editor.chmによると書式はこう。

・<<(["'`]?)(\w+)\1 .... ^$2$
    ヒアドキュメント1。後ろのディスクリプターは行内に唯一でなければ
    ならない。

右側の検索文字列には、後方参照が使えます。 左側で()でくくってグルーピングしたマッチ文字列を、 右側の検索文字列の中で取得できます。

取得するには、 K2Editorの置換機構の 後方参照と同じように、$1,$2などを使います。

\1、\2でなくて $1、$2だから、右側のパターンは左側のパターンマッチングが終わった後で、置換されてからコンパイルされるのかも。

SHJS(と萌ディタ)にあてはめた場合、$1、$2がどのマッチングのキャプチャを指しているのかが明らかではない。というところで二の足を踏んでいる次第。

 @2010-04-08: くわえて

  formatted_text = <<TEXT.strip.gsub(/\t/, " "*8)
TEXT
  texts = [<<TEXT1, <<TEXT2]
TEXT1
TEXT2

こんなんどうする?

最終更新: 2009-12-06T02:34+0900

[SakuraEditor] 再度WSHプラグイン

たとえば、http://sakura.qp.land.to/?Junk%2F31 で展開されている GNU Global対応。息の長い支持があるが本体に取り込まれてはいない。こういう万人向けでない機能がプラガブルになっていると、

  • エディタ本体は「大きなパッチ」を取り込んで、バイナリを肥大化させたり、安定性を損なうリスクを避けられる。
  • 本体とは別のサイクルで、また、ユーザーサイドで GNU Global対応を進めることができる。
  • 機能が不要な人はインストールしないから、目にすることもコストを払うこともない。

プラグイン化を推し進めると、不要な機能をそぎ落として、メニューも整理して、必要な機能は自分で用意する。自分だけのエディタになる。

っていうのが xyzzyや Emacsの方向性? そう思うと途端につまらなく思えてくるのは何故? プラットフォームだと思うとアイデンティティが希薄に感じられるのと、なんでもできる/やろうとする/できてしまう無節操さが嫌いなのかも。

いったい自分はどうしたいんだ?

なんでもできるエディタで、やりたいことだけを可能にする!?

でも実際は、エディタなんてなんでもいい&使い比べもしないものぐさな人間だということを行動が示している。最初はメモ帳でスクリプトを書いていて、エラー行を見つける手段(行ジャンプ、行番号表示)がないのに困って最初にダウンロードした TeraPadを 2、3年使い、正規表現検索がないのを不便に思って最初にダウンロードしたサクラエディタを 5年以上使い、ソースが公開されてるもんだから色分けの不足を補えてしまって萌ディタをカスタマイズする機会を逸したまま現在に至る。名前の良さと最初から大概のことができる間口の広さで誘い込まれ、ソースをいじる究極のカスタマイズができる自由さで閉じ込められた。

  1. 見た目がよくて、(ダウンロード)
  2. (適切なデフォルト、複雑すぎない設定など)とっつきがよくて、(しばらくつかってみよう)
  3. 幅広いユーザーのニーズを満たす機能セットが揃っていて、(使用をやめる理由がない)
  4. なくても困らないニッチな要求にも応えられる。(乗りかえる理由がない)

という要素を自分は求めている(らしい。サクラエディタに最初の二つはなかったが、必要だとは思う)ので、プラグイン化で機能をそぎ落とせる必要はなく、それなりに需要のある機能をプラグインで置き換える必要もないかもしれない。プラグインの本命はニッチな機能、取り込むには大きすぎる機能、ライフサイクルの異なる機能の実現にある。……が、なんでもプラグインにしてしまって柔軟にデフォルトを設定できるような状態にしておく、というのもやはり魅力的だ。(それに、デフォルトのタイプ別設定(AWK、アセンブラ、COBOL、Java、TeX、Visual Basec、……)のうち使わないものは目にするのも嫌だという人種(潔癖だね)が一定数いるらしいから、それに応えることにもなる)

っていうのが Linuxの現れては消えるディストリビューション? 適切なデフォルトが対象別に無数に存在する状態を、適切なデフォルトが用意されている、とは言いたくないな。適切なデフォルトはとっつきの良さのために導入した指標だから(注:Linuxの話ではない)。

この展開の着地点を Windows ということにしてみよう。エディタ界の Windows。普及(利益)を目指すなら当然の帰結、とかいって。とりあえず Linuxには、何も考えずこれを入れとけ、っていう強力なディストリビューションが一つだけ、ほしいね。(Ubuntuが五年後も続いていたらいいポジションだ)


2009年11月05日 (木) [Vista] まただ。カーソル移動がもっさりすると思ったら。

最終更新: 2009-11-19T05:26+0900

[SakuraEditor] 前略

  1. 矩形選択範囲が勝手に折り返し桁まで拡大されるのが嫌なので、まずそこをコメントアウト。(不自然な動作を持ち込んだ上に、その理由を説明しないのであれば削除されて当然)
  2. そうすると矩形選択範囲が幅0のときに一切の文字が挿入されなくなるので、選択範囲の幅に頼った間接的かつ誤った条件判断を正す。(正すと書いたが、いまの条件判断が正しいという確信はない。明らかな誤りはなくせたが)

すくなくとも幅0の矩形選択で改行の手前にタブやスペースを挿入できるし、選択範囲の勝手な拡大も行われないが、折り返しが絡んでくるとどのように文字が挿入されるのが正しいのかなんてわからないのでそこんところは考慮外。

折り返しの結果として行頭に改行がきている場合もタブやスペースが挿入されなくなるはず、と思って試したら予測不可能な結果に。もともと折り返し行に対して文字を挿入すると挿入した結果により折り返される位置が変化してしまい結果がどんどん予測不可能になっていくんだけど、それを上まわるかもしれない。

Index: sakura_core/CViewCommander.cpp
===================================================================
--- sakura_core/CViewCommander.cpp	(リビジョン 42643)
+++ sakura_core/CViewCommander.cpp	(リビジョン 42644)
@@ -4733,11 +4733,11 @@
 	// From Here 2001.12.03 hor
 	/* SPACEorTABインンデントで矩形選択桁がゼロの時は選択範囲を最大にする */
 	//	Aug. 14, 2005 genta 折り返し幅をLayoutMgrから取得するように
-	if((wcChar==SPACE || wcChar==TAB) && m_pCommanderView->GetSelectionInfo().IsBoxSelecting() && GetSelect().GetFrom().x==GetSelect().GetTo().x ){
-		GetSelect().SetToX( GetDocument()->m_cLayoutMgr.GetMaxLineKetas() );
-		m_pCommanderView->RedrawAll();
-		return;
-	}
+	//if((wcChar==SPACE || wcChar==TAB) && m_pCommanderView->GetSelectionInfo().IsBoxSelecting() && GetSelect().GetFrom().x==GetSelect().GetTo().x ){
+	//	GetSelect().SetToX( GetDocument()->m_cLayoutMgr.GetMaxLineKetas() );
+	//	m_pCommanderView->RedrawAll();
+	//	return;
+	//}
 	// To Here 2001.12.03 hor
 	wchar_t szWork[2];
 	auto_sprintf( szWork, L"%lc", wcChar );
@@ -4833,7 +4833,8 @@
 			nDelLen = nIdxTo - nIdxFrom;
 
 			/* TABやスペースインデントの時 */
-			if( bIndent && 0 == nDelLen ) {
+			const bool emptyLine = ! pcLayout || 0 == pcLayout->GetLengthWithoutEOL();
+			if( bIndent && emptyLine ) {
 				continue;
 			}
 

 @2009-11-08

隠し機能がでてきましたよ。>「矩形選択時のSPACE/TAB動作に手を入れる場合、実装上、>>dev:4103 あたりのSPACE/TABインデント仕様を実現するための実装部が絡んできそうです。

これだから迂闊なことはできない。自分用だと自分が使う範囲で問題がない限り気にしないで済むけど。

リンク先で議論されている桁揃えのためのインデント(条件によりタブやスペースが挿入されない行があり、その結果インデントが揃う)は、桁(レイアウトX座標)を文字単位の座標に変換するときに、中途半端な(=文字途中を指す)レイアウト座標が正規化されることに依っている、のかな?

矩形選択はつっつくと魔物が出てきそうだ。正解がわからないから、2バイト文字が分割されるなど明らかな不具合以外は実装が仕様になってしまいそう。


挿入位置の文字の末尾が矩形選択範囲に含まれていないときにインデント用の文字を入力しないことで、インデント揃えができるように追加修正した版 > fix_indentation (4.1KiB, diff to trunk2@1674)


矩形選択時、その範囲内に文字がない状態でインデントすると桁が揃うようにスペースを補完します。それ以外の場合、範囲内に文字のない行はインデント対象外になります。

「範囲内に文字のない行」は考慮外だったけど、怪我の功名で改行の後ろにインデント用の文字が挿入されないようにもなっていた。>fix_indentation


あいう
abc

というテキストの一桁目(「あ」の前半と「a」)や、

^   ABC
DEF

というテキストの一桁目(タブの前半と「D」)を矩形選択してタブやスペースを入力すると珍妙なことになるのは変わっていない。普通の文字を入力した場合は、右移動で入力された文字の幅だけ移動することが決まっているけど、入力された文字がインデント用の文字でそれが挿入されなかった場合、右移動の移動幅がもともと選択範囲にあった文字「あ」の幅になってしまうのが原因。

一応入力された文字の幅を考慮して右移動しているけど、右移動を行うのが選択範囲の一行目だから、この場合一回右移動するだけで行き過ぎてしまう。

それも修正 > fix_indentation.rev2 (5.3KiB, diff to trunk2@1674)

問題の存在がわかれば叩きようも考えられるけど、それがわからなければ手の打ちようがない。テスト重要。


どうして、(幅のある)文字の先頭部分が矩形選択範囲に含まれているときだけインデント用の文字を挿入、ではなく文字の末尾が含まれているときだけ、なのかといえばおそらく、そうでないとインデントの桁揃えができないから。実際に試してみればすぐわかるけど、文字の先頭を条件にするとほとんど常にインデント文字が挿入されてしまって桁揃えにならない。


現在認識している問題点。

  1. ソフトタブ設定のときに桁揃えができていない。
  2. 入力がインデント用の文字のときにも矩形選択の幅0を維持するようにした結果、CViewCommander::Command_INDENT_TAB()の

    if(m_pCommanderView->GetSelectionInfo().IsTextSelected() && m_pCommanderView->GetSelectionInfo().IsBoxSelecting() && GetSelect().GetFrom().x==GetSelect().GetTo().x){
    	Command_INDENT( WCODE::TAB );
    	return;
    }

    このコードが発動してしまい、ソフトタブ設定にかかわらず常にタブ文字が挿入される。

修正した。>fix_indentation.rev3 (5.8KiB, diff to trunk2@1674)

1つ目は fix_indentaiton.rev2のバグ。意図せず bIndent引数を trueから falseに変更してしまっていることがあった。2つめは該当コードを削除した。もうひとつ fix_indentation.rev2のバグ。幅0の矩形選択のときにもインデント用の文字の挿入をうっかりスキップすることがあった。


 @2009-11-09

指摘を受けて修正。原因は rev2のタイポ。指摘を受けたケースは fix_indentationのときにしかテストしていなかった。> fix_indentation.rev4 (5.8KiB, diff to trunk2@1674)

本腰を入れて読んでいなかった、というか、自分でやってみた今だからこそよく理解できるんだけど、4127で実際に文字を挿入された行をもとにして選択範囲を移動することが既に行われている。さらに気になってはいたけどそのままにしていた、全角文字がはみ出すことへの対処も行われている。なんて車輪の再発明。ちょっと違う点を見つけるなら、文字を挿入された行をもとにするだけでなく、選択範囲から文字がはみ出していない行をもとに選択範囲の移動量を決定しているところだろうか。だから 4138の指摘を rev2改めrev4では回避できている。


つっこみ。非互換ではないけれど

あいうえお
1かきくけこ

という行で幅1矩形選択をしてインデント用の文字を入力するとおかしな事になる。文字を挿入するときは幅0選択でいいじゃないかと思っていたが全角半角が混じるといつでも幅0で選択できるとは限らない。幅2以上であれば問題は起こらないのでこれはインデント揃えの弊害。右移動に頼らず直接、入力文字のレイアウト幅を計算して選択範囲を移動すればなんとかなる、かも。方法は知らないけれど。

ptLayoutNewを使って計算」< 上の例で考えると矩形選択範囲に入るのは一行目と二行目をあわせても、ある文字の前半と別の文字の後半だけ。前半だけの行にはインデント文字が挿入されないから入力のレイアウト幅を知るためには使えない。後半だけが入っている行では、挿入位置として与えるのが文字の真ん中を指すレイアウト座標。返ってくる ptLayoutNewが相変わらず文字の真ん中を指す座標だとは考えにくい。最大でタブ幅-1のずれが生じたりしないだろうか。(一人言: ptLayoutNewって、名前から CLayoutのインスタンスだと思っていた。pじゃなくて ptだったとは)

オプション化不要と書いたとたんのこの難題。どうしましょ。


とりあえずインデント文字のうちスペースを入力したときに、選択範囲が全角文字の前半部分ばかりを移動してしまって全く入力が行われないのを改善した。>fix_indentation.rev5 (7.8KiB, diff to trunk2@1674)

また従来は矩形選択範囲が折り返し桁に達した場合、行番号はそのままで選択範囲が行頭に移動して循環していたが、折り返し桁でとどまるようになった。これは意図したものではないが、従来の挙動を期待する人がいるとも思えないのでそのまま。

折り返しといえば

1|ABC<
2|DEF<
3|GHI<

CFIを矩形選択して _を入力したとき、_が Fと Iの直前に入力されるわけではないというのはどう考えられているのだろう。これがあるから矩形選択入力と折り返しを組み合わせてはいけない、どんな結果も期待してはいけない、と思っている。


タブが入力されたときもおかしなことにならないように改善した。>fix_indentation.rev6 (8.4KiB, diff to trunk2@1674)

原因はインデント文字の入力をスキップされた行が取り残されることにある。入力がタブだったりしたら 8桁分選択範囲が後ろに移動することもあるわけで、そのとき選択範囲の中に収まっている文字は、タブの入力をスキップされた行においては、ユーザーが最初に選択した文字とは全く異なっている。インデント文字の入力スキップがインデントを揃えるためにあるというのならば、実際そこにインデント文字があるかどうかをチェックして、あるときだけ入力をスキップすればよい。条件を厳しくすることで全角文字が取り残されることがなくなった。

テスト。1行目と 2行目をどこでも幅1矩形選択してタブを入力する。最初に選択した文字が取り残されないことを確認する。

あいうえお
1かきくけこ

4タブ設定で「う」の前半と「き」の後半を幅1矩形選択してタブをいくつか入力したとき、初回だけ「う」が後ろに行きすぎる。これはもうあきらめている。


 @2009-11-10

0123456789
あいうえお
1かきくけこ
(TAB幅は4の設定)

で、1行目の「4」の左から3行目の「き」の右までを矩形選択(幅1桁)して
TABを3回入力すると、1行目の「4」の左右にTABが入ります。 

これは、「これはもうあきらめている」(@2009-11-09)ケースなんですよね。事前に選択行をすべてチェックする必要があるように思えたので……*。ちょっとやってみますが。

行番号が55行ほどずれてしまっています...

うっかりしていました。矩形選択中にカーソルが折り返し桁一つ手前で折り返してしまうことの対策と同じブランチを使っているせいだと思います。

 Editor.Char(9) と Editor.IndentTab() の使い分け

すでに BOOL bIndent引数が存在するのだからこれを厳密に適用しようということですね。悪くないと思いますし、対象も重なっていますが、いっしょくたにしていいものか……。


矩形選択範囲がタブ境界にあり、全角文字の前半分が範囲からはみ出しているときにタブを挿入すると、行によりタブの幅が最小と最大になってしまい、選択されていた文字を選択範囲内にとどめることができなくなってしまう問題に対処した。>fix_indentation.rev7 (10.2KiB, 今度こそ diff to trunk2@1674)


 @2009-11-11

あいうえお
1かきくけこ

で、「い」の左から「き」の右まで矩形選択します。
まず、「さ」を入力します。
次に、「a」を入力します。
結果、1行目には「さ」の手前に「a」が入ってしまいます。 

不安に思っていて、でも知らぬが仏とばかりに追求しようとしなかった部分(全角文字の入力)を見事に突いてきますね。(すごくありがたいです)

TABを含めた文字列をクリップボードから貼り付けた場合

この場合はインデントではありませんし、揃えることよりもクリップボードの中身を指定された場所に貼り付けることが第一だと思います。これまで通り。

'int' から 'CLayoutInt' に変換できません。

直しました。個人的にデバッグモードのエラーを潰すためだけに CLogicInt(0)や static_cast<CLogicInt>(0)と書かされるのが嫌なのですね。せめて警告にしろと(無視する気満々)。いっても仕方ないですが。


二、三日前から毎日これぞ決定版っ、と思ってるんだけど。今日こそ >fix_indentation.rev8 (10.8KiB, diff to trunk2@1674)


 @2009-11-12

 selectionIsOutOfLineの判定条件が(たぶん)おかしいです。
(括弧が足りてない気がします)

詳細なレポートありがとうございます。条件演算子の優先順位は &&と ||の次ですから、おっしゃるとおり reachEndOfLayout && の部分も含めて ? の前と後ろの二つにわかれてしまっています。誤)A&&B?C:D 正)A&&(B?C:D)

一日を失う手痛いミス >fix_indentation.rev8.1 (10.8KiB, diff to trunk2@1674)


 @2009-11-13 メモ

  • タブキーとスペースキーにはそれぞれ「TABインデント」「SPACEインデント」機能が割り付けられている。
  • Aや Bという文字の入力は Aや Bというキーに割り付けられた機能によるものではない。
  • タブキーとスペースキーに割り付けられた機能を削除しても、タブやスペースの入力が行える。
  • ただし、ソフトタブは「TABインデント」の機能。
  • 選択範囲をタブやスペースでインデントできるのももちろん「TABインデント」と「SPACEインデント」の機能。

インデント揃えにからむ機能のオンオフを機能の割り付けでコントロールできるかと思ったが、TABインデントが高機能なので取捨選択ができなければ意味がない。

タブインデントとタブ文字の入力を区別。>fix_indentation.rev9


 @2009-11-15

矩形選択入力で、(TABインデントや SPACEインデントによらない)タブやスペースを、改行文字の後ろや空行にも挿入するように。矩形選択中の、TABインデントと区別されるタブ文字の入力と SPACEインデントと区別されるスペースの入力は、前例がないので自由に変更しています。>fix_indentation.rev9.1 (13.4KiB, diff to trunk2@1674)

rev9.1を眺めていて、従来の動作に疑問。テキストが選択されていなかったり、選択範囲が一行だけだったとき、Command_INDENT_TAB()は Command_INDENTの代わりに Command_WCHAR()を呼び出す。これにより選択範囲が一行のときだけ、インデントではなく選択範囲がタブで上書きされる。潔癖より実用本位ということだろうけど。


 収支

わかっている範囲では以下の四つが改善され、二つの非互換が確認されている。

  • 矩形選択で、改行文字の手前にインデント用の文字(タブとスペース)を挿入できる。

    ABC
    ABC

    Cの後ろを幅0矩形選択してスペースを二回入力して、(なぜか)全体が選択されたあと行頭がインデントされたりしないことを確認する。

  • 矩形選択範囲の先頭が全角文字やタブなど幅広の文字のとき、インデント用の文字の挿入が桁揃えのためにスキップされても、選択範囲の移動幅が入力文字と異なることがない。

    あいう
    abc

    一桁目(あの前半とa)を矩形選択してスペースを二回入力し、(奇妙にも) aの前と後ろにスペースが挿入されたりしないことを確認する。(あをタブにするともっと極端な結果を確認できる)

  • 矩形選択範囲が全角文字の前半ばかりを移動してしまい、スペースが入力できなくなったりしない。

    あいうえお
    1かきくけこ

    1行目と 2行目をどこでも幅1矩形選択して、スペースをいくつか入力し、入力が連続してスキップされないことを確認する。

  • 矩形選択してタブを入力したとき、最初に選択されていた文字を置いてきぼりにして選択範囲が後ろに移動したりしない。

    あいうえお
    1かきくけこ

    1行目と 2行目をどこでも幅1矩形選択して、タブをいくつか入力し、最初に選択した文字が範囲内に残っていることを確認する。

  • (非互換) 矩形選択中に文字を入力し続けたとき、範囲が折り返し桁から行頭にループしない。
  • (非互換) タブひとつの貼り付け、スペースひとつの貼り付け、TABインデントを割り付けていないタブキー入力、SPACEインデントを割り付けていないスペースキー入力で、矩形選択中のインデント揃え機能が発動しなくなった、また、ほかの文字と同じように改行の後ろや空行にもそれらが挿入されるようになった。Editor.Char(9)、Editor.Char(32)の結果も同じように変わっているはず。

 @2009-11-18

(何人いるのかわからない)ななしさんに協力してもらったということもあるので、パッチにして投稿しなければいけないとは思っていたが、あまりに次々バグ報告が来たので寝かせておく期間が必要かも、とも思っていた。でも目を通した上で代わりにやってくれるのは歓迎です。>unicode:1054, SourceForge.net: Sakura Editor: Detail: 2899665 - 矩形入力動作の改善

追加修正もあるようで、

  • ソフトタブ設定のときに挿入するスペースの数を、選択一行目だけで判断せず、すべての行(文字の前半分だけ選択範囲からはみ出してる行なども含めて)に対して適切な数を選ぶ。
    • ぱっとできる対処が思いつかなかったので見て見ぬふりをしました。
  • Command_INDENT()と Command_WCHAR()の交差した呼び出しを解消。
    • 内部の話。
  • SPACEインデントによる全角文字の左側揃え。選択幅1のときは全角文字の凸凹を調整して揃える。(>>dev:4136の件)
    • どこを選択してスペース3つなのかが書いていなかったので読み飛ばした部分です。

元に戻った点も、

  • 幅0矩形選択時のインデントで選択範囲最大化。
    • 今日の日記の最初をみるとわかるが、掲示板に投稿された「改行文字直前の幅0矩形選択インデントが行頭インデントになる」のを修正するのはついでで、範囲が勝手に最大化されるのをやめることが個人的なスタート地点だった。だから「微妙だが、自ら引導を渡すほど忌むような挙動でもないかな?」という見方には同意できないが、このパッチにより矩形選択範囲が幅0であることに特別な意味がなくなるので、野良パッチ、野良ビルドで対処しやすくはなる。前進。

ダウンロードしてパスは通していたものの、今日初めて patch.exeを使った。つまずいた点は、

  1. パッチに記述されたパスにあうようにカレントディレクトリを設定したなら -p0 オプションが必要。(デフォルトの動作ではパスを無視してファイル名だけをみるため)
  2. Subversionがよく出力する LF/CRLF混合の差分は受け付けなかったので、CRLFに統一。

GNU patchが5年ぶりにバージョンアップ バージョン2.6リリース:CodeZine」なんて話題が今月にあったけど、インストールされていたのはこんな patch。見慣れた名前があります。

patch 2.5.4
Copyright 1984-1988 Larry Wall
Copyright 1989-1999 Free Software Foundation, Inc.

This program comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of this program
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.

written by Larry Wall and Paul Eggert

* 追記@2009-11-18 http://sakura-editor.sourceforge.net/cgi-bin/cyclamen/cyclamen.cgi?log=dev&v=4137#4137 にまさにその手順が書かれていた。ぱっと見で理解できなかったので例によって読み飛ばしていたが。というよりこの例は再現手順に不備があるので問題の所在から理解できていなかった。

本日のツッコミ(全25件) ツッコミを入れる

Before...

ななしデバッグモードでコンパイルすると、4883行で、 error C2440: 'int' から 'CLayoutInt..

ななしrev8です。 あいうえお 1かきくけこ 0123456789 「い」の右側から、3行全部を0幅選択してスペース..

ななしrev8.1でOKな気がします。 いい感じ (^^)

anonymouse「1文字のTAB/SPACE入力が必ずインデント扱いになってしまっていて変」 (2009年11月10日 (火) 10..

ななし念のため。 上記の、 ・タブキーとスペースキーに割り付けられた機能を削除すると、  複数行選択したときのタブやスペ..

ds14050ええと、具体的にどういう動作が不満で、どういう結果になるのがよいのでしょうか。rev.9版のバイナリは http:/..

ななし行末を超えた位置にも通常文字は入る。 SPACEキーにインデントを割り付けて*いない*ときは、 行末を超えた位置には..

ds14050この部分ですね。 ---- if( nDataLen == 1 && IsIndentChar( pData[0] ..

ななしnDataLen == 1 && IsIndentChar( pData[0] ) なんていう条件だと、 クリッ..

ななし> 選択範囲が一行だけだったとき、Command_INDENT_TAB()は Command_INDENTの代わりに..

ds14050>1字のSPACE/TABという条件は、コードをはじめて見た >瞬間におかしいと思ったし、誰でも同じことが想像できる..

ds14050どうしようもないな。「元の挙動を残し」た。<<<大嘘

ds14050なんかもうぐだぐだだけど気づいてしまってので訂正。 >知らないのは事実です。最初のコメントに書いたとおり。 最初のコ..


2009年10月26日 (月) [tDiary] aq=3 というようなクエリパラメータを含んだ google検索からのリファラをうまく置換できないので調べたら、最新のではしっかり q= というパターンが [^ao]q= に更新されていた。設定ファイルは古いものを引き継いでいたから対応できていなかった。ところで、[^ao]q= より \bq= の方が将来性があって良い。というか、[?&;]q= でどうか?

最終更新: 2011-12-20T23:29+0900

[SakuraEditor] 矩形選択時のカーソルの動きを修正。

発端はこれ > 「折り返ししている物理行末を、キーボードで左から右へ矩形選択しようとすると、 次の物理行にカーソルが移動して意図した通りに選択できません

折り返し桁に到達した瞬間、次の行の始めにキャレットが移動してしまうために末尾一桁が選択不可能になっている。

いいだしっぺの責任のようなものを感じて一応やってみた。

  • 矩形選択中はキャレットを操作と違う方向に移動しない。
    • 右を押していて、折り返しで次の行頭に移動しない。
    • 下を押していて、EOFのある行に着いたとき X座標の最大値を EOFの位置に規正しない。
  • (ついでに) EOFの位置にキャレットがあるときに下を押すと選択解除。
    • EOFの位置で右を押したときに選択解除はすでに行われている。

ざっくり書き換えてしまった部分があるのと、CMemoryIteratorと CLayoutがよくわかっていないために、さっぱり自信が持てない。道具が初めて扱うものばかりなのに加え、フリーカーソルモード、矩形選択中、改行の位置、折り返し桁(設定)、(実際の)折り返し位置など、考慮すべき対象も多すぎる。

いじったのはキャレットの移動部分だけで選択については見ていない。ぶら下がり文字についても考慮していない。選択できないわけではないので、特に不都合だとは思っていない。(改行がぶら下がってるときは不都合があるかも)


 @2009-10-28

矩形選択をキャンセルしたときにカーソルが改行の後ろに取り残されてる。

矩形選択を上下左右矢印で解除したときはカーソルを矩形の左上隅に移動するようになっている。でも現状では、矩形選択は Shift+F6での矩形選択ロックを利用したインターフェイスしかない(マウスのことは知らない)から、矢印で選択状態を解除はできない。で、Escを利用して選択解除するんだけど、このコマンドはキャレットの移動を行わない。だから取り残される。

取り残されるよりはましだろうと思って、必ず左上隅に移動するようにした。

別件。選択を矢印で解除するとき、右(左)矢印だったら選択解除だけが行われてキャレットの右(左)移動は行われない。でも上(下)矢印だったら選択解除とキャレットの移動が両方行われる。どっちでもいいし、今のように混在してても不満はない。

さらに別件。キャレットが EOFの位置にあるとき右矢印で選択解除ができるようになっていたので下矢印でも選択解除ができるようにしたが、キャレットが先頭行にあるとき上矢印で選択解除はできない。キャレットの実質的移動がなければ選択解除はしない、ということで統一し、EOFの特別扱いをやめてもいい気がする。

違うなあ。ファイルの先頭で左を押すと選択解除ができる。EOFでの右解除はこれにならったものだ。最終行での下矢印で選択解除できるようにしたなら、先頭行での上矢印解除も対応しろ、ってことだ。(そのほうが修正点が少ない)

した。

たぶん、二行下移動(そういうコマンドがあって、↓に割り当てたりできる。矩形選択用の二行下移動もある)ではここまでの修正が効いていないだろう。

と思ったら、二行下移動では EOFのみの行に一気に移動できない。必ず手前の行で一度止まってしまう。結果的に問題は起こっていなかったわけだけど、EOFのみの行に一気に移動できるようにしたうえで、修正が効くようにした。

ちょっと考えればわかるけど、左上隅だからって改行の後ろでない保証はなかった。普通の選択解除と同じようにコマンドの方向も考慮しながら(右移動による選択解除なら右下隅にキャレットを置くとか)、キャレットが有効な位置におさまるようにまじめに対応した方がいい。左(右)矢印が押されたときに選択解除とキャレットの移動を両方行うようにすれば、上(下)矢印の場合の動作と統一されるし、キャレットが有効な位置に収まることも左(右)移動コマンドによって特別なことをせずとも保証される。一石二鳥。


 @2009-10-29

ツッコミが入りました。

今のサクラで、選択を上下左右の矢印キーで解除するときの挙動は、秀、Em、MS Wordなどと同じ動きです。

秀丸エディタ、EmEditorはおろか Wordも使ったことがない物知らずなもので……。左右の選択解除でキャレットの移動がなくて上下の選択解除ではキャレットが移動することに関しては、(俺がいう)一貫性以外に、他と揃えるという評価軸もあるということでしょうか。メモ帳と Firefoxのテキストエリアでは左右の選択解除でもキャレットが移動するので、やっぱりどっちでもいいことだと思うな(俺は)。どっちでもよくないという意見があるのだから「一石二鳥」を強行したりはしないけど。

(折り返し位置の1字手前から次行に移動する)も、概ね多くのエディタと同じ動きだと思います。

これ、キャレットの表示を折り返し位置で留まるようにして次行の行頭に飛ばないようにしたけれど、その右、は次行の一文字目と二文字目の間だから実質的なキャレットの位置は変えていないのだよね。行頭の左が前行の折り返し位置の一文字手前であることの対称になることも意図した。折り返しの一文字手前の右が次行の行頭である場合より、ユーザーのできることは増えるし、キャレットが現在の行を端から端まで移動する前にワープしてしまったような印象も受けないし、で、他のエディタも見習ってほしい動作だと思ってる。これに関してメモ帳は、折り返し一文字手前の右が次行の行頭。Firefoxのテキストエリアは、折り返し位置と次行の行頭の間に仮想の一文字が存在する。Firefoxはありだと思うけどメモ帳はどうかと思う。どうかとは思うけど自分は折り返さないのでまったくの他人事だったり。

書いてるうちにさらなるツッコミ。

通常選択や通常カーソル移動の仕様変更するのは本末転倒かな。

「本末転倒」はそうだったかもしれない。折り返し位置での右移動がややこしすぎて、矩形選択の不都合の修正とカーソル移動を分離できなかった、というか、キャレットがおかしな動き(改行文字の後ろに止まったり)をしないように試行錯誤しながらの修正だったから、その結果が自分好みの動きになるのは当然というか。

二人とも、矩形選択中にキャレットが折り返さないことに異論はないのかな。


 自然にこうなるはずもなし。
 先人の意向ということで。

レガシィは積極的に振り捨てたい。それが自然でないのならばなおさら。


個人的な主張や好みはおいておいて、波状攻撃をくらってしまったので折り返しでの右移動を修正した。元の通りに(なったはず)。ちょっと余裕ができたのでコードを整理して仕様変更をしやすくした。これで、こんどまた折り返し行の右端でキャレットを止めようと思ったときも変更がしやすい。MOVE_NEXTLINE_IMMEDIATELYを MOVE_NEXTLINE_NEXTTIME_AND_MOVE_RIGHTに置換するだけじゃないかな。オプション化も簡単だ。わざわざ設定画面を用意して使用者の煩わしさを増大させるほどのものではないけど。


 @2009-10-31 パッチ。

SourceForge.net: Sakura Editor: Modify: 2889930 - 矩形選択中にキャレットが操作と異なる方向に移動しないように。



 @2011-11-30 コミット。

  1. r1966(2011-11-15) コミット by syat.
  2. r1973(2011-11-29) キャレットが -1行目へ移動するバグの修正 by moca_skr.
  3. r1983(2011-12-20) (F6と ESCキーによる)選択中の未選択状態で選択をキャンセルできないバグの修正 by moca_skr.
本日のツッコミ(全3件) ツッコミを入れる

anonymouse今のサクラで、選択を上下左右の矢印キーで解除するときの挙動は、 秀、Em、MS Wordなどと同じ動きです。 折り返..

ななし矩形選択という「おまけ」にあわせて、 通常選択や通常カーソル移動の仕様変更するのは 本末転倒かな。

ななし現行仕様は明らかに他のエディタを調べてそれに合わせた結果と思われ。 自然にこうなるはずもなし。 先人の意向ということ..


2009年09月23日 (水) Subversionの嫌なところ - 日記を書く [・w・] はやみずさん < 既に存在するリポジトリの形式はサーバープログラム(svnadminとか)をアップデートしたとしても自動ではアップグレードされないことになってる。明示的にコマンド(svnadmin upgrade)を打つか DUMP&LOADするまで。だから古いクライアントプログラム(svn)がお行儀悪く fileプロトコルでリポジトリを直接読もうとしても(他に原因がなければ)失敗はしないんじゃないかと。濡れ衣くさいので書いた。 <追記@2010-04-21>ワーキングコピーの話だったらそれはアップグレードされる。所詮ただのコピーなんだからクライアントごとにチェックアウトすればいいんですよ。</追記>

最終更新: 2013-04-29T21:18+0900

[SakuraEditor] 矩形選択を普通の選択と同じ操作感に。(Shift+○という操作を Alt+○に置き換えるだけ)

いままでは、Alt+矢印で矩形選択モードに入った後、Altを放して、それから選択範囲の拡大を(矢印で。Shiftは不要)行う必要があった。また、知らないうちに矩形選択モードに入ってしまっていて驚かされることも何度かあった。それら、Altを放す必要や知らぬ間のモード変更がなくなる。

2000年にはそのための布石というか、コメントアウトされたプレースホルダが用意されていた。そのおかげで、全くたいしたことはしてないのだけど、これまで放置されてきた理由なり原因なりを何か見落としてる?


 差分更新

easy_box_selection.rev2.txt (30.6KiB, 2010-04-13)
trunk2@1732に対する差分。
キー割り当ての初期設定の間違いを一つ修正。
折り返し行頭への移動が本当の行頭(改行文字の直後)への移動だったのを修正。

 @2013-04-27 Mocaさんによるパッチ

Sakura Editor / PatchUnicode / #449 矩形選択移動コマンドの追加

俺みたいにありもののコマンドで間に合わせるのでなく、足りないコマンドの実装までされています。

今思うと矩形選択しながらの、(折り返しでない本当の)改行単位での行頭・行末移動は不要だった気がする。プレースホルダはあったけど、使わないでしょう? 改行単位の GoLineEnd自体は、矩形選択と組み合わせては使わないにしても、なくて不便だった(20120227p01.02)ので必要だけど。

残念なのは、既存ユーザーの sakura.iniには Alt+↑、Alt+↓、Alt+←、Alt+→に対する「矩形選択開始」の割り当てが既に書き込まれていること。勝手に設定を書き換えることはできないから、プログラムをアップデートしただけでは利便性の増した矩形選択に気付けない。関連するキー割り当てがデフォルトのときだけ書き換えてしまうのはありかもしれない。アップデート後1回だけ ini書き換えを実行するために、iniにフラグのための項目を増やすことが考えられる。WSHで独立したスクリプトを書く方がオーバーヘッドは少ないが、実効性は著しく下がりそう。別に隠れ機能でもいいけどね。よく使う人ほどこれまでの操作に慣れてるだろうから。ヘルプに2通りの操作があることを書いておけば気付くでしょ。でも、慣れてるけど不便だと思ってる人に気付いてもらえないなあ。俺みたいにリリースノートを嬉々として読む人間ばかりではないだろうし。


2009年09月22日 (火) [790FX-GD70] BIOS v1.5

最終更新: 2016-03-05T00:30+0900

[SakuraEditor][正規表現] 正規表現を使った検索・置換で、改行の意味を LFのみから CRも含むように。

経緯 > サクラエディタBBS[r7030]

差分 > fix_cr_handling_of_regex(下に修正版がある)

お試し > sakuraW.zip (547KiB)(下に修正版がある) (正規表現検索・置換を試すには bregonig.dll(Unicode対応版)が別途必要)

検索、置換を数度試したが機能しているみたい。ただ、$ が本当に改行の手前でマッチする関係で

^.*$

を空文字列に置換するという最初に提起されたケースでは、置換後の空行までが置換対象になってしまう(置換回数が 2倍)。目的に適う、より適切なパターンは

^.+$

あるいは、エディタの行置換機能を使っているのだから、もっと単純に

.+

で良い。


 @2009-09-24

正規表現 - SakuraEditorWiki」を見ていて気付いた。\c[\c]\c$\c. という制御文字のひとつを表すパターンが存在する。「鬼車 正規表現 Version 5.9.1」によれば \C-[\C-]\C-$\C-.\M-[\M-]\M-$\M-. も存在しうる。\M-\C-[ なども存在しそうに思ったけど、これはこういう結果になった。

irb(main):001:0> /\M-\C-[/
SyntaxError: (irb):1: too short escaped multibyte character: /\M-\C-[/
        from c:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb(main):002:0

制御文字なんて扱ったことがないからなあ(もはや relicだという認識)。対処の必要性がさっぱり感じられないけど……。


 @2009-09-25

一括置換で $ が CRLFの CR直前、LF直前、LF直後(正規表現DLLに与えた文字列末尾)の三カ所にマッチしてしまうとの指摘 >サクラエディタBBS[r7039]

逐一、置換を実行した場合は問題ないことを確認していたのだが、一括置換はライブラリに全部お任せで、検索開始位置を調整することもできないから動作が違っていたのだろう。$ が CRと LFの間にマッチするのはわかっていたが、明示的に \r を食べた場合にだけ影響があると思っていた。一括置換なんてありふれた操作でそれが明るみに出るとは思いもせず。

急いで修正 > fix_cr_handling_of_regex.rev2sakuraW.rev2.zip (547KiB)(さらなる修正版 rev3が下に)

初めて戻り読みを使った。なんとなく反則的な手段の気がして、使わないですむ方法をいつも考えるのだけど無理だった。これで bregonig.dll依存が決定的になった。[] の入れ子のことだけなら ] が見つかったときに charset_levelを一気に 0 にするだけで BREGEXP.DLL対応もできたのだが。


\C-X、\M-X というのは Ruby向けなのかも。サクラエディタ(+bregonig.dll)で \C-[ を検索しようとすると「premature end of char-class」というメッセージが出る。となれば、\cX だけが引っかかった小骨ということになる。

対処 > fix_cr_handling_of_regex.rev3sakuraW.rev3.zip

<追記>bregonig.dllでは \c\X が \cX の意味になるとか。もう知らねー。</追記>


個人プロジェクトでもないと色々大変そう。ドッグフードでも食べながら様子見します。とりあえず反応だけ。

 2.非対応となっているBREGEXP.DLL(ANSI版)への対処方法
 ANSI版とUNICODE版は別仕様としてしまうのか?

使用できる正規表現自体が別物なので BREGEXP.DLLは CBregexp::MakePattern()でよいかと。ユーザーを驚かさないための変更なので、. が \r にマッチすることを期待していた人以外に影響はないつもりでいる。

<追記>ANSI版+bregonig.dll向けのパッチを用意したので、別仕様は ANSI版+(BREGEXP.DLL/bregonig.dll)と Unicode版+bregonig.dllの間、または、 ANSI版+BREGEXP.dllと (ANSI版/Unicode版)+bregonig.dllの間のどちらでも選べる。BREGEXP.DLLのサポートするオーソドックスな(戻り読みをサポートしない)正規表現で、$を改行直後の行文字列終端にマッチさせない方法が見つからない限り BREGEXP.DLL対応は無理。</追記>

<追記>BREGEXP.DLL版も用意した。>_ANSI.rev2 >_ANSI.rev3</追記>

 3.$ が改行なし最終行のEOF手前ともマッチするように改善すること
 $ を (?=\r\n?|(?<!\r)\n|(?<[^\r\n])$) に置き換える方法を試してみたけどエラーで動きませんでした。

肯定の戻り読みは (?<=) でした(なにせ使用経験がないもので)。気を取り直して、パターンを (?=\r\n?|(?<!\r)\n|(?<=[^\r\n])$)* に置き換えたところ、検索は予想通り、最終行がEOFのみの場合を除いて文書末にマッチするようになったのだけど、置換が行われない。(以前は行われていたのだろうか? マッチのインデックスが文書の長さと同じ(=1つはみ出した状態)になっているはずだから特別な対処が必要なのだろう)

「以前は行われていたのだろうか?」< 行われていなかった。なら、(間違ってるけど)おいておこう。

 4.検索強調表示が検索時の選択反転表示と一致すること
 $ を (?=\r\n?|(?<!\r)\n) に置き換えた版で $ を検索すると、改行文字自体は選択反転表示にはならない(マッチしない)のに検索強調表示されている。
 また、なぜか上方向検索では改行文字自体にマッチしたかのように選択反転表示になる。

$で検索したときに改行文字が強調表示されるのは、幅0のハイライトには意味がないので、実用面から今のように最低でも幅 1を保つべきだと思っていた。

上検索で改行が選択されてしまうのは間違いなので修正したい。これまでが、知らず $ が改行にマッチする仕様に依存していたのかもしれず、こういう修正は正しい方向に向かうためのものだと考えている。

修正した(rev4)。無限ループを避けるためにマッチ幅が 0のときに検索開始位置を特別にインクリメントするんだけど、そのタイミングが悪くて検索開始位置だけでなくマッチの範囲までがインクリメントされていたのが原因。

 5.正規表現キーワードでの $, . 指定も検索・置換と挙動が一致すること
 現状、正規表現キーワードには $, . に検索・置換でやっているような細工が入っておらず、素の正規表現ライブラリ挙動になっている模様。
 検索・置換時の . の細工([^\r\n]への置換)が追加されると、今よりも差異が大きくなって混乱しそう。

すでに書いたように、. が \r にマッチすること、$ が CRLF の真ん中にマッチすることを期待していた人(いるのか?)以外は違いに気付かないだろう。

\r\n$ みたいな書き方をしていた場合にマッチしなくなる。このケースはなくはないかも。

 6.検索・置換や正規表現キーワードの複数行対応への順応性

ノーチェック。sフラグが含まれる( . があらゆる文字にマッチするようになる)ときには . を置き換えないようにする、mフラグが含まれない( ^、$ が行頭、行末にマッチしなくなる)ときには $ を置き換えないようにする、とか?


>fix_cr_handling_of_regex.rev4sakuraW.rev4.zip


2ch民は 1.6.5.0をつかうのね。♥マークはいらないんだ。Consolasも使いたくないんだ。(これは俺の理由だけど) r1663を使おうぜ。


 @2009-09-28

Unicode版Revision1662>http://sakura-editor.svn.sourceforge.net/viewvc/sakura-editor?view=rev&sortby=date&revision=1662

Ansi版Patch>http://sourceforge.net/tracker/?func=detail&aid=2869238&group_id=12488&atid=312488


勘違いしていた。Unicode版のサクラエディタで使用できる正規表現ライブラリは bregonig.dll(Unicode版)だけだ、という事実がいつの間にか、bregonig.dllは Unicode版専用だ、という思い込みにすり替わっていた。

だったら、採用の可否はともかく、Ansi版(trunk2の (Release|Debug)_Ansiビルドのことでなく trunkのビルド産物のこと、だろう)向けのパッチを作成する意味はあるわけだ。CBregexpのインスタンスがその寿命を通じて 1つの DLLだけを扱うのであれば、コストを初回に払うだけで、処理の振り分けを行うことができる。どっちかな?

>>> DLL初期化時に呼ばれる仮想関数がありました。(そのたびにチェックを行えばいい。実際は 1回しか呼ばれないだろう)


CheckRegexpSyntax() は癌だ。検索ボタンを押すたびに DLLのロードからはじめて、文法をチェックしたら使い捨てるって何事。文法チェックは Compile()で十分。その後の Match()のための準備にもなってちょうどいい。もろもろの手順を共通化したいのなら引数として CBregexpを受け取るべきだ。正規表現のチェックをしたい(=正規表現を利用したい)部分ではもちろん CBregexpなりなんなりをすでに持っているだろう。CheckRegexpSyntax()がこんな重量級のローカル変数をもつ必要はない。無効な検索パターンを履歴に追加したくないがために、検索の主体でない検索ダイアログが利用しているのかもしれないけど。


 @2009-09-29

やっつけで一応。これで昨日書いた「コストを初回に払うだけで、処理の振り分けを行うことができる」が事実になった。昨日の段階では、検索ボタンを押すたびに DLLがサポートする文法をチェックする関数が実行されていた(初回どころではない)。これでもまだ、検索ボタンを押すたびに Compile()が 2回走るのは変わっていない。

おまけとして、bregexp.dllだけが sakura.exeの隣にある状態でエディタを起動し、その後 bregonig.dllを配置したとき、検索ダイアログでは 「bregonig.dll Ver....」と表示され、bregonig.dllしかサポートしない戻り読みを使用しても正規表現エラーにはならないものの、実際の検索には bregexp.dllが使用されるためだろう、戻り読みが機能していればマッチするはずの条件でもマッチ無しになってしまう、こういう、説明もややこしい起こりづらい状況が起こらなくなる。(文法チェックと実際の検索が CBregexpの同じインスタンスによって行われるようになるから)

本当は CBregexpが CDllHandlerを継承するのをやめて分離して、1つの CDllHandler(DLLインスタンス)を多数の CBregexp(BREGEXP構造体)から参照するのがいいのかも。もっといえば、BREGEXP構造体もコンパイル済みパターンとマッチ結果に分離したい。サポートする文法の情報はもちろん DLL付きの情報。CDllHandlerは汎用的すぎるから、その任には、CDllHandlerを継承したいまの CBregexpから BREGEXP構造体だけを追い出したものを充てればいい。

いまの CBregexpは InitDll()を呼び出されて、途中で違う正規表現ライブラリを読み込まされたとき、コンパイル済みの BREGEXP構造体を正しく解放できるのだろうか?


 @2009-10-01

BREGEXP.DLLでも . と $ を置き換えるようにしてみた > fix_cr_handling_of_regex_ANSI.rev2(下に rev3)

副作用があって、XYZ(CR)(LF) という行に対して XYZを検索すると XYZ(CR)(LF) がマッチする。マッチ結果が改行に隣接しているとき、改行がマッチに含められます。$を検索すると (CR)(LF) がマッチするのは以前からの通り。ここが変わらないのは、一括置換での過剰な置換を防ぐ手立てがこれしか BREGEXP.DLLからは与えられていない、ということ。

ついでに気になった、\r\n を検索したときステータスバーに 1 bytes selected. と表示されるのを修正。>fix_selection_area_and_selected_byte_count_ANSI 選択領域が中途半端なサイズだったのも直った。それもこれも CLayoutが EOLの長さを常に 1とカウントしていたせい。マッチ範囲が勝手に 1切り詰められていた。

表示としては ↵ も ⇠ も ⇣ も同じ一字だから CLayoutのすることにも一理あるのかもしれない。それなら改行文字の部分の選択領域をせめて全角幅にして検索結果のハイライト部分と大きさをそろえよう。

ANSI版の View関連のソースを見てたら気が遠くなる。Unicode版で

  • CRLFを全角幅で表示
  • CRLFの CR、LFのみハイライト、選択
  • LF、CRの全角表示、全角幅選択(or半角幅ハイライト)
  • 行頭マッチ(^)でキャレット描画

あたり、なんとかならんかな。検索結果の選択範囲とハイライト領域のずれが気になる。


 @2009-10-03

ANSI版を BREGEXP.DLLと組み合わせているときに、不必要に改行が検索結果に含まれてしまう場合を rev2より大幅に減らした。意地悪なパターンを与えられたときにどうなるかは把握しきれていない。

> fix_cr_handling_of_regex_ANSI.rev3(rev2と rev3にバグ発覚。rev4へ)


fix_cr_handling_of_regex_ANSI.rev4

どういうバグだったかというと、一括置換をしたときに改行や行文字列末尾付近で過剰に置換が行われないように、戻り読みが使えない BREGEXP.DLLのときは検索パターンと置換文字列に細工を施すのだけど、検索パターンの置き換え方がまずかった。

 誤: /A|B/ -> /A|B((?:\r\n?|\n\r?)?)/
 正: /A|B/ -> /(?:A|B)((?:\r\n?|\n\r?)?)/

選択 | の結合順位は一番低いのでした。


バグは CBregexp.cppを好き勝手にいじっていた結果をテストしている最中にたまたま見つかった。

  • メンバ関数に constをつけたり
  • 正規表現フラグを指定する引数の型を intから専用のものに変えたり
  • CBregexp::IsLookAhead(const char *pattern)が内部状態を変更して、CBregexp::Match()の結果に意図しない影響を与える可能性を排除したり

していた。これは単なる自己満足。


 @2009-10-04

不必要に選択範囲が改行にかかっていたケースををさらに減少。> fix_cr_handling_of_regex_ANSI.rev5 検索パターンが LF直前や文字列末尾に幅0マッチしそうなときにだけ細工を行うことにした。なんというか、盆栽趣味?

バイナリ>sakura.zip


 @2009-11-25

AINI版では LFCRの LFと CRの間に幅0マッチしそうなときも細工を行わないといけないだろうな。やらないけど。(LFCR?なにそれ?という立場)

* あえて (?<=[^\r\n])$ を使ったつもりでいたけど、実は (?<![\r\n])$ の方が最適だった可能性。二者の違いは>[[20080528p01]]。ただし、サクラエディタ的には EOFのみの行は存在しない(行番号も表示しない)ものらしいので、どちらのパターンを使っても実際の違いは生じない。

 扱うファイルが ASCII onlyという可能性、FontLinkパッチ<https://sourceforge.net/tracker/?func=detail&aid=1832567&group_id=12488&atid=312488>を自分で当てている可能性はある。


2009年09月12日 (土) ブラウザとエディタで確認した。Ctrl+BackSpace、Ctrl+Deleteで単語単位の削除。

最終更新: 2011-03-25T01:34+0900

[SakuraEditor] シンボリックリンクを開いたとき、更新通知の無限ループ

そして素朴な疑問。選択肢が 4つあるんだけど

  • 再読込(&R)
  • 閉じる(&C)
  • 以後通知メッセージのみ(&M)
  • 以後更新を監視しない(&N)

閉じるをクリックしても予想に反してエディタは閉じられないのと、(延々と表示され続けてもおかしくない)通知メッセージはどこに出ているのか?


 @2010-07-08 補足。

シンボリックリンクを開くと、ショートカットファイルを開いたときと同じようにターゲットファイルの内容がエディタに表示される。そして他で何もせずとも、最初に必ず更新通知ダイアログが表示される。だから「再読込」を選ぶと読み込み後にまた更新通知ダイアログが表示されることになって無限ループ。「閉じる」(=ダイアログを閉じる=更新を無視する)を選ぶと今度はターゲットファイルが本当に更新されたときも察知できなくて永遠に黙る。

対策は、シンボリックリンクを開いていることを意識して、常に(ファイルの読み込みと更新監視で共通して)ターゲットファイルの更新時刻を調べるようにすること。

っていうほど単純でもない。更新日時だけ特別扱いしたらファイルの属性に一貫性がなくなる。更新監視部分でだけターゲットファイルの更新日時を比較するのが影響範囲が最小だけど更新日時を保存するメモリ領域をどこかの管理下に用意しないといけない(だれが管理する?もちろん CEditDocのメンバの CAutoReloadAgent)。一番面倒がないのはシンボリックリンクのターゲットをたぐってそのファイルを開いたことにすること(ショートカットと同じ)。なんとなくこれが嫌なのはカレントディレクトリが変わってしまうこと。他にもいろいろあると思う。ショートカットでなくシンボリックリンクを使うのは、ターゲットファイルがそこにあるようにアプリケーションをだましたいときだから、サクラエディタも(今はタイムスタンプ取得方法の一貫性のなさからかおかしなことになっているうえ、だまされているせいで更新の監視ができていないが)上手にだまされてほしい。

 @2010-07-08 更新通知ダイアログがわかりにくい

  • 「閉じる」って何を閉じるの?
  • 「以後通知メッセージのみ」「以後更新を監視しない」って結局再読み込みするの?しないの?

ので、こうした(improve_fileupdatequery_dialog.patch)。

わかりにくいと感じてるのは俺だけじゃなくて、sakura-dev:3014で wmlhq氏が書いている。

なお、更新通知ダイアログはわかりづらいようなので、次のようにしてください。

----------------------------------------
<!> このファイルは別のプログラムによって変更されました。

読み直しますか?
----------------------------------------
 [ ]今後、ステータスバーに通知する 
 [ ]今後、通知しない 
----------------------------------------
[はい] [いいえ]
----------------------------------------

日記を書く段になって見直したんだけど wmlhq氏のメッセージのほうが良い。

  • 「更新の監視をやめる」という俺のメッセージは不正確だから。(タイマーは常に動いていて、タイムスタンプの比較をしなくなるだけ)
  • 通知メッセージがステータスバーに表示されることがわかる。
  • サルでも答えられる Yes/Noクエスチョン。

2009年09月02日 (水)

最終更新: 2009-09-02T23:44+0900

[SakuraEditor] http://coderepos.org/share/browser/platform/sakura-editor/

キーワードファイルなんかはみんなでいじくって改善するのにちょうどいいものだと思ったら、やはり、CodeReposにあった。ただし PHPのみ。

キーワードの羅列には興味がないけど(php-mkkwd.phpは別)、正規表現キーワードは共有して他人のも見てみたいなあ(楽ができるから)。javascript_re_keywords.rkwRuby_re_keywords.rkw


2009年08月25日 (火) Emacsってイーマックスだったのねん。エマックスだとばかり……。VMAX(名前からの連想)みたいなデカブツは好みじゃないんだよね……って、どちらも重量級だからそれでいいのか。Emacsは(名前も含めて)好きにならないだろう。

最終更新: 2010-05-19T17:19+0900

[SakuraEditor] クォーテーション文字列の色分け。

 確かに変ですが、ここの部分をきっちりやろうとするとレイアウト処理性能にシビアに影響するみたいです。
 ざっと試したところでは、ファイル読み込みで1.5~3倍くらいの処理時間がかかるようになってしまいました。
 右端で折り返す設定で画面幅を変化させるときの応答にも同様に効いてきます。

さらりと、できなくはないと書かれているが、どうやるんだろう?

sakura_core\view\colors\CColorStrategy.cpp の後半(「色開始」部分)をこう書きかえてみても中途半端な結果。ファイルの内容は同じでも、文字の追加や削除、アンドゥなどの操作によって、意図通りの結果になったり現行通りだったり。処理速度に関しては、5MBのファイルを開いてファイルタイプをいろいろ切り替えてみたら、変更前よりプログレスバーの進みが明らかに遅い。1.5から 2倍というのは体感に一致している。

bool CColorStrategyPool::CheckColorMODE(
	CColorStrategy**	ppcColorStrategy,	//!< [in/out]
	int					nPos,
	const CStringRef&	cLineStr
)
{
	//色終了
	if(*ppcColorStrategy){
		if((*ppcColorStrategy)->EndColor(cLineStr,nPos)){
			*ppcColorStrategy = NULL;
			return true;
		}
	}

	//色開始
	if(!*ppcColorStrategy){
		for(int i = 0; i < (int)m_vStrategies.size(); ++i) {
			if(m_vStrategies[i]->BeginColor(cLineStr, nPos)) {
				*ppcColorStrategy = m_vStrategies[i];
				break;
			}
		}
	}
	return false;
}

違う。CheckColorMODE()のときに正規表現キーワードは働いてない。そもそも CheckColorMODE()の目的って? CLayoutMgr::Match_Quote()がとりあえず行末を返す( return cLineStr.GetLength(); )のって? それでどうやって行をまたげているんだろう。


白々しさ爆発だけど書く。下は sakura/trunk2/sakura_core/doc/CLayoutMgr_DoLayout.cpp から削除されたコード(の一部)。この部分が修正を加えられたうえで sakura_core/view/colors/CColorStrategy.cppに移動している。return falseを使わずに breakしているあたりがさらに嘘くささを増してるけど、別に、このときの変更をロールバックしたかったわけじゃない。知らなかったし、参考にしたのは SColorStrategyInfo::DoChangeColor()の方。

	if(!*ppcColorStrategy){ 		
		CColorStrategyPool* pool = CColorStrategyPool::Instance(); 		
		for(int i=0;i<pool->GetStrategyCount();i++){ 		
			CColorStrategy* pcSample = pool->GetStrategy(i); 		
			if(pcSample->BeginColor(cLineStr,nPos)){ 		
				*ppcColorStrategy = pcSample; 		
				//bRet = true; 		
				break; 		
			} 		
		} 		
	} 		

俺が感じたプログレスバーの進みの遅さはたぶん基底クラスからの仮想関数の呼び出しに伴うものだったんだろう。一歩戻って進んで、ふりだしに戻る。


CheckColorMODE()がないとクォーテーション文字列が行をまたげない。

レイアウト(禁則処理とか折り返しとか)とクォーテーション文字列(+コメント)の関係がわからない。癒着してるなら、ボトルネックにもなってるらしい CheckColorMODE()をなくして、正規表現キーワードが行をまたぐことでカバーしたい。


 @2010-05-19 関連ログ発見

http://sakura-editor.sourceforge.net/cgi-bin/cyclamen/cyclamen.cgi?log=dev&v=4079#4083

サクラエディタの色分け解析ルーチンは、全部で3つあって、

  • 行データの変更に、各レイアウト行の先頭色を決めるもの(CLayoutMgr)
  • 実際の作画時に各文字の色を決定しつつ作画するもの(CEditView::OnPaint)
  • 対括弧の色を戻すときに各文字の色を決定するもの(CEditView::GetColorIndex)