Packages: [Python] Reindent for def and class not working

Created on 23 Oct 2016  路  7Comments  路  Source: sublimehq/Packages

Try to run _Indention: Reindent Lines_ command from command pallet for the following peace of code:

import sublime_plugin


def tabs_to_spaces(view, set_translate, only_leading):
    view.run_command('expand_tabs', {
                     'set_translete_tabs' : set_translate,
                     'only_leading' : only_leading })


def spaces_to_tabs(view, set_translate, only_leading):
    view.run_command('unexpand_tabs', {
                     'set_translete_tabs' : set_translate,
                     'only_leading' : only_leading })


class SetTabsizeCommand(sublime_plugin.TextCommand):

    def run(self, edit, tab_size = 4):
        view = self.view

        translate_tabs = view.settings().get('translate_tabs_to_spaces', False)
        if translate_tabs:
            spaces_to_tabs(view, False, True)
            view.settings().set('tab_size', tab_size)
            view.run_command('reindent')
            tabs_to_spaces(view, False, True)

        else:
            view.settings().set('tab_size', tab_size)
            tabs_to_spaces(view, False, True)
            view.run_command('reindent')
            spaces_to_tabs(view, False, True)

        # restore settings as 'expand_tabs' does not
        view.settings().set('translate_tabs_to_spaces', translate_tabs)

This will break indention as follows:

import sublime_plugin


def tabs_to_spaces(view, set_translate, only_leading):
    view.run_command('expand_tabs', {
                     'set_translete_tabs' : set_translate,
                     'only_leading' : only_leading })


    def spaces_to_tabs(view, set_translate, only_leading):
        view.run_command('unexpand_tabs', {
                         'set_translete_tabs' : set_translate,
                         'only_leading' : only_leading })


        class SetTabsizeCommand(sublime_plugin.TextCommand):

            def run(self, edit, tab_size = 4):
                view = self.view

                translate_tabs = view.settings().get('translate_tabs_to_spaces', False)
                if translate_tabs:
                    spaces_to_tabs(view, False, True)
                    view.settings().set('tab_size', tab_size)
                    view.run_command('reindent')
                    tabs_to_spaces(view, False, True)

                else:
                    view.settings().set('tab_size', tab_size)
                    tabs_to_spaces(view, False, True)
                    view.run_command('reindent')
                    spaces_to_tabs(view, False, True)

        # restore settings as 'expand_tabs' does not
        view.settings().set('translate_tabs_to_spaces', translate_tabs)

As _reindent_ seems to be a built-in function of Sublime Text I guess this is an issue caused by the Indention Rules of python.

Adding the _class_ keyword to decreaseIndentPattern made things a bit better.

        <key>decreaseIndentPattern</key>
        <string>^\s*(class|elif|else|except|finally)\b.*:</string>

But I can't find a solution for _def_ which works well with comments etc. Maybe someone else has an idea?

enhancement

Most helpful comment

If reindent doesn't work, then just Undo.

All 7 comments

In Python, it is possible to define classes and other functions inside a function, so having it automatically change indentation when typing class or def won't be desirable.

You are basically right, but unfortunately this means built-in _reindent_ command is most commonly useless for python language as it breaks indention due to lack of detecting embedded function or class definitions.

There is no way to tell _reindent_ to try to keep the current indention level as it always makes use of _increaseIndentPattern_ and _decreaseIndentPattern_ only?

Hmm. Seems I need an alternative strategy to fix indention after tab_size change.

I basically wanted to update a view's content, if the user clicks on Main Menu / View / Indention / Tab Width ... as changing the _tab_size_ setting only causes different issues with functions that assume this setting to match the current content such as translate_tabs_to_spaces.

There isn't much helping re-indenting code with significant whitespace since your tool would have to be able to predict semantics. Furthermore, code has to be indented in the first place in order to work.

Chances are you'll be able to fix indentation using a regular expression replace instead.

Automatic indenting rules are an area that Sublime Text needs some better conventions, and possibly functionality around.

Currently we have what we inherited from TextMate, however that isn't capable of handling lots of different situations and doesn't really allow for certain indentation conventions.

I don't think this is actually solveable for a language with significant whitespace like Python, so imo this issue should be closed.

A pop dialog tip is recommend before _re-indent_ python codes, instead of a silent inproper re-indentation.
Is it worthy to sacrifice sublime-dev-code simplicity for user-friendly?
Confilcts like this choice always consume huge time on my dev-road 馃槼

If reindent doesn't work, then just Undo.

Was this page helpful?
0 / 5 - 0 ratings