秀丸エディタで「インデント整形」:タブ⇔スペース変換/インデント増減/行頭揃え

インデントが乱れると、読みにくいだけじゃなく事故る。

  • タブとスペースが混在して見た目が崩れる
  • 貼り付けたブロックだけ段がズレる
  • 箇条書きや設定ファイルの行頭が揃わない
  • コードのインデントをまとめて右に寄せたい/戻したい

そこで、秀丸マクロで「インデント整形」を一気にやる。

この記事で作るのはこの3つ。

  1. タブ→スペース(指定幅)
  2. スペース→タブ(指定幅のまとまりをタブ化)
  3. インデント増減(選択行を右へ/左へ)
  4. 行頭揃え(最小インデントへ寄せる)(ブロック全体を左詰め)

前提(対象範囲の考え方)

この手の整形は、行単位でやるのが安全。
なのでマクロは次の仕様にする。

  • 選択範囲がある → その選択行全体を対象
  • 選択がない → カーソル行を対象

マクロ本体(コピペで使える)

ファイル名:indent_tools.mac

/*
  indent_tools.mac
  インデント整形ツール(行単位):
    1) タブ → スペース(幅指定)
    2) スペース → タブ(幅指定)
    3) インデント増やす(右へ)
    4) インデント減らす(左へ)
    5) 行頭揃え(ブロックの最小インデントまで左詰め)

  仕様:
    - 選択が無ければカーソル行を対象にする
    - 選択があれば、その範囲の行を対象にする
*/

#cmd  = val(input("1=TAB→SP / 2=SP→TAB / 3=INDENT+ / 4=INDENT- / 5=ALIGN-LEFT", "3"));
#tabw = val(input("幅(スペース数): 2 or 4 など", "4"));
if (#tabw < 1) #tabw = 4;

$CR = char(13);
$LF = char(10);
$TAB = char(9);
$SP  = " ";

// tabw個スペース
$SPW = "";
#i = 0;
while (#i < #tabw) {
  $SPW = $SPW + $SP;
  #i = #i + 1;
}

// 選択が無ければカーソル行を選択
if (!selecting) {
  golinetop;
  beginsel;
  golineend;
}

// 選択文字列取得
#sx = seltopx;
#sy = seltopy;
$s  = gettext(#sx, #sy, selendx, selendy, 1);

// 改行をLFに寄せて行分解
$s2 = strreplace($s, $CR + $LF, $LF);
$s2 = strreplace($s2, $CR, $LF);

#slen = strlen($s2);
#start = 0;
$out = "";

// 先に「最小インデント」を求める(ALIGN-LEFT用)
#minIndent = 999999;

if (#cmd == 5) {
  #st = 0;
  while (1) {
    #p = strstr($s2, $LF, #st);
    if (#p < 0) {
      $line = midstr($s2, #st + 1, #slen - #st);
      #last = 1;
    } else {
      $line = midstr($s2, #st + 1, #p - #st);
      #last = 0;
    }

    // 空行は無視
    if ($line != "") {
      // 行頭の空白/タブを「幅換算」して数える
      #llen = strlen($line);
      #k = 0;
      #w = 0;

      while (#k < #llen) {
        $c = midstr($line, #k + 1, 1);
        if ($c == $SP) {
          #w = #w + 1;
        } else if ($c == $TAB) {
          #w = #w + #tabw;
        } else {
          break;
        }
        #k = #k + 1;
      }

      if (#w < #minIndent) #minIndent = #w;
    }

    if (#last) break;
    #st = #p + 1;
  }

  if (#minIndent == 999999) #minIndent = 0;
}

// 行ごとに処理
while (1) {
  #p = strstr($s2, $LF, #start);
  if (#p < 0) {
    $line = midstr($s2, #start + 1, #slen - #start);
    #last = 1;
  } else {
    $line = midstr($s2, #start + 1, #p - #start);
    #last = 0;
  }

  $newline = $line;

  // ---- 1) TAB→SP
  if (#cmd == 1) {
    $newline = strreplace($line, $TAB, $SPW);
  }

  // ---- 2) SP→TAB(行頭のみをタブ化:安全寄り)
  if (#cmd == 2) {
    // 行頭のスペース連続を tabw 単位でタブにする
    #llen = strlen($line);
    #k = 0;
    while (#k < #llen) {
      $c = midstr($line, #k + 1, 1);
      if ($c == $SP) {
        #k = #k + 1;
      } else {
        break;
      }
    }

    $head = midstr($line, 1, #k);
    $rest = midstr($line, #k + 1, #llen - #k);

    // head を tabw スペース単位でTAB化
    #h = strlen($head);
    #tabs = #h / #tabw;
    #rem  = #h % #tabw;

    $t = "";
    #i = 0;
    while (#i < #tabs) { $t = $t + $TAB; #i = #i + 1; }
    $r = "";
    #i = 0;
    while (#i < #rem)  { $r = $r + $SP;  #i = #i + 1; }

    $newline = $t + $r + $rest;
  }

  // ---- 3) インデント増やす(右へ)
  if (#cmd == 3) {
    if ($line != "") $newline = $SPW + $line;
  }

  // ---- 4) インデント減らす(左へ)
  if (#cmd == 4) {
    // 行頭から tabw まで削る(タブは tabw として扱う)
    if ($line != "") {
      #llen = strlen($line);
      #k = 0;
      #w = 0;

      while (#k < #llen && #w < #tabw) {
        $c = midstr($line, #k + 1, 1);
        if ($c == $SP) {
          #w = #w + 1;
          #k = #k + 1;
        } else if ($c == $TAB) {
          // 先頭タブは一発で消す
          #k = #k + 1;
          #w = #tabw;
          break;
        } else {
          break;
        }
      }

      $newline = midstr($line, #k + 1, #llen - #k);
    }
  }

  // ---- 5) 行頭揃え(最小インデント分だけ左詰め)
  if (#cmd == 5) {
    if ($line != "" && #minIndent > 0) {
      #llen = strlen($line);
      #k = 0;
      #w = 0;

      while (#k < #llen && #w < #minIndent) {
        $c = midstr($line, #k + 1, 1);
        if ($c == $SP) {
          #w = #w + 1;
          #k = #k + 1;
        } else if ($c == $TAB) {
          #w = #w + #tabw;
          #k = #k + 1;
        } else {
          break;
        }
      }

      // minIndentを超えた分は雑に切る(厳密なタブ境界揃えまではやらない)
      $newline = midstr($line, #k + 1, #llen - #k);
    }
  }

  $out = $out + $newline;

  if (#last) break;

  $out = $out + $CR + $LF;
  #start = #p + 1;
}

// 置換
delete;
moveto #sx, #sy;
insert $out;

message "インデント整形 完了";

導入手順(3分)

  1. 秀丸で新規ファイルを開く
  2. 上のマクロを貼り付ける
  3. indent_tools.mac で保存
  4. マクロ → マクロ登録 で登録
  5. 必要ならキー割り当て

使い方(実用パターン)

1) タブ→スペース(混在を潰す)

  • 対象範囲を選択(無ければカーソル行)
  • マクロ → 1 → 幅 4(または 2

2) スペース→タブ(行頭だけ)

  • マクロ → 2
    行頭のスペースをタブ化する。本文中のスペースは触らないので事故が少ない。

3) インデント増やす(右へ)

  • マクロ → 3
    選択行の先頭にスペース幅を追加。

4) インデント減らす(左へ)

  • マクロ → 4
    行頭から最大ぶん削る。先頭タブがあればそれを優先して削る。

5) 行頭揃え(最小インデントまで左詰め)

  • マクロ → 5
    選択したブロック内で「最も浅いインデント」を基準に、全行を左へ寄せる。
    貼り付けでズレたブロックの修正に効く。

動作例

インデント増減

入力(幅=2でINDENT+):

a
  b
    c

出力:

  a
    b
      c

行頭揃え

入力:

      a
        b
      c

最小インデントは a/c の分。そこまで揃えると:

a
  b
c

注意点(ここだけ読めば事故が減る)

  • SP→TABは行頭だけにしてある(本文のスペースを崩すと事故るから)
  • ALIGN-LEFT(行頭揃え) は、タブ境界を厳密に揃えるところまではやってない
    “ズレを直す用途”として割り切って使う
  • YAML/Pythonなど、インデントが意味を持つものは慎重に(幅を揃えるのが前提)

まとめ

  • タブ/スペース混在を潰すだけで表示崩れが減る
  • 選択行のインデント増減があると、ブロック編集が速くなる
  • 行頭揃えは「貼り付け後のズレ直し」で効く

インデント整形は地味だが、入れておくと作業の詰まりが減る。

タイトルとURLをコピーしました