マクロでのUndo回避

  1. 某エディタの更新が止まり、マクロ機能も弱いため、
    最近Meryを使用し始めました。マクロも便利で愛用しております。

    ところで、マクロをつかってデータ加工を行っていますが、
    処理途中で固まってしまいます。

    データ件数を少なくしたり、
    処理ステップを減らすと完走するので、
    おそらくUndoの記録が限界を超えてしまっているのだと推測しています。

    Undoを記録せずマクロを実行する、あるいは記録をクリアするなど、
    問題を回避する方法がありましたら、ご教示いただけますと幸いです。

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

     |  bx  |  返信
  2. > Undoを記録せずマクロを実行する、あるいは記録をクリアするなど、
    > 問題を回避する方法がありましたら、ご教示いただけますと幸いです。

    途中経過を Document.Text に書き込まず、全てマクロ内で処理して最終結果だけを書き込むのが、Undo バッファも積まない一番の手ですね。
    あるいは、Editor.NewFile() で作業用の Document を作成し、それを Close() すればその Document 内の Undo バッファはクリアされます。
    ただ、前者の方が高速だし良いことずくめかと思います。

     |  ks  |  返信
  3. 早速のご返送ありがとうございます。

    > 途中経過を Document.Text に書き込まず、全てマクロ内で処理して
    > 最終結果だけを書き込むのが、Undo バッファも積まない一番の手ですね。

    こちらで対応したいのですが、
    マクロ内で処理するには具体的にどうしたら良いでしょうか。
    初歩的な質問で申し訳ないです。
    知識不足でマクロに落とすことができませんでした。

    例えば、下記のような処理を行っています。
    aaa|11111
    aaa|アア
    bbb|22222
    bbb|イイイイ
    ccc|33333
    ccc|ウウウウウウ

    aaa|11111|アア
    bbb|22222|イイイイ
    ccc|33333|ウウウウウウ

     |  bx  |  返信
  4. 例に挙げられた条件だけであれば、マクロを使わずとも以下の正規表現置換で実現できます。

    検索文字列:
    ([^\|]+)\|([^\n]+)\n\1\|([^\n]+)\n
    置換文字列
    \1\t\2\t\3\n

    マクロで処理するとしたら、こんな感じ

    arrLines=document.text.split("\n"); //こんな感じで、各行を配列に取り込んで
    pre="";
    for(i=0;i<arrLines.length;i++){  //1行ずつ順番に処理
      eachLine=arrLines[i];
      arrWords=eachLine.split("|");  //処理する行も区切り文字で配列に
      if(arrWords[0]==pre && arrWords.length>0){
        arrLines[i-1] += ("|"+arrWords[1]); //連結する処理
        arrLines[i]="" ;  //削除する行はとりあえず空白に
      }else{
        pre=arrWords[0];
      }
    }
    document.text=arrLines.join("\n").replace(/\n\n/g,"\n");//空白行を削除してまとめて書き戻し
     |  通りすがり  |  返信
  5. > 置換文字列
    > \1\t\2\t\3\n

    まちがえた
    \1|\2|3\n
    ですね。
    あとマクロは、インデントを脳内補完してください。

     |  通りすがり  |  返信
  6. 通りすがりさんのコードで、例示されたデータは上手くいきますね。
    ちょっと自分でもいじってみました。
    違い:
    ・キー部分が連続していなくてもいい
    ・3列目以降も足す

    var result = {};                                  // 結果格納先準備
    var lines = document.text.split("\n");            // こんな感じで、各行を配列に取り込んで
    for (var i = 0; i < lines.length; i++) {          // 1 行ずつ順番に処理
      var cols = lines[i].split("|");                 // 処理する行も区切り文字で配列に
      var key = cols[0];                              // まとめるためのキーを取り出す
      if (result[key] != null) {                      // すでに同じキーが出現しているなら
        result[key] += lines[i].substring(key.length);// キー以外の2列目以降を追加
      } else {                                        // まだキーがないなら
        result[key] = lines[i];                       // 新しいキーの追加
      }
    }
    var array = [];                                   // キーに紐付いてしまっているので行に直す
    for (var key in result) {
      array.push(result[key]);
    }
    document.text = array.join("\n");                 // 結果を Mery に戻す
     |  ks  |  返信
  7. >> bx さん
    Mery をお試しくださりありがとうございます。Mery を開発している者です。
    ちょっと風邪で寝込んでいまして返信が遅くなってしまい申し訳ございません。

    >> ks さん
    ks さん、本当にお久しぶりです。ご無事で、本当に良かったです。マクロ実験室のほうも更新が途絶えていたので、体調崩されたりしてないか心配していました。

    確かこのスレッドで…
    https://www.haijin-boys.com/discussions/2818

    そしてサポートのご協力ありがとうございます!

    >> 通りすがり さん
    サポートのご協力ありがとうございます。
    私はマクロを書くのは得意ではないので助かりました。

    あと、一応、Mery の仕様では Undo の記録は無制限でメモリがいっぱいになっても HDD にスワップするだけなので、処理速度は重くなりますが編集は続行できるような仕組みになっています。でも、データ量によっては非常に遅くなってフリーズしたように見えるのかもしれませんね。

    Undo を記録せずマクロを実行する機能につきましては、今のところ搭載していませんが、すでに仕組みは開発済みで用意できています。

    具体的には、Redraw プロパティを利用して、Redraw 開始から Redraw 終了までは 1 Undo、みたいな仕組みを考えていますが、このような仕様はいかがなものか、マクロに詳しいみなさんのご意見が頂けると参考にさせていただきたいと思いますので、よろしくお願いいたします。

     |  Kuro  |  返信
  8. >> kuroさん
    > Undo を記録せずマクロを実行する機能につきましては、今のところ搭載していませんが、すでに仕組みは開発済みで用意できています。
    >
    > 具体的には、Redraw プロパティを利用して、Redraw 開始から Redraw 終了までは 1 Undo、みたいな仕組みを考えていますが、このような仕様はいかがなものか、

    横から失礼…。マクロに詳しくない私としましては大賛成です。1マクロ=1undo が簡単に実現できるのはとても素敵。
    ちょっと複雑な操作を「マクロの記録」して試しに「実行」してみたら、「元に戻すのにいったい何回Ctrl+Z押さないとイカンのじゃい?」なんていうジレンマが解消されますね。楽しみです。

     |  sukemaru  |  返信
  9. >>ksさん
    >>通りすがりさん
    対応方法をご丁寧に教えてくださりありがとうございます。

    キーマクロで対応することで頭が固まっていたため、
    テキスト処理で対応する発想が抜けていました。

    おかげさまで解決できそうです。
    頭が硬いのは私の悪い癖です…。

    >>kuroさん
    マクロ作成に時間をあまりかけられないときは、
    キーマクロでの対応は簡単でスピーディーなので、
    Undo を記録せずマクロを実行する機能実装楽しみにしております。

     |  bx  |  返信
  10. bx さん

    はじめまして、失礼します。おこがましいとは思うのですが…

    お話の流れの中で、お使いのデータの例をご紹介くださった
    ことで投稿が活発になりました。マクロもまた一部を紹介して
    下さると、状況の再現ができ、何にお困りなのか「具体的に」
    ほかの人が理解するのに、きっと役に立つと思います。

    Mery エディタの使い方は、とてもいろいろです。
    自分の目の前にある風景が、相手に伝わるように、思い込みに
    気をつけて、うまく工夫をしていきたいと、自分では心がけて
    いるのですが、いつまでたってもうまくできません。

    マクロにもさまざまな方法があるので、皆さんのコードに加え、
    さらにご参考までに、マクロで JavaScript 正規表現の置換を
    使った例を作りました。データはいい加減な推測です。

    データを範囲選択して使います。

    ・完了("Done")をステータスバーに表示
    ・選択範囲が論理行単位の選択でなければ行選択に拡張
    ・キー前後の空白文字を除去
    ・キー途中の空白を許容
    ・同一キーは3件まで順に結合

    {
      var s = document.selection;
      var tx = s.GetTopPointX(mePosLogical);
      var ty = s.GetTopPointY(mePosLogical);
      var bx = s.GetBottomPointX(mePosLogical);
      var by = s.GetBottomPointY(mePosLogical);
      var aStr;
    
      Status = "";
      if (!s.IsEmpty) {
        s.SetAnchorPoint(mePosLogical, 1, ty);
        s.SetActivePoint(mePosLogical, 1, (bx > 1 ? by + 1 : by), true);
        aStr = s.Text;
        s.Text = aStr.replace(/^\s*([^|]*?)\s*(\|[^|]*?)(?:(?:\n\s*\1\s*(\|[^|]*?))(?:\n\s*\1\s*(\|[^|]*?))?)?$/gm, "$1$2$3$4");"Done";
      }
    }

    ※不規則なデータを含めてテスト※
    ---------------------------------------
    aaa |11111
    aaa |アア
    bbb|22222
    bbb |イイイイ
     ccc |33333
    ccc  |ウウウウウウ
    dd d |11111
    dd d |アア
    eee|22222
    eee|イイイイ
    fff|33333
    fff|ウウウウウウ

    ggg|11111

    ggg|アア
    hhh|22222
    hhh|イイイイ
    iii|33333

    iii|ウウウウウウ

    jjj|11111
    jjj|
    kkk|
    kkk|イイイイ
    lll|
    lll|

    mmm|11111
    nnn|22222
    ooo|33333

    ppp|11111
    ppp|アア
    ppp|AA
    qqq|22222
    qqq|イイイイ
    qqq|BBBB
    rrr|33333
    rrr|ウウウウウウ
    rrr|CCCCCC

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

    ※結果※
    ---------------------------------------
    aaa|11111|アア
    bbb|22222|イイイイ
    ccc|33333|ウウウウウウ
    dd d|11111|アア
    eee|22222|イイイイ
    fff|33333|ウウウウウウ
    ggg|11111|アア
    hhh|22222|イイイイ
    iii|33333|ウウウウウウ
    jjj|11111|
    kkk||イイイイ
    lll||
    mmm|11111
    nnn|22222
    ooo|33333
    ppp|11111|アア|AA
    qqq|22222|イイイイ|BBBB
    rrr|33333|ウウウウウウ|CCCCCC

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

     |  inuuik  |  返信
  11. 表題の、「マクロでのUndo回避」についてですが、先日回答しました内容に一部説明不足がございましたので補足させてください。

    > 具体的には、Redraw プロパティを利用して、Redraw 開始から Redraw 終了までは 1 Undo、みたいな仕組みを考えています

    ↑ これですが、確かに文字通りの仕様を実装する予定ではあるのですが、これは Undo の記録自体を抑制するわけではなく、1 度の Undo をグループ化することで Undo ポイントを設定できる仕組みなので、Undo の記録自体は行われますから、Undo バッファが増えるという状況の改善にはなりませんでした。

    sukemaru さんの「元に戻すのにいったい何回Ctrl+Z押さないとイカンのじゃい?」の改善にはなると思います。

    window.Redraw = false; // Undo ポイント開始
    document.selection.Text = "a";
    document.selection.Text = "b";
    document.selection.Text = "c";
    window.Redraw = true; // Undo ポイント終了
    
    window.Redraw = false; // Undo ポイント開始
    document.selection.Text = "d";
    document.selection.Text = "e";
    document.selection.Text = "f";
    window.Redraw = true; // Undo ポイント終了

    ↑こんな感じでグループ化しておくと、1 度めの Undo で def が削除され、2 度めの Undo で abc が削除されるようになるっていう仕様を予定しています。

     |  Kuro  |  返信
  12. Redraw プロパティによる Undo グループ化

    これ、いろいろ使えそうです。Undo の programming ができるようになりますね。

    Undo バッファの消費削減はないとしても、このグループ化で、画面操作と Undo を
    同じタイミングで積極的に操作できる。

    作成中は Redraw = false のままにしておいて動作確認、でき上がったら true に
    すればいいので使い勝手もよさそう。

    グループにまとめたい単位 = 表示更新をしたいタイミング = Undo で戻りたい区切り、
    これらを意識して遷移を考える…、面白い新機能ですね、楽しい。

     |  inuuik  |  返信
  13. > 作成中は Redraw = false のままにしておいて動作確認、でき上がったら true に
    > すればいいので使い勝手もよさそう。

    逆でした…、ごめんなさい _o_

    作成中は Redraw = true のままにしておいて動作確認、でき上がったら false に
    すればいいので使い勝手もよさそう。

     |  inuuik  |  返信
  14. > 逆でした…、ごめんなさい _o_
    Undo のグループ化のために Redraw プロパティっていう画面の描画を抑制するための仕組みを流用、という点がちょっと分かりづらいかもしれませんね。

    例えば Delphi 独特の書き方ですが、BeginUpdate ~ EndUpdate みたいな専用のメソッドを用意するっていうのも考えたのです。

    でも、投稿されているマクロを見てみると結構 Redraw プロパティって使われているみたいだったので、Redraw プロパティを流用すれば、画面の描画を抑制できるうえに Undo のグループ化もできて、既存のマクロに手を加えることなく 1 発で Undo ができるようになって一石三鳥かな?と思って、こんな仕様を考えてしまいました。

    > 作成中は Redraw = true のままにしておいて動作確認、でき上がったら false に
    > すればいいので使い勝手もよさそう。

    そうなんですよね、この仕様、利便性は良さそうですが、実は、こまめに Undo ポイントを作りたいようなシーンが出てくると、Redraw = true を使用することで再描画が 1 発、発動しちゃいますから、マクロの実行速度に若干影響があるという点が気がかりではあります。

    個別にメソッドを用意したほうがいいよ!っていうご意見もあれば聞いてみたいです。

    ---- ここから脱線します ----
    あと、スレッドの本題から脱線してしまいますが、フォーラムに貼り付けたソースコードが見やすくなるように pre タグを使用できるようにしてみました。

    HTML の記述方法と同じで、半角で <pre> (←これは全角で書いてますが半角でね) で囲んでやると、インデントが反映されてソースコードの言語を自動判別して色分けして投稿できるようになっています。

    <pre> や <PRE> のように大文字・小文字どちらでも大丈夫ですが、<pre style="height: 480px;"> みたいな属性は使えません。単純に <pre> ~ </pre> のみ認識されますのでご注意ください。あと、高さは 640px を超えると縦スクロールバーになります。

    ↓テストですが、pre タグを使うとこんな感じで貼りつきます。

    if (document.selection.Text == "")
    	document.selection.SelectAll();
    var s1 = document.selection.Text.split("\n");
    var s2	= new Array();
    for (var i = 0; i < s1.length; i++) {
    	if (i == 0 || s1[i-1] != s1[i])
    		s2.push(s1[i]);
    }
    document.selection.Text = s2.join("\n");

    また、投稿内容の記入欄で [TAB] キーも効くようにしてみましたので、ソースコードを貼り付けるときにお役立てくださいませ。

    とりあえず、このスレッドは実験ということで、勝手ながらみなさんの貼ってくれたソースの前後に pre タグを仕込んでみましたが、「やめて!」っていうかたがいらっしゃいましたらご一報ください…。

     |  Kuro  |  返信
  15. >> Kuro さん
    > 個別にメソッドを用意したほうがいいよ!っていうご意見もあれば聞いてみたいです。

    現状の仕様って明示的に Redraw=true を指定してないと false なんですよね?
    undo ポイントを挟みこんだばあいには、マクロ実行中に画面がちらついたりすることになっちゃうよというのは… 美しくないかも :(

    Redraw とは別のメソッド?/プロパティ?がよろしいかとおもいますが、
    ここはあえて Kuro さんの美学的ご判断におまかせします、と言うべきところかしら? :D

     |  sukemaru  |  返信
  16. ご意見ありがとうございます。

    > 現状の仕様って明示的に Redraw=true を指定してないと false なんですよね?

    いいえ、何も指定しない場合は Redraw = true です。つまりデフォルトの状態では、マクロ実行中でも呼び出すメソッドによっては再描画が発生します。

    明示的に再描画を抑制するための仕組みが Redraw = false (再描画を無効) です。

    > undo ポイントを挟みこんだばあいには、マクロ実行中に画面がちらついたりすることになっちゃうよというのは… 美しくないかも :(

    そうなんですよね。Redraw = true を実行すれば、そこで再描画が行われますので、ネガティブに考えちゃうと画面のチラツキというふうにとらえられますね ^^;

    ポジティブに考えると、Undo ポイントなので、その時点を画面に反映させてます。っていうとらえ方もできるかなーとも思います。

    使われ方として 1 マクロで 1 Undo にしたいという需要が多いのではないかと予想しているのと、過去のマクロも Redraw を使ってくれているものは自動的に 1 Undo にできちゃうところでメリットを感じています。

    ただ、私はあまりマクロを書いたことがないので、マクロを駆使される方ですと、Undo ポイントを刻むようなマクロを考えたりするのでしょうか。

    > Redraw とは別のメソッド?/プロパティ?がよろしいかとおもいますが、
    > ここはあえて Kuro さんの美学的ご判断におまかせします、と言うべきところかしら? :D

    あはは…。
    私はマクロを全然使わないので、実装が楽なほうに流れちゃいますねー。新しくメソッドを作るのは面倒くさいのと、マクロリファレンス書かないといけないのを考えるだけでゾッとします (w

     |  Kuro  |  返信
  17. > Undo のグループ化のために Redraw プロパティっていう画面の描画を抑制するための仕組みを流用、という点がちょっと分かりづらいかもしれませんね。

    重ね重ね申し訳ないです。この仕組みは分かりづらくありません。
    間違えたのは、私がそそっかしくて、見直しもサボったから…だけです。_o_

    > でも、投稿されているマクロを見てみると結構 Redraw プロパティって使われているみたいだったので、Redraw プロパティを流用すれば、画面の描画を抑制できるうえに Undo のグループ化もできて、既存のマクロに手を加えることなく 1 発で Undo ができるようになって一石三鳥かな?と思って、こんな仕様を考えてしまいました。

    大賛成です!

    まず共用で実装して、実際の使用感を確かめ、
    どうしても不都合が解消できなければ、別の仕組みを追加する。
    …でお願いします。

    逆の流れでは、これができませんので。

     |  inuuik  |  返信
  18. > 何も指定しない場合は Redraw = true です。つまりデフォルトの状態では、マクロ実行中でも呼び出すメソッドによっては再描画が発生します。
    > 明示的に再描画を抑制するための仕組みが Redraw = false (再描画を無効) です。
    (拙作のマクロですら)ふだん使っていて画面のちらつきを感じることがなかったから、暗黙的に Redraw = false になっているんだとおもってました。 :)

    > 使われ方として 1 マクロで 1 Undo にしたいという需要が多いのではないかと予想しているのと、過去のマクロも Redraw を使ってくれているものは自動的に 1 Undo にできちゃうところでメリットを感じています。
    いずれのかたちにせよ新仕様が楽しみです。(むしろ、明示的に Redraw を書いていないものは「暗黙的に 1-undo」とかでもよいのでは?) XD

     |  sukemaru  |  返信
  19. > (拙作のマクロですら)ふだん使っていて画面のちらつきを感じることがなかったから

    そうですね、通常、すべてのコマンドで再描画が必ず発生するわけではなく、例えば SetActivePos メソッドなど、エディタエンジンの仕様上、画面の移動がともないどうしても再描画が発生してしまうシーンがあり、それを無理やり抑制するのが Redraw = false ですから、普段のマクロではそれほど意識する必要はないかと思います。

    > 明示的に Redraw を書いていないものは「暗黙的に 1-undo」とかでもよいのでは?

    おっしゃる通り、マクロを書く側からするとその仕様は合理的だと思います。

    ただ、マクロ機能の位置づけとして、操作を記録して再実行するための機能、という大前提があるので、通常の操作と仕様が変わってしまうのは問題がありそうですね ^^;

     |  Kuro  |  返信
  20. Kuro さん、開発お疲れ様です。
    風邪から復帰されたようで何よりです。

    Undo のタイミングを決める方法ないだろうか…と思っていたところで丁度議論されていたので、意見を一票投じさせてください😃

    Redraw と連動させるか、別のメソッドを用意するか、とのことですが、別のメソッド追加に一票です。

    理由は、

    1. 命名: Undo OFF の機能とRedraw という名前が紐付かない
    2. 柔軟性: デバッグ時や動作仕様上、描画はさせたいけど Undo 記録はしたくない (もしくはその逆) という場面があっても対応できる
    3. 安全性: 新規追加であれば、現存のマクロに影響を及ぼさない

    という点からです。 (Redraw とはセットで使う場面が多そうですが…😅)

     |  yuko  |  返信
  21. ご心配いただきありがとうございます。

    今年の風邪は鼻から来ました。おかげさまでなんとか Mery の記事を書き上げ、本日公開しようとしていたところでした。最近、気温の変化が激しいので yuko さんもお気をつけください。

    > 別のメソッド追加に一票です。

    えー。もう Redraw プロパティに実装しちゃいましたし、使い方の記事も書いちゃったよー!

    > 1. 命名: Undo OFF の機能とRedraw という名前が紐付かない

    そもそも Undo OFF 機能なんてない!と思えば、Redraw でできるっていう抜け道が用意されていた、みたいな考え方はダメですか?(w

    > 2. 柔軟性: デバッグ時や動作仕様上、描画はさせたいけど Undo 記録はしたくない (もしくはその逆) という場面があっても対応できる

    そこまで細かく Undo ポイントを考慮してマクロを書きたい場合、この Redraw 流用案はダメですね。

    > 3. 安全性: 新規追加であれば、現存のマクロに影響を及ぼさない

    既存のマクロも自動的に 1 発 Undo になるから便利!だと思っていたのですが、逆にそうされたくないケースもあるかもしれませんね。

    記事公開前で良かったです。とりあえず、Undo ポイントを Redraw で行う仕様は見送りとさせていただきますね。MeryWiki の開発室のほうに将来的な課題としてメモっておきます。

     |  Kuro  |  返信
  22. Redraw=true は Redraw=false を受けて記述されるものと考えると、あえて Undo ポイントを置くために Redraw=true; Redraw=false; を記述しないといけないのは冗長な気がします。
    オブジェクト省略可で UndoEnable() みたいに簡潔にはさみこめるほうがよいかと。
    (既存のマクロも含めて)デフォルトで「暗黙的に 1-マクロ = 1-Undo」への仕様変更するなら引数なしのほうが分かりやすそうですが、そうでない場合にもコードの先頭に UndoEnble( false ); を追加するだけで済みます。
    あるいは、UndoEnable(true) 以下の行で継続的に true にしたい場合がありえるとするなら、Undo( [enble option] , [multiple option] ) のようなかたちで引数を2つとるように… とか。

    「マクロの記録でコード化した場合 Undo ポイントの多いマクロができあがって使いづらい」という私のような初心者のために、

    UndoEnable( false );		// このマクロを「元に戻す」1回の操作で Undo 可能にする(不要ならコメントアウト)

    みたいな行が自動的に1行目に追加されるとハッピーになれそうです。 XD

     |  sukemaru  |  返信
  23. > えー。もう Redraw プロパティに実装しちゃいましたし、使い方の記事も書いちゃったよー!

    おお……やぶへびなことを言ってしまいましたね(汗)

    Kuro さんも考えていることと思いますが、やはり「Undo は都度記録したい」という意見の方が遥かに少数派な気がしますので、Redraw プロパティとしても抵抗が無い範囲の仕様変更だと感じます。

    それとすみません。以下のコメントを読み飛ばしていました。

    > ポジティブに考えると、Undo ポイントなので、その時点を画面に反映させてます。っていうとらえ方もできるかなーとも思います。
    >
    > 使われ方として 1 マクロで 1 Undo にしたいという需要が多いのではないかと予想しているのと、過去のマクロも Redraw を使ってくれているものは自動的に 1 Undo にできちゃうところでメリットを感じています。

    なるほどと思いました。私の出した意見より、受けるメリットの方が大きい気がします。(やっぱり Redraw 統合でいいんじゃないかなーという思えてきました…😓)

    また sukemaru さんの、

    > 「マクロの記録でコード化した場合 Undo ポイントの多いマクロができあがって使いづらい」という私のような初心者のために、

    の意見も、マクロ記録から利用する際の利便性がグッと上がりそうですね!「Undo ポイントを都度設定したい」という方が上級者的な思考だと感じるので、この仕様としても良さげな気がします。

     |  yuko  |  返信
  24. >> sukemaru さん
    なるほど、難しい…。
    ちょっとすでに用意している仕組みでは対応できないような気がして来ました ^^;

    やはりマクロを活用されている方は複雑な使い方を想定されているのですね、新バージョンリリース前にご意見を頂けて良かったです。

    次のバージョンでは実装を見送りましたので、将来的な課題として検討事項にさせてくださいませ。

    >> yuko さん
    > おお……やぶへびなことを言ってしまいましたね(汗)
    いいえー、意見を募集したのは私ですから (w
    (ちょっと実装の解除に時間がかかってしまい新バージョンリリースがまだできていませんが、近日中には公開できる予定です。ちなみに、次のバージョンはめっちゃ地味です)

    > 「Undo ポイントを都度設定したい」という方が上級者的な思考
    そうなんですよね。もともとは、Undo ポイントを減らしたいというご要望だったので、それだったらすぐに実装できる仕組みを用意しているので!っていうノリで盛り上がった話題なのですが、気が付けば逆に Undo ポイントを刻みたい方向へ… ^^;

    反対派多数ということで、本件はボツとさせていただきます。(MeryWiki の開発室の ToDo リスト行き)

     |  Kuro  |  返信
  25. 「もったいないお化けが来るよっ」

    アイデアを得て形にして下さった Kuro さんのご好意と「技」がもったいない…。

    Redraw プロパティで Undo グループ化を兼用、なのは便利で美しい、という考え
    なのだけれど…

    > ご意見・ご要望
    >
    > 内容 状態 備考
    >
    > マクロで Undo ポイントの設定 検討 Redraw プロパティ流用派 VS 新メソッド用意派 (メソッドにするかプロパティにするか?メソッド名、プロパティ名の案が欲しい)

    ということで…、
    今、要望させていただきます。

    ・RedrawUndo プロパティの追加

    既存の Redraw プロパティはそのままに、新しい RedrawUndo プロパティが欲しいです。
    見送りとされた Undo グループ化兼用 Redraw の機能に相当、継承するものです。

    自分には Undo を小刻みにしたい高度なテクニックや、同時だと危険な操作、などのマクロは
    ないです。
    なので、すべてに設定したいのですが、これまで作ったマクロのすべてに、2行の追加を
    するのは気が進まなく、せめて扱いやすい名前で全置換にしたい、という動機です。

    むずかしい制御をしたい方にも気に入っていただけるとありがたいです。

    【マクロリファレンス】
    --------------------------------------------------------------------------------
    Redraw プロパティ

    ウィンドウの再描画の有効・無効を設定または取得します。

    構文
    function get Redraw() : boolean
    function set Redraw(value : boolean)

    プロパティ値
    * 再描画を行う場合は true を示し、それ以外の場合は false を示すブール値。
    --------------------------------------------------------------------------------
    ※追加案※
    --------------------------------------------------------------------------------
    RedrawUndo プロパティ

    ウィンドウの再描画の有効・無効と Undo ポイントのグループ開始・終了を同時に設定または取得します。

    もし RedrawUndo プロパティを true に設定したときに Redraw プロパティが false ならば、ウィンドウの再描画を行わず Undo ポイントの設定だけを行います。

    構文
    function get RedrawUndo() : boolean
    function set RedrawUndo(value : boolean)

    プロパティ値
    * 再描画と Undo (Undo ポイント・グループ終了)を行う場合は true を示し、描画と Undo の抑止(Undo ポイント・グループ開始)を同時をする場合は false を示すブール値。
    --------------------------------------------------------------------------------

    【参照先】
    https://www.haijin-boys.com/wiki/マクロリファレンス:Window_インターフェイス#Redraw_.E3.83.97.E3.83.AD.E3.83.91.E3.83.86.E3.82.A3

    【使い方】

    使い方-1: [従来通り] 描画の無効 → 再描画。

    Redraw = false;   // 描画抑止
    ...
    Redraw = true;    // 再描画

    使い方-2: [新] 描画の無効と Undo 抑止(グループ開始)→ 再描画と Undo 再開(グループ終了)

    RedrawUndo = false;   // 描画と Undo 抑止(Undo グループ開始)
    ...
    RedrawUndo = true;    // 再描画と Undo 再開(Undo グループ終了)

    使い方-3: [新] 描画はずっと有効、Undo 抑止(グループ開始)→ Undo 再開(グループ終了)

    RedrawUndo = false;   // 描画と Undo 抑止(Undo グループ開始)
    Redraw = true;        // 再描画、ここからずっと描画
    ...
    RedrawUndo = true;    // Undo 再開(Undo グループ終了)

    使い方-4: [新] 描画はずっと無効、Undo 抑止(グループ開始)→ Undo 再開 … 抑止 を複数回 → 再描画と Undo 再開(グループ終了)

    RedrawUndo = false;   // 描画と Undo 抑止(Undo グループ開始)
    Redraw = false;       // 描画抑止(すでに抑止されてるけど…)
    ...
    RedrawUndo = true;    // 描画抑止のまま Undo 再開(Undo グループ終了)
    ...                   // この間は Undo 有効
    RedrawUndo = false;   // 描画抑止のまま Undo 抑止(Undo グループ開始)
    ...
    RedrawUndo = true;    // 描画抑止のまま Undo 再開(Undo グループ終了)
    Redraw = true;        // 再描画

    【ご注意】
    Redraw プロパティを false に設定したとき、JavaScript エラーなど何かのはずみで true に設定されずマクロが終了した場合、画面の再描画が行われないままになってしまうことがあります。
    RedrawUndo プロパティでも同じことが発生するでしょう。

    このようなときにパニックにならないように…、

    RedrawUndo = true;
    Redraw = true;

    というだけの簡単なマクロを用意して、ショーカットキーに割り当てておくといいです。
    --------------------------------------------------------------------------------

    ここから下には不適切な内容が含まれます。善良なユーザの皆さんはご覧にならないことを
    お勧めいたします。_o_

    --------------------------------------------------------------------------------
    んで…、最後にこっそりと魔改造もお願いしたいのですが、内緒ですよ。

    Mery.ini
    に次の制御を追加してほしいです。

    [General]
    Redraw=Redraw

    としてこれがデフォルト。これを

    Redraw=RedrawUndo

    とすると、全部の Redraw を RedrawUndo 扱いにして… (ry

     |  inuuik  |  返信
  26. > > 「Undo ポイントを都度設定したい」という方が上級者的な思考
    > そうなんですよね。もともとは、Undo ポイントを減らしたいというご要望だったので、それだったらすぐに実装できる仕組みを用意しているので!っていうノリで盛り上がった話題なのですが、気が付けば逆に Undo ポイントを刻みたい方向へ… ^^;

    基本的には 1-マクロ = 1-undo のための仕組みというだけでよいとおもうのですが、ディスカッションの場が設けられてしまうと「色々な発展性が考えられますよね」という意見やアイデアもでてくるものだとおもいます。:)

    自分としては今まで undo ポイントの設定の使い道について、マクロのデバッグぐらいしか考えていませんでしたが、「そういえば!」という必要性の高い?使いみちがありました。
    文字列操作系のマクロで事前処理として選択範囲を拡張・調整(行単位とか)するものでは、現在の仕様にあわせて 1-マクロ = 1-undo にする書き方でも undo (Ctrl+Z) したときに「拡張・調整した範囲選択」状態に戻りますよね。
    選択範囲のない状態からでも行全体を処理できるようなマクロ(コメントアウトやインデント、置換処理など)で undo したときに、元のキャレット位置に復帰できるようにマクロの冒頭の「選択範囲の拡張・調整」前の状態で undo ポイントを置いておくというのは個人的に必須になりそうな気がします。
    今のところ行単位で処理するマクロでは undo 後に範囲選択が残ってしまうので Esc キーにショートカットを仕込んだ「選択範囲の解除」を使っていますが、やはりキャレットの位置までは元通りにならないんですよね。

    …あれっ? これだけだとやっぱり Redraw = true/false; だけでもいいような?

     |  sukemaru  |  返信
  27. > > そうなんですよね。もともとは、Undo ポイントを減らしたいというご要望だったので、
    > 「色々な発展性が考えられますよね」という意見やアイデアもでてくるものだとおもいます。:)

    私が「Undo ポイント」という言葉を使ってしまったので、ちょっと誤解が生じているように思います。

    Redraw プロパティを流用して対応できるかもしれないと申し上げたのは、「Undo ポイントを設定する機能」ではなく「Undo をグループ化する機能」です。

    Undo ポイントが設定できるわけではなく、Undo 処理をグループ化できるだけですので、Undo の仕様は Mery 内部の Undo の挙動に依存します。

    つまり、「選択範囲を変更しただけ」のように Mery 本体側で Undo として記録されない動作に対して Undo ポイントを設定して復元ポイントのように使うといったことはできません。

    そういった意味でも Redraw プロパティの流用という形での簡易な実装を想定していました。

     |  Kuro  |  返信
  28. ご返信ありがとうございます。&スレッドを掘りおこしちゃってごめんなさい。

    > つまり、「選択範囲を変更しただけ」のように Mery 本体側で Undo として記録されない動作に対して Undo ポイントを設定して復元ポイントのように使うといったことはできません。
    諒解です、やはり制限がありましたか。XD

    SetAnchorPos( GetAnchorPos() );  SetActivePos( GetActivePos(), true );

    みたいに冒頭に書いて Redraw() を置けば… などとセコイことを考えていました。 :)

    あとで仕様を見直し・手直しするとなったらご面倒でしょうしご慎重になるというのもお察ししますが、「Redraw プロパティで1undo できるようにしたから、これで我慢しなさい」ということであっても喜ぶ人は多いとおもいます。
    マクロへの理解の浅い私の現状としては「選択範囲の文字列を変数に格納して~」とかでなんとか 1マクロ = 1undo にできるようになりましたが、マクロの記録に頼っているユーザーには変数を使うことですらなかなか難しいですから…

     |  sukemaru  |  返信
  29. > Redraw プロパティを流用して対応できるかもしれないと申し上げたのは、「Undo ポイントを設定する機能」ではなく「Undo をグループ化する機能」です。
    >
    > Undo ポイントが設定できるわけではなく、Undo 処理をグループ化できるだけですので、Undo の仕様は Mery 内部の Undo の挙動に依存します。
    >
    > つまり、「選択範囲を変更しただけ」のように Mery 本体側で Undo として記録されない動作に対して Undo ポイントを設定して復元ポイントのように使うといったことはできません。
    >
    > そういった意味でも Redraw プロパティの流用という形での簡易な実装を想定していました。

    今更なレスですが、私も復元ポイント的なものだと勘違いしていました。。。
    この意味合いの動作なら確かに、別メソッドよりも Redraw の流用はしっくりとくる気がします。

     |  yuko  |  返信
  30. ご意見ありがとうございます。
    この案件は、予想以上にご意見が分かれてしまい、収拾がつかなくなってしまいましたね… ^^;

    > この意味合いの動作なら確かに、別メソッドよりも Redraw の流用はしっくりとくる気がします。
    あれから結構時間がたつので、もう時効ということにして、しれーっと Redraw 流用方式で実装しておきましょうかね。特に害があるような仕様変更でもないと思いますので…。

     |  Kuro  |  返信
  31. > あれから結構時間がたつので、もう時効ということにして、しれーっと Redraw 流用方式で実装しておきましょうかね。特に害があるような仕様変更でもないと思いますので…。

    支持! ノシ
    「1マクロ = 1アンドゥ」のためのお手軽な仕組みができるのは喜ばしいことです。

     |  sukemaru  |  返信
  32. > 支持! ノシ
    実装しました!もう、どんなご意見が来ても Undo しないからねっ!

     |  Kuro  |  返信
  33. > どんなご意見が来ても Undo しないからねっ!

    うまいw
    地味な仕様変更ですが、自作マクロ達で便利な場面が多そうで、楽しみです!

     |  yuko  |  返信
  34. こんにちは。
    標記の件についてですが、Ver 2.6.15 で Redraw プロパティ流用方式でお試し実装してみましたところ、マクロの中で Undo メソッドを使っているものに影響が及ぶというコメントをいただきました。

    やっぱり廃止…、というのも残念なので、Redraw プロパティ案を投稿したときにチラッと書いた専用メソッド案 (BeginUpdate ~ EndUpdate) を再提案してみます。(ジャンプできるようにその投稿に返信しています)

    Redraw プロパティを流用すれば既存のマクロも勝手に 1 Undo 化できて便利かも、という案が発端だったので、みなさんからはそれを生かしたアイデア (プロパティを分けて、RedrawUndo にする案など) をいただいたり、あと、私の仕様説明が足りなかったので復元ポイント的な用途を想定したメソッドおよび仕組みをご提案いただいたりしました。

    その節はありがとうございました。ちょっと色々詰め込みすぎて混乱を招いてしまった気がします。

    ・Redraw プロパティは忘れて、既存のマクロに影響を及ぼさないこと
    ・復元ポイントではなく Undo をグループ化する機能であること

    この 2 点を踏まえて、シンプルに専用メソッドを用意する案です。

    document.BeginUndoGroup(); // Undo グループ開始
    document.selection.Text = "a";
    document.selection.Text = "b";
    document.selection.Text = "c";
    document.EndUndoGroup(); // Undo グループ終了
    
    document.BeginUndoGroup(); // Undo グループ開始
    document.selection.Text = "d";
    document.selection.Text = "e";
    document.selection.Text = "f";
    document.EndUndoGroup(); // Undo グループ終了

    こんな感じで、明示的に Undo をグループ化する BeginUndoGroup, EndUndoGroup メソッドを使う仕組みです。

    メソッド名に UndoGroup って付いているので、これなら復元ポイントという使い方ではなく、Undo 情報のグループ化ができるんだな、と一目で分かるかなと思います。

    1 点、気がかりなのは、これらのメソッドを持たせるオブジェクト (document, editor, window など) です。

    使い勝手を考えるとこれらのメソッドは Undo メソッドなどと同じで、document オブジェクトに持たせるのが分かりやすいと思うのですが、仕組み上、Undo のグループ化は document ごとではなく、全体 (window オブジェクトレベル) に対して発動します。

    したがって…

    document.BeginUndoGroup(); // Undo グループ開始
    for (var e = new Enumerator(editor.documents); !e.atEnd(); e.moveNext()) {
      var item = e.item();
      item.selection.Text = "a";
      item.selection.Text = "b";
      item.selection.Text = "c";
    }
    document.EndUndoGroup(); // Undo グループ終了

    こんな感じで記述すると、BeginUndoGroup, EndUndoGroup はアクティブな document から呼び出しているだけなのにアクティブな document 以外の document に対してもそれぞれ Undo のグループ化が行われます。

    これは 1 回の Undo ですべての document の状態が Undo するという意味ではなく、それぞれの document ごとに "abc" が 1 Undo として登録されるという意味です。

    つまり、仕様上の BeginUndoGroup, EndUndoGroup の影響範囲として考えると window オブジェクトにメソッドを持たせて、window.BeginUndoGroup(), window.EndUndoGroup() という表現のほうが正しいのですが…。

    Undo 情報を操作するメソッドが window の中にあるっていうのもなんだか変な気がして、ちょっと困っています。

    廃止にする前にワンチャンあるかなーと思って書かせていただきましたが、またややこしい話になってきてしまい、すみません…。

     |  Kuro  |  返信
  35. 既存マクロに影響があったとのことで、それは残念でしたね。
    現仕様の Redraw を試して、Undo が一纏まりになるのはやっぱり便利だなぁ…と感じたので、廃止にせず、新メソッドか新プロパティの実装で対応してもらえると嬉しいです。

    そして、絶賛悩み中の「どのオブジェクトに属すると適切か?」という問題ですが、私は window オブジェクトでいいと思います。

    Kuro さんが懸念されているように影響範囲と直接関係するオブジェクトにぶら下げた方が、コーディングの際に記述するスコープを意識しやすくなるため良いのではと考えます。

    「Undo 操作は各ドキュメント単位で行うものなのに、window オブジェクトで持たせることには違和感がある」という話は、感覚的に何となく分かります。
    が、そこはマクロ製作でのバグを減らすためと割り切って、影響範囲との関係性を重視するのが良いと思います。

    それと、これはあまり重要なことではないので聞き流していただいてもいいくらいに思っている意見なのですが…メソッドではなくて Redraw のようなプロパティで持たせてはどうでしょう?

    例えば UpdateUndo というプロパティを新設し、今の Redraw が担っている Undo グループ化機能の部分を持たせるなどです。
    つまり、True の間は通常通り Undo が記録されていき、False の間は Undo が記録されないイメージです。

    プロパティで持たせることでマクロ開発者諸氏は今の Redraw と同じような感覚を持つことができ、すぐに使いこなせるのではないかな?と思った次第です。

     |  yuko  |  返信
  36. ご返信ありがとうございます。

    確かに、スコープという点からみると window オブジェクトが妥当ですね。

    > 「Undo 操作は各ドキュメント単位で行うものなのに、window オブジェクトで持たせることには違和感がある」という話は、感覚的に何となく分かります。

    そこなんですよね。
    document オブジェクトに持たせて、Undo のグループ化も document オブジェクト単位でできるに越したことはないと思うので、現在の仕様でとりあえず window オブジェクトに実装して…ではなく、将来的に document オブジェクト単位で Undo を管理できる仕組みが出来上がるまで保留 (出来上がらない可能性もありますが) にするという手もあるかと思います。

    マクロの仕様は後戻りがしづらいので…。

    > 例えば UpdateUndo というプロパティを新設し、今の Redraw が担っている Undo グループ化機能の部分を持たせるなどです。

    プロパティ案も一理あると思います。

    以前にそれに近いご意見を頂いたことがあって、RedrawUndo プロパティというのを用意する案でしたが、そのほうが Redraw と同じ感覚で使えますし、既存のマクロの Redraw プロパティの部分に対して修正を加えやすいというメリットがありました。

    その通りだと思うのですが、これらの発端は私が Redraw プロパティを流用するアイデアを提案してしまったため、それを生かす形になってしまったこともありますので、今回は、Redraw プロパティのことは一度忘れて、Undo をグループ化するための機能ということで、純粋にプログラミング言語の仕様という気持ちで考えてみました。

    > つまり、True の間は通常通り Undo が記録されていき、False の間は Undo が記録されないイメージです。
    そこなんですよね。私が最初にプロパティ案を出しちゃったもので、Redraw プロパティみたいに Undo の記録を抑制するための仕組みだと思われてしまっていますが、違うんです。

    Undo データは常に記録されます。そのデータに対してグループ化を行うための仕組みですので、機能としては Objective-C の beginUndoGrouping, endUndoGrouping メソッドが近いです。
    https://developer.apple.com/documentation/foundation/nsundomanager/1409894-beginundogrouping?language=objc

    このような名前のメソッドにしておけば、言語仕様としては分かりやすいのではないかなーと思いまして、BeginUndoGroup、EndUndoGroup メソッド案を考えてみました。

     |  Kuro  |  返信
  37. > Undo データは常に記録されます。そのデータに対してグループ化を行うための仕組みですので、機能としては Objective-C の beginUndoGrouping, endUndoGrouping メソッドが近いです。

    なるほど、そうだったんですね。
    であれば、メソッドなら BeginUndoGroup, EndUndoGroup で良いですね。

    あるいはプロパティなら、 DocumentsUndoGroup = True/False (デフォルト False) などでしょうか。
    このプロパティなら「ウィンドウ内の各ドキュメントで Undo グループ化機能が有効化される」という捉え方もしやすいかも? (ちょっと、こじつけ過ぎですかね。。。)

    > document オブジェクト単位で Undo を管理できる仕組みが出来上がるまで保留 (出来上がらない可能性もありますが) にするという手もあるかと思います。

    確かにそれが一番収まりがいいですね。

    しかし、これが無いとマクロが成り立たないというほどの機能ではなく、Redraw プロパティと同じような「あればちょっと便利になる」という立ち位置の機能だと思いますし、「document オブジェクト単位で Undo を管理できる仕組み」を作る難度がよほどヘビーになるのであれば、Kuro さんの時間も限られていますし、今の状態で実装するのも妥当かなぁと私は感じます。

    あとは他の方の意見もちょっと気になるところですねー。

    私としては今まで Undo を一纏まりにしたいときには、複数行の文字列を頑張って作り込んで一発で挿入するなり、置換で一発で動くようにするなりと工夫していました。この機能があることで、そのあたりの作成難易度はグッと下がるので、どんな形であれ正式実装に期待が高まります。

     |  yuko  |  返信
  38. ご返信ありがとうございます。

    > あるいはプロパティなら、 DocumentsUndoGroup = True/False (デフォルト False) などでしょうか。
    > このプロパティなら「ウィンドウ内の各ドキュメントで Undo グループ化機能が有効化される」という捉え方もしやすいかも? (ちょっと、こじつけ過ぎですかね。。。)

    プロパティにするならそんな感じの名称で良さそうですね。
    ただ、プロパティにした場合、グループ開始とグループ終了が、それぞれ True と False のどっちなのかが分かりづらいような… (Redraw プロパティだと、False で抑制、True で再開、ですがその逆?)

    > しかし、これが無いとマクロが成り立たないというほどの機能ではなく、Redraw プロパティと同じような「あればちょっと便利になる」という立ち位置の機能だと思いますし、「document オブジェクト単位で Undo を管理できる仕組み」を作る難度がよほどヘビーになるのであれば、Kuro さんの時間も限られていますし、今の状態で実装するのも妥当かなぁと私は感じます。

    ありがとうございます。「document オブジェクト単位で Undo を管理できる仕組み」は、まったく用意していませんので、ゼロからの開発となりますから、待っていると数年後の可能性も…?

    それか、現状ではスコープが分かりづらいけど、とりあえず document オブジェクトに持たせておいて、将来的に document 単位で発動するように仕様変更するという手もありますね。あ、でも将来的にそれを開発しない場合、ただスコープが分かりづらいだけで終わっちゃいますね… ^^;

    > あとは他の方の意見もちょっと気になるところですねー。

    そうですねー。window オブジェクトに持たせるのが相当イヤ!っていうわけではないので、みなさんが納得できそうな着地点を探したいです。

    > 私としては今まで Undo を一纏まりにしたいときには、複数行の文字列を頑張って作り込んで一発で挿入するなり、置換で一発で動くようにするなりと工夫していました。この機能があることで、そのあたりの作成難易度はグッと下がるので、どんな形であれ正式実装に期待が高まります。

    ご意見、大変参考になります。みなさん苦労をされていたのですね…。私はキーを押しっぱなしにして「Undo おっそ!」とか愚痴りながらダダダダダって Undo してました (w

     |  Kuro  |  返信
  39. > ただ、プロパティにした場合、グループ開始とグループ終了が、それぞれ True と False のどっちなのかが分かりづらいような… (Redraw プロパティだと、False で抑制、True で再開、ですがその逆?)

    うーむ、確かにちょっとあるかもですね。

    UndoGroup と Redraw は一緒に使うことが多そうですから、

    Redraw = False
    DocumentsUndoGroup = True

    なんていうセットで書くことになりそうですね^^;

    まぁデフォルトが、再描画(Redraw)は On
    状態、UndoGroup 機能は Off 状態ですから、その辺の意味が入れ替わるのも仕方なしかなと。
    それにこれくらいなら慣れの問題かなーとも思います。

     |  yuko  |  返信
  40. > まぁデフォルトが、再描画(Redraw)は On
    > 状態、UndoGroup 機能は Off 状態ですから、その辺の意味が入れ替わるのも仕方なしかなと。
    > それにこれくらいなら慣れの問題かなーとも思います。
    ご意見ありがとうございます。
    Redraw プロパティのことは忘れた上でのプロパティ案ということで、True と False の意味合いもその感覚で良さそうですね。

    その後、もう少し調べてみたのですが、某有名テキストエディタのマクロでも似たような機能が用意されていたので、参考までに記載しておきます。

    秀〇エディタさんは、begingroupundo, endgroupundo ということでメソッド方式を採用されているようです。
    https://help.maruo.co.jp/hidemac/html/155_OtherStatement_begingroupundo.html

    E〇Editor さんは、CombineHistory プロパティということでプロパティ方式を採用されているようです。しかも windows オブジェクトに持たせてありますね。
    http://www.emeditor.org/ja/macro_window_combine_history.html

    結局、どっちなんや!ということになりそうではありますが… (w とりあえず次のバージョンでは Redraw 方式を廃止しただけ、という形になってしまうかもしれません。

     |  Kuro  |  返信
  41. 両エディタとも搭載されていたのですね。
    まぁ確かに使ったら便利でしたし、あちらもかつて要望とかあったのかもですね。

    私の感覚では document 単位ならメソッド、window 単位ならプロパティの方がしっくり来るかなぁ…。

    ただ前述の通り、document 単位にするためにそこまで時間を割かなくてもいいのではないかなぁと思うところがあるので、そういう意味も込めて、私としては window 単位でのプロパティ案に一票です。
    (もちろん利用できることが一番嬉しいので、最終的にはメソッドでもプロパティでも構いませんよ!)

     |  yuko  |  返信
  42. ご返信ありがとうございます。

    その後、検討しまして、仕様を決定しました
    yuko さんのご希望の案と私の案の中間になりますが、window 単位で BeginUndoGroup() と EndUndoGroup() メソッドにしました。

    yuko さんのおっしゃる通り、スコープの分かりやすさという点と、document 単位にするのに時間を割くのも…という点で window 単位にしました。

    プロパティとメソッドで非常に悩んだのですが、最終的にメソッドにしたのは Microsoft の ITextDocument Interface の仕様で BeginUndoGroup を発見したのと、Adobe のスクリプトの仕様で beginUndoGroup() を発見したためです。

    ITextDocument.BeginUndoGroup Method
    https://docs.microsoft.com/en-us/uwp/api/windows.ui.text.itextdocument.beginundogroup#Windows_UI_Text_ITextDocument_BeginUndoGroup

    Application object > Methods >‎beginUndoGroup()
    http://aejsx.hiroshisaito.net/application-object/methods/beginundogroup

    こういった BeginXXXX ~ EndXXXX という名前のメソッドは一般的にネスト可能なメソッドになっています。(上記の MS や Adobe のメソッドの他にも、例えば beginTransaction ~ endTransaction など)

    したがって、Mery の Undo グループもネスト可能なメソッドとして実装します。

    // BeginUndoGroup(); // 全体 (ひとまずコメント)
    try {
    	BeginUndoGroup(); // 1 つめのグループ
    	try {
    		document.selection.Text = "a";
    		document.selection.Text = "b";
    		document.selection.Text = "c";
    	} finally {
    		EndUndoGroup();
    	}
    	BeginUndoGroup(); // 2 つめのグループ
    	try {
    		document.selection.Text = "d";
    		document.selection.Text = "e";
    		document.selection.Text = "f";
    	} finally {
    		EndUndoGroup();
    	}
    } finally {
    	EndUndoGroup();
    }

    こんな感じで、入れ子にしてやることが可能で、例えば、テスト段階では一番外側の "BeginUndoGroup(); // 全体" はコメントアウトしておけば、"abc" と "def" がグループ化され、テスト完了後に一番外側の "BeginUndoGroup(); // 全体" を有効にしてやれば、全体を 1 Undo 化できる感じです。

    (従来のプロパティ方式では、False にした時点でネストに関係なくグループが解除されていたので、こういった使い方はできませんでした)

    また、EndUndoGroup() を省略した場合でもマクロ実行後に自動的にグループは閉じられますので、例えば過去のマクロを全部 1 Undo 化したい場合などは、先頭に 1 行、"BeginUndoGroup();" を付け足すだけで OK な感じになります。

    …これで行かせていただけると、私の日曜日が報われます。

     |  Kuro  |  返信
  43. スレッドがすごく伸びてるとおもったら色々と紆余曲折があったんですね。

    > window 単位で BeginUndoGroup() と EndUndoGroup() メソッドにしました。
    > Mery の Undo グループもネスト可能なメソッドとして実装します。

    これはスゴイ。あらためて、支持! ノシ

     |  sukemaru  |  返信
  44. とうとう仕様が決まったようで、まずはご検討お疲れさまでした!

    その案で全く問題ないと思います!
    これでまた、Mery マクロ職人達の未来は明るくなりますねw

     |  yuko  |  返信
  45. みなさん、ご意見ありがとうございました。

    私一人だと、たぶん document 単位で、ネスト不可な BeginUndoGroup メソッドというかたちで、微妙に使いづらいことになっていたと思います。

    window 単位で、ネスト対応の BeginUndoGroup は、(゚∀゚)キタコレ!! 感ありますので、yuko さんをはじめ、ご意見をくださった皆様、ありがとうございました!

     |  Kuro  |  返信
スポンサーリンク