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 automatically wraps long lines of Python code for me when I hit the character limit. But in comments and docstrings, I need to wrap text at 72 characters instead.

Is there any way to make Vim automatically set textwidth to 72 when I'm in a comment or docstring, and set it back when I'm done?

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

Answer 1

So, I've never done any Vim scripting before, but based on this question about doing something similar in C and this tip for checking if you're currently in a comment, I've hacked together a solution.

By default, this uses the PEP8-suggested widths of 79 characters for normal lines and 72 characters for comments, but you can override them by letting g:python_normal_text_width or g:python_comment_text_width variables, respectively. (Personally, I wrap normal lines at 78 characters.)

Drop this baby in your .vimrc and you should be good to go. I may package this up as a plugin later.

function! GetPythonTextWidth()
    if !exists('g:python_normal_text_width')
        let normal_text_width = 79
        let normal_text_width = g:python_normal_text_width

    if !exists('g:python_comment_text_width')
        let comment_text_width = 72
        let comment_text_width = g:python_comment_text_width

    let cur_syntax = synIDattr(synIDtrans(synID(line("."), col("."), 0)), "name")
    if cur_syntax == "Comment"
        return comment_text_width
    elseif cur_syntax == "String"
        " Check to see if we're in a docstring
        let lnum = line(".")
        while lnum >= 1 && (synIDattr(synIDtrans(synID(lnum, col([lnum, "$"]) - 1, 0)), "name") == "String" || match(getline(lnum), '\v^\s*$') > -1)
            if match(getline(lnum), "\\('''\\|\"\"\"\\)") > -1
                " Assume that any longstring is a docstring
                return comment_text_width
            let lnum -= 1

    return normal_text_width

augroup pep8
    autocmd CursorMoved,CursorMovedI * :if &ft == 'python' | :exe 'setlocal textwidth='.GetPythonTextWidth() | :endif
augroup END

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

Answer 2

The accepted answer is great! It does not, however, support the habit I have for formatting/editing comments: I make my edits and then use the gqj command, which is essentially, "reformat the current line combined with the next". Then I hit '.' to repeat that for each line (the command itself advances the cursor to the next line). I don't know the vim scripting language very well, so someone may be able to add support for this to the accepted answer. In the meantime, what I have done is map a function key (F6) to change the textwidth to 72, format the line and then change the textwidth back to 79.

nmap <F6> :set textwidth=72<CR>gqj:set textwidth=79<CR>

Now, when I'm in a docstring, I just make the edit, (ESC) and then hit F6 repeatedly until all the lines are properly formatted.

I added my map command and the accepted answer script to my .vim/after/ftplugin/python.vim.

Answered by: Lucas448 | 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!"""

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...

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 docstr...

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