【GAS向け】TypeScriptの長いソースをEmacsのOutlineマイナーモードで折りたたんでみた（2020-07-28追記アリ！）

# 2020-11-16 追記：

以下の方法（```/*～*/``` 式のコメントでorg-modeの```*```を包む）の方が簡単で強力なのでそっちに移行しました。

https://qiita.com/query1000/items/ba0205bc39610f953b84

# 概要
GAS (Google Apps Script）をTypeScriptで開発している。
エディターはEmacs26.3で、tide.elを使っている。
GASをTypeScriptで書く時、現状ではファイルを分割できないため、Code.tsという長いファイルにすべての関数を詰め込んでいる。
そこで、視認性をEmacsのoutline-minor-modeで見出し行を設定した。
これで、長いファイルを折りたたみ表示できるので、ちょっとは楽になるんじゃないだろうか。
# 実装
とりあえず、行頭が `//@` であれば大見出し、`//@@` であれば中見出し、`//@@@` であれば小見出しという構成にしてみた。
以下のように、`~/.emacs.d/init.el` で、typescript-modeにoutline-minor-modeを追加し、見出し行を設定した。

```~/.emacs.d/init.el
  (require 'typescript-mode)
  (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-mode))
  (require 'tide)
  (add-hook 'typescript-mode-hook
	    (lambda ()
	      (tide-setup)
	      (flycheck-mode t)
	      (setq flycheck-check-syntax-automatically '(save mode-enabled))
	      (eldoc-mode t)
	      (setq typescript-indent-level 2)
	      (company-mode-on)
	      (outline-minor-mode t) ;;; 今回追加した行
	      ))
  ;;; 以下すべて、今回追加した行
  (make-variable-buffer-local 'outline-regexp)
  (add-hook
   'typescript-mode-hook
   (function
    (lambda ()
      (setq outline-regexp "^\\(//@ \\|//@@ \\|//@@@ \\)")))) ;;; マッチした見出しのうち、短い順に上に階層化される
  (add-hook 'outline-minor-mode-hook
	    (lambda () (local-set-key "\C-c\C-o" ;;; C-c @ を C-c C-o に変える
				      outline-mode-prefix-map)))
```

## 注釈以外の見出し

記事を投稿してから気づいたが、`function`、`type`、`interface`などの言葉を見出しにすればもっと直截で便利になる。
試行錯誤中なのでヒントのみ。

# キーバインド
M-x helper-describe-bindingsのoutline関係だけを抜き出すと以下のようになる。
（プレフィックスは C-c @ なのを C-c C-oに変えている）
いっぺんに覚えられないので、どうしようかなあと思っている。

## 移動系
- C-c C-o C-b:	outline-backward-same-level 同じレベルでバック（Back）
- C-c C-o C-f:	outline-forward-same-level 同じレベルで前進（Forward）
- C-c C-o C-p:	outline-previous-visible-heading 前の表示されている見出しに移動（Previous）
- C-c C-o C-n:	outline-next-visible-heading 次の表示されている見出しに移動（Next）
- C-c C-o C-u:	outline-up-heading 上の階層（Up）に移動

## 隠す系
- C-c C-o C-t:	outline-hide-body バッファ内のボディを全部隠す（Trancate）
- C-c C-o C-o:	outline-hide-other 今の見出し階層以外の全部（Other）を隠す
- C-c C-o C-c:	outline-hide-entry 今の（Current）見出し階層のボディを隠す
- C-c C-o C-l:	outline-hide-leaves 今の見出し階層のボディとサブツリーを隠す（Leaves=枝葉）
- C-c C-o C-d:	outline-hide-subtree 今の見出し階層以下のボディを消すけど見出しは残す
- C-c C-o C-q:	outline-hide-sublevels 見出し階層 n 以下のすべてを隠す

## 見せる系
- C-c C-o C-a:	outline-show-all バッファ内をすべて（ALL）表示
- C-c C-o C-e:	outline-show-entry 今の見出し階層（Entry）を表示
- C-c C-o C-i:	outline-show-children 今の見出し階層直下の（Immidiate）小見出しを表示する
- C-c C-o C-k:	outline-show-branches 今の見出し階層以下の小見出し（KOMIDASHI）だけを表示する 
- C-c C-o C-s:	outline-show-subtree 今の見出し階層以下のすべて（SUBETE）を表示する

## 編集する系（とりあえず使わない）
- C-c C-o RET:	outline-insert-heading
- C-c C-o C-v:	outline-move-subtree-down
- C-c C-o C-^:	outline-move-subtree-up
- C-c C-o C-o:	outline-mark-subtree
- C-c C-o C-<:	outline-promote
- C-c C-o C->:	outline-demote

## とかなんとか言っちゃってメニューバーを復活したら楽だった

```~/.emacs.d/init.el
;(menu-bar-mode -1)     ;メニューバーをなくす
(menu-bar-mode 1)     ;メニューバーを出す
```

## (2020-07-28追記）もっとスゴイ！ org-modeの<TAB>が使える！！
いろいろ探していたら、超スゴイ記事をみつけた。

Quickhack Diary | emacs-lisp-mode でも org-mode の恩恵を受ける
http://quickhack.net/nom/blog/2012-09-05-org-mode-with-elisp.html

org-modeはoutline-modeから派生しているので、org-modeの機能の一部を使えるという！
具体的に言うと、```org-cycle```（<TAB>で箇条書きを拡縮する）が使える！！

``` .emacs.d/init.el
	      (outline-minor-mode t) ;;; さっき追加した行
              (define-key outline-minor-mode-map "\C-i" 'org-cycle) ;;; ここから追加する行
              (define-key outline-minor-mode-map "\C-c\C-f" 'outline-forward-same-level)
              (define-key outline-minor-mode-map "\C-c\C-b" 'outline-backward-same-level)
              (define-key outline-minor-mode-map "\C-c\C-n" 'outline-next-visible-heading)
              (define-key outline-minor-mode-map "\C-c\C-p" 'outline-previous-visible-heading) ;;; ここまで追加する行
	      ))
```
これでオッケーだ！！！
めっちゃ便利！！！

いっつもチョコチョコ追記するとき```□ 変更通知を送る```っていうのチェックしてなかったけど、今日は送っちゃうよ～～ん

# 試す
以下のようなソース ```foo.ts``` を読み込んだとする。

```foo.ts
//@ 大見出し
//@@ 中見出し-1
function foo () {
  // 内容1
}
function bar () {
  // 内容2
}
//@@@ 小見出し-1
function baz () {
  // 内容3
}
```

上記の状態で ```//@ 大見出し``` にカーソルを置いて ```C-c C-o C-s``` を押下すると ```M-x outline-hide-subtree``` が実行され、以下の階層が折り畳まれる。

```
//@ 大見出し...
```

その状態で ```C-c C-o C-k``` を押下すると ```M-x outline-show-branches``` が実行され、以下の見出し行だけが表示される。

```
//@ 大見出し
//@@ 中見出し-1...
//@@@ 小見出し-1...
```

その状態で ```//@@@ 小見出し-1``` にカーソルを置いて ```C-c C-o C-t``` を押下すると ```M-x outline-show-body``` が実行され ```//@ 小見出し-1``` の内容が表示される。

```
//@ 大見出し
//@@ 中見出し-1...
//@@@ 小見出し-1
function baz () {
  // 内容3
}
```

# 参考資料
最初はorg-modeでやりたかった。

アステリスクを ```//@``` とかに変えればできると思って調べたが、同じことをやろうとしている人の質問に当たって、org-modeはアステリスクを変えることは出来ないが、あんたのやりたいことはOutline-modeでできるんじゃないのと言うのを見つけた。
https://emacs.stackexchange.com/questions/26180/change-the-asterisk-heading-identifier-to-some-other-symbol-in-org-mode

それで、Outlineモードで日本語の資料を調べたら、YaTeXをOutlineモードでやっている人がいて、それを読んだらほぼ解決した。
http://www.math.s.chiba-u.ac.jp/~matsu/emacs/emacs21/outline.html

```C-c @``` というマイナーモードプレフィクスを ```C-c C-o``` に変えるやり方が最近変わったらしいので以下のサイトを参考にした。
https://rion778.hatenablog.com/entry/20100214/1266151330

その他はオンラインマニュアル等に当たった。

(2020-07-28 追記）
見出しの拡縮にorg-modeの機能（の一部）を使う方法。超便利！

Quickhack Diary | emacs-lisp-mode でも org-mode の恩恵を受ける
http://quickhack.net/nom/blog/2012-09-05-org-mode-with-elisp.html


# 関連記事
ぼくのGAS＋TypeScript＋Emacs奮闘記は以下の通り。
他にもGAS系、Emacs系の記事を書いているので暇な人は読んでツッコんでください。

https://qiita.com/query1000/items/6a9d0cc23a44db6c7654

**（この項終わり）**