web-dev-qa-db-ja.com

vimでpythonファイルを編集するより効率的な動き

pythonファイルがあり、次のことが際限なく繰り返されているとします。

def myFunction(a, b, c):
    if a:
        print b
    Elif c:
        print 'hello'

おなじみのvimの動きを使って、このファイルを移動して編集したいと思います。たとえば、(、)、[[、]]、{、}を使用したり、di}などのコマンドを使用してテキストを削除/ヤンク/変更したりします。

他の言語(C++、Java、C#など)では中括弧がたくさんあるので、di}のような動きを使用すると、一致する中括弧を簡単に見つけて、そのブロックに作用できます。実際、上記のテキストの「b」文字を使用して、vimでdi)を実行すると、2つの親の間のテキストが正常に削除されます。

問題は、Pythonによるコードブロックの検出にあると思います。 (、)、[[、]]、{、または}を移動として使用すると、ほとんど同じことが行われ、の開始(関数の最後の行の後)または終了(関数の最後の行の後)に移動します。関数。そして、私が知る限り、vimに「このインデントブロックのすべてを選択する」と簡単に伝える方法はありません。上記の例では、if行の「i」をオンにしてdi}と入力し、ifブロック全体を(この特定の関数の最後まで)削除します。

そのような動きに対してインデントベースで動作するようにvimに指示することは可能であると確信しています(まあ、その特定の動きではないかもしれませんが、いくつかのユーザー定義のアクション)。これを達成する方法について何か考えはありますか?

49
Astronomer

角括弧マッピング[[]][m]mなど

$VIMRUNTIME/ftplugin/python.vim now(2018)は、:h ]]および:h ]mで文書化されているすべての組み込みマッピングをpython言語に再マッピングします。マッピングは:

]] Jump forward to begin of next toplevel
[[ Jump backwards to begin of current toplevel (if already there, previous toplevel)
]m Jump forward to begin of next method/scope
[m Jump backwords to begin of previous method/scope

][ Jump forward to end of current toplevel
[] Jump backward to end of previous of toplevel
]M Jump forward to end of current method/scope
[M Jump backward to end of previous method/scope

コメント付きの次のサンプルソースコードは、さまざまなマッピングを示しています

class Mapping:                              # [[[[
    def __init__(self, iterable):
        pass

    def update(self, iterable):
        pass

    __update = update                       # []

class Reverse:                              # [[ or [m[m
    def __init__(self, data):               # [m
        self.data = data
        self.index = len(data)              # [M

    def __iter__(self):                     # <--- CURSOR
        return self                         # ]M

    def __next__(self):                     # ]m
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]        # ][

class MappingSubclass(Mapping):             # ]] or ]m]m

    def update(self, keys, values):
        pass

マッピングが追加され、コミットで改善されました abd468ed (2016-09-08)、 1164a6546b4 (2017-11-02)、および 7f2e9d7c9cd =(2017-11-11)。

このファイルの新しいバージョンをまだお持ちでない場合は、ダウンロードして~/.vim/ftplugin/python.vimに入れることができます。このフォルダは$VIMRUNTIME/ftpluginの前に優先されます。

これらのマッピングが$VIMRUNTIMEに追加される前に、python-mode[[]]、および[Mを提供するプラグイン]Mがありました。さらに、python-modeは、テキストオブジェクトaCiCaM、およびiMも定義します。

プラグイン python-mode

このvimプラグインは、組み込みのものと同様のモーションを提供します。

2.4 Vim motion ~
                                                                *pymode-motion*

Support Vim motion (See |operator|) for python objects (such as functions,
class and methods).

`C` — means class
`M` — means method or function
                                                            *pymode-motion-keys*

==========  ============================
Key         Command (modes)
==========  ============================
[[          Jump to previous class or function (normal, visual, operator)
]]          Jump to next class or function  (normal, visual, operator)
[M          Jump to previous class or method (normal, visual, operator)
]M          Jump to next class or method (normal, visual, operator)
aC          Select a class. Ex: vaC, daC, yaC, caC (normal, operator)
iC          Select inner class. Ex: viC, diC, yiC, ciC (normal, operator)
aM          Select a function or method. Ex: vaM, daM, yaM, caM (normal, operator)
iM          Select inner func. or method. Ex: viM, diM, yiM, ciM (normal, operator)
==========  ============================

プラグイン Pythonsense

このプラグインは同様のモーションを提供しますが、わずかに変更されています。

ストックVim8.0の「クラス」モーション( "]]"、 "[["など)は、メソッド/ファンクションモーション中に、クラスブロックかファンクションブロックかどうかに関係なく、最初の列から始まるブロックを検索します。 ( "[m"、 "] m"など)クラスまたはファンクションブロックであるかどうかに関係なく、任意のインデントですべてのブロックを検索します。対照的に、「Pythonsense」クラスモーションは、インデントレベルに関係なく、すべてのクラス定義のみを検索しますが、メソッド/関数モーションは、インデントレベルに関係なく、すべてのメソッド/関数定義を検索します。

すべての詳細と例は https://github.com/jeetsukumaran/vim-pythonsense#stock-vim-vs-pythonsense-motions にあります。さらに、このプラグインは、テキストオブジェクトic/ac(クラス)、if/af(関数)、id/ad(docstring)を定義します。

pythonのtextobjectsに関する議論については、 VIM経由でPythonの関数を選択する最も速い方法は何ですか? を参照してください。

28
Hotschke

python.vim

pythonコードブロック内を移動するのがはるかに簡単になります。

ショートカット:

---(python_match.vim

%を拡張します:

  • %-if/Elif/else、try/exception/catch、for/continue/breakを循環します
  • g%-%の反対側に移動します
  • [%-現在のコードブロックの先頭に移動します
  • ]%-現在のコードブロックの最後に移動します

上記のすべてのモーションは、通常、視覚、およびオペレーター保留モードで機能するため、次のようになります。

  • d]%-現在のブロックが終了するまで削除します
  • v]%d-何が削除されているかを確認できるように、ビジュアルモードを使用して同じことを行う必要があります
  • V]%d-上記、ただし行選択あり
20
Rudiger Wolf

_set foldmethod=indent_がある場合、インデントされたブロックを移動するのは非常に簡単です。たとえば、次のスニペットのdef main():行を使用している場合:

_def main():
+-- 35 lines: gps.init()-----------------------------------------------------

if __== "__main__": main()
_

次に、djがメイン関数全体を取得し、他の場所に貼り付けることができます。

6
tzot

最後の段落に対処するために、次のスクリプトは、アクションを実行できる新しい「インデント」テキストオブジェクトを定義します。例えば、 dii カーソルが置かれている行と同じレベルでインデントされているすべてのものを削除します。

詳細については、プラグインのドキュメントを参照してください: http://www.vim.org/scripts/script.php?script_id=3037

0
Randy Morris