python-modeでhideshow.el, hideshowvis.elを使って関数やクラスとかを折りたたんで表示する

前々からEmacsIDEみたいに関数の折りたたみができないもんかと思っていました。

folding.elの存在は知っていたのですが、これはユーザが打ち込んだ"{{{"と"}}}"の間を折りたたむというもので、実際には

# {{{ func
def func(foo)
    bar()
    hoge()

# }}}

のように書いておいてそこでC-c @ >すると"# {{{ func ... # }}}"みたいに畳むことができるっていうものです。
いちいち{{{なんて打つのは面倒だし、さらにそこにいちいちコメントを付けていかないとなにを折りたたんだのかがわからなくなるっぽいのであきらめてましたが、hideshow.elで行けるみたいです。

それと、hideshowvis.elは折りたためる行の横に"-", 展開できる行の横に"+"と行末に何行畳まれているかを表示してくれたり、マウスのクリックで簡単に折りたたみと展開をトグルしてくれるようにするものです。

やっぱりemacsは素敵です。

ただ、Cやlispではわりとサクッと折りたためましたが、python-modeだとちょっと設定が必要だったので、備忘録としてこの記事を書いています。

hideshow.elは標準でemacsに添付されているっぽいのでこれに関しては

(load-library "hideshow")

だけで大丈夫です。
hideshowvis.elはauto-install-from-emacswiki hideshowvis.elでインストール可能です。
hideshowvis.elの最後に書かれている";; Add the following to ~~~"の下にあるコメントアウトされている部分を全部コピーしてきて;;を消して.emacsに書きこむといろいろ便利なのでやっておきましょう。

その下に、

(autoload 'hideshowvis-enable "hideshowvis" "Highlight foldable regions")

(dolist (hook (list 'emacs-lisp-mode-hook
                    'c++-mode-hook
		    'python-mode-hook))
  (add-hook hook 'hideshowvis-enable))

としておけばemacs-lisp-modeやc++-modeでは上手く畳んだり開いたりできるようになるはずですがpython-modeだと上手くいかないので以下も付け加えます。

(defcustom py-hide-show-keywords '("class" "def" "elif" "else" "except"
 "for" "if" "while" "finally" "try" "with")
  "*Keywords used by hide-show"
  :type '(repeat string)
  :group 'python)

(defcustom py-hide-show-hide-docstrings t
  "*If doc strings shall be hidden"
  :type 'boolean
  :group 'python)




;; Add support for HideShow
(add-to-list 'hs-special-modes-alist (list
             'python-mode (concat (if py-hide-show-hide-docstrings "^\\s-*\"\"\"\\|" "") (mapconcat 'identity (mapcar #'(lambda (x) (concat "^\\s-*" x "\\>")) py-hide-show-keywords ) "\\|")) nil "#"
             (lambda (arg)
               (py-goto-beyond-block)
               (skip-chars-backward " \t\n"))
             nil))

これで上手く行くんじゃないでしょうか。

参考サイト
http://www.emacswiki.org/emacs-se/HideShow
http://www.emacswiki.org/emacs/hideshowvis.el
http://www.mail-archive.com/python-mode@python.org/msg00412.html

                                                                                                                                                    • -

追記

                                                                                                                                                    • -

hideshowvis.elがちょっとダーティーっぽくてキーマップを奪っちゃったりしてて気がついたらC-c C-cで実行とかができなくなったりメニューバーのPythonが消えてたりしてえーって思ったんですが上記参考サイトの一番上の最後の部分にあるdiffの結果を自力パッチでちゃんと使えるようになりました。

一応ここにも書いておきます。

   @@ -128,6 +130,11 @@
         hideshowvis-mode-map)
       "Keymap for hideshowvis mode")
     
    +(setq minor-mode-map-alist
    +      (cons (cons 'hideshowvis-minor-mode hideshowvis-mode-map)
    +            minor-mode-map-alist))
    +
    +
     (define-minor-mode hideshowvis-minor-mode ()
       "Will indicate regions foldable with hideshow in the fringe"
       :init-value nil
    @@ -140,7 +147,7 @@
                 (hideshowvis-highlight-hs-regions-in-fringe (point-min) (point-max) 0)
                 (add-to-list 'after-change-functions
                              'hideshowvis-highlight-hs-regions-in-fringe)
    -            (use-local-map hideshowvis-mode-map))
    +            )
             (remove-overlays (point-min) (point-max) 'hideshowvis-hs t)
             (setq after-change-functions
                   (remove 'hideshowvis-highlight-hs-regions-in-fringe