glyph / python-docstring-mode

Emacs minor-mode for editing Python docstrings.
MIT License
70 stars 22 forks source link

`:return:` and `:raise:` sometimes get wrapped differently from other fields #3

Closed exarkun closed 8 years ago

exarkun commented 9 years ago

If the point is between the :s of the :return: then M-q produces this result:

def foo():
    """                                                                                                                           
    :return: Words words words words words words words words words words words
        words words.                                                                                                         
    """

This seems good and right and pleasant to me.

If the point is somewhere else in the docstring then M-q instead produces:

def foo():
    """                                                                                                                           
    :return: Words words words words words words words words words words words
             words words.                                                                                                         
    """

This seems dire and wrong and bad.

This behavior seems distinctive to :raise: and :return:. I have not observed it for :param ...: or :ivar ...:.

exarkun commented 8 years ago

bump

glyph commented 8 years ago

Oops. I wasn't getting notifications from this project for some reason.

This behavior is quasi-intentional; it was written to facilitate a popular style of docstring wrapping I've observed quite frequently in the wild where the indent is matched to the hanging colon.

However, this quickly becomes ridiculous when you have e.g. :param SomeVeryWordyType some_very_wordy_local_parameter_name: so it goes back to wrapping at a 4-space indent if the identifier is too long. ("too long" is pretty arbitrary and I selected it based on just observing what people were doing by hand in the ReST-format codebase I was looking at).

glyph commented 8 years ago

The reason you're seeing this behavior is a bug in the way that the docstring wrapper sizes strings. In order to track the position of the point in the docstring and re-position it in the same place, it inserts a UUID into the line at the point before re-wrapping, then removes it and puts the point where it removed it. Some of the code in there accidentally sizes the "raw" text (i.e. before pre-processing it to remove the UUID). So what is happening is that docstring_wrap.py thinks that the hanging-indent version is "right"; in the case where the cursor is between the colons, it thinks you are wrapping a docstring that looks like:

def foo():
    """                                                                                                                           
    :retB88E7545-2F85-406B-A00E-63598C9915F5urn: Words words words words words words words words words words words
             words words.                                                                                                         
    """

and therefore a hanging indent is necessary. So if the obvious bug is fixed here it will always choose the "wrong" way. I think that this behavior needs to be an option, since a lot of people seem to like it, but I agree that it is slightly inconsistent and weird (and since I've never seen it with epytext, the behavior is always disabled when wrapping epytext-format strings).

jbms commented 8 years ago

This is fixed by pull request #14

glyph commented 8 years ago

14 is merged so hopefully this is fixed. There's now a tiny bit of a test suite (thanks @hynek !) so an enterprising individual might even add a regression test for this...