Sublime Forum

Inconsistent Indentation in Python

#1

I am noticing an inconsistency with indentation in Python (default language package). I’m running the latest Sublime Text. Depending on current indentation, one type of automatic indentation does not happen as expected. The only deviation from the defaults with regards to indentation is that I have indent_to_bracket set to true.

Here is the indentation inside the brackets that I want, and it is the one that is done automatically when at the base of no indentation yet.

example = {
    'test1': 1,
    'test2': 2
}

Here, I want the same type of auto indent. But, it indents to the same indentation as the variable.

def indent():
    example2 = {
    'test1': 1,
    'test2': 2
    }

First of all, this autoindent causes a pycodestyle linter error because it violates PEP8:

pycodestyle: error
E122 - continuation line missing indentation or outdented

Second, this autoindent behavior is different than Jupyter and other IDEs.

I understand that there are many concious decisions made about indentation and features in Sublime Text and the Python package. Is the above auto indent behavior by design? If so, where is this controlled in the syntax, and is there a way to override this in settings?

0 Likes

#2

For me with ST build 4134, { never indents in Python and } never unindents, so even your first example is “flat” when I try typing it out.

To fix this, you’ll want to override the Packages/Python/Indentation.tmPreferences file:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
	<key>scope</key>
	<string>source.python</string>
	<key>settings</key>
	<dict>
		<key>decreaseIndentPattern</key>
		<string>^\s*(elif|else|except|finally)\b.*:|^\s*\}[;\s#,]*$</string>
		<key>increaseIndentPattern</key>
		<string><![CDATA[(?x)
			^\s*
			(
			# declaration or control flow keywords
			  (
			  	( async\s+ )? ( def | for | with )
			  | class | elif | else | except | finally | if | try | while
			  ) \b
			# pattern matching keyword followed by at least one non-whitespace token
			| ( case | match )\b \s* [^:]
			)
			# terminated by colon and followed only by optional whitespace or comment
			.* : \s* (\#.*)? $
			|
			^.*(\{[^}"']*)$
		]]></string>
		<key>disableIndentNextLinePattern</key>
		<string></string>
	</dict>
</dict>
</plist>

It seems like there are currently no indentation tests at https://github.com/sublimehq/Packages/tree/master/Python, so hard to say for sure if it’s by design, but I would guess it’s just an oversight. Feel free to raise a PR for discussion.

0 Likes

#3

Thanks for the pointer as to where to override this.

I have indent_to_bracket set to true. I have edited my original post to specify this. The defaults in ST are the following:

	// Calculates indentation automatically when pressing enter
	"auto_indent": true,

	// Makes auto indent a little smarter, e.g., by indenting the next line
	// after an if statement in C. Requires auto_indent to be enabled.
	"smart_indent": true,

	// Adds whitespace up to the first open bracket when indenting. Requires
	// auto_indent to be enabled.
	"indent_to_bracket": false,

If your ST never indents, then you have changed your default settings. The one that you have changed from default is auto_indent from true to false.

0 Likes

#4

actually, I turn off auto_match_enabled so the keybinding which executes res://Packages/Default/Add Line in Braces.sublime-macro on pressing Enter between { and } doesn’t apply, because there is no }. So it’s unrelated to indentation settings.

0 Likes