I'm wondering if it is possible to automatically fold only specific sections of code in vim (specifically for python files).

I'm currently using the indent fold method. And I would like to only fold an indented block if the header matches a pattern.

For instance, if I'm in a file with this function, I would like all blocks that start with Example: or References: to be automatically folded, but I don't want anything else to be folded.

Is there a simple way to do this?

def spawn_background_process(func, *args, **kwargs):
    Run a function in the background
    (like rebuilding some costly data structure)


        func (function):

        python -m utool.util_parallel --test-spawn_background_process

        >>> # DISABLE_DOCTEST
        >>> from utool.util_parallel import *  # NOQA
        >>> import utool as ut
        >>> import time
        >>> from os.path import join
        >>> # build test data
        >>> fname = 'test_bgfunc_output.txt'
        >>> dpath = ut.get_app_resource_dir('utool')
        >>> ut.ensuredir(dpath)
        >>> fpath = join(dpath, fname)
        >>> # ensure file is not around
        >>> sleep_time = 1
        >>> ut.delete(fpath)
        >>> assert not ut.checkpath(fpath, verbose=True)
        >>> def backgrond_func(fpath, sleep_time):
        ...     import utool as ut
        ...     import time
        ...     print('[BG] Background Process has started')
        ...     time.sleep(sleep_time)
        ...     print('[BG] Background Process is writing')
        ...     ut.write_to(fpath, 'background process')
        ...     print('[BG] Background Process has finished')
        ...     #raise AssertionError('test exception')
        >>> # execute function
        >>> func = backgrond_func
        >>> args = (fpath, sleep_time)
        >>> kwargs = {}
        >>> print('[FG] Spawning process')
        >>> threadid = ut.spawn_background_process(func, *args, **kwargs)
        >>> assert threadid.is_alive() is True, 'thread should be active'
        >>> print('[FG] Spawned process. threadid=%r' % (threadid,))
        >>> # background process should not have finished yet
        >>> assert not ut.checkpath(fpath, verbose=True)
        >>> print('[FG] Waiting to check')
        >>> time.sleep(sleep_time + .1)
        >>> print('[FG] Finished waiting')
        >>> # Now the file should be there
        >>> assert ut.checkpath(fpath, verbose=True)
        >>> assert threadid.is_alive() is False, 'process should have died'
    import utool as ut
    func_name = ut.get_funcname(func)
    name = 'mp.Progress-' + func_name
    proc_obj = multiprocessing.Process(target=func, name=name, args=args, kwargs=kwargs)
    #proc_obj.isAlive = proc_obj.is_alive
    return proc_obj

There is a way to do this, you just have to write yourself a custom fold function.

Put the following code in .vim/after/ftplugin/python/folding.vim (creating directories and files if not present):

function! ExampleFolds(lnum)
  let s:thisline = getline(a:lnum)
  if match(s:thisline, '^\s*Example:$') >= 0
    return '>1'
  elseif match(s:thisline, '^\s*$') >= 0
    return '0'
    return '='

setlocal foldmethod=expr
setlocal foldexpr=ExampleFolds(v:lnum)

You will still need to adapt that function a bit to suit your needs. What it does right now is to start a fold with foldlevel 1 whenever it meets an Example: block. The fold includes all following lines till either a new example block is there (starting a new fold) or an empty line closes it.

Besides the link, check :h foldexpr and :h foldlevel.

| improve this answer | |

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.