emacsのpython-modeで、TABキーでのインデント位置を固定する方法

自分はキーボタンにモードがあるのが嫌いです。たとえばIMEではトグルは使わず、macのように変換/無変換キーにON/OFFを割り当てて使っています。これによってキーを何度押してもASCIIはASCIIだし、ひらがなはひらがなになります。*1

emacspython-modeでは、同じ位置でTAB keyを複数回押すと、インデントが下がる(outdent)ようになっていて、これが非常にいらつかせます。

そこで、以下のようなフックを.emacsで入れることで、cやrubyなどの言語モードと同じように、python-modeでも何回TABを押してもインデント位置が変わらないようにしています。

(add-hook 'python-mode-hook
          '(lambda()
             (defun my-indent-line (&optional arg)
               "modeless indent for python indentation"
               (interactive "P")
               (let ((old-this-command this-command))
                 (setq this-command t)
                 (py-indent-line arg)
                 (setq this-command old-this-command)
                 ))
             (setq indent-line-function 'my-indent-line)
             ))

ちなみに、インデントを戻すときはブロックの最後に必ず pass や return を入れることになります。*2

emacs23 progmodes/python.elの場合

コマンド名や引数がpython-mode.elから若干変わっていますが、やり方は一緒です。

(add-hook
 'python-mode-hook
 '(lambda ()
    (defun my-indent-line ()
      "modeless indent for python indentation"
      (interactive "P")
      (let ((old-this-command this-command))
        (setq this-command t)
        (python-indent-line)
        (setq this-command old-this-command)
        ))
    (setq indent-line-function 'my-indent-line)
    ))

python-mode.elとprogmodes/python.el両方に対応するフック

(add-hook
 'python-mode-hook
 '(lambda ()
    (defun my-indent-line (&optional arg)
      "modeless indent for python indentation"
      (interactive "P")
      (let ((old-this-command this-command))
        (setq this-command t)
        (cond
         ((fboundp #'python-indent-line) (funcall #'python-indent-line))
         ((fboundp #'py-indent-line) (funcall #'py-indent-line arg))
         )
        (setq this-command old-this-command)
        ))
    (setq indent-line-function 'my-indent-line)
    ))

*1:つまりはドナルド・ノーマンの言うmodeless、またはRESTの冪等性(idenpotent)のメリットをWebだとか以前に実感しているわけですわ

*2:py-indent-lineを別キーにでも割り当てるのでもいいだろうけど。