0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Emacs 編集時のみ Python のブロック終端を明示する

Last updated at Posted at 2023-04-06

Python のブロック終端処理

Emacs で TAB キー (indent-for-tab-command) を多用する人向けのツールです。

TAB キーでインデントが深くなっていく…

次のソース(※1)

class A:
    def __init__(self):
        self.data = []

    def append(self, value):
        self.data.append(value)


class B:
    def __init__(self):
        self.data = 0

    def add(self, value):
        self.data += value

を Emacs で開いて各行で TAB キーを押したとき

class A:
    def __init__(self):
        self.data = []

        def append(self, value):
            self.data.append(value)


            class B:
                def __init__(self):
                    self.data = 0

                    def add(self, value):
                        self.data += value

となってしまいます。(古い Emacs では M-x indent-region でも同様でした...)

そこで、ソース(※1) にブロック終端を明示して(※2)

class A:
    def __init__(self):
        self.data = []
        return

    def append(self, value):
        self.data.append(value)
        return

    pass


class B:
    def __init__(self):
        self.data = 0
        return

    def add(self, value):
        self.data += value
        return

    pass

の状態を維持すると、TAB キーを押したときの動作が(ブロック範囲が明確な)他の言語モードと大差がなくなります。

欲しい機能

自動的な処理により、次の状況になれば少しはマシになるかもしれません。

  1. ファイルを開くとブロック終端なし(※1)でもブロック終端あり(※2)の状態になる
  2. 保存するファイルはブロック終端あり(※2)からブロック終端なし(※1)に変換される
  3. エディタでの編集はブロック終端あり(※2)のまま継続する

ブロック終端の追加・削除ツール

Python プログラム pyblockend.py では以下の処理を行います。

  • ブロック終端なし(※1) から pass/continue/return を自動追加
  • ブロック終端あり(※2) から pass/continue/return を自動削除

ブロック終端の追加では pass 以外に

  • def ブロックでは return
  • for, while ブロックでは continue

を選択可能です。

ブロック終端の削除では pass/continue/return の行に空白とキーワード以外があると削除されません。

Emacs : py-blockend マイナーモード

.emacs で py-blockend.el の読み込みとフックの追加すると Python モードのマイナーモードが追加されます。

(add-hook 'python-mode-hook 'py-blockend-mode)

pyblockend.py を pyblockend コマンドとして呼び出せるようにするか、カスタマイズ変数 py-blockend-command を変更してください。

コマンド 内容
M-x py-blockend-mode py-blockend-mode マイナーモードの有無の切り替え
M-x py-blockend-append-buffer バッファ内のブロック終端の追加
M-x py-blockend-remove-buffer バッファ内のブロック終端の削除
M-x py-blockend-append-region 選択範囲中のブロック終端の追加
M-x py-blockend-remove-region 選択範囲中のブロック終端の削除
M-x py-blockend-toggle-append-after-save 保存後処理のブロック終端追加処理の有無を切り替え
M-x py-blockend-toggle-global py-blockend-mode のグローバル フラグを切り替え
M-x py-blockend-global-enable py-blockend-mode のグローバル フラグを有効
M-x py-blockend-global-disable py-blockend-mode のグローバル フラグを無効

※グローバル フラグの操作は既に開いているファイル(バッファ)には影響しません。

カスタマイズ変数 内容 既定
py-blockend-global py-blockend-mode のグローバル フラグ t
py-blockend-command pyblockend.py を実行できるコマンド pyblockend
py-blockend-command-append ブロック終端追加用 pyblockend オプション --append
--def-return
py-blockend-command-remove ブロック終端削除用 pyblockend オプション --remove
py-blockend-append-after-save ファイル保存直後のブロック終端追加処理 t

def ブロックの終端を return にするには "--def-return" を、
for,while ブロックの終端を continue にするには "--loop-continue" を
py-blockend-command-append に追加してください。

ファイルを開いた直後に "undo" する

ファイルを開いた直後に M-x undo できます。
ブロック終端の追加前の状態になるので、保存されているファイルの状態を確認できます。

pyblockend の失敗により壊れたときの対処方法にもなります。

既知の問題

ブロック終端の変化により、カーソルが元の位置から移動することが屢々あります...

プログラム

ブロック終端の追加・削除に pyblockend.py を使用します。これをカスタマイズ変数の py-blockend-command で実行できるようにしてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?