5

When I edit C-style languages, I can use % to jump between pairs of square brackets, braces, and parenthesis. If there an equivalent between for, while, def, if and the last indented line for the block in python?

I know python blocks like this tend to be shorter, but I just wondered anyway.

5

That functionality is provided by the matchit plugin that is bundled with Vim. The distributed C filetype plugin includes the configuration b:match_words that defines those jumps for the matchit plugin.

Unfortunately, the distributed python filetype does not include a similar change. You can however configure b:match_words for that case. Simply put the definition of the b:match_words variable into ~/.vim/after/ftplugin/python.vim (create non-existing direcotories).

Even better would be to create a PR with a working definition for the b:match_words variable at the upstream python filetype repository so that it can be distributed with one of the next runtime files updates.

For the configuration of the b:match_words variable, see the help page at :h b:match_words. (You might need to do :packadd matchit or the help file won't be found.)

EDIT: So it looks like this might be more complex for python, because python uses no explicit end delimiter but rather the number of spaces. I did not think of it, because I usually do not use python. However, it should still be possible to match those parts. I tried with this simple(?) regex for matching if/elif/ parts:

let b:match_words = &matchpairs . ',^\(\s*\)\<if\>:^\1\<elif\>:^\1\zs\%(elif\)\@!.'

(That works, because it matches the number of spaces in front of the if statement and uses that to match either to the next elif or the end of the if block. A similar think should work for for and similar blocks). However one caveat: doesn't work if the if block itsself is the last part of an containing block, so this it does not catch currently:

for line in input.readlines():
    if (find(line,"endinput")<0):
        Zeile=line[0:len(line)-1]+"[Italy]\n"
        nZeile.append(Zeile)
input.close()

Also there seems to be a bug in the matchit plugin, because adding \zs to the elif pattern to make the cursor stop at the beginning of the elif (instead of at the beginning of the line), breaks it. Not sure why. However, the basic principle should be clear with the example.

| improve this answer | |
  • 1
    I'm afraid this won't work for Python's control blocks. They're based on indentation, not on starting and ending keyword or sign – grodzik Aug 9 '17 at 15:48
  • @grodzik It's almost possible: you can use back references to refer to capture groups in the regexp for the start of block within the regexp for the end of block, so you use these to match the indent before the block but because you can outdent multiple levels in a single line, and because the allowed indent is unlimited, you can't quite make the regexps work. (At least, I couldn't.) – Rich Aug 9 '17 at 16:00
  • It should still work for python. I added a basic example for python. – Christian Brabandt Aug 9 '17 at 20:48
  • 1
    What about the plugin vim.org/scripts/script.php?script_id=386? – Hotschke Aug 14 '17 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.