sponsor Vim development Vim logo Vim Book Ad

Efficient python folding : Fold python code nicely and toggle with one keystroke

 script karma  Rating 144/61, Downloaded by 13153  Comments, bugs, improvements  Vim wiki

created by
Daniel Nogradi
script type
Folding goes like this:

1. Only top level class or function definitions are folded (no nesting)
2. Folding is done one line after the class or function definition, so
    for example the line 'class foo( bar )' is right above the fold
3. Fold text is the first line of the corresponding docstring (if any)
    together with the number of folded lines
4. Toggle all folds on/off with the key F
5. Toggle the fold under the cursor on/off with the key f
6. In some rare cases folding can break down which can be fixed by :call ReFold()
    The reason for this break down is not known sometimes it happens when jumping
    between different files using tags.

In addition the script binds the key <Shift-e> (hint: _e_xecute) to saving the file and executing it in the interpreter assuming that /usr/bin/env exists otherwise you need to change this key mapping slightly. The keys 'gd' (hint: _g_o _d_efinition) are also bound to look for the definition of a function under the cursor similarly to the same key binding for C.

Inspired by vimscript #515, actually the way the number of lines are displayed is stolen from there :). A related script is vimscript #781 and a tip on toggling a fold is vimtip #108.

The content of the script is this, in case you find it more convenient to copy/paste it than downloading:

" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
let b:did_ftplugin = 1

map <buffer> <S-e> :w<CR>:!/usr/bin/env python % <CR>
map <buffer> gd /def <C-R><C-W><CR>

set foldmethod=expr
set foldexpr=PythonFoldExpr(v:lnum)
set foldtext=PythonFoldText()

map <buffer> f za
map <buffer> F :call ToggleFold()<CR>
let b:folded = 1

function! ToggleFold()
    if( b:folded == 0 )
        exec "normal! zM"
        let b:folded = 1
        exec "normal! zR"
        let b:folded = 0

function! PythonFoldText()
    let size = 1 + v:foldend - v:foldstart
    if size < 10
        let size = " " . size
    if size < 100
        let size = " " . size
    if size < 1000
        let size = " " . size
    if match(getline(v:foldstart), '"""') >= 0
        let text = substitute(getline(v:foldstart), '"""', '', 'g' ) . ' '
    elseif match(getline(v:foldstart), "'''") >= 0
        let text = substitute(getline(v:foldstart), "'''", '', 'g' ) . ' '
        let text = getline(v:foldstart)
    return size . ' lines:'. text . ' '

function! PythonFoldExpr(lnum)
    if indent( nextnonblank(a:lnum) ) == 0
        return 0
    if getline(a:lnum-1) =~ '^\(class\|def\)\s'
        return 1
    if getline(a:lnum) =~ '^\s*$'
        return "="
    if indent(a:lnum) == 0
        return 0

    return '='

" In case folding breaks down
function! ReFold()
    set foldmethod=expr
    set foldexpr=0
    set foldnestmax=1
    set foldmethod=expr
    set foldexpr=PythonFoldExpr(v:lnum)
    set foldtext=PythonFoldText()

install details
Drop the file in your .vim/ftplugin/ directory (in case you already have a file there called python_editing.vim, don't forget to change the name).

rate this script Life Changing Helpful Unfulfilling 
script versions (upload new version)

Click on the package to download.

package script version date Vim version user release notes
python_editing.vim 1.1 2006-03-28 6.0 Daniel Nogradi Recognizes both double quoted (""") and single quoted (''') docstrings.
Added a function to fix folding if it breaks down for some reason.
python_editing.vim 1.0 2006-03-13 6.0 Daniel Nogradi Initial upload
ip used for rating:

If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to the maillist. Help Bram help Uganda.
Vim at Github