行頭か行末 または 選択範囲の始点か終点

ダウンロード 編集

ファイル:行頭か行末 または 選択範囲の始点か終点.zip

  • 通常版
  • GetKeyState.exe による機能拡張版
  • マテリアルデザインっぽいアイコン

通常版 編集

ショートカットキーやツールバーアイコンを削減するために、自分がよく使う機能をひとまとめにしてみました(ショートカットの割りあては Home または End キーひとつで済み、ツールバーアイコンやマウスボタンへの割りあてもこれひとつで)。

  • 行頭/行末のトグル移動のパターンは 2in1 モードと 4in1 モードを選択可
#title = "行頭か行末 または 選択範囲の始点か終点"
#tooltip = "行の先頭か末尾 または 選択範囲の始点か終点 にカーソルを移動する"
// #icon = "invert_caret_pos[2].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",129

/**
 * ---------------------------------------------------------
 * 「行頭か行末 または 選択範囲の始点か終点」マクロ
 * sukemaru, 2018/07/20 - 2020/06/26
 * ---------------------------------------------------------
 * (2020/06/26: マルチカーソル対応)
 */

// ---------- ▼ 設定項目 ▼ ---------- //

// ■ トグルパターン設定: 2in1モード or 4in1モード
var toggleMode2 = false;

// true のとき  ⇒ 2in1トグルモード(行頭 ⇔ 行末)
// false のとき ⇒ 4in1トグルモード(行頭 → 行頭空白の後ろ → 行末空白の前 → 行末)

// ---------- ▲ 設定項目 ▲ ---------- //


editor.ExecuteCommandByID( 2189 );	// アクティブなペイン
var sx = ScrollX,  sy = ScrollY;
var s = editor.ActiveDocument.selection;
var st = s.Text;

// マルチカーソル対応
var arg = [ toggleMode2 ];
// 選択範囲が1つで矩形選択ではないとき
if ( ! s.Mode || s.Mode === 1 ) {
  TopEndOfLine( arg );
}
// 矩形選択または複数選択のとき
else {
  BeginUndoGroup();
  AddUndo();
  MultiFunction( TopEndOfLine, arg );
  EndUndoGroup();
}

// ScrollX = sx;
ScrollY = sy;


/**
 * TopEndOfLine( toggleMode2 )
 * 「行頭か行末 または 選択範囲の始点か終点」
 */
function TopEndOfLine( arg ) {
  var toggleMode2 = arg[0];

  var d = editor.ActiveDocument;
  var s = editor.ActiveDocument.selection;
  var act = s.GetActivePos();

  // 選択範囲あり
  if ( s.Text ) {
    var anc = s.GetAnchorPos();
    // 「選択範囲の始点終点を交替」
    s.SetAnchorPos( act );
    s.SetActivePos( anc, true );
  }

  // 2in1 トグルモード 「行頭か行末」
  else if ( toggleMode2 ) {
    if ( s.GetActivePointX( mePosLogical ) != 1 ) {
      // ➀ 行頭に移動
      s.StartOfLine( false, mePosLogical );
    }
    else {
      // ➁ 行末に移動
      s.EndOfLine( false, mePosLogical );
    }
  }

  // 4in1 トグルモード
  else {
    var ax = s.GetActivePointX( mePosLogical );
    var ay = s.GetActivePointY( mePosLogical );
    var str = d.GetLine( ay, 0 );
    var top = act + 1 - ax;             // 行頭位置
    var sId = str.search( /[^  \s]/ );  // 行頭の空白文字数
    var eId = str.replace( /[  \s]*$/, "" ).length; // 行末の空白を除いた文字数
    var ind = top + sId;                // インデントの後ろ位置
    var end = top + eId;                // 行末空白の前の位置

    if ( act == top && sId > 0 ) {
      // ➁ 文字列開始位置に移動(インデントの後ろ)
      s.SetActivePos( ind );
    }
    else if ( act != end && ( act == ind || act == top ) ) {
      // ➂ 文字列終了位置に移動(行末空白の前)
      s.SetActivePos( end );
    }
    else if ( act != top + str.length && ( act == end || act == ind || act == top ) ) {
      // ➃ 行末に移動
      s.EndOfLine( false, mePosLogical );
    }
    else {
      // ➀ 行頭に移動
      s.StartOfLine( false, mePosLogical );
    }
  }
}


/**
 * 関数 MultiFunction( Fn, arg )
 * マルチカーソル(複数選択範囲)に対応させる
 * 第1引数: Function; 選択範囲ごとに適用する処理の関数
 * 第2引数: Function に渡す引数をまとめた配列
 */
function MultiFunction( Fn, arg ) {
  var d = editor.ActiveDocument;
  var s = d.selection;

  // 矩形選択範囲は行に分ける
  s.Mode = meModeMulti;

  // 選択範囲の座標を取得
  var sCount = s.Count;
  var Sel = [];
  for ( var i = 0; i < sCount; i ++ ) {
    Sel[i] = {
      act: s.GetActivePos( i ),
      anc: s.GetAnchorPos( i )
    };
  }

  // 各選択範囲を処理;
  for ( var i = 0, diff = 0, dl; i < sCount; i ++ ) {
    dl = d.TextLength;
    s.SetActivePos( Sel[i].act + diff );
    s.SetAnchorPos( Sel[i].anc + diff );

    Fn( arg );	// TopEndOfLine() 関数「行頭か行末 または 選択範囲の始点か終点」

    // Fn() の残した選択範囲(またはキャレット位置)を回収
    Sel[i].act = s.GetActivePos();
    Sel[i].anc = s.GetAnchorPos();
    diff += d.TextLength - dl;	// 文字数の増減量(累積)
  }

  // マルチカーソル(複数選択範囲)を復帰
  for ( var i = 0; i < sCount; i ++ ) {
    s.AddPos( Sel[i].anc, Sel[i].act );
  }
}

GetKeyState.exe による機能拡張版 編集

自家用の機能拡張版です。

GetKeyState.exe を利用して、マクロ実行時の Shift / Ctrl キーの押し下げ状態により拡張機能を適用します。

※ ツールバーアイコンまたは右クリックメニューからの起動用です。

※ 選択範囲ありの状態から実行したときの処理速度が遅い…。

マクロライブラリ の「GetKeyState.exe(キー状態取得実行ファイル)」のページから ZIP 書庫をダウンロードし、解凍した中の実行ファイル GetKeyState.exe を Mery インストールフォルダ内の Macros フォルダに配置してください。

  • GetKeyState.exe を導入していない場合は「通常版」とおなじ機能しか使用できません。
選択範囲ありのとき
  • Ctrl キーのみ押し下げあり
⇒ 選択範囲を前後に1文字ずつ増加
※ マルチカーソルでは選択範囲が結合することがある
  • Shift キーのみ押し下げあり
⇒ 選択範囲を前後から1文字ずつ減少
※ マルチカーソルでゼロ幅の選択範囲がある場合とキャレットが「行頭に移動」する
  • CtrlShift キーの押し下げあり
⇒ 選択範囲の先頭側にキャレットを移動
※ マルチカーソル複数選択範囲でキャレットの前後関係をそろえる
  • Ctrl / Shift キーの押し下げなし
⇒ 「選択範囲の開始位置と終了位置を入れ替え」
選択範囲なしのとき
  • キャレットが複数あり(マルチカーソル)で Ctrl キーの押し下げあり
⇒ すべてのキャレットを行頭に移動
  • Ctrl / Shift キーの押し下げなし
⇒ 「行頭か行末」(2in1 トグル または 4in1 トグル)
#title = "行頭か行末 または 選択範囲の始点か終点 または 選択範囲の拡張"
#tooltip = "行の先頭か末尾 & 選択範囲の始点か終点 & 選択範囲の拡張"
// #icon = "invert_caret_pos[2].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",129

/**
 * ---------------------------------------------------------
 * 「行頭か行末 または 選択範囲の始点か終点 または 選択範囲の拡張」マクロ
 * sukemaru, 2018/07/20 - 2020/06/26
 * ---------------------------------------------------------
 * 2020/06/26: マルチカーソル対応
 */

// ---------- ▼ 設定項目 ▼ ---------- //

// ■ トグルパターン設定: 2in1モード or 4in1モード
var toggleMode2 = false;

// true のとき  ⇒ 2in1トグルモード(行頭 ⇔ 行末)
// false のとき ⇒ 4in1トグルモード(行頭 → 行頭空白の後ろ → 行末空白の前 → 行末)

// ---------- ▲ 設定項目 ▲ ---------- //


// GetKeyState で修飾キーの状態を取得(Macros\GetKeyState.exe)
var gks = editor.FullName.replace(/[^\\]+$/, "Macros\\GetKeyState.exe");
var gksEnable = new ActiveXObject("Scripting.FileSystemObject").FileExists(gks);
var $Ctrl = function() {
  return (gksEnable
  && new ActiveXObject("WScript.Shell").Run('"' + gks + '" c', 0, true) === 1);
}
var $Shift = function() {
  return (gksEnable
  && new ActiveXObject("WScript.Shell").Run('"' + gks + '" s', 0, true) === 1);
}

editor.ExecuteCommandByID( 2189 );	// アクティブなペイン
var sx = ScrollX,  sy = ScrollY;
var s = editor.ActiveDocument.selection;
var st = s.Text;

// マルチカーソル対応
var arg = [
  // トグルパターン設定
  toggleMode2,
  // 選択範囲ありかマルチカーソル
  ( st || s.Count ) ? $Ctrl() : false,
  // 選択範囲あり
  st ? $Shift() : false
];

// 選択範囲が1つで矩形選択ではないとき
if ( ! s.Mode || s.Mode === 1 ) {
  TopEndOfLine( arg );
}
// 矩形選択または複数選択のとき
else {
  BeginUndoGroup();
  AddUndo();
  MultiFunction( TopEndOfLine, arg );
  EndUndoGroup();
}

// ScrollX = sx;
ScrollY = sy;


/**
 * function TopEndOfLine()
 * 「行頭か行末 または 選択範囲の始点か終点 または 選択範囲の拡張」
 */
function TopEndOfLine( arg ) {
  var toggleMode2  = arg[0];
  var $ctrl  = arg[1];
  var $shift = arg[2];

  var d = editor.ActiveDocument;
  var s = editor.ActiveDocument.selection;
  var act = s.GetActivePos();

  // 選択範囲あり
  if ( s.Text ) {
    var anc = s.GetAnchorPos();
    var tp = Math.min( anc, act );
    var bp = Math.max( anc, act );
    var direction = ( anc < act );

    // 「選択範囲を前後に1文字ずつ増加」
    if ( $ctrl && ! $shift ) {
      s.SetActivePos( direction ? bp + 1 : tp - 1 );
      s.SetAnchorPos( direction ? tp - 1 : bp + 1 );
    }
    // 「選択範囲を前後から1文字ずつ減少」
    else if ( $shift && ! $ctrl ) {
      s.SetActivePos( direction ? bp - 1 : tp + 1 );
      s.SetAnchorPos( direction ? tp + 1 : bp - 1 );
    }
    // Ctrl + Shift なら「選択範囲の先頭」
    else if ( $shift && $ctrl ) {
      s.SetActivePos( tp );
      s.SetAnchorPos( bp );
    }
    // 「選択範囲の始点終点を交替」
    else {
      s.SetAnchorPos( act );
      s.SetActivePos( anc, true );
    }
  }

  // 選択範囲なし + Ctrl キーならつねに行頭
  else if ( $ctrl ) {
    s.StartOfLine( false, mePosLogical );
  }

  // 2in1 トグルモード
  else if ( toggleMode2 ) {
    // 「行頭か行末」マクロ
    if ( s.GetActivePointX( mePosLogical ) != 1 ) {
      // ➀ 行頭に移動
      s.StartOfLine( false, mePosLogical );
    }
    else {
      // ➁ 行末に移動
      s.EndOfLine( false, mePosLogical );
    }
  }

  // 4in1 トグルモード
  else {
    var ax = s.GetActivePointX( mePosLogical );
    var ay = s.GetActivePointY( mePosLogical );
    var str = d.GetLine( ay, 0 );
    var top = act + 1 - ax;             // 行頭位置
    var sId = str.search( /[^  \s]/ );  // 行頭の空白文字数
    var eId = str.replace( /[  \s]*$/, "" ).length; // 行末の空白を除いた文字数
    var ind = top + sId;                // インデントの後ろ位置
    var end = top + eId;                // 行末空白の前の位置

    if ( act == top && sId > 0 ) {
      // ➁ 文字列開始位置に移動(インデントの後ろ)
      s.SetActivePos( ind );
    }
    else if ( act != end && ( act == ind || act == top ) ) {
      // ➂ 文字列終了位置に移動(行末空白の前)
      s.SetActivePos( end );
    }
    else if ( act != top + str.length && ( act == end || act == ind || act == top ) ) {
      // ➃ 行末に移動
      s.EndOfLine( false, mePosLogical );
    }
    else {
      // ➀ 行頭に移動
      s.StartOfLine( false, mePosLogical );
    }
  }

}


/**
 * 関数 MultiFunction( Fn, arg )
 * マルチカーソル(複数選択範囲)に対応させる
 * 第1引数: Function; 選択範囲ごとに適用する処理の関数
 * 第2引数: Function に渡す引数をまとめた配列
 */
function MultiFunction( Fn, arg ) {
  var d = editor.ActiveDocument;
  var s = d.selection;

  // 矩形選択範囲は行に分ける
  s.Mode = meModeMulti;

  // 選択範囲の座標を取得
  var sCount = s.Count;
  var Sel = [];
  for ( var i = 0; i < sCount; i ++ ) {
    Sel[i] = {
      act: s.GetActivePos( i ),
      anc: s.GetAnchorPos( i )
    };
  }

  // 各選択範囲を処理;
  for ( var i = 0, diff = 0, dl; i < sCount; i ++ ) {
    dl = d.TextLength;
    s.SetActivePos( Sel[i].act + diff );
    s.SetAnchorPos( Sel[i].anc + diff );

    Fn( arg );	// TopEndOfLine() 関数「行頭か行末 または 選択範囲の始点か終点」

    // Fn() の残した選択範囲(またはキャレット位置)を回収
    Sel[i].act = s.GetActivePos();
    Sel[i].anc = s.GetAnchorPos();
    diff += d.TextLength - dl;	// 文字数の増減量(累積)
  }

  // マルチカーソル(複数選択範囲)を復帰
  for ( var i = 0; i < sCount; i ++ ) {
    s.AddPos( Sel[i].anc, Sel[i].act );
  }
}

メモ 編集

  • 2018/12/03 初版 (sukemaru)
    • 3in1 トグルモード
  • 2019/03/19 第2版 (sukemaru)
    • 2in1 or 4in1 トグルモード
  • 2020/06/26 第3版 (sukemaru)
    • あまり必要性を感じないけどマルチカーソルに対応
    • 「GetKeyState.exe による機能拡張版」を追加
    • ZIP 書庫をアップロード
スポンサーリンク