Sublime Text 4: folding Python functions with a line break

Question:

I’m running Sublime Text Build 4143. Given a function with parameters that spill over the 80 character limit like so:

def func(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6):
    """
    """

    print("hello world")

    return

ST will show a PEP8 E501: line too long warning and highlight the line (which is fine):

enter image description here

But I can fold this function appropriately:

enter image description here

If I modify it to avoid the PEP8 warning:

enter image description here

I can no longer fold it:

enter image description here

This changed in the last update I think, because I used to be able to fold these functions without issues. How can I get around ths?

Asked By: Gabriel

||

Answers:

There are a couple of solutions. The first is to use the folding keyboard shortcut (CtrlShift[ on Windows/Linux, Shift[ on Mac) with the cursor either before or after the colon : at the very end of the function signature – outside the parentheses (). You can unfold using CtrlShift] (Shift]), or by using the arrow in the gutter just to the left of the def keyword.

The second method is a little more involved, but allows you to use the fold arrows as well as the keyboard shortcuts, and your cursor can be anywhere when you fold. Open the Command Palette with CtrlShiftP (ShiftP on Mac) and type v, then select the View Package File option. Next, type in python/fold and select Python/Fold.tmPreferences. A PLIST/XML file will open up, containing language-specific rules for folding.

Before we can edit the file, we need to save it and turn off its read-only protection. First, save the file by selecting File → Save As…. It should automagically select the Packages/Python directory, where Packages is

  • Linux: ~/.config/sublime-text-3/Packages or ~/.config/sublime-text/Packages
  • macOS/OS X: ~/Library/Application Support/Sublime Text 3/Packages or ~/Library/Application Support/Sublime Text/Packages
  • Windows Regular Install: C:UsersYourUserNameAppDataRoamingSublime Text 3Packages or C:UsersYourUserNameAppDataRoamingSublime TextPackages
  • Windows Portable Install: InstallationFolderSublime Text 3DataPackages or InstallationFolderSublime TextDataPackages

The exact path depends on whether or not you upgraded from Sublime Text 3.

Next, select View → Show Console and type in

view.set_read_only(False)

You can close the Console by hitting Esc or selecting View → Hide Console.

In Fold.tmPreferences, select lines 24-29 and comment them out – Ctrl/ for Win/Lin, / for macOS. It should look something like this:

                <string>punctuation.section.arguments.begin</string>
                <key>end</key>
                <string>punctuation.section.arguments.end</string>
            </dict>
<!--             <dict>
                <key>begin</key>
                <string>punctuation.section.parameters.begin</string>
                <key>end</key>
                <string>punctuation.section.parameters.end</string>
            </dict>
 -->            <dict>
                <key>begin</key>
                <string>punctuation.section.sequence.begin</string>
                <key>end</key>

lines 20-33

Finally, save your changes. Test that everything worked correctly by closing the file after you save it, then going to File → Open Recent and verifying that Fold.tmPreferences is at the top of the list. Click on it to open it, and double-check that lines 24-29 are still commented out. Once you’ve done that, you can close it again.

And that should be it! Once the changes to Fold.tmPreferences have been saved, they’ll be effective immediately.


A big thank you to the regulars on the Sublime Text Discord server for their suggestions to look at Fold.tmPreferences.

Answered By: MattDMo

This is not a "fair" answer, but may be helpful. If you use black-like line folding (or anything similar, but with one important property: the closing parenthesis should be on its own line and be indented to the same level as def, see below), then folding works even better:

def func(
    parameter_1, 
    parameter_2, 
    parameter_3, 
    parameter_4, 
    parameter_5, 
    parameter_6,
):
    """
    """

    print("hello world")
    return

Now you have three arrows: the first folds function arguments, the second folds all function body and the third folds only the docstring.

You can wrap parameters in any way you like, if closing parenthesis remains in place. I personally prefer this style, and it can be auto-formatted with black. Your solution is PEP8-compatible, but ST doesn’t like it. It folds to the next line with the same level of indentation (so I’m very surprised that it worked before). This line-wrapping style is especially cute if you use type hinting: every argument appears on its own line together with type, and return type is written on the last line – still separate).

This problem also arises in languages with goto construct and labels, which can be indented to the same level as function body – wrapping dies as well.

Behaviour screenshot

Answered By: SUTerliakov
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.