/ 最近 .rdf 追記 設定 本棚

脳log[SakuraEditor: 2010-09-15~]



2010年09月15日 (水)

最終更新: 2013-01-11T22:45+0900

[SakuraEditor] 拡張子のないファイルにもタイプ別設定を自動適用する。

どこかに書いた気がするのに見つからないのでもう一度。

サクラエディタは拡張子を見てファイルの種類を区別し、色分けルールやタブ幅、折り返しルールなどを使い分けるが、拡張子がない makefileや ChangeLogはみんな「基本」設定になってしまう。

 案1: 「拡張子」ではなくファイル名の末尾に対するマッチングでファイルタイプを区別する。

ファイル名の末尾が .rb だったら Ruby。.js だったら JavaScriptという具合。ファイル名の末尾(といいつつ全体)が makefileだったら makefile、.htaccessだったら Apache HTTPD設定ファイル。

ところがサクラエディタが設定として持ってる、判別のための拡張子リストが

c,cpp,cxx,cc,cp,c++,h,hpp,hxx,hh,hp,h++,rc,hm

という具合に、「ドット省略必須」「スペースorカンマorセミコロン区切り(ヘルプによればカンマ区切りらしいが、「,」と「.」が紛らわしいのでスペース区切りにするのがいいよ)」のリストなもんで、この案は没。広まってしまったドット省略拡張子リストに対処することができないので。

 案2(採用): 「拡張子」がないときはファイル名を拡張子として扱う。

makefileを .makefileだとみなしてファイルタイプを判別するということ。

パッチ> guess_filetype_of_extlessfile.rev2.patch (0.9KiB)

JSという名前のファイルが拡張子が .jsの JavaScriptファイルだとみなされることになるけど、気にしないよね。

 @2012-11-04 moca_skrさんによるパッチ。

>>SourceForge.net: Sakura Editor: Detail: 3581841 - タイプ別設定の拡張子を二重・なしにも対応

0 < _tcslen が使われてないところが好み。zero fill(""での初期化)するかしないかに強い意見はない。結局呼び出した関数が null-terminateするかギリギリまで書き込むかに依存するのだから。自分に影響がありそうな部分にコメントした(試してないので勘違いかも)。


杞憂だった。恥ずかし。GetDocumentTypeOfExtはパッチだけでは全体がわからないから元のファイルにあたってみて、その後でパッチの追加部分に戻ってくるのを忘れてた(という言い訳)。


GetDocumentTypeOfPathでごちゃごちゃせずに、引数として渡されたファイルパス(pszFilePath)をたどって最後のパスセパレータの次の位置を指すポインタを GetDocumentTypeOfExtに渡すだけにしたらすっきりするのに、と思った。a...............................................b.txtみたいなファイルでスタックオーバーフローを起こすだろうか。


@2012-11-06 ちょっと臆病になってここに書くけど、二重拡張子探索のためにファイル名からピリオドを探索するときに _tcschr を使ってるけど _tcsrchr ではないのかな。_tcschr を使ってるなら、すぐ上に書いたようにバッファの確保も _tsplitpathも省いて _tcsrchr(pszFilePath, TEXT('\\'))で得たポインタ+1を GetDocumentTypeOfExtに渡すのと似た結果になりそうだが。

_tcsrchrを使うには表(Shift_JISだと2バイト目が\と同じ)のような文字対策が必要で、_tsplitpathはそういうのも隠蔽してくれてるのかな。だとしたら似た結果にはならないか。

再度考え直し。_tcsrchr が _mbsrchr にマップされる可能性。_mbsrchr はうまくやってくれるのだろうか。

こんなんだからこそ JScriptでパスを扱うときは必ず

new ActiveXObject("Scripting.FileSystemObject").GetFileName
new ActiveXObject("Scripting.FileSystemObject").BuildPath

を使って、自分で文字列処理をしないのだけど、_tsplitpath が拡張子付きのファイル名を返してくれなかったりするから自前でやるはめに。Cだから固定長バッファが前提でその長さが問題になってくるからかもしれないが、ケチるんだったらポインタで返してくれたらいいのに。引数のここからここまでがファイル名ですって。正規化したいから無理だって?


 @2012-11-13

..............................................................................................................................................................................................................................................t

というファイル名を、trunk2@2457 + skr_imp_ext_ex.patchで、試してみたけれどスタックオーバーフローは起こせませんでした。ピリオドの数よりちょっと少ないくらい GetDocumentTypeOfExtが呼ばれる(二重拡張子でなく多重拡張子をテストしてる)のは確認できたけれど。

 @2013-01-11 コミットされています。

http://sourceforge.net/p/sakura-editor/code/2565/

そういう機能が欲しいと思ったから自分でも改造してたんだし喜ばしいことなんだけど、自分でビルドするサクラエディタに反映するとコンフリクト必至なのが憂鬱。

 RUNESOFTのインストーラが、ユーザーがインストール先を変更したときに、レジストリに記録するインストールフォルダ末尾に \ を付け忘れてしまい、おそらくファイル名を連結するときに \ を補わなかったのだろう、ゲームの起動に失敗するというポカをやらかしていた。


2010年09月07日 (火)

最終更新: 2010-09-15T20:40+0900

[SakuraEditor][正規表現] 検索。置換。

Command_REPLACE(置換)や Command_REPLACE_ALL(すべて置換)が Command_SEARCH_NEXT(下検索)を呼ぶのをやめたい。連携手段がレイアウト座標を基にした選択範囲しかなく、一文字で表現される CRLFの LFだけがマッチしたときに情報が欠落するし、Command_SEARCH_NEXTが持つ検索以外の事前・事後処理が無駄になるし、正規表現検索が BMatch(検索), BSubst(検索&置換)の計二回行われるのも無駄。

wchar_t単位で検索を行う CSearchAgent::SearchWordが、検索結果をレイアウト座標に変換する際の誤差(前述)を考慮してマッチ範囲を拡大し、結果を不正確なものにするのは誤りだと思う。それより、上の層でこれを呼び出している CLayoutMgr::SearchWordがその配慮を行うべきでは。

 あったらいい操作

Match
対象文字列の対象範囲全体がパターンに一致するか調べる。
Search
対象文字列の対象範囲からパターンに一致する部分を探す。
Replace
対象文字列の対象範囲からパターンに一致する部分を探し、与えられたフォーマットの文字列に置き換えた文字列を返す。(返るのは対象文字列の対象範囲に相当する文字列)
Expand
Matchや Searchの結果を用い、マッチ全体($0)を与えられたフォーマットの文字列に置き換えた文字列を返す。
パターン
BREGEXP.DLLは m/pattern/flags/pattern/replace/flag も同じ一つのパターンとして扱うので、検索用のパターンと置換用のパターンに互換性がない。そうではなく、Search(Compile("pattern", flag), "target", startindex), Replace(Compile("pattern", flag), "target", startIndex, "replace") だったら良かった。(※ "pattern" と "target" と "replace" は実際は二つの引数で表す)

bregonig.dllや bregexp.dllを使いながらパターンの共通化や Expandの不足に対処するにはどうするか。自分で Expandを実装し、dllが用意した置換機能(置換パターン)を使わないで済ませる。でもねえ、実装の数だけ仕様がある状態を避けたいから Expand機能をライブラリに用意して欲しいわけで。(置換文字列の $$ が $に展開されなかったり、\1 が展開されたり、$1が展開されなかったり、色々あるんよね)


 @2010-09-10 悪夢のような「クリップボードから貼り付ける」置換オプション。(本当は矩形選択が)

  • CRLFの CRだけや LFだけをクリップボードの内容で置き換えることができない。
  • 正規表現検索のとき検索始点(終点)挿入オプションがきかない。
  • クリップボードの形式が矩形テキストだったときに検索条件によっては無限ループ。

    例えばクリップボードに

    789
    456
    123

    という 3行9文字(改行文字はない)がおさめられているとき、マッチと置き換えられるのは 789 であり、456 123 はそれぞれ次行、次々行に挿入される。つまり、456 123 はこれから検索対象になるということだ。検索条件が \d{3} だったり ^ だったり、矩形テキストの二行目以降にマッチするものだったら無限ループ。

置換操作が二階層潜らないとロジック単位にならないというのも悩みの種。検索はロジック単位で行えてるのに、それをレイアウト単位に変換してそれがさらにロジック単位に変換されて、一対一対応じゃないからごにょごにょしないと思い通りに置換されなくて。

 @2010-09-15

どうして最上層のレイアウトを基準にして文字列処理を行わなければいけないか。文書(wchar_t列としておく)の変更を LayoutMgrに通知する仕組みを整備するのを怠って、LayoutMgrを通して文書の変更を行うことで通知を不要にしていることが背景にあるのでは? GUIを通しての文字列操作に限ってはそれで十分だからそうなるのも仕方ないし、必要に迫られた人間(俺とか)がより汎用的な手段を整備せずにダーティハック*に頼る方が罪は重いかも。

* 挿入位置・置換範囲を文字レイアウト境界まで拡大して、挿入・置換文字列も同じだけ拡張する。


2010年08月30日 (月)

最終更新: 2010-08-30T23:07+0900

[SakuraEditor] 2ch. 正規表現キーワード

規制で書き込めないのでここで。

583 :名無しさん@お腹いっぱい。:2010/08/25(水) 15:31:52 ID:wtW19SUb0
    頭に**がある行はコメント行として緑色にする
    という正規表現での色分けと
    ABCという言葉は赤色にする
    という正規表現の色分けを同時にする方法はありますか? 

    (省略)

587 :名無しさん@お腹いっぱい。:2010/08/30(月) 14:18:00 ID:yI6qoQsb0
    >>584
    正規表現キーワードって、設定の上下に優先度あるらしいけど(ヘルプ情報)、結局の所、先に検索で引っかかった方が優先されるらしいよ。
    wiki でバグじゃないかと報告されて、誰かが仕様じゃボケぇ、なんもおかしなことないわ! と切れてた。

    個人的には、キーワードに優先順位があるならそれに準拠して欲しいと思うんだけどね。
    なんていうか、二つの仕事を割り振られたA君が優先順位を決めて作業した結果、端から結果だけ見ると作業をひとつしか終えていないように見えるんだよね。
    言葉の意味をはき違えているように思えて、そこが気持ち悪い。 

言及されてるバグ報告ってのはこれ。>>BugReport/60 - SakuraEditorWiki

587の、自分の想定した動作モデル以外を認めない姿勢がなんだかなあ。いわく「優先順位があるならそれに準拠して欲しい」いわく「言葉の意味をはき違えているように思え(る)」。バグ報告者の方は単なる理解不足だし、あんなに噛みつかれたことに同情するけど。

優先順位は確かに存在してる。使われ方が 587の期待と違うだけで。たとえに沿って説明すると、仕事は最初から一つしかない。「正規表現キーワードの色分け」これひとつ。何をキーワードとみなすかの判断基準として複数の正規表現が存在してるだけ。複数の正規表現のマッチが重なったときに最も左から始まり最も上にあるパターンが優先される。最も左が優先されるのは正規表現キーワードを含む色分け要素(文字列、コメント、URLなど)間の順序付けにも利用されてる大原則なのでわざわざヘルプに書く必要を感じなかったんでしょうよ。上の方のパターンが優先されるというのは、コメントなど他の色分けより正規表現キーワードの色分けが優先される(これもヘルプに書いてある)と言うときと、全く同じ意味で使われている。不自然なことはない。

「先に検索で引っかかった方が優先されるらしいよ」というのは嘘。「先に」(時間的な前後)ではなく「前の方で」(空間的な前後)なら間違いではないが。

バグ報告した人(たぶん 587も)の希望する動作を強調キーワードに置き換えると、「『IN』『SELECT』『EXISTS』『JOIN』というのを強調キーワード1,2,3,4にしてそれぞれ別の色に色分けするようにしている。強調キーワード1は強調キーワード4より優先されるはずだから JOINの中の INが色分けされないのはおかしい。」という内容になる。Keywordの中に別の Keywordがあるなんて想定はない方が普通でしょう。

7195の System_UPJさんのように動作を理解した上で使いこなしてる人もいる。ヘルプには改善の余地があるとしても今の動作はバグではないし変更されると困る人が(正規表現キーワードの利用者の中では、たぶん)大多数。存在しない別の機能を要望していることに気付くべき。

583へのレスとして用意した、んで規制された、文章ものせとく。

Wikiでも似たような要望がバグとして報告されてたけど、よくある要望なんかね。
手持ちの案はこげな感じ。
1.キャブチャ部分に別の色を指定できるようにする。
2.従属的な正規表現キーワードを指定できるようにしてキーワード内キーワードを
  色分けできるようにする。
3.萌ディタのように色分けに状態を持たせる。
実装の難易度   1=2<3
設定の面倒さ   1=2<3
色分けの自由度 1<2<3

2010年07月30日 (金)

最終更新: 2012-11-01T13:41+0900

[SakuraEditor][SHJS][Ruby] Rubyの %リテラルの色分けを修正。

説明が面倒なのと誰も知りたくないだろうから適当に、備忘のためだけに。

  1. まさか %{literal}literal部分で \{\} を使う人間がいるとは思わなかった。(違う種類の括弧を使えばいいじゃない。開閉の釣り合いがとれてれば同じ種類の括弧でもエスケープ不要だし)
  2. だのに Ruby1.9の rake.rbにこんなパターンが……

    %r{[*?\[\{]}
  3. エスケープされた { 2のはの考慮がないから、閉じ括弧が足りないとしてファイル末尾まで正規表現として色分けされてしまう。
  4. ちょちょちょいと .rkw2ファイルにエスケープ文字を追加してサクラエディタに対する修正は完了
  5. SHJSの lang/sh_ruby.js(自作)への対応も同じですむはずが、入力の末尾に達した時点で意図せぬバックトラックが発動し、閉じ括弧が足りなくても色分けが適当な閉じ括弧で終了してしまう現象に遭遇。これは自業自得(20090808p01)なので自分でなんとかせねば。間違いが埋没してしまうのはよろしくない。
  6. こうした

    %r{余分な開き括弧{。間違いはインタープリタを通す前から目立つように}

2のは Rubyインタープリタに対するエスケープ、と同時に正規表現パターンとしてのエスケープですよ。%r[\[] と /\[/ が同じパターンになって、%r[[] がRubyのシンタックスエラー、/[/ がパターンのコンパイルエラーになるんだから。(ruby 1.8.7 (2010-01-10 patchlevel 249) [i386-mswin32] / ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32])


2010年07月09日 (金) Windows Confidential: The Third Rail of Keyboard Shortcuts | TechNet Magazine」を読んでの違和感。レイモンド チェンは Win+Eがどこを開くかの話をしている。おれは Win+Eがどこを開くかなんて確かめたことがなく、Windows Explorer――フォルダを表示するときに利用される簡易表示ではなくフォルダツリーが付いた正式版――を起動するためのショートカットだと思っていた。そんで、だから、使ってない。

最終更新: 2014-01-02T18:04+0900

[SakuraEditor][正規表現] 「鬼車と bregonigに hitEnd(20100531p01)機能が搭載されることを願う他力本願日記」

なんてことをこの日記の冒頭に掲げたもんだから自分でやってみた(どういうこと?)。

 更新履歴

rev3 (2010-09-05, そのうち書く)
(サクラエディタ) 複数行検索を利用した複数行置換を実装。(複数行全置換はまだ。似たようなコードだし必要なのは手間だけだけど)
rev2.1 (2011-01-29)
(サクラエディタ) バグ修正。複数行検索モードでマッチ位置をバッファ内インデックスから(行,桁)に変換する際にミス。誤った検索結果が表示されることがあった。
rev2 (2010-08-27)
(サクラエディタ) 複数行検索モード実装。(正規表現を使った下検索のみ。50MiB制限あり。制限による探索打ち切り・マッチ範囲切り上げの通知なし)
テストバイナリ+変更点(test_multiine_search.zip)
rev1
(鬼車) 普通のマッチなしと、入力次第でマッチする可能性のあるマッチなしに異なる戻り値を割り当てた。
(bregonig) 入力不足のときに BMatchの戻り値を 0(正常終了,マッチなし)にして、エラーメッセージで入力延長によるマッチ成功の可能性を伝えている。
(サクラエディタ) 下検索での入力不足によるマッチ失敗をステータスバーで通知。

 bregonig

既存アプリに影響があるので良くないけど、bregonigへの暫定的な変更はこう。

 regexec_onig(bregonig.cpp)
	} else {
		/* ERROR */
		onig_err_to_bregexp_msg(err_code, NULL, msg);
-		return -1;
+		return err_code == ONIG_MISMATCH_INPUTSHORTAGE ? 0 : -1;
	}

入力が足りなくてマッチしなかったときは、エラーメッセージをセットするけど戻り値は負数(エラー)ではなく 0(マッチなし)。

 鬼車

鬼車(5.9.2)に「K.Takata's software : bregonig.dll」で手に入る onig-5.9.2-mod.diffを適用したものをさらに変更。マッチに失敗したときのエラーの種類で hitendしたかどうかを伝える。ちゃんと動くのか非常にあやしい代物。TODOもいっぱいある。

  • 特定のパターンのパターンに向けた最適化を無効にしている。(そこまで手が回らない)
  • backward searchに対していつ hitendフラグを立てていいのかわからない。(ので未対応)
  • "aaaaa\n" という文字列から [a\r\n]+a というパターンを検索したときにバックトラックにより "aaaaa" がマッチするわけだが、その次の行にも "aaaa.." という文字が続いていた場合は……。一応マッチは見つかっているが hitendフラグも立てたい。
  • [\w\W\s\S] というようなパターンで、メタ文字の登場順([\W\S\w\s]とか)に 依存しておかしな結果になる。(もちろん俺のミス。原因は解らない)

やっぱり鬼車は手に負えないかも。

 サクラエディタ

なんのことはない、影響を受ける既存アプリにはサクラエディタが含まれている。正規表現のコンパイルエラーと入力不足によるマッチなしを区別するためにちょっと変更した。

 複数行検索モード

一行検索(従来動作)してみて、マッチが行末まで続いていたり次の行の内容次第でマッチが成功に変わりそうなときはとりあえず二行ぶん検索してみる。それでも状況が同じなら 50MiBのバッファを埋めてから三度目の検索を行う。50MiBって大きすぎるだろうか。大きさの問題だろうか。かかか。

実装は CSearchAgent::SearchWord()に。これって単語検索専用のメソッドではなかったのですよ。CGrepAgentもこれを利用したらよかった。

バッファの実体は std::wstringで。文字列を比較するにも wmemcmpなりを使おうとして結局 std::wstring("hoge") == L"hoge" を使ったへたれなので、str系のライブラリ関数は恐ろしくて毎回すぐに投げ出します。(あれを使いこなせる人は VBや PHPも使いこなせると思うんですよ)

 TODO
  • 上検索。
  • 検索語ハイライトの処理がたぶん一行ごとに行われている。一行ずつ進みながら複数行を対象に検索を行ってるってわけ。無駄だし目に見えて遅い。
  • バッファ長の制限により、マッチ範囲が途中で切られたりマッチの探索が打ち切られたりしても何も言わないのをなんとか。(制限をなくすかメッセージでも)
  • SourceForge.net: Sakura Editor: Detail: 2309002 - 正規表現による複数行検索対応(簡易版)」のコメントを見ると、検索語ハイライトのほかに「すべて置換」にもパッチが必要そう。パッチを流し読みしてたら BookmarkManager(::MarkSearchWord)までが GrepAgentが持ってたような検索の勝手実装を持ってるらし。SearchAgentを使ってよね。(あ、いや、SearchAgentは当時なかったんだっけ)
  • (複数行)検索にマッチしたなかでも、最初の行がマッチに含まれているか含まれていないかというのは区別する価値がある。サクラエディタの既存の実装は行指向が強いだろうから、「マッチした(ただし先のほうの行で)」ということを勘違いしかねない。(SearchAgentや選択範囲にはそういう指向がないから運良く複数行検索が自然に実装できただけ)
  • (@2011-08-01) [\s\S]*$ というパターン。最後の行の末尾までマッチして欲しいのに一行目の改行直前で止まってしまう。マッチに成功したときの hitEndフラグの扱い。

 @2010-07-12 「鬼車 for Java

hitEnd()の実装の参考になるか?と思ったけどそうもいかなそう。

Revision  74 hitEnd()の実装(但し仕様は満たしていない)。
Revision  85 useAnchoringBounds()及びuseTransparentBounds()に対応。→hitEnd()の実装を修正。
Revision 103 hitEnd()に@Deprecatedを追加。
    /**
     * This method is experimentation phase, and implementation has not been completed yet.
     * @return
     * @deprecated
     */
    @Deprecated
    public boolean hitEnd() {
        return (hasAnchoringBounds ? (range == region.end(0)) : (input.length() == end()));
    }

hasAnchoringBoundsが設定されてる場合は無視するとして、そうでないときは入力の長さとマッチの末尾(end())が一致してることをテストしてるだけに見える。それって hitEnd()とは違うよね。5月31日の日記文字列 aa に対してパターン aa を適用したときに hitEnd()が falseになった事例を引用した。

そうそう。これこそが hitEnd()の使い道 >Check if string is a prefix of a Javascript RegExp - Stack Overflow コメントの最後に見たことのある名前が☺


 @2010-07-12 PCRE

PCRE(現在 ver. 8.10)は戻り読みも再帰も(パターンのコンパイル時の)改行指定オプションもスキャナー的に使うための hitEnd()のような機能(read pcrepartial)も、およそ欲しいものをすべて備えている。悪名高いスタックオーバーフローにも、1.スタック使用量を減らす。2.代替メモリ確保関数を使う(汎用ゆえに遅いmalloc/freeか自作)。3.pcre_exec()の代わりに pcre_dfa_exec()を使う。みたいな各種対策があるらしい。


2010年06月22日 (火) 支払い完了。コナミスタイル先着特典のチャームコレクション3キャラセットでないなら通常版でよい。

最終更新: 2010-06-26T01:41+0900

[SakuraEditor] メニューコマンドの点々。

https://sourceforge.net/tracker/?func=detail&aid=3002900&group_id=12488&atid=1013762#artifact_comment_4019898

たんなる自己弁護に終始するのでここに書くけど、

  • 俺の態度が「現状が最高」と誤解された部分は、張っていた予防線の内幕ばらしに過ぎない。防衛線に余裕をもたせていたというだけのことで、誤解された部分を攻撃材料に使ってはいない。
  • パッチ(現状への変更)を基準にして意見したら、現状支持が目立つのは当然では?
  • パッチを基準にせず、現状の「印刷プレビュー...」の点々を削るようにも意見できたはずだけど、そのときはガイドライン(間違いようもなく、PrintPreviewには付けんな、って例示してある)を未読だったのと最初に参考にしたのが WordPadだった(「印刷プレビュー...」になってる)のでできなかった。
  • 現状の「アウトライン解析...」と「ウィンドウ一覧...」の点を削るように意見しなかったのは、もう書いたように、アウトライン解析というのは名前から推測されるように解析を行うのが主目的のコマンドというだけでなく、関数を一覧にしてその定義にジャンプするためのものだと自分でも思っていたから(むしろそちらが主目的)。定義にジャンプするのが「primary/intended action」だとするなら、表示される解析結果はコマンド実行に必要な補足情報をユーザーに選んでもらうためのダイアログとなり、まさしく点々を付ける理由になる。
  • 現状が基本的に納得できる点々の付け方だった。moca_skrさんのコメントでそれはみくさんの仕事だと紹介されているが、そのときの基準「操作が確定しないものには"..."を付ける」というのは「...はクリックしただけではコマンドが未遂*のものに付いている」という自分の理解と違わないのだから。
  • 他アプリケーションを見ても、...の使い方はかなり恣意的な様です

    だからこそ俺はガイドライン(を紹介するコラム)を紹介したし、MSのアプリしか参考にしてないし、俺判断が入り込まないようにできるだけ緩くガイドラインを適用してはみだした部分だけを指摘したつもりだけど、それでも現状最高うぜーと思うならガイドラインに従って反論してほしいと思う(もちろんガイドライン不採用というのも一つの選択肢として残ってるけど)。

別コメントへの反応。ダイアログのモーダル/モードレスと点々には関係がないと思う。検索ダイアログがモードレスだとモーダルに比べて、ダイアログを表示してからでも検索文字列を編集テキストからコピーしてきたり、スクロールしてテキストを確認しながら検索条件を練ることができて便利、ぐらいの違いしかないのでは。


ああ、いやいや、モードレスであることで違う使い道ができる。コマンドの目的(できれば名前も)が変われば点々の必要性も変わる。

  • 「検索...」->「検索ウィンドウ表示」
  • 「アウトライン解析」->「アウトライン解析結果表示」

ツールパレットを表示するコマンドには点々が付かない(これは既定事項)。サクラエディタの検索画面はモードレスだし勝手に閉じないようにも設定できるので、メインウィンドウの横に置いてツールウィンドウとして利用することができる。その場合「検索...」コマンドは「検索ウィンドウ表示」コマンドとして振る舞っている。モーダルだった以前と違い多目的コマンドなのだが点々はいかがすべき?という内容だったのかも。

こうなると複数あるかもしれないコマンドの使途ではなく、コマンドの名前から主目的を一つ判断して点々の有無を決めることになるだろう。してみると「コマンド名に『アウトライン解析』を選んでいるからには、点々を付けるべきではない」と主張すべきだったかもしれない。解析結果がモーダルダイアログに表示されていたときでも同じ(点々を付けるべきではない)。

「指定行へジャンプ...」のアウトライン版に相当するコマンド名を採用したときには点々を付けるべきだが……と考えながら思い立って「指定行へジャンプ...」を実行したらメモ帳のそれより大きいダイアログが表示された(初めて見た)。場所をとってるのは PL/SQLのコンパイルエラー行を選択するためのもの。先を越された。アウトライン解析結果を参考に特定の行にジャンプするのが目的なら、こういうアプローチもありでは?(やっぱり専用画面の魅力には負ける気もするが)


 @2010-06-25

アウトライン解析ってその結果をジャンプだけでなく色分けや補完にも使いたくなるから、「アウトライン解析」っていう名前のコマンドは消えてもいい。

* 確認のメッセージが表示されるコマンドも未遂には違いないけど、この場合は点々をつけないらしい。

 適用と適応が使い分けられない人はそもそも二種類の似たものがあるということを知らないんだろうなあ。applyと adaptだよ、って見分け方を教える以前の問題。個人的には適応より順応を使うし、「過剰適応」とか「適応放散」みたいな熟語で使うぐらい。あ、過剰適応って専門用語なのね。[[知らなかった|20100512]]。外面と内面の不一致が前提にあるらしい。


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