秀丸エディタで折りたたみを手軽で便利に拡張する(再帰、トグル、範囲)


概要

  • 秀丸は高度な折りたたみ機能を持っています。
  • 一方で、アウトライナー(アウトラインプロセッサ)にあるような手軽で便利に折りたたむ機能はついていません。
    • 例えば、トグル & 再帰的な折りたたみ/展開 & 範囲選択した場合は折りたたみ/展開可能な場所を探して実行、をショートカットキーひとつ(例えば SHIFT+CTRL+「.」)で手軽にできると便利です。
    • 本記事はそれを可能にする方法を提供します。

説明

  • プレーンテキストを読み書きするとき、
    • 折りたたみ/展開できると楽なことがあります。
  • アウトライナー等のアプリによっては、以下のようなことが可能です。
    • ショートカットキーひとつで折りたたみ/展開できる。(例えば SHIFT+CTRL+「.」
    • トグルでできる。折りたたみ済みなら展開し、そうでないなら折りたたみ。
    • 再帰的に折りたたみ/展開できる。つまりネストした階層があるとき、浅い階層から深い階層まですべて折りたたみ/展開できる。
    • トグルと再帰は、VS Codeで例えると、 CTRL+K CTRL+[CTRL+K CTRL+] (再帰的な折りたたみ/展開)を、トグルで行うイメージです。
    • 範囲選択した場合、最上位階層が複数あっても、まとめて折りたたみ/展開できる。
  • 秀丸エディタでそれを実現するには、マクロを作成してショートカットキーに割り当てればOKです。
    • なおマクロなしの場合、秀丸エディタは、
      • ショートカットキーが割り当てられていません
      • トグルができません
      • まとめて折りたたみ/展開、ができません
        • 再帰的に(深い階層をまとめて)、ができません
        • 選択範囲をまとめて(最上位階層を複数それぞれ)、ができません
        • (選択範囲を単純に1つの階層として折りたたむことはできます)
        • (ファイル全体を対象にする折りたたみ/展開はできます)
  • 掲載したマクロは、
    • トグルができます。
    • 再帰的に折りたたみ/展開できます。
    • 範囲選択した場合、範囲内に最上位階層が複数あればそれぞれ折りたたみ/展開できます。
    • 構造化ルールは インデント括弧アウトライン解析で検出された構造 としています。
      • #foldcond で設定しています。詳しくは、秀丸エディタ マクロ言語ヘルプ目次をweb検索いただき、foldの説明をご一読ください。
      • うまく動作しない場合
        • まず秀丸エディタ設定 アウトライン解析の設定 をご確認ください。
          • ファイルタイプ別の設定/アウトライン/解析 にあります。
          • インデントよりも優先されて適用されるようです。
            • インデントを優先する方法はわかりませんでした。
          • もし アウトライン解析で検出された構造 を対象外にしたい場合、#foldcondから0x0020を外してみてください。
        • また、#foldcondから0x00020x0008を外すこともお試しください。
      • カスタマイズ(ルール変更)はおそらく楽ですので各位お試しいただければと存じます。
        • インデントで構造化したファイルと、インデント以外で構造化したファイル、などで構造化ルールを切り替えたいとき、
          • 拡張子等のファイル情報を元に #foldcondを動的に変更するのも手かもしれません。
          • マクロでメニューを用意する等して、構造化ルールを切り替えるのも手かもしれません。
    • VS Codeの「トグルでない再帰」を実現したい場合、カスタマイズが必要です。おそらく楽ですので各位お試しいただければと存じます。

主な想定読者

  • 構造化テキストの読み書きをもっと楽にやれないか、
    • 各種アウトライナーや各種アプリを試した人
    • アプリによっては、範囲選択可能で再帰的に折りたたみ/展開トグルがショートカットキー一発(SHIFT+CTRL+「.」等)でできるのを知り、それが秀丸でもほしくなった人
  • なお、このマクロの初期設定は、構造化をインデントで行っていますが、
    • カスタマイズできるため、ほかの構造化にも対応可能と考えます。

秀丸マクロ

  • 筆者は、SHIFT+CTRL+「.」に割り当てて使っています。
fold_unfold_all_toggle.mac
// 折りたたみと展開 all toggle
//  カーソルのある位置の配下をすべて折りたたみます。そこが折りたたまれていた場合、すべて展開します。
//  範囲選択していた場合、そこを対象にします。
#foldcond = 0x0002 + 0x0008 + 0x0020; // 0x0040は外す。用途に合わない。selectfoldable の範囲外も巻き込んでしまう。0x0004はソース先頭で操作したときソース全体をトグルしたいなら外す。

disabledraw; // 高速化用

if (selecting) {
  // 範囲選択中の場合、選択範囲内にfoldedがあるかで分岐する
  #y0 = seltopy;
  #y1 = selendy;
  escape;
  call searchFolded #y0, #y1;
  #isFolded = ##return;
  if (#isFolded) {
    moveto 0, #y0;
    call unfoldUnder #y0, #y1;
  } else {
    call foldUnder #y0, #y1;
  }
} else {
  if (folded) {
    // 単純展開し、配下を範囲選択し、その範囲を展開する
    unfold;
    selectfoldable #foldcond;
    #y0 = seltopy;
    #y1 = selendy;
    escape;
    call unfoldUnder #y0, #y1;
  } else {
    selectfoldable #foldcond;
    #y0 = seltopy;
    #y1 = selendy;
    escape;
    if (#y1 - #y0 == linecount - 1) {
      // [用途] カーソルがファイル先頭にあるとき、折りたたみ / 展開 をtoggleする用。全選択折りたたみ直後に、全展開する用。
      call searchFolded #y0, #y1;
      #isFolded = ##return;
      if (#isFolded) {
        moveto 0, #y0;
        call unfoldUnder #y0, #y1;
      } else {
        call foldUnder #y0, #y1;
      }
    } else {
      call foldUnder #y0, #y1;
    }
  }
}

enabledraw; // 高速化用
endmacro;

searchFolded:
  ##y0 = ##1;
  ##y1 = ##2;
  moveto 0, #y0;
  while (1) {
    down;
    if (folded) return 1;
    if (#y1 <= y) return 0;
  }
  return 0;

foldUnder:
  ##y0 = ##1;
  ##y1 = ##2;
  moveto 0, #y1;
  while (1) {
    up;
//    message "before :" + str(y) + " foldable:" + str(foldable);
    if (foldable(#foldcond)) fold #foldcond;
    if (y <= #y0) break;
  }
  return;

unfoldUnder:
  ##y0 = ##1;
  ##y1 = ##2;
  moveto 0, #y0;
  while (1) {
    down;
//    message "before :" + str(y) + " foldable:" + str(foldable);
    if (#y1 <= y) break;
    unfold;
  }
  moveto 0, #y0;
  return;

1階層トグルのみの秀丸マクロ

  • カーソルのある行の1階層だけを、折りたたみ/展開 トグルだけするマクロです。
  • 筆者は、CTRL+「.」に割り当てて使っています。
  • VS Codeの CTRL+K CTRL+L に近いふるまいです。
fold_unfold_toggle.mac
// 折りたたみ / 展開 toggle
/*
制約
  よくある「選択範囲を1階層折りたたみ」には対応できませんでした。
    イメージ:
      図1:
        aaa
          bbb
        ccc
          ddd
      を範囲選択して
      図2:
        aaa
        ccc
      にはできない
*/
#foldcond = 0x0002 + 0x0008 + 0x0020; // fold_unfold_all_toggle.mac と同じ条件にし、使っていてわかりやすくする

if (folded) {
  unfold;
} else {
  if (foldable(#foldcond)) fold #foldcond;
}

マクロをショートカットキーに割り当てる方法は?

  • 「秀丸 マクロ ショートカット」等でweb検索してください。