マルチカーソルの折り返し行に対する挙動

  1. 動作確認環境
    * Mery Portable(32bit) v3.2.8
    * Windows10 64bit

    設定は、新規インストール後に、以下の2カ所のみ変更。
    * [ツール>オプション>基本>マルチカーソルを有効にする]チェックする
    * [ツール>オプション>基本>折り返し方法]指定文字数で折り返し

    Meryはマルチカーソルが使えて軽いテキストエディターなので助かっています!
    相談です。

    折り返し行がある場合に、[編集>次の行にカーソルを追加]すると、論理行でなく「物理的な次の行」にカーソルが追加されてしまいます。

    その後、たとえば「インデントを下げたいなぁ」とか思ってDelキーで1文字削除すると行の途中の文字が消えて、おかしな文になります。この挙動で何度も文を壊してしまった……

    VSCode v1.58.2 でも同じ挙動なのですが、VSCodeでは回避方法があります。

    * マルチカーソル出した後に[Home]ボタン押下で、論理行のみのマルチカーソル(が行頭にある状態)にできる
    * 拡張機能 https://marketplace.visualstudio.com/items?itemName=MartinZimmermannApps.CursorColumnSelectOnTrueLines で論理行カーソル追加の挙動にできる

    Meryはこのような回避方法がないようなので、ご相談しました。
    個人的には、論理行カーソル追加になるのが最も理想的な挙動です。

    現状でもVSCodeと同じ実装なので、修正しなくても納得ですが、ご検討いただけますでしょうか。

    (参考にしました1: https://stackoverflow.com/questions/53283020/how-to-avoid-multi-cursor-on-wrapped-lines-in-vs-code

    (参考にしました2: https://github.com/microsoft/vscode/issues/26393 )
    > VSCodeの現在の実装は、まったく危険なものだと言えます。
    > 私は何度も誤って折り返し行の中にゴミを追加してしまい、後でそれを探さなければならなくなりました。

     |  Red  |  返信
  2. > * マルチカーソル出した後に[Home]ボタン押下で、論理行のみのマルチカーソル(が行頭にある状態)にできる
    > * 拡張機能 https://marketplace.visualstudio.com/items?itemName=MartinZimmermannApps.CursorColumnSelectOnTrueLines で論理行カーソル追加の挙動にできる
    >
    > Meryはこのような回避方法がないようなので、ご相談しました。

    「マルチカーソル出した後に[Home]ボタン押下で、論理行のみのマルチカーソル(が行頭にある状態)にできる」の方の回避方法にはなりますが、そちらならマクロでどうにかなりそうです。

    マクロで「document.selection.Mode」プロパティは、マルチカーソル使用時に定数「meModeMulti」の値を指すので、以下のようなマクロを用意してHomeキーで動くように設定すれば、マルチカーソルを行頭に移動させ、各論理行ごとにまとめることができます。

    // シフトの状態(オンの場合は選択、オフの場合は移動)
    var shift = false;
    
    if (document.selection.Mode === meModeMulti) {
      document.selection.StartOfLine(shift, mePosLogical);
    } else {
      document.selection.StartOfLine(shift, mePosView);
    }
     |  yuko  |  返信
  3. よくよく観察してみるとVSCodeの場合は、「表示行先頭にカーソルがある場合に再度Homeキーを押すと論理行先頭に移動する」という動きをするのですね。これはこれで表示行と論理行の先頭移動が両方使えるので、いい感じかもしれませんね。

    ここまで再現したい場合は、以下のような感じでしょうか。

    // シフトの状態(オンの場合は選択、オフの場合は移動)
    var shift = false;
    
    if (document.selection.Mode === meModeMulti) {
      doMultiAction(homeLikeVscode);
      document.selection.CharRight();
      document.selection.CharLeft();
    } else {
      homeLikeVscode();
    }
    
    function homeLikeVscode() {
      var actViewX = document.selection.GetActivePointX(mePosView);
      if (actViewX === 1) {
        document.selection.StartOfLine(shift, mePosLogical);
      } else {
        document.selection.StartOfLine(shift, mePosView);
      }
    }
    
    function doMultiAction(fn) {
        var d = document, s = d.selection;
        s.Mode = meModeMulti;
    
        var selections = [{ s: s.GetAnchorPos(), e: s.GetActivePos() }];
        if (s.Count > 0) {
            selections = [];
            for (var i = 0; i < s.Count; i++)
                selections.push({ s: s.GetActivePos(i), e: s.GetAnchorPos(i) });
        }
        var p = 0;
        var q = 0;
        for (var i = 0; i < selections.length; i++) {
    
            s.SetActivePos(selections[i].s + p);
            s.SetActivePos(selections[i].e + p, true);
            q = d.TextLength;
    
            fn();
            p += d.TextLength - q;
    
            selections[i] = { s: s.GetAnchorPos(), e: s.GetActivePos() };
        }
    
        for (var i = 0; i < selections.length; i++)
            s.AddPos(selections[i].s, selections[i].e);
    }
     |  yuko  |  返信
  4. Mery をご愛用いただきありがとうございます。

    [次の行にカーソルを追加] の挙動につきましては、将来的には変更される可能性もありますが、現在のところ VSCode、Visual Studio、Atom、Sublime Text なども同様の仕様になっているようなので Mery の仕様も現状通りとさせていただければと思います。

    yuko さん、ご協力ありがとうございます。

    [Home] ボタンを使う方法の場合は yuko さんのマクロで行けそうですね。

    VSCode の [Home] ボタンの挙動はなかなか面白いですが、この仕様が採用されているのは VSCode と Sublime Text ぐらいでしょうか。

    > * 拡張機能 https://marketplace.visualstudio.com/items?itemName=MartinZimmermannApps.CursorColumnSelectOnTrueLines で論理行カーソル追加の挙動にできる

    マクロを使えばそれっぽいことはできると思います。

    例えば…

    【論理座標で前の行にカーソルを追加】

    var x = document.selection.GetActivePointX(mePosLogical);
    var y = document.selection.GetActivePointY(mePosLogical);
    document.selection.AddPoint(mePosLogical, x, y - 1);

    【論理座標で次の行にカーソルを追加】

    var x = document.selection.GetActivePointX(mePosLogical);
    var y = document.selection.GetActivePointY(mePosLogical);
    document.selection.AddPoint(mePosLogical, x, y + 1);

    こんな感じのマクロをそれぞれ、ショートカットキーに割り当てれば VSCode の拡張機能のような動作になると思います。(マクロはサンプルなので良い感じにカスタマイズしてください)

    ちなみに、テキストに半角と全角が混在している場合、X 座標は文字数が基準なのでズレますが、これは VSCode の拡張機能でもそうなっているようなので、ご容赦いただければと思います。

     |  Kuro  |  返信
  5. > 例えば…
    > 【論理座標で前の行にカーソルを追加】
    > 【論理座標で次の行にカーソルを追加】

    検証していたらちょっと問題がありました。

    [次の行にカーソルを追加] をしている途中で [前の行にカーソルを追加] を呼び出したとき、またはその逆のときを考慮していませんでした。

    あと、直前に追加されたカーソルの位置を基準にしているので VSCode の拡張機能とはちょっと動作が異なる場合がありますね。

    VSCode の拡張機能はソースが公開されているようなので、Mery のマクロでももう少し頑張れば実現できそうではあるのですが…。

     |  Kuro  |  返信
  6. 改善してみました。

    【論理座標で前の行にカーソルを追加】

    var x = document.selection.GetActivePointX(mePosLogical, document.selection.Count - 1);
    var y = document.selection.GetActivePointY(mePosLogical, 0);
    document.selection.AddPoint(mePosLogical, x, y - 1);

    【論理座標で次の行にカーソルを追加】

    var x = document.selection.GetActivePointX(mePosLogical, 0);
    var y = document.selection.GetActivePointY(mePosLogical, document.selection.Count - 1);
    document.selection.AddPoint(mePosLogical, x, y + 1);

    まだ、X 座標の基準となるカーソル位置が完璧ではありませんが、普通に使う分には実用の範囲内かと思うのですがいかがでしょうか。

     |  Kuro  |  返信
  7. yukoさん Kuroさん VSCodeを調査したうえでマクロを提示いただきまして、ありがとうございます。

    Kuroさん Mery の仕様は現状通りとのこと、承知しました。
    マクロにショートカットキーを設定すれば、もとからある機能のように使えますので、私はこれで十分です。

     |  Red  |  返信
  8. マクロ便利に使えています! ありがとうございました。

     |  Red  |  返信
  9. VSCodeの行頭/行末移動の動作(表示行上、行頭/行末にいる場合に論理行上の行頭/行末に移動)が気に入ったので、再現動作マクロとして Mery Wiki に公開しました。(先刻提示した行頭移動のマクロに微妙な動作の箇所もあったので、修正しつつ)

    https://www.haijin-boys.com/wiki/VSCode風、行頭/行末に移動

    マクロ作成の良いアイデアを頂けたことに感謝します。

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