秀丸エディタでMarkdownが爆速になる「行頭トグル」マクロ(箇条書き / 引用 / タスク / 番号)

Markdownでブログを書くとき、地味にダルいのが 行頭の整形 だ。

  • 箇条書きにしたい → - を行頭に付ける
  • 引用にしたい → > を付ける
  • タスクにしたい → - [ ] を付ける
  • 番号付きにしたい → 1. 2. 3.…` を付ける

手でやると遅い。そこで秀丸マクロで 選択行をまとめて一発整形 できるようにする。
しかも、もう一回実行すると 解除(トグル) もできる。これが強い。


何ができる?(このマクロの特徴)

このマクロは「選択行」または「カーソル行」に対して、次を切り替える。

  • l:箇条書きトグル(- 付与 ↔ 解除)
  • q:引用トグル(> 付与 ↔ 解除)
  • t:タスクトグル(- [ ] 付与 ↔ 解除)
  • n:番号トグル(1. 連番付与 ↔ 解除)

さらに便利なポイントはこれ:

  • 選択が無い場合:自動で「カーソル行」を対象にする
  • 選択がある場合:その範囲の行をまとめて処理する
  • 空行は基本スルー(番号・箇条書きで空行が荒れにくい)

完成品:行頭トグルマクロ(コピペで使える)

ファイル名:md_line_prefix_toggle.mac

/*
  md_line_prefix_toggle.mac
  Markdown 行頭トグル
    l: -  (箇条書き)
    q: >  (引用)
    t: - [ ]  (タスク)
    n: 1. (番号)
  選択なしならカーソル行を対象にする。
*/

$mode = input("MD prefix: l(- ) / q(> ) / t(- [ ] ) / n(1. )", "l");

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

$CR = char(13);
$LF = char(10);

// 選択文字列を取得(選択は維持)
$s = gettext(seltopx, seltopy, selendx, selendy, 1);
#len = strlen($s);

// 先頭の空白/改行をスキップ(トグル判定用)
#i = 0;
while (#i < #len) {
    $ch = midstr($s, #i + 1, 1);
    if ($ch == " " || $ch == "\t" || $ch == $CR || $ch == $LF) {
        #i = #i + 1;
    } else {
        break;
    }
}

// -----------------------------
// l / q / t は replaceallfast で高速処理
// -----------------------------
if ($mode == "l") {
    if (midstr($s, #i + 1, 2) == "- ") {
        // 解除
        replaceallfast "^[ \\t]*- ", "", inselect, regular;
    } else {
        // 付与(空行は除外:.+)
        replaceallfast "^(.+)$", "- \\1", inselect, regular;
    }
    endmacro;
}

if ($mode == "q") {
    if (midstr($s, #i + 1, 2) == "> ") {
        replaceallfast "^[ \\t]*> ", "", inselect, regular;
    } else {
        replaceallfast "^(.+)$", "> \\1", inselect, regular;
    }
    endmacro;
}

if ($mode == "t") {
    if (midstr($s, #i + 1, 6) == "- [ ] ") {
        // [] は正規表現の予約語なので \\[ \\] としてエスケープ
        replaceallfast "^[ \\t]*- \\[ \\] ", "", inselect, regular;
    } else {
        replaceallfast "^(.+)$", "- [ ] \\1", inselect, regular;
    }
    endmacro;
}

// -----------------------------
// n(番号)は手作業で組み立て(連番が必要だから)
// -----------------------------
if ($mode == "n") {

    // 先頭行が「数字+. 」っぽければ解除モード
    #isOn = 0;
    #j = #i;
    while (#j < #len) {
        $c = midstr($s, #j + 1, 1);
        #a = ascii($c);
        if (#a >= 48 && #a <= 57) {
            #j = #j + 1;
        } else {
            break;
        }
    }
    if (#j > #i) {
        if (midstr($s, #j + 1, 2) == ". ") {
            #isOn = 1;
        }
    }

    // 改行をLFに統一して処理
    $s2 = strreplace($s, $CR + $LF, $LF);
    $s2 = strreplace($s2, $CR, $LF);

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

    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;
        }

        // 空行判定(空白/タブだけなら空行扱い)
        #llen = strlen($line);
        #k = 0;
        #has = 0;
        while (#k < #llen) {
            $c2 = midstr($line, #k + 1, 1);
            if ($c2 != " " && $c2 != "\t") {
                #has = 1;
                break;
            }
            #k = #k + 1;
        }

        $processed = $line;

        if (#has) {
            // インデント抽出
            #k = 0;
            while (#k < #llen) {
                $c2 = midstr($line, #k + 1, 1);
                if ($c2 == " " || $c2 == "\t") {
                    #k = #k + 1;
                } else {
                    break;
                }
            }
            $indent = midstr($line, 1, #k);
            $rest = midstr($line, #k + 1, #llen - #k);

            if (#isOn) {
                // 解除: indent + (数字+. ) を剥がす
                #m = 0;
                #rlen = strlen($rest);
                while (#m < #rlen) {
                    $d = midstr($rest, #m + 1, 1);
                    #a = ascii($d);
                    if (#a >= 48 && #a <= 57) {
                        #m = #m + 1;
                    } else {
                        break;
                    }
                }
                if (#m > 0 && midstr($rest, #m + 1, 2) == ". ") {
                    // ". " の2文字を飛ばす(開始位置は +3)
                    $rest = midstr($rest, #m + 3, #rlen - (#m + 2));
                }
                $processed = $indent + $rest;
            } else {
                // 付与: indent + "n. " + rest
                $processed = $indent + str(#num) + ". " + $rest;
                #num = #num + 1;
            }
        }

        $out = $out + $processed;

        if (#last) break;

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

    // 選択範囲を置き換える
    #sx = seltopx;
    #sy = seltopy;
    delete;
    moveto #sx, #sy;
    insert $out;

    endmacro;
}

// 不明モード
message "mode error";

導入手順(3分で終わる)

1) マクロをファイル保存

  1. 秀丸で新規ファイルを開く
  2. 上のマクロを貼り付ける
  3. md_line_prefix_toggle.mac という名前で保存する

2) 秀丸に登録

  1. [マクロ] → [マクロ登録] を開く
  2. 空いてる番号を選ぶ
  3. さっき保存した .mac を指定して登録

3) ショートカット割り当て(超おすすめ)

  1. [その他] → [キー割り当て] を開く
  2. 登録したマクロにキーを割り当てる
  • 例:Ctrl + Shift + L(好きに決めろ)

使い方(例)

例1:箇条書き(l)

対象の行を複数選択してマクロ → l

実行前

リンゴ
バナナ
みかん

実行後

- リンゴ
- バナナ
- みかん

もう一回 l を実行すると、- が外れて元に戻る。


例2:引用(q)

引用したい段落を選択して q

実行前

この設定は環境によって差が出る。
原因の切り分けが重要。

実行後

> この設定は環境によって差が出る。
> 原因の切り分けが重要。

例3:タスク(t)

手順チェックに最強。選択して t

実行前

WordPressに貼り付ける
見出しを整える
公開する

実行後

- [ ] WordPressに貼り付ける
- [ ] 見出しを整える
- [ ] 公開する

例4:番号(n)

連番が必要だから、ここだけは自前で組んでる。

実行前

下準備
本文を書く
推敲する

実行後

1. 下準備
2. 本文を書く
3. 推敲する

もう一回 n を実行すると、番号が剥がれて元に戻る。


仕組み(ざっくり理解でOK)

  • l/q/t は正規表現で一括置換してる
  • 付与:^(.+)$- \1 みたいに付ける
  • 解除:^[ \t]*- を消す
  • n は連番が必要なので、行ごとに分解して 1. 2. 3. を付け直す
  • すでに番号っぽい(数字+.)なら解除に回る

よくある質問

Q. 空行も - になる?

A. ならない。^(.+)$ を使ってるので 空行は対象外

Q. インデント(先頭の空白)はどうなる?

A. なるべく崩れないようにしてる。特に番号(n)は インデントを保持してから n. を付ける。


まとめ:ブログ執筆で地味に最強

ブログは「本文を書く」より「整形が遅い」と止まる。
このマクロがあると、

  • 手順 → タスク化
  • 補足 → 引用化
  • まとめ → 箇条書き化
  • 手順書 → 番号化

が一瞬でできる。記事が止まらなくなる。

次に組み合わせるなら「見出しレベル上下」「リンク化」も相性がいい。
この2本が揃うと、秀丸だけでブログ執筆が完結する。

コメント

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