python-modeの使い方メモ

独自の設定を積み重ねても仕方がないので、python-modeの機能の使い方をメモする。
(この記事はpython-modeを起動してC-c ?で見ることができるヘルプを元にして作られてます)

python-modeの提供する機能

  1. syntax-highlight
  2. python-shellとの通信
  3. コードのインデント
  4. 範囲選択
  5. コードのコメント/アンコメント
  6. カーソルの移動

試しに使ってみる。

python-shellを立ち上げる。

C-c Sを入力。shellが立ち上がる*1

python-shellとの通信

python-shellと通信する前にshellを立ち上げておく必要がある。shellが立ち上がっていなかったら、C-c Sで立ち上げておく。
python-shellとの通信をするコマンドは以下のとおり*2

コマンド 説明
C-c RET imports or reloads the file in the Python interpreter
C-c C-c sends the entire buffer to the Python interpreter
C-c I(Iではなく、パイプの縦棒) sends the current region
C-M-x sends the current function or class definition
C-c C-s sends an arbitrary string
C-c S starts a Python interpreter window; this will be used by subsequent Python execution commands

実際に利用してみる。下のコードをpython-modeの有効なバッファにコピペして。"# i)"に書いてある作業を行う。

print "foo"
print "bar"
# 1)  C-c C-c #> 現在開いているバッファ内容をシェルに送信 => "foo"と"bar"が表示
# 2) C-@でprint "bar"の行を選択。C-c | #>選択したregion(範囲)をシェルに送信 => "bar"と表示


# 3) カーソルを関数/クラス定義の中に移動させる。 C-M-x | #>現在の関数あるいはクラスをシェルに送信 => 送信した関数/クラスが利用可能
def add(x,y):
    #このあたりでC-M-x
    return x+y

class A(object):
    #このあたりでC-M-x
    def foo(self):
        print "A.foo()"

print add(10,20) #この行を選択して、C-c | => (addが利用可能なので) 30と表示

# 範囲選択が面倒であれば、C-c C-kを使うと良い。 #>現在のブロックを選択
# 4) C-c C-k, C-c | => 現在の行(ブロック)をシェルに送信

A().foo() #ここでC-c C-k C-c |

# ミニバッファに入力した文字列をシェルに送信。(機能が貧弱なので要改善)
# 5) C-c C-s (ミニバッファ開く), ミニバッファに文字列入力 => 入力した文字列をシェルに送信

コードのインデント

コードのインデントに関するコマンドは以下のとおり。
1. インデントオフセットの推測。

C-c : guess py-indent-offset from file content; change locally
C-u C-c : ditto, but change globally

2. インデントの調節。

C-c TAB reindent region to match its context
C-c shift region left by py-indent-offset
C-c > shift region right by py-indent-offset

実際に使ってみる。同様に"# i)"の操作を行う。

## オフセットの推測は省略

## インデントの調節
print "foo"

# 1) print "foo"にカーソル行を合わせてC-c C-k,C-c > #>選択した範囲を右にインデント => 右にインデント
# 2) 1)の後、 C-c < #>選択した範囲を左にインデント => 元の位置に戻る。
# 3) 1の操作で右にずらす。 C-c C-i #> 文脈にしたがってインデントする。 => 先頭の位置にもどる 

範囲選択

範囲選択のコマンドは以下のとおり

C-c C-k mark block of lines
C-M-h mark smallest enclosing def
C-u C-M-h mark smallest enclosing class

実際に使ってみる。以下のコードをコピペして、"# i)"の操作を行う。

class Dummy(object):
    pass
class A(object):
    """A class"""

    def f(self):
        """method of A""" # 1) ここにカーソルをあててC-M-h
        return 10

    def g(self):
        """method of A""" # 1) ここにカーソルをあててC-M-h
        return 100

# 1) バッファの先頭でC-c C-k #>現在のブロックを選択 => 一まとまりの範囲が選択される(再度C-c C-kを入力すると次のブロックへ)
# 2) AのメソッドにカーソルをあててC-M-h #>現在の最小の関数定義を範囲選択 => f,gの定義が選択される
# 3) 2)と同様の位置でC-u C-M-h #>現在の最小のクラス定義を範囲選択 => classAの定義が選択される。

コメント/アンコメント

C-c q comment out region of code
C-u C-c q uncomment region of code
C-c # Like `comment-region' but uses double hash (`#') comment starter.
C-u C-c # Like `uncomment-region' but uses double hash (`#') comment starter.
print "foo"

# 1) 範囲選択 C-c q => コメントされる
# 2) 範囲選択 C-u C-c q => 鵜アンコメントされる。

C-uを前置するのが面倒なのでC-c Qを使えるようにして使ってる。

(define-key py-mode-map "\C-cQ" 'uncomment-region)

カーソル移動

C-c C-p move to statement preceding point
C-c C-n move to statement following point
C-c C-u move up to start of current block
C-M-a move to start of def
C-u C-M-a move to start of class
C-M-e move to end of def
C-u C-M-e move to end of class

行頭移動(C-a)、行末移動(C-e)の拡張考えれば良い。
対象を関数にしたければ、Mを付加。対象をクラスにしたければ、C-u Mを付加

C-c C-uが地味に便利。

実際に使ってみる。

class Dummy(object):
    pass
class A(object):
    """A class"""

    def f(self):
        """method of A""" # 1) ここにカーソルをあててC-M-h
        return 10

    def g(self):
        """method of A""" # 1) ここにカーソルをあててC-M-h
        return 100

#1) バッファの下部にカーソルを持っていく
#2) C-M-a #>関数定義の先頭に移動 => g()のdefにカーソルが移動
#3) C-M-e #>関数定義の末尾に移動 => return 100の次の行にカーソルが移動
#5) C-u C-M-a #>クラス定義の先頭に移動 => Aのclassにカーソル移動
#6) C-u C-M-e #>クラス定義の末尾に移動 => return 100の次の行にカーソルが移動
#7) 何回かC-c C-uを入力 #>一つ上のブロックに移動 => 関数定義 -> class定義 とカーソルが移動。
#8  (C-x C-x => C-c C-uを入力する前の位置に戻る)

*1:立ち上がったシェルにフォーカスが移動するのが嫌なら、後で設定変更

*2:C-u で非同期にできるけれどそれについては省略