outline mode

outline mode って何?

Emacs に元々ついている機能で、文字通り文章をアウトライン構造を把握しながら編集していくことができる mode です。 具体的には、特定のレベル以下の部分や見出し以外の部分、今書いている部分以外の本文を隠したりすることができます。 outline-mode は major-mode で、outline-minor-mode はその minor-mode 版です。 (従って YaTeX などの他のモードと組み合わせて使うことができます。)

Outline Mode の使い方

まず感じを掴んでもらうために Outline Mode で説明します。新規にファイル を開いて、次のようなテキストを書いてみましょう。

     * 第1章
     ** 1.1 はじめに
     何から始めようかな。    
     ** 1.2 最後に
     いきなり終わりかよ。

そして、おもむろに M-x oultine-mode として outline-mode を起動します。

Outline Mode では、ヘッドライン行と本体行の二種類の行があります。 ここで * や ** で始まる行は、ヘッドライン行、その他の行は本体となります。 ヘッドライン行では * の数が多いほど、レベルは低くなっていきます。 つまり、より * の数が少ないヘッドラインの枝になっているわけですね。

さて、一行目の先頭にカーソルを置いて、C-c C-d (hide-subtree) とします。すると、画面には

     * 第1章...    

のように表示されるはずです。 これは「第1章」の枝にあたる部分を全て隠すコマンドです。 このとき実際のバッファの内容は変わったわけではありません。 ただ、表示が変わっただけです。C-c C-a (show-all) とタイプすれば、元のテキストが全て表示された状態に戻るのが確認できます。

     * 第1章
     ** 1.1 はじめに
     何から始めようかな。    
     ** 1.2 最後に
     いきなり終わりかよ。

今度は、二行目の先頭にカーソルを置いて、C-c C-t (hide-other) とタイプしてみましょう。すると、

     * 第1章
     ** 1.1 はじめに
     何から始めようかな。    
     ** 1.2 最後に...

のように表示されたはずです。 これは、現在編集している部分以外の本体部分を全て隠すコマンドです。 文章の全体構造を見ながら編集を行うときに重宝します。

また、1.1 にどんなことを書いたっけと思ったなら、* 1.1 の行に移り、 C-c C-e (show-body) とすれば中身を見れます。 もう一度隠すときは C-c C-c (hide-body) です。 ... はここにテキストがたたみ込まれていることを示しています。 実際のテキストがバッファから消えてしまったわけではないので、 cut ;& paste するときとかに戸惑わないようにしましょう。

このような表示は行末コードを LF を CR に変更することで実現されています。 まず普通は起こらないと思いますが、万が一こうなったままテキストが保存されてしまった場合も、パニックに陥いらずに、黙ってM-% C-q  RTN  RTN  C-q  C-j  RTNとして復帰コードを改行コードに置換すれば、元のテキストが復元できます。

他にもいろいろと便利なコマンドが用意されていますが、もしメニューバーが表示されていれば、Show とか Hide とかいうメニューが表示されているはずなので、試してみると良いでしょう。 また、Info の Outline Mode の項にも詳しい説明があります。

ここで、「私は * でヘッドラインを記述するのは好きじゃないなあ」という人もいるでしょう。 これは、outline-regexp という変数でカスタマイズすることができます。 カスタマイズの仕方は上の Info にも説明されていますが、次の Outline Minor Mode のところで、具体的な例を説明したいと思います。

Outline Minor Mode の使い方

さて、Outline Mode は確かに便利です。でもこれだと、他のモード (例えば YaTeX など) と併用することはできません。 そこで Outline Minor Mode の出番です。 ここでは私の個人的な好みで YaTeX Mode (LaTeX を編集するためのモード)で説明することにしましょう。

まず、YaTeX Mode で、LaTeX で書かれたファイルを開きます。 そして、おもむろに M-x outline-minor-mode としましょう。 すると、モードラインには、

 [--]E.:-----Emacs: test.tex       (やてふ Fill Outl)--L1--Top------- 

などのように表示されるはずです。 もちろん、環境によってちょっとした違いはあるでしょうが、Outl という文字があれば、ちゃんと Outline Minor mode が起動されています。 一々このようなコマンドをタイプするのが面倒であれば、ファイルの最後に

     %%% Local Variables: ***
     %%% mode:outline-minor ***    
     %%% End: ***

などと書いておけばよいでしょう。 次からは自動的に Outline Minor Mode が起動してくれます。 また、yatex-mode では常に outline-minor を起動したい場合は、.emacs

(add-hook 'yatex-mode-hook
          '(lambda () (outline-minor-mode t)))

とでも書いておけば良いでしょう。

しかし、勿論これだけでは何の役にも立ちません。LaTeX ファイルではヘッドラインを * で記述するようにはなっていないので当たり前です。

さて、実際のテキストが次のようだったとしましょう。

     \documentclass{jarticle}
     \usepackage{amsmath,amssymb,amsthm,amscd}    
     \begin{document}
      \section{}
       \subsection{はじめに}
     何から始めようかな。
       \subsection{最後に}
     いきなり終わりかよ。
     \end{document}

LaTeX を知らない人のために説明しておくと \section{} とか \subsection{} というのがヘッドラインになっています。 そこで、Emacs にこれらをヘッドラインだと認識させましょう。 前節で説明したように、outline-regexp という変数を書き換えます。 この変数、初めからは局所的な変数になってないみたいで、普通に書き換えると、 global に変わっちゃいます。 これは、ファイルに直接 Local variables として書込むことを期待してのことかもしれません。 それには、上でやったのと同様にファイルの最後に

     %%% Local Variables: ***
     %%% mode:outline-minor ***
     %%% outline-regexp:"[ \t]*\\\\\\(documentstyle\\|documentclass\\|chapter\\|section\\|subsection\\|subsubsection\\)\\*?[ \t]*[[{]"
     %%% End: ***

のように書けばよいです。 しかし、大抵は YaTeX mode では、常に同じ設定を使いたいのが普通でしょう。 この場合は .emacs に次のように書くことになります。

(make-variable-buffer-local 'outline-regexp)
(add-hook
 'yatex-mode-hook
 (function
  (lambda ()
    (setq outline-regexp
          (concat "[ \t]*\\\\\\(documentstyle\\|documentclass\\|"
                  "chapter\\|section\\|subsection\\|subsubsection\\)"
                  "\\*?[ \t]*[[{]")))))

そしてこれらS式の直後にカーソルを持っていって、 C-x C-e とタイプしてこの式を評価し、もう一度先程の LaTeX ファイルを開き直してみます。 これで、\section などのヘッドラインが認識できてるはずです。 試しに、「最後に」と書かれた行にカーソルを持っていって C-c C-o C-e とタイプしてみましょう。 (最近の Emacs だと C-c @ C-e かも。 私は C-c @ というプレフィクスは押しにくくて嫌いなので、.emacs

(setq outline-minor-mode-prefix "\C-c\C-o")

と書いて変更していますが。) すると、画面には

     \documentclass{a4paper,10pt]{jarticle}...    
      \section{}
       \subsection{はじめに}
     何から始めようかな。
       \subsection{最後に}...

と表示されるはずです。 しかしこれでもまだ不都合があります。Emacs はヘッドラインの親子関係を outline-regexp に一致した長さで判断しています。 (短い程、上位と認識する。) これでは \documentstyle\section よりも下になってしまいます。

この問題は、outline-level という関数を変更することで可能です。 Outline (Minor) Mode では一旦 outline-level という変数を定義して (funcall outline-level) でこの関数を呼出しているので、次のようにすればバッファローカルに変更することができます。 まず、.emacs

(make-variable-buffer-local 'outline-level)
(setq-default outline-level 'outline-level)
(defun latex-outline-level ()
  (save-excursion
    (looking-at outline-regexp)
    (let ((title (buffer-substring (match-beginning 1) (match-end 1))))
      (cond ((equal (substring title 0 4) "docu") 15)
            ((equal (substring title 0 4) "chap") 0)
            ((equal (substring title 0 4) "appe") 0)
            (t (length title))))))

みたいなのを追加します。 これは、outline-regexp を見つけてその level に対応する数を返す関数です。 (返す数が大きい程 level は低くなる。) そして、先程の yatex-mode-hook のところを

(add-hook
 'yatex-mode-hook
 (function
  (lambda ()
    (progn
      (setq outline-level 'latex-outline-level)
      (setq outline-regexp
            (concat "[ \t]*\\\\\\(documentstyle\\|documentclass\\|"
                    "chapter\\|section\\|subsection\\|subsubsection\\)"
                    "\\*?[ \t]*[[{]")
     )))))

のように変更して、変数 outline-level を書き換えるようにしておきます。 これで、ヘッドラインの上下関係も正しく認識されるようになったはずです。

YaTeX 以外でも上のS式を適当に書き換えれば同じことが可能です。 同じく TeX を編集するモードである AUC-TeX は、このような仕組を自前で持っているようです。

noutline.el

いつからか知らないのですが、noutline.el を load しておくと、一つの Outline mode のバッファを複数のビュー画面で表示できるらしいです。 n は new の略だと思うのですが、将来的にはこちらで現在の outline.el が置き換えられるそうです。 ということは、Emacs-20.x では置き換わっているんだろうか。


[Mule のページに戻る]