Python: select logical code blocks with VIM

pythonselectionvim

How does one select logically indented code blocks with VIM? For instance, consider this bit of Python:

01:class Foo(object):
02: 
03:    def __init__(self, bar):
04:
05:        if 'baz' in bar:
06:            print("I love baz!")
07:
08:            print("You made the best choice!")
09:
10:        elif 'boo' in bar:
11:            print("I like boo!")
12:
13:        else:
14:            print("I like your choice!")
15:
16:        self.choice = bar
17:        self.someList = []
18:
19:        print("Foo sucessfully created!")
20:
21:
22:    def bim(self):
23:        print("Bam boo")
24:        return True

How can I select all the lines of common indentation? That is, if I'm on line 06, it would select lines 06-08 (inclusive)? Or if I'm on line 16, it would select lines 05-19.

How can I select all the lines of common indentation and additionally the line which 'initializes' it? That is, if I'm on line 06, it would select lines 05-08 (inclusive)? Or if I'm on line 16, it would select lines 03-19.

How can I easily add to the selection the upper-level indentation? That is, if I've got the __init__ method selected, how would I then transition to having the entire class selected?

This question encompasses the general case of many other (often unanswered) VIM/Python questions, such as this one. My initial inclination was to put a bounty on that question, but I would actually prefer to know this more general case, which would help users in that situation and in other situations.

Best Answer

Have a look at the vim-indent-object plugin, which defines a new text object based on indentation levels. It provides the following mappings (taken from documentation):

    Key Mapping       Description

    <count>ai         (A)n (I)ndentation level and line above.
    <count>ii         (I)nner (I)ndentation level (no line above).
    <count>aI         (A)n (I)ndentation level and lines above/below.
    <count>iI         (I)nner (I)ndentation level (no lines above/below).

Therefore:

  • Press vii to select all the lines of common indentation

  • Press vai to select all the lines of common indentation and additionally the line which 'initializes' it

Note that after selecting an indentation level you can go further by pressing ii or ai again. For example, if you are on line 06 and press vai, lines 05-08 are selected. If you press ai again, you get the whole __init__() selected (i.e. lines 03-19). Pressing ai once again will select the entire class.