行を複製 (複数行可)

2019年3月29日 (金) 05:45時点におけるSukemaru (トーク | 投稿記録)による版 (ソースコードを更新)

選択範囲がないばあいはカーソル位置の論理行を、選択範囲があるばあいは選択範囲をふくむ論理行全体(複数行可)を、下または上に複製します。

  • 行の途中からべつの行の途中までのような大ざっぱな範囲選択状態から「行の複製」を実行することを想定しています。
  • ルーラーの行番号のドラッグでの複数行選択やトリプルクリックでの行選択などで、選択範囲の末尾に改行が含まれているばあい、さいごの改行を無視します。


ソースコード

#title = "行を複製 (複数行可)"
#tooltip = "選択範囲(複数行可)の論理行を複製する"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",222
// 上向きの矢印のアイコンのインデックスは 223

/**
 * 2018/08/12 - 2019/03/28
 * 
 * 選択範囲を拡張してカーソル行(論理行)を "複製" する (複数行可)
 *
 * 文書終端の空行 ( ^[EOF] ) を選択範囲の末尾にぶら下げての "複製" はできるが、
 * 可否について条件あり。
 *
 *   選択範囲の確定時点でのキャレットの位置が "選択範囲の先頭にあるか"
 *   または "末尾 ( [EOF] マークの直前) にあるか" で判別する。
 *
 *   文字列または行番号をドラッグ(または "クリック & Shift+クリック" )して
 *   選択範囲を確定するさいに
 *   ・上から下にむけて選択範囲をつくった場合 → 終端の空行 ( ^[EOF] ) を含める
 *   ・下から上にむけて選択範囲をつくった場合 → 終端の空行 ( ^[EOF] ) を含めない
 *
 * ※ 文書終端の空行を含めているか否かで実行後のキャレットの位置をかえているのは、
 *    連続で実行するさいに同じ範囲を選択状態にして複製するための仕様
 *
 * 1行だけの複製なら
 * document.selection.DuplicateLine();
 */


// ■ 複製先	( 2018/12/26 追加 )
var duplicateDown = true;	// (下に:true / 上に:false)


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 ey = document.GetLines( 0 );	// 文書終端行の Y

// 選択範囲の末尾が終端の空行 ( ^[EOF] ) にあるときの調整用
var eof = ( ty < by && bx == 1 && ! document.Text.charAt( s.GetActivePos() ) )
              ? "\n"	// カーソル位置に文字がないばあいを [EOF] と判定する
              : "";

// 選択範囲の末尾が行頭にあるときの調整
if ( ty < by && bx == 1 ) {
  by --;
}

// 選択範囲の拡張
s.SetActivePoint( mePosLogical, 1, by );
s.EndOfLine( false, mePosLogical );
s.SetAnchorPoint( mePosLogical, 1, ty );

// 選択範囲の文字列を取得
var st = s.Text;

// カーソル位置は複製した行の末尾
// s.Text = st + eof + "\n" + st;	// ( 2019/03/28 コメントアウト )


// ■「下に複製」した行全体を範囲選択する

if ( duplicateDown ) {			// ( 2018/12/26 オプションフラグを追加 )
  s.Collapse( meCollapseEnd );	// ( 2019/03/28 追加 )
  s.Text = eof + "\n" + st;		// ( 2019/03/28 追加 )

  if ( eof.length ) {
    // 終端の空行をふくめて複製した場合 → カーソル位置は選択範囲の末尾
    s.SetActivePoint( mePosLogical, 1, by + 2 );
    s.EndOfDocument( true );
  }
  else {
    // 通常の行の複製の場合 → カーソル位置は選択範囲の先頭
    s.SetAnchorPos( s.GetActivePos() + 1 );
    s.SetActivePoint( mePosLogical, 1, by + 1, true );
  }
}


// ■「上に複製」した行全体を範囲選択する ( 2018/12/26 追加 )

else {
  s.Collapse( meCollapseStart );	// ( 2019/03/28 追加 )
  s.Text = st + eof + "\n";			// ( 2019/03/28 追加 )

  if ( ty == ey && ! st.length ) {
    // 終端の空行だけを複製した場合 → 範囲選択なし
    s.SetActivePos( s.GetActivePos() - 1 );
  }
  else {
    // 通常の行の複製の場合 → カーソル位置は選択範囲の末尾
    s.SetAnchorPoint( mePosLogical, 1, ty );
    s.SetActivePoint( mePosLogical, 1, by + 1, true );
    if ( eof.length ) {
      // 終端の空行をふくめて複製した場合 → カーソル位置は選択範囲の末尾
      s.SetActivePos( s.GetActivePos() + 1, true );
    }
  }
}


メモ

  • 文書終端の空行(EOF マークのみの行)を含めているかいないかで「行の複製」マクロ実行後のキャレット(入力カーソル)の位置をかえているのは、連続で「行の複製」を実行するさいに同じ範囲を選択状態にして複製させるための仕様です。
  • 2019/03/28 (sukemaru)
"上に複製" するためのオプションフラグを追加(デフォルトで "下に複製" )
以前のコードでは "ブックマークの位置がズレる" 問題があったので、動作仕様を変更
スポンサーリンク