incolormarker の動作No.08763
IKKI さん 15/10/18 21:37
 
秀丸担当さん、こんにちは。

incolormarker を使ってみました。下記の テスト.mac をサンプルテキスト上で続け
て実行すると、

 ・期待する動作: ケース 3〜7 のみヒットし、他はヒットしない
  (ケース 2, 8 がヒットするべきか否かは議論の余地あり)

 ・実際の動作: 全てのケースでヒットする

という結果になりました。
私が期待していた動作は、下記 SearchInColorMarker サブルーチンのような感じです。

追加の条件のカラーマーカーを使うこと自体初めてなので、何か根本的な勘違いをし
ているかもしれません。
仕様と使い方をご教示いただければ幸いです。

秀丸エディタ v8.56β10


// テスト.mac
$L = currentmacrobasename;
if (!replay) {
 deletecolormarkerall $L;
 // 3桁の数字、および、「<」の直前の0文字を塗る
 setsearch "\\d{3}\\n?|(?=<)", 0x10;
 colormarkerallfound 0xFFFFFF, 0x6666FF, 11, 0, 0, $L;
 settargetcolormarker $L;
}
escape;
searchdown2 "(?\\1)ケース\\d+: *(.*)$", regular, nohilight;
if (!result) endmacro;
$src = gettext(foundtopx, foundtopy, foundendx, foundendy, false);
moveto2 0, lineno + 1;
if (1) {
 searchdown2 $src, regular, incolormarker, nohilight;
} else {
 loaddll hidemarudir + "\\HMJRE.DLL";
 call SearchInColorMarker $src;
 freedll;
}
endmacro;

SearchInColorMarker:
 if (getcolormarker(0x08, $L) == ""){
  nextcolormarker 0x09, 0, $L;
  if (!result) return false;
 }
 ##c = column;
 ##l = lineno;
 nextcolormarker 0x0A, 0, $L;
 $$text = gettext2(##c, ##l, column, lineno, false);
 ##p = dllfunc("FindRegular", $$1, $$text, 0);
 if (##p < 0) return false;
 // このサンプルでは複数行のマッチを考慮していない
 moveto2 ##c + ##p + dllfunc("GetLastMatchLength"), ##l;
 beginsel;
 moveto2 ##c + ##p, ##l;
 endsel;
 return true;

/*
▼サンプルテキスト
テストケース: 検索文字列
対象文字列 → 期待する動作

ケース1: _+\d+
__123__ → ヒットしない

ケース2: (?<=_)\d+
__123__ → ヒットしない (議論の余地あり)

ケース3: _*\d+
__123__ → 「123」にヒットする

ケース4: \d+
__123__ → 「123」にヒットする

ケース5: \c+
__123__ → 「123」にヒットする

ケース6: [\d\n]+
__123
456__ → 「123\n456」にヒットする

ケース7: \d+_*
__123__ → 「123」にヒットする

ケース8: \d+(?=_)
__123__ → ヒットしない (議論の余地あり)

ケース9: \d+_+
__123__ → ヒットしない

ケース10: \d+_+\d+
123__456 → ヒットしない

ケース11: \d+_+
123__456 → ヒットしない

ケース12: _+\d+
123__456 → ヒットしない

ケース13: _+
123__456 → ヒットしない

ケース15: >
__><<__ → ヒットしない

ケース16: <
__><<__ → ヒットしない

*/

[ ]
RE:08763 incolormarkerの動作No.08765
h-tom さん 15/10/19 03:19
 

h-tom です。

settargetcolormarkerのヘルプを見ると、
> 文字列の先頭に"#"を付けると、次の文字から任意のレイヤー名を指定できます。
> (例:"#mylayer")
となっているので、

> settargetcolormarker $L;
  settargetcolormarker "#" + $L;
とするのが正しいかと思います。

変更後は、全部ヒットする事は無くなりましたが、ケース5、7がヒットしません
でした。
マクロの使い方は間違っていないと思ってますが、確認してみてください。

[ ]
RE:08765 incolormarkerの動作No.08767
秀丸担当 さん 15/10/19 13:50
 

settargetcolormarkerについては、h-tomさんの言われる通り、"#"を先頭に付け
るとできると思います。
それを適用させた場合、ケース2と8はヒットする、ケース5と7が期待とはヒット
しない、という期待とは違うかもしれないことになりました。

動作としては、範囲に絞らない通常のヒットした結果がまずあり、その結果と、
カラーマーカーの重なりをチェックして、カラーマーカーの中に全部入っていた
らヒットとみなす、というようにしています。
これは従来からある「追加の条件」の強調表示に絞った場合も同様でした。

あらかじめ範囲に絞ってから検索するという方法に変えるとしたら、ちょっとや
やこしいことになりそうです。
CSVの列に絞った置換で変換モジュールを使う話題のとき、カラーマーカーに絞
った検索を作っても、こういう問題が起こり得るのではないかということがあり、
やはりそういう問題はありそうです。

[ ]
RE:08767 incolormarkerの動作No.08769
IKKI さん 15/10/19 16:54
 
h-tomさん、秀丸担当さん、ご教示ありがとうございました。

>動作としては、範囲に絞らない通常のヒットした結果がまずあり、その結果と、
>カラーマーカーの重なりをチェックして、カラーマーカーの中に全部入っていた
>らヒットとみなす、というようにしています。
期待とは違いましたが、既存の「カラー表示の条件」と同じ動作ということで了解し
ました。

>settargetcolormarkerについては、h-tomさんの言われる通り、"#"を先頭に付け
>るとできると思います。
あああ…そうでした。私もヘルプを読んで「気をつけねば」と思ったのですが、案の
定失念しました。
予約語が普通の文字列で、一般のレイヤ名が特別扱いになっているというのは非常に
違和感があり、今後もうっかり忘れそうです。
内部実装がそのようになっているのは構いませんが、ユーザーに見せる部分に関して
は、もうちょっとこう、何というか、何とかならなかったものでしょうか…。
じゃあ代案を出せと言われると自信がないのですが、あえて例を挙げれば…

 // 代案1
 settargetcolormarker $mylayer; // 一般のレイヤ
 settargetcolormarker ""; // 一時的なカラーマーカー
 settargetcolormarker "\x01"; // すべて検索 - 色付け
 settargetcolormarker "\x02"; // 複数選択予約

 // 代案2
 settargetcolormarker 0, $mylayer; // 一般のレイヤ
 settargetcolormarker 0; // 一時的なカラーマーカー
 settargetcolormarker 1; // すべて検索 - 色付け
 settargetcolormarker 2; // 複数選択予約

…という感じで、いかがでしょうか。

>CSVの列に絞った置換で変換モジュールを使う話題のとき、カラーマーカーに絞
>った検索を作っても、こういう問題が起こり得るのではないかということがあり、
>やはりそういう問題はありそうです。
この問題に対しては、置換の変換モジュールを使えばとりあえず対応できますが、
それとは別に、もっと包括的な解決策を別途提案してみたいと思います (後日になり
ます)。

[ ]
RE:08769 incolormarkerの動作No.08772
秀丸担当 さん 15/10/20 09:40
 

settargetcolormarkerについては、β10より前は、以下のような感じにしていま
した。
 settargetcolormarker $mylayer; //一般のレイヤ
 settargetcolormarker "\x01#allfound"; // すべて検索 - 色付け

内部的な表記が見えてしまうのはユーザーフレンドリーではなく、何とかならな
いかと思って"#mylayer" "allfound"としてみました。
"\x01" "\x02"と制御コードを使っていくと、もし今後増えるとしたら"\x0A"ま
で行ったりすると少し変な気がします。(そこまで行くことは無いと思います
が)

数値も考えましたが、targetcolormarkerというキーワードもあり、一意の文字
列であったほうがいいと思います。
このあたりがどうもしっくりこなかったので、仕様として確定させていなかった
点でした。
"\x01#allfound";という方式のほうがよさそうであれば、いまのうちであれば変
更できると思います。どうでしょうか。

[ ]
RE:08772 incolormarkerの動作No.08775
IKKI さん 15/10/20 12:52
 
>"\x01#allfound";という方式のほうがよさそうであれば、いまのうちであれば変
>更できると思います。どうでしょうか。
内部レイヤ名が "\x01#〜〜" の形で統一されていて、他のカラーマーカー系の文で
も同様に使えるのなら、それをユーザーに公開してしまうのが一番スッキリすると思
います。
重要なのは getcolormarker(0x08, targetcolormarker) のように値をそのまま他の
カラーマーカー系の文に与えることができることであって、そこに制御コードが含ま
れているかどうかは今さら気にすることでもないと思います。
というわけで、こんな感じでどうでしょうか。

 // 代案3
 settargetcolormarker $mylayer; // 一般のレイヤ
 settargetcolormarker ""; // 一時的なカラーマーカー
 settargetcolormarker "\x01#allfound"; // すべて検索 - 色付け
 settargetcolormarker "\x01#diff"; // 比較結果
 settargetcolormarker "\x01#reservedmultisel"; // 複数選択予約

ユーザーフレンドリーという観点では、代替表記として内部レイヤを示す予約語を受
け付けるようにしてもいいかもしれません。

 settargetcolormarker findmarker; // すべて検索 - 色付け
 settargetcolormarker diff; // 比較結果
 // (複数選択予約レイヤを示す予約語はない?)

ご検討いただければ幸いです。

[ ]
RE:08775 incolormarkerの動作No.08776
IKKI さん 15/10/20 12:56
 
> 代替表記として内部レイヤを示す予約語を受け付けるようにしてもいいかもしれま
>せん。
もしこれをするなら、findmarker などの予約語を単なる文字列値にしてしまうと良
いと思います。
そうすると if (targetcolormarker == findmarker) {...} のような比較ができて嬉
しいです。

[ ]
RE:08775 incolormarkerの動作No.08777
colder さん 15/10/20 14:13
 
colderです。

>>"\x01#allfound";という方式のほうがよさそうであれば、いまのうちであれば変
>>更できると思います。どうでしょうか。
>内部レイヤ名が "\x01#〜〜" の形で統一されていて、他のカラーマーカー系の文で
>も同様に使えるのなら、それをユーザーに公開してしまうのが一番スッキリすると
>思います。
>重要なのは getcolormarker(0x08, targetcolormarker) のように値をそのまま他の
>カラーマーカー系の文に与えることができることであって、そこに制御コードが含
>まれているかどうかは今さら気にすることでもないと思います。
問題は一般のレイヤ名に制御コードが含まれているものも使えてしまうことだと思い
ます。
特に、targetcolormarkerの値をそのままカラーマーカー系の文に渡すと内部的なレ
イヤ名と同名のレイヤ名と簡単に作れてしまいます。
そのようなものを作ってしまうとその後の検索等にいろいろ不具合が出てくる可能性
が高いです。
現在の方式であれば、このような問題は発生しません。

[ ]
RE:08777 incolormarkerの動作No.08778
IKKI さん 15/10/20 15:14
 
>問題は一般のレイヤ名に制御コードが含まれているものも使えてしまうことだと思
>います。
私もその懸念は考えましたが、任意名のレイヤを作れるのはマクロ作者だけなので、
基本的には

(a) 制御コードを含むレイヤ名はいじらないようにする

という紳士協定で十分かなと思いました。もし紳士協定では不十分なのだとしたら、

(b) colormarker 文等でレイヤ名をチェックし、制御コードを含んでいたらエラーに
する
(c) 内部的に読み取り専用フラグを追加し、ユーザーによる改変を防ぐ

のような方法で不具合は防げると思います。いかがでしょうか。

[ ]
RE:08778 incolormarkerの動作No.08779
秀丸担当 さん 15/10/20 15:57
 

"\x01#〜〜"の方式で、さらに予約語としてあるとすっきりしていいと思います。

colderさんの言われるような懸念も確かにありますが、先頭の\x01はできないよ
うに変更してしまっても大きな問題にはなりにくいと思います。
"\x01#〜〜"のやり方で考えてみます。

[ ]
RE:08779 incolormarkerの動作No.08783
秀丸担当 さん 15/10/22 16:56
 

β11で仕様を変更してみました。
settargetcolormarkerは、"\x01#"が先頭にある場合は予約語で、それ以外は"#"
を付けずにできるようにしました。

 settargetcolormarker $mylayer; // 一般のレイヤ
 settargetcolormarker ""; // 一時的なカラーマーカー
 settargetcolormarker "\x01#findmarker"; // すべて検索 - 色付け
 settargetcolormarker "\x01#reservedmultisel"; // 複数選択予約

以前にgetcolormarkerで"\x01#allfound"をやめてfindmarkerにしたということ
を忘れていました。
それに合わせて"\x01#findmarker"にしました。
"\x01#allfound"も一応使えますが同じ意味です。

固定文字列のキーワードとしてfindmarkerとreservedmultiselを追加しました。
"\x01#diff"とdiffキーワードも一応付けてみて、このあたりの詳しくはヘルプ
には書いていないです。
settargetcolormarkerのヘルプに注意書きのように書いてあるだけで、また書き
ます。

[ ]
RE:08783 incolormarkerの動作No.08844
IKKI さん 15/11/24 00:08
 
秀丸担当さん、こんにちは。

settargetcolormarker文のヘルプの例が
 settargetcolormarker "allfound";
になっていますが、これは
 settargetcolormarker "mylayer";
とした方が、「"allfound" は特別な意味がある」というような誤解を招かないと思
います。

あと、以下のキーワードもマクロヘルプのキーワード一覧に載せておいてください。

 reservedmultisel
 findmarker
 diff

よろしくお願いいたします。

[ ]
RE:08769 プレースホルダ編集機能No.08846
IKKI さん 15/11/24 07:07
 
>>CSVの列に絞った置換で変換モジュールを使う話題のとき、カラーマーカーに絞
>>った検索を作っても、こういう問題が起こり得るのではないかということがあり、
>>やはりそういう問題はありそうです。
>この問題に対しては、置換の変換モジュールを使えばとりあえず対応できますが、
>それとは別に、もっと包括的な解決策を別途提案してみたいと思います (後日にな
>ります)。
そういえばこんなことを書いていましたが、その後すっぱり忘れていました…。

アイディアは(言うのは)簡単で、「複数箇所に分散した文字単位の部分編集を可能
にする」というものです。
「プレースホルダ編集」と呼ぶとわかりやすいかもしれません。
カーソルがプレースホルダ外に出れないとか、Tabキーを押すと隣のプレースホルダ
に移るとか、そういうイメージです。
さらに
 ・検索/置換はプレースホルダ毎に行う(プレースホルダをまたいでヒットしない)
 ・全置換は各プレースホルダに対する置換処理を順次行う
という動作を実現すれば、CSVカラム内の全置換なども汎用的な枠組みに収めること
ができそうです。

ユーザーに見せるインターフェイスとしては、既存の部分編集機能が文字単位&複数
可能になるだけで、新しいコマンドやメニューは追加しなくて済むかもしれません。
あるいは、部分編集とは用途がだいぶ違うので、プレースホルダ編集機能として別物
のように見せた方がいいかもしれません。
いずれにせよ、実装するのは言うほど簡単じゃないんじゃないかと想像します。(^^;

将来用のネタとしてご検討いただければと思います。

[ ]
RE:08844 incolormarkerの動作No.08848
秀丸担当 さん 15/11/24 13:59
 

settargetcolormarkerのヘルプの例は確かに変でした。修正させていただきます。

reservedmultisel, findmarker, diff については一応「結果コードと定数」の
ところに書いてみましたが、ヘルプの画面で検索できてなかったので検索できる
ようにします。

[ ]
RE:08846 プレースホルダ編集機能No.08850
秀丸担当 さん 15/11/24 17:13
 

複数個所で、文字単位の部分編集ということができれば、列に絞った置換だけで
なく、いろいろと便利になると思います。
ご推察の通り、おそらく簡単ではない話になってくると思います。
将来用のネタとして参考にさせていただきます。

[ ]
RE:08848 incolormarkerの動作No.08852
秀丸担当 さん 15/11/26 16:34
 

V8.56β17でレイヤー名を指定できるようにしました。
やっぱり第5パラメータにレイヤー名を指定するようにしてみました。
colormarkersnapshot 0,0,0,0,"mylayer";
範囲が0,0,0,0の場合は全体が対象で、レイヤー名を省略した場合は全てのレイ
ヤーが対象です。

[ ]