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.

1 Answer 1

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.

4
  • 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, 2017 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, 2017 at 16:00
  • It should still work for python. I added a basic example for python. Aug 9, 2017 at 20:48
  • 2
    What about the plugin vim.org/scripts/script.php?script_id=386?
    – Hotschke
    Aug 14, 2017 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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