"""Sublime Text plugin to format the output of Python programs nicely."""

import tokenize
from io import BytesIO

import sublime
import sublime_plugin


class PythonOutputFormatCommand(sublime_plugin.TextCommand):

    """The Sublime Text plugin class."""

    indentation_level = 0
    newline = (tokenize.NL, '\n')
    indentation = '    '

    def set_indentation(self):
        """Set internal variable based on the indentation settings of the document."""
        if self.view.settings_object.get('translate_tabs_to_spaces'):
            self.indentation = ' ' * self.view.settings_object.get('tab_size')
        else:
            self.indentation = '\t'

    def indent(self):
        """Return the indentation needed at the current level."""
        return (tokenize.INDENT, self.indentation * self.indentation_level)

    def run(self, edit):
        """Main function which is called when the plugin is activated."""
        self.set_indentation()

        for region in self.view.sel():
            if region.empty():
                region = sublime.Region(0, self.view.size())

            region_data = self.view.substr(region).encode('utf-8')
            result = []

            try:
                for token in tokenize.tokenize(BytesIO(region_data).readline):
                    if token.type == tokenize.OP:
                        if token.exact_type in [tokenize.LBRACE, tokenize.LSQB]:
                            result.append(self.indent())
                            result.append((token.exact_type, token.string))
                            result.append(self.newline)
                            self.indentation_level += 1
                        elif token.exact_type in [tokenize.RBRACE, tokenize.RSQB]:
                            if result[-1] != self.newline:
                                result.append(self.newline)
                            self.indentation_level -= 1
                            result.append(self.indent())
                            result.append((token.exact_type, token.string))
                        elif token.exact_type == tokenize.COLON:
                            result.append((token.exact_type, token.string))
                            result.append((tokenize.STRING, ' '))
                        elif token.exact_type == tokenize.COMMA:
                            result.append((token.exact_type, token.string))
                            result.append(self.newline)
                        else:
                            result.append((token.exact_type, token.string))
                    elif token.type != tokenize.NL:
                        result.append(self.indent())
                        result.append((token.exact_type, token.string))
            except tokenize.TokenError as error:
                sublime.status_message(str(error))
                return

            self.view.replace(edit, region, tokenize.untokenize(result).decode('utf-8'))

        if self.view.settings().get('syntax') == 'Packages/Text/Plain text.tmLanguage':
            self.view.set_syntax_file('Packages/Python/Python.tmLanguage')

@@ -1360,33 +1360,33 @@
 n.exact_type in 
-%5B
+%7B
 tokenize.LBRACE,
@@ -1399,17 +1399,17 @@
 ize.LSQB
-%5D
+%7D
 :%0A      
@@ -1696,17 +1696,17 @@
 type in 
-%5B
+%7B
 tokenize
@@ -1727,17 +1727,17 @@
 ize.RSQB
-%5D
+%7D
 :%0A      
@@ -2076,35 +2076,36 @@
 oken.exact_type 
-== 
+in %7B
 tokenize.COLON:%0A
@@ -2102,16 +2102,17 @@
 ze.COLON
+%7D
 :%0A      
@@ -2289,27 +2289,28 @@
 .exact_type 
-== 
+in %7B
 tokenize.COM
@@ -2311,16 +2311,17 @@
 ze.COMMA
+%7D
 :%0A      

Use sets for quicker lookups