アンドゥでカラーマーカーも再現してほしNo.08810
IKKI さん 15/11/08 17:59
 
秀丸担当さん、こんにちは。

v8.56 で、アンドゥでカラーマーカーが復活する仕様変更がありました。
カラーマーカーが存在していた時点までアンドゥしたらカラーマーカーが復活すると
いう仕様は便利で良いのですが、
さらに遡ってカラーマーカーが存在していなかった時点までアンドゥしたら、そのカ
ラーマーカーは消えるようにしてほしいです。

たとえば、末尾に書いた test.mac はカーソル行を適当に編集するマクロですが、
ユーザーが
 (1) マクロ実行
 (2) アンドゥ
 (3) カーソルを別の行に移動
 (4) マクロ実行
という操作をした場合、(4) 時点の位置だけでなく (1) 時点の位置も編集されてし
まい、ユーザーの意図に反します。
少なくとも、マクロの内部処理用に塗ったカラーマーカーがアンドゥしたらユーザー
に見えてしまうのは不都合です。

この問題をマクロ側で回避するには、カラーマーカーが塗られた文字列を編集する前
に必ず deletecolormarker すればよさそうですが、これは非常にデリケートな処理
で、マクロの処理内容によってはうまくできません。
あるいは、deletecolormarker をするためにマクロの処理手順が制約を受けて、迂遠
な処理を書かざるを得なくなります。

というわけで、何らかの方法でアンドゥ後の編集バッファとカラーマーカーの整合性
を保証できるようにしてほしいです。

案としては
 (A) カラーマーカーも文字編集と同様にアンドゥバッファで履歴管理を行う
 (B) 文字編集した時点でカラーマーカーの状態を記憶する
 (C) begingroupundo した時点でカラーマーカーの状態を記憶する
という感じでしょうか。

A案は、文字編集を伴わないカラーマーカーのみの変更もアンドゥできるという意味
です。
B案は、カラーマーカーのみの変更はアンドゥできないが、文字編集をアンドゥした
ら編集前のカラーマーカーの状態が再現されるという意味です。test.mac の2行目の
ように、カラーマーカーをいじる前にアンドゥバッファに目印を付けておけば、カ
ラーマーカーを塗る前の状態に戻すことができます。
C案は、そのような目印を付けなくても、begingroupundo した時点までアンドゥした
らカラーマーカーの状態が再現されるという意味です。

ご検討のほどよろしくお願いいたします。

// test.mac
begingroupundo;
beginsel; endsel; insert ""; // アンドゥバッファに目印を付ける
colormarker 0x000000, 0x3399FF, 11, 2, 0, currentmacrobasename, lineno, 4, l
ineno, 6;
colormarker 0x000000, 0x3399FF, 11, 2, 0, currentmacrobasename, lineno, 10,
lineno, 12;
colormarker 0x000000, 0x3399FF, 11, 2, 0, currentmacrobasename, lineno, 14,
lineno, 16;
selectcolormarker currentmacrobasename;
insert "■"; // 塗られた範囲に対して何らかの編集を行う
endgroupundo;

[ ]
RE:08810 アンドゥでカラーマーカーも再現No.08815
秀丸担当 さん 15/11/09 13:19
 

カラーマーカーが復元されると都合が悪いことがあるということで、
begingroupundoが無くても、まずは従来通り復元されないようになるべきだと思
います。

そのうえで、新しいパラメータ等を用意するなどをして、カラーマーカーの復元
も可能にできたらいいと思います。
パラメータによって現在と同等にするか、またはA案のようなことができたらい
いというネタもあったので、それができたらいいと思います。

C案の場合とても多くのカラーマーカーがあるとパフォーマンス的にもよくない
気がします。
そういう方向で考えてみます。

[ ]
RE:08815 アンドゥでカラーマーカーも再現No.08834
IKKI さん 15/11/12 18:06
 
(turukame.3:08833 から引っ越しました)

> V8.56β15でsetcompatiblemodeでカラーマーカーをやり直しできるかどうかを追
加しました。
少し試してみました。ビット22を立てると v8.56β1 相当の動作になる、と理解しま
した。

もともとの要望は、2つの要件
 (1) カラーマーカーが存在していた時点までアンドゥしたらカラーマーカーが復活
してほしい
 (2) カラーマーカーが存在していなかった時点までアンドゥしたら、そのカラー
マーカーは消えてほしい
を同時に満たしたいということでした。

今回追加された setcompatiblemode のビット22は (1) を満たしますが (2) を満た
さないので、これを使っても「マクロの内部処理用に塗ったカラーマーカーがアンド
ゥしたらユーザーに見えてしまう」という不都合が残ることになり、使いどころがあ
りません。
私としては setcompatiblemode のビット22を使うことはありませんので、もし私だ
けの要望のために追加されたのでしたら、他の人が使い始めないうちに撤去していた
だいた方がいいかもしれません。
お手数をおかけして申し訳ありません。

上記2つの要件を満たす方法としては、これは私案ですが、
 (A) カラーマーカーのスナップショットを撮る文を追加
 (B) スナップショットされたカラーマーカーを復帰する文を追加
 (C) アンドゥバッファを遡ってスナップショット地点を通過したらカラーマーカー
を復帰する
のうち「(A)と(B)」もしくは「(A)と(C)」を実装するのが良いと思っていました。
この考えに至った背景は後述します。

手戻りになってしまい恐縮ですが、あらためてご検討いただければ幸いです。


------ 以下は turukame.3:08736 へのレスとして書きかけて投稿しなかった文章で
す ------

カラーマーカーが復活すると便利だと言った背景には
「ある時点の複数選択の状態を記憶しておき、復元できるようにしたい」
という要求があります。
複数選択はカラーマーカーに変換可能なので、この要求は
「ある時点のカラーマーカーの状態を記憶しておき、復元できるようにしたい」
と言い換えることができます。

秀丸 v8.40 を境に、選択範囲に対して何か処理するマクロを書くときの考え方が
「座標を変数に入れて保持」から「範囲をカラーマーカー化して保持」へガラッと変
わりました。
それに伴い、カラーマーカーを容易に記憶/復元したい場面が増えています。

この話は要するに、turukame.3:07727 あたりで話していた「選択範囲の扱いを抽象
化したい」という話につながるのですが、あのときの話では
「位置情報を抽象化して保持しても、テキストを編集したらずれて無意味になる」
という問題があり、この問題を回避できる妙案として
「編集しても自動的に追従するカラーマーカーとして範囲を保持する」
というアイディアを得たのでした。

カラーマーカーの記憶/復元を実現するアプローチとしては
 (a) テキストとカラーマーカーの整合性が自動的に保たれる仕組み
 (b) テキストとカラーマーカーの整合性をマクロ側で担保する仕組み
の2通りが考えられます。
(b) は現状でも実現可能ですが、上述の議論を踏まえると (a) が理想的です。

ところで、秀丸エディタの編集機能は現に (a) の要件を満たしていますよね。
そして、テキストの状態を記憶/復元する仕組みとしてアンドゥバッファがあります
ね。
同様に、カーラーマーカーの状態を記憶/復元する仕組みとしてもアンドゥバッファ
を使えばいいのでは?
つまり、アンドゥバッファを拡張して、テキストとカラーマーカーを含めた「編集画
面のスナップショット」を記憶/復元する仕組みとして再構築すれば、万事丸く収ま
るのではないか?
…というのが、turukamee.3:08735 のネタを出した時点で考えていたことです。

とはいえ、アンドゥバッファ周りをいじるのはそう簡単なことでもないと思います。
そこで、当座の利便のために、位置情報のみを保持する (b) のアプローチをもっと
簡単・高速・確実にできないだろうか?ということも考えています。
現時点では、h_tom さん作「カラーマーカーデータ保存・復元マクロ」のような方法
でファイルに保存するか、もしくは、末尾に書いたようなサブルーチンを使って静的
変数に保存することになります。
いずれも簡単とは言えないし、それなりに時間がかかるし、静的変数を使う場合は容
量の問題もあります。

というわけで、カラーマーカーのスナップショットをメモリ上に記憶/復元 (and/or
 ディスクに保存/読み込み) する仕組みを本体に搭載できませんでしょうか?
…というネタも出してみます。
ご検討いただければ幸いです。

---------------------------------------------------------------------

以下は複数選択範囲を静的変数に記憶/復元するサブルーチンです。
わりと速度に留意して書いたつもり。もったいないので貼っておきます。。。

SaveRegion: // 選択範囲を記憶
 $$y = currentmacrobasename + "#selection";
 if (multiselecting || rectselecting) {
  colormarker 0xFFFFFF, 0xCC6666, 11, 2, 0, $$y;
  gofiletop;
  nextcolormarker 0x09, 0, $$y;
  while (result) {
   ##bc = column; ##bl = lineno;
   nextcolormarker 0x0A, 0, $$y;
   $$e = $$e + sprintf("%i,%i\t%i,%i\n", ##bl, ##bc, lineno - ##bl, column -
 ##bc);
   nextcolormarker 0x01, 0, $$y;
  }
  selectcolormarker $$y;
  deletecolormarker $$y;
 } else if (selecting) {
  $$e = sprintf("%i,%i\t%i,%i", seltoplineno, seltopcolumn, selendlineno - s
eltoplineno, selendcolumn - seltopcolumn);
 } else {
  $$e = sprintf("%i,%i\t%i,%i", lineno, column, 0, 0);
 }
 setstaticvariable currentmacrobasename + "#region", $$e, 0;
 return;

LoadRegion: // 選択範囲を復元
 $$e = getstaticvariable(currentmacrobasename + "#region", 0);
 if ($$e == "") {
  return;
 }
 $$y = currentmacrobasename + "#selection";
 while (##i < strlen($$e)) {
  ##bl = val(midstr($$e, ##i));
  ##i = strstr($$e, ",", ##i) + 1;
  ##bc = val(midstr($$e, ##i));
  ##i = strstr($$e, "\t", ##i) + 1;
  ##wl = val(midstr($$e, ##i));
  ##i = strstr($$e, ",", ##i) + 1;
  ##wc = val(midstr($$e, ##i));
  ##i = strstr($$e, "\n", ##i) + 1;
  if (##i == 0) break;
  colormarker 0xFFFFFF, 0x663333, 11, 2, 0, $$y, ##bl, ##bc, ##bl + ##wl, ##
bc + ##wc;
 }
 if (##i > 0) {
  selectcolormarker $$y;
  deletecolormarker $$y;
 } else {
  moveto2 ##bc, ##bl;
  beginsel;
  moveto2 ##bc + ##wc, ##bl + ##wl;
  endsel;
 }
 return;

[ ]
RE:08834 アンドゥでカラーマーカーも再現No.08835
秀丸担当 さん 15/11/13 09:53
 

コメント先を間違えていました。すみません。
今回の修正は、非互換が見つかったため、少なくとも互換性は維持するための修
正でした。
あと、キー操作の記録と再生ができることは少なくともできるべきことだと思い
ます。

手動のアンドゥで、マクロのみぞ知る作業用のカラーマーカーが復活してしまう
ことは問題なので、setcompatiblemode 0x200000;が無いマクロはカラーマー
カーは復活しないようになります。

キー操作の記録と再生で、カラーマーカーを削除した場合は、自動的に
setcompatiblemode 0x200000;が付き、復活できる通常の操作と同じになります。

それとは別にカラーマーカーを任意のポイントまで復元したいということは理解
していて、それはまだできていないです。

1.互換性の維持
2.キー操作の記録と再生
3.任意のカラーマーカー復元

の3つの要件があって、1と2をとりあえずして、3がまだでした。
新しい文やパラメータが必要になってくると思います。

スナップショットを取る方法は、作るのも使うのもわかりやすくていいと思いま
す。
その案も含めて検討させていただきます。

[ ]
RE:08835 アンドゥでカラーマーカーも再現No.08837
IKKI さん 15/11/13 11:52
 
秀丸担当さん、おはようございます。

すみません、キー操作の記録と再生のことをすっぱり忘れていました。
早とちりして余計なことを言ってしまったようで申し訳ありません。

>スナップショットを取る方法は、作るのも使うのもわかりやすくていいと思いま
>す。
はい。その方法がいちばん汎用性もあって良いと思います。
よろしくお願いいたします。

[ ]
RE:08837 アンドゥでカラーマーカーも再現No.08841
秀丸担当 さん 15/11/19 16:20
 

V8.56β16で、colormarkersnapshotという文を追加してみました。
パラメータなしだと全てで、パラメータで範囲を指定すると範囲だけをやり直し
可能になります。

[ ]
RE:08841 アンドゥでカラーマーカーも再現No.08843
IKKI さん 15/11/23 21:44
 
>V8.56β16で、colormarkersnapshotという文を追加してみました。
ありがとうございます。
こちらのマクロで使ってみたところ、期待通りに動いているようです。
http://mobitan.org/hm/takoashi/

>パラメータなしだと全てで、パラメータで範囲を指定すると範囲だけをやり直し
>可能になります。
これはカラーマーカーが大量にあるときのパフォーマンスを懸念してのことと思いま
すが、レイヤ名を指定する方式でもよかったんじゃないかなと思います。

範囲を指定するには処理範囲の始端と終端を得る必要がありますが、複数選択範囲の
始端/終端(ファイル先頭/末尾に一番近い座標)を得るには一旦カラーマーカー化
しなきゃいけないので、「カラーマーカーがない状態のスナップショットを撮ってお
きたい」と思うと鶏卵になってしまいます。

今ならまだ colormarkersnapshot レイヤ名, [開始行, 開始桁, 終了行, 終了桁] と
いうパラメータ順に変更しても誰も困りませんが、いかがでしょう。

[ ]
RE:08843 アンドゥでカラーマーカーも再現No.08847
秀丸担当 さん 15/11/24 13:54
 

colormarkersnapshotでレイヤー名も指定できたらいいと思います。
全てのレイヤーを記述する書き方が無いので、やるとしたら、レイヤー名は最後
のパラメーターのほうが都合がよさそうです。
範囲を全体とする場合はは0,0,0,0とするとか。
または全てのレイヤーを表す新たなキーワードを作ってもいいかもしれないです。
どちらにしてもできるように検討したいと思います。

[ ]
RE:08847 アンドゥでカラーマーカーも再現No.08855
IKKI さん 15/11/27 05:21
 
(turukame.3:08850 から引っ越してきました)

> V8.56β17でレイヤー名を指定できるようにしました。
> やっぱり第5パラメータにレイヤー名を指定するようにしてみました。
> colormarkersnapshot 0,0,0,0,"mylayer";
ありがとうございました。
実験してみたところ、範囲指定・レイヤー指定とも適切に動いているようです。
また何か気づいたらご連絡します。

# 範囲指定については、スナップショット範囲がカラーマーカーに重なっていなくても
# 外接していれば OK という動作で一瞬「あれ?」と思いましたが、
# 幅ゼロのカラーマーカーを扱うにはこうするしかないですね。


参考までにお伺いしますが、マクロの引数で「引数なし」と「空文字列」と「数値の
ゼロ」は互いに区別可能という理解でよろしいでしょうか?
たとえば writeininum 文は文字列を指定するべきところに数値のゼロを指定したら
別の動作をしますが、他の文もそのような動作にすることができるものでしょうか。

[ ]
RE:08855 アンドゥでカラーマーカーも再現No.08858
秀丸担当 さん 15/11/27 09:42
 

すみません。またまたコメント先を間違えていました。

>参考までにお伺いしますが、マクロの引数で「引数なし」と「空文字列」と「数値の
>ゼロ」は互いに区別可能という理解でよろしいでしょうか?
>たとえば writeininum 文は文字列を指定するべきところに数値のゼロを指定したら
>別の動作をしますが、他の文もそのような動作にすることができるものでしょうか。

引数なしと引数ありは区別可能です。引数なしにできるのは終端のパラメータだ
けになります。
colormarkersnapshot ,,,,"mylayer";
という書き方はできないです。

「空文字列」と「数値のゼロ」も区別できます。
というか文字列か数値かも区別できます。
そういう意味では、
colormarkersnapshot #l1,#c1,#l2,#c2;

colormarkersnapshot $layer;
を両立させることも不可能ではないと思います。
ただ何番目のパラメータかによって意味を持たせているので、そういう仕様にす
ることはほとんどはしていないです。

writeinistrについては、Win32APIのWritePrivateProfileStringに合わせてそう
なっていました。
https://msdn.microsoft.com/ja-jp/library/cc429952.aspx

[ ]