26 May 2011

emacs の python 開発環境を整える

今まで何もしていなかったのですが flymake 位はほしいなと思い立ち, emacs の python 環境をセットアップしました.

python.el と python-mode.el

python.el とは emacs にバンドルされている python-mode を, python-mode.el は python コミュニティによってメンテナンスされている elisp の事を指しています.

ネット上では python.el は機能が少ないので python-mode.el に置き換えましょう, と述べているブログ記事やチュートリアルをしばしば見かけます. しかし, ここのところはネット上にいろんな情報があって, かつ正確なところがよくわかりませんでした.

今のところの自分の結論は, できるだけ設定ファイルをシンプルに保つことを優先し, 基本的に python.el を使う方針にしています. python.el で最低限の機能はそろっているようだし, ちょっと物足りないところだけ別途追加設定することにしました.

細かな設定

上記をうけ, こちらを参考に ちょこちょこと細かな設定を行いました. 具体的には

  • 閉じカッコの補完
  • 改行時のオートインデント
  • タブの設定

の3つです.

閉じカッコの補完には, 以下の elisp を .emacs に追加します. 各種カッコに加えクオート, ダブルクオートも対応する閉じを補完し, その間にカーソルを移動してくれます.

(add-hook 'python-mode-hook
          (lambda ()
            (define-key python-mode-map "\"" 'electric-pair)
            (define-key python-mode-map "\'" 'electric-pair)
            (define-key python-mode-map "(" 'electric-pair)
            (define-key python-mode-map "[" 'electric-pair)
            (define-key python-mode-map "{" 'electric-pair)))
(defun electric-pair ()
  "Insert character pair without sournding spaces"
  (interactive)
  (let (parens-require-spaces)
    (insert-pair)))

改行時のオードインデントの設定は以下です. 何も設定しないと改行時のカーソルは行頭に合わせられます. この設定をすることで改行前の状況に応じて適切なインデントを行頭に入れ, その直後にカーソルを合わせてくれるのでタイプ数が減らせます.

(add-hook 'python-mode-hook '(lambda () 
     (define-key python-mode-map "\C-m" 'newline-and-indent)))

最後にインデント幅の設定です. python はインデントでブロックを表現する言語なので, インデントの設定は重要です. インデント幅は pep8 (python のスタイルガイド) に従いスペース4つ分にするのが標準です.

インデント幅はメジャーモードのデフォルトでスペース4つに設定されていると思うので, 実際には特に何もする必要がないと思われます. 実際自分は何もしませんでした. もしうまくインデント幅が設定出来ていない場合は, まず emacs グローバルのインデント設定を以下のようにしてみるとよいでしょう.

(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)

上がインデントとして tab を使用しないようにする設定. 下が tab 幅をスペースいくつ分にするかの設定です. これは emacs 全体に効果のあるせっていですが, もし何らかの原因で python.el などメジャーモードの方が変わってしまっている場合はそちらの変更も必要になるでしょう.

flymake の設定

当初の目的であった flymake の設定をします. flymake はバッファのコードが書き変わるたびにコードを外部の make なり syntax chacker なりに投げ, その結果をバッファに表示してくれるという機能です. 今回はこの外部のチェッカーとして pyflakes と pep8 を使います. pyflakes は python のソースコードの文法をチェックしてくれるツール, pep8 は pep8 のスタイルに則った書き方をしているかチェックしてくれるツールです.

それぞれ pip でインストールするのが簡単だと思います.

% pip install pyflakes pep8

2つのチェッカーを同時に走らせるためにひとつのシェルスクリプトにまとめます. 以下のスクリプトを pychecker という名前で保存し, 実行権限を与えパスの通った場所に置いておきます.

#!/bin/bash

/Users/kosei/share/pyenv/bin/pyflakes "$1"
/Users/kosei/share/pyenv/bin/pep8 --ignore=E221,E701,E202 --repeat "$1"
true

自分は virtualenv 環境下にインストールしたので, それぞれのスクリプトをフルパスで指定していますが, ふつうにグローバルな場所にインストールした場合はわざわざフルパスを指定する必要はありません.

# こんな感じでOK
pyflakes "$1"
pep8 --ignore=E221,E701,E202 --repeat "$1"
...

つぎに flymake-cursor.el を導入します. ミニバッファにエラーや warning のメッセージを表示してくれる便利なものです.

elisp のインストールには install-elisp.el を使っています. emacs 上で "M-x install-elisp-from-emacswiki RET flymake-cursor.el" でインストールできます.

(と思ってたんですが, いまでは後継の AutoInstall というのがあるのですね... こちらを使うべきです.)

あとは pychecker を呼び出す elisp を書きます. .emacs に以下の内容を追加します.

;;; flymake for python
(add-hook 'find-file-hook 'flymake-find-file-hook)
(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
    (let* ((temp-file (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-inplace))
           (local-file (file-relative-name
                        temp-file
                        (file-name-directory buffer-file-name))))
      (list "pycheckers"  (list local-file))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init)))
(load-library "flymake-cursor")
(global-set-key [f10] 'flymake-goto-prev-error)
(global-set-key [f11] 'flymake-goto-next-error)

ようやく完了です. こんな感じにチェックしてくれます.

python 開発のためのエディタ

ここまでみてきてわかるように, emacs に python の環境を準備するのはなかなか面倒な作業です. flymake ひとつ設定するのにいくつもスクリプトをインストールしなければいけないし, 自分でシェルスクリプトも準備する必要もあります. メジャーモードは今回はデフォルトの物にしていますが, もし機能が足りなければまた別のパッケージを入れたりしないといけません. 設定ファイルが複雑になっていけば, メンテナンス性・ポータブル性がどんどん損なわれていきます.

もし emacs にそこまではまり込んでいないのならば, Vim や IDE を使うことをおすすめします. 実際 エキスパート Python プログラミング のエディタのセクションでも Vim や IDE が勧められていました.

まとめ

emacs の Python 環境設定について説明してきました. 標準の python メジャーモードの機能に加え, オートインデントなどの設定や flymake の導入を行いました.

ただ emacs はそれほど python friendly ではないこともみえてきました. emacs にこだわりのない人は vim や IDE を使ったほうが幸せになれるかもしれません.

メジャーな設定のうち今回扱っていないのはキーワードの補完でしょうか. 自分は動的略語展開で割と間に合ってしまっているんですが, いずれ導入するかもしれません.

参考