How to fold long docstrings in python source code in VIM?

Does anybody know of a method, or perhaps a plugin, that will automatically fold long docstrings in Python? I have docstrings in my code that span several pages, so it is troublesome to keep paging through them. The other tricky part is that there is embedded python testing code in the docstrings, so that might make parsing them difficult. Note that I only need to automatically fold the entire docstring, regardless of what is in it.

Asked by: Elise623 | Posted: 30-11-2021

Answer 1

This is a bit of a dirty hack, but you can go through the python syntax file (:sp $VIMRUNTIME/syntax/python.vim) and find all the syntax regions for triple-quoted strings (search for ''' and """) and add the fold keyword to the end of those statements. Then just set foldmethod=syntax for python files and the comments should be folded.

Answered by: Maddie719 | Posted: 01-01-2022

Answer 2

I'm not sure about a plugin or automation, but if you type zf/ you can then search for something and it will fold up to the next instance of it. So in a document like the following (where [] is the cursor):

def foo():
    Some long docstring
    that takes up many

Look at edit2 first for the updated search string!

If you use the command zf/"""[ENTER], it should fold everything from the current line (the beginning of the docstring) to the next occurrence of """ which should be the end of the docstring.

I know this isn't automation, but perhaps it will help in the interim, or lead you down the right path to automating it. See edit2 for a better search function, although I still don't know how to automate.

Hope this helps.

Edit: in a corollary, you can search for any docstring with /"""\_.\{-}""", although this will also return the code within the docstring. To search for a function definition followed by a docstring, you can use /def\_.\{-}"""\_.\{-}""", although this breaks on a def inside the docstring.

Edit2: Actually, some more playing with regexs led me to this: /def.\{-}):\_s*"""\_.\{-}""" which should find any function followed by a docstring. It searches for def followed by any characters, then ): followed by a newline and/or whitespace followed by """ followed by any number of lines than the next """, but always ensures the 2nd triple quote is the one immediately following the first.

Answered by: Joyce892 | Posted: 01-01-2022

Answer 3

In your .vimrc add:

" folding
set foldmethod=indent

This will auto-fold at every indentation, which, in python, translates to docstrings. It works VERY VERY nice. Give it a try. The above answer is correct, but requires a bunch of keystrokes (blah!)

Answered by: Wilson502 | Posted: 01-01-2022

Answer 4

I think I've found a slight improvement to the answer of @too_much_php by trying to figure out how to do the same thing without root access. Copying the syntax region definitions from $VIMRUNTIME/syntax/python.vim to ~/.vim/after/syntax/python.vim and editing them solved the problem for me. Here's my code for ~/.vim/after/syntax/python.vim:

syn region  docString1
      \ start=+[uU]\=\z('''\|"""\)+ end="\z1" keepend transparent fold
syn region  docString2
      \ start=+[uU]\=[rR]\z('''\|"""\)+ end="\z1" keepend transparent fold

Now I can run :set foldmethod=syntax to fold docstrings.

PS: Credits to @too_much_php for the initial idea

Answered by: Ned548 | Posted: 01-01-2022

Answer 5

You can do this with :set foldmethod=marker foldmarker=""",""", I think. I haven't tested it, but that should do the trick. The arguments to foldmarker are start and end markers.

Answered by: Miranda835 | Posted: 01-01-2022

Answer 6

I wrote a vimscript plugin many years ago to do exactly this, but never got around to publishing it. I've put it up as a gist, but have also pasted the source below. I've also replicated its functionality for Sublime Text here.

" Fold multi-line Python comments into one line.
" Also maps the "-" key to toggle expansion and <C-f> to toggle all folding.
setlocal foldmethod=syntax
setlocal foldtext=FoldText()
setlocal fillchars=

map <buffer> - za
map <buffer> <C-f> :call ToggleFold()<CR>

let b:folded = 1

hi Folded     gui=bold cterm=bold guifg=cyan ctermfg=cyan guibg=NONE ctermbg=NONE

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

function! s:Strip(string)
  return substitute(a:string, '^[[:space:][:return:][:cntrl:]]\+\|[[:space:][:return:][:cntrl:]]\+$', '', '')

" Extract the first line of a multi-line comment to use as the fold snippet
function! FoldText()
  let l:snippet = getline(v:foldstart)
  if len(s:Strip(l:snippet)) == 3
    let l:snippet = strpart(l:snippet, 1) . s:Strip(getline(v:foldstart + 1))
  return '+' . l:snippet . ' ...'

Answered by: Maria780 | Posted: 01-01-2022

Answer 7

My solution involves using SimpylFold. After installing it using Vundle, I put this in my vimrc file:

autocmd FileType python setlocal foldlevel=2

Which makes all docstrings folded by default when you open a python file, which is super awesome.

Answered by: David552 | Posted: 01-01-2022

Similar questions

python - Docstrings for data?

Is there a way to describe the module's data in a similar way that a docstring describes a module or a funcion? class MyClass(object): def my_function(): """This docstring works!""" return True my_list = [] """This docstring does not work!"""

python - Avoid docstrings from parent, in Sphinx

I use Sphinx for autodocs, but I find it annoying how it by default appends the parent class docstring to my docstring. The result is that for each and every documented test class inheriting from unittest.TestCase, I get the docstring "Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name...

python - Group method docstrings in sphinx

Is it possible to group several method docstrings with sphinx using it's autodoc capabilities, so that they are listed together? class Test(object): def a(self): """A method of group foo.""" def b(self): """A method of group bar.""" def c(self): """A method of group bar.""" def d(self): """A method of group foo.""" In the generated documen...

python - Pydoc not seeing docstrings?

Obviously I am missing something serious here. Here is my test program: """ Doc and nothing but doc """ class TestMe(object): """ class documentation goes here """ def testFunc(self): """ FunctionDoc Goes here """ print "Hello world" if __name__ =="__main__": t=TestMe() t.testFunc() I run it and it prints "Hello world", natch. But ...

using :ref: in Python docstrings using Sphinx

I'm using Sphinx to document a python project, and I'm trying to create a reusable tip to be used in several locations. Typically, I'll use the following syntax in a python file: """ .. tip:: I want this tip to be used in several locations. Why? - Save time - Work less """

Is there something like C#'s "see cref" in Python ReST docstrings?

I'm converting some C# code to Python 3, including documentation which is typically written as XML summaries in the original C# code. Those summaries have references to class names as a &lt;see cref="ClassName"/&gt; element or &lt;paramref name="fileName"/&gt; elements for references to parameters, creating clickable links when converting it to HTML for example. I wonder if there's somethi...

python - Is it ok to put links in docstrings?

Say, for example, that I am writing a function based on a paper. Is it OK to put a link to the paper in the docstring? Or is this considered bad coding? I could imagine that being frowned upon by the Python community due to the fact that the link could break.

Regex to match Python docstrings

I would like to parse Python docstrings as follows: Summary of class that is multiple lines. Parameters ---------- param1 : str Param 1 is a param Returns ------- value : str Examples -------- &gt;&gt;&gt; print() Maps to { 'base': 'Summary of class that is multiple lines.', 'params': 'param1 : str\n\tParam 1 is a param', 'returns': 'value : str', 'examp...

python - Docstrings for data?

Is there a way to describe the module's data in a similar way that a docstring describes a module or a funcion? class MyClass(object): def my_function(): """This docstring works!""" return True my_list = [] """This docstring does not work!"""

syntax error - python docstrings

ok so I decided to learn python (perl, c, c++, java, objective-c, ruby and a bit of erlang and scala under my belt). and I keep on getting the following error when I try executing this: Tue Jul 21{stevenhirsch@steven-hirschs-macbook-pro-2}/projects/python:--&gt;./ File "./", line 17 print __doc__ ^ SyntaxError: invalid syntax #!/usr/local/bin/python """...

Python decorator handling docstrings

I have a problem using docstrings with decorators. Given the following example: def decorator(f): def _decorator(): print 'decorator active' f() return _decorator @decorator def foo(): '''the magic foo function''' print 'this is function foo' help(foo) Now the help doesn't show me the docstring of foo as expected, it shows: Hel...

Are Python docstrings and comments stored in memory when a module is loaded?

Are Python docstrings and comments stored in memory when a module is loaded? I've wondered if this is true, because I usually document my code well; may this affect memory usage? Usually every Python object has a __doc__ method. Are those docstrings read from the file, or processed otherwise? I've done searches here in the forums, Google and...

python - Using shorter textwidth in comments and docstrings

From the mighty PEP 8: [P]lease limit all lines to a maximum of 79 characters. For flowing long blocks of text (docstrings or comments), limiting the length to 72 characters is recommended. When editing Python code in Vim, I set my textwidth to 79, and Vim au...

python - Writing docstrings - specifying functions arguments and returns

Suppose I have a function, say: &gt;&gt;&gt; def foo(a): return a+1 I want to write a documentation string for it. what is the convention in specifying in the docstring that it takes a and returns a+1?

python - Is there a way to keep docstrings separate from the functions they document?

I'm working on a module with many small functions but whose docstrings tend to be quite long. The docstrings make working on the module irritating as I have to constantly scroll over a long docstring to find a little bit of actual code. Is there a way to keep docstrings separate from the functions they document? I'd really like to be able to specify the docstrings at the end of the file away from the code or, even...

How do I change Emacs's font face for Python docstrings?

I'm just starting to learn Python and use Emacs as my editor. Currently, Emacs uses the same color for normal strings (single quotes) and docstrings (triple quotes). I want docstrings to be a different color, so I used the 'Options->Customize Emacs' menu option to change 'font-lock-doc-face' to a new color and saved the changes. However, Emacs continues to keep docstrings the same color as normal strings. Changing the ...

python - Put docstrings on special methods?

I'm trying to decide what information to put in the class docstring and what to put in the __init__ method docstring. Up until now I've been putting an overview of the class and how to work with it in the class docstring, while stuff directly related to initialization (argument details etc.) I put in the __init__ docstring. Today I started wondering if this was the right way of doing it, s...

static analysis - How to calculate lines of code, comments and docstrings for a Python module?

Is there a tool or snippet that produces the following output in some form: lines_of_code = 98 lines_of_comments = 24 lines_of_documentation = 11 NOTE 1: I will then try to feed this data to Jenkins to graph. NOTE 2: I am aware that CLOC co...

Still can't find your answer? Check out these communities...

PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python