Пример #1
0
    def setup(self, **kwargs):
        path_packages = sublime.packages_path()

        # Get get general document preferences from sublime preferences
        settings = sublime.load_settings('Preferences.sublime-settings')
        eh_settings = sublime.load_settings(PACKAGE_SETTINGS)
        self.tab_size = settings.get('tab_size', 4)
        self.char_limit = int(eh_settings.get("valid_selection_size", 4))
        self.bground = ''
        self.fground = ''
        self.gbground = ''
        self.gfground = ''
        self.sbground = ''
        self.sfground = ''
        self.numbers = kwargs["numbers"]
        self.hl_continue = None
        self.curr_hl = None
        self.sels = []
        self.multi_select = self.check_sel() if kwargs["multi_select"] else False
        self.size = self.view.size()
        self.pt = 0
        self.end = 0
        self.curr_row = 0
        self.empty_space = None

        # Get color scheme
        if kwargs["color_scheme"] != None:
            alt_scheme = kwargs["color_scheme"]
        else:
            alt_scheme = eh_settings.get("alternate_scheme", False)
        scheme_file = settings.get('color_scheme') if alt_scheme == False else alt_scheme

        self.csm = ColorSchemeMatcher(
            scheme_file,
            strip_trans=True,
            ignore_gutter=True,
            filter=(lambda x: ColorSchemeTweaker().tweak(x, kwargs["filter"]))
        )
        (
            self.bground, self.fground, self.sbground,
            self.sfground, self.gbground, self.gfground
        ) = self.csm.get_general_colors()
Пример #2
0
    def setup(self, **kwargs):
        # Get get general document preferences from sublime preferences
        eh_settings = sublime.load_settings(PACKAGE_SETTINGS)
        settings = sublime.load_settings("Preferences.sublime-settings")
        alternate_font_size = eh_settings.get("alternate_font_size", False)
        alternate_font_face = eh_settings.get("alternate_font_face", False)
        self.font_size = settings.get("font_size", 10) if alternate_font_size == False else alternate_font_size
        self.font_face = settings.get("font_face", "Consolas") if alternate_font_face == False else alternate_font_face
        self.tab_size = settings.get("tab_size", 4)
        self.padd_top = settings.get("line_padding_top", 0)
        self.padd_bottom = settings.get("line_padding_bottom", 0)
        self.char_limit = int(eh_settings.get("valid_selection_size", 4))
        self.bground = ""
        self.fground = ""
        self.gbground = ""
        self.gfground = ""
        self.sbground = ""
        self.sfground = ""
        self.numbers = kwargs["numbers"]
        self.date_time_format = kwargs["date_time_format"]
        self.time = time.localtime()
        self.show_full_path = kwargs["show_full_path"]
        self.highlight_selections = kwargs["highlight_selections"]
        self.browser_print = kwargs["browser_print"]
        self.auto_wrap = kwargs["wrap"] != None and int(kwargs["wrap"]) > 0
        self.wrap = 900 if not self.auto_wrap else int(kwargs["wrap"])
        self.hl_continue = None
        self.curr_hl = None
        self.sels = []
        self.multi_select = self.check_sel() if kwargs["multi_select"] and not kwargs["highlight_selections"] else False
        self.size = self.view.size()
        self.pt = 0
        self.end = 0
        self.curr_row = 0
        self.tables = 0
        self.curr_annot = None
        self.curr_comment = None
        self.annotations = self.get_annotations()
        self.annot_num = -1
        self.new_annot = False
        self.open_annot = False
        self.no_header = kwargs["no_header"]
        self.annot_tbl = []
        self.toolbar = kwargs["toolbar"]
        self.toolbar_orientation = (
            "block" if eh_settings.get("toolbar_orientation", "horizontal") == "vertical" else "inline-block"
        )
        self.matched = {}
        self.ebground = self.bground
        self.lumens_limit = float(eh_settings.get("bg_min_lumen_threshold", 62))

        self.highlights = []
        if self.highlight_selections:
            for sel in self.view.sel():
                if not sel.empty():
                    self.highlights.append(sel)

        fname = self.view.file_name()
        if fname == None or not path.exists(fname):
            fname = "Untitled"
        self.file_name = fname

        # Get color scheme
        if kwargs["color_scheme"] != None:
            alt_scheme = kwargs["color_scheme"]
        else:
            alt_scheme = eh_settings.get("alternate_scheme", False)
        scheme_file = settings.get("color_scheme") if alt_scheme == False else alt_scheme

        self.csm = ColorSchemeMatcher(
            scheme_file,
            strip_trans=True,
            ignore_gutter=(not kwargs["style_gutter"]),
            track_dark_background=True,
            filter=(lambda x: ColorSchemeTweaker().tweak(x, kwargs["filter"])),
        )
        if kwargs["shift_brightness"]:
            self.csm.shift_background_brightness(self.lumens_limit)
        (
            self.bground,
            self.fground,
            self.sbground,
            self.sfground,
            self.gbground,
            self.gfground,
        ) = self.csm.get_general_colors()
Пример #3
0
class ExportHtml(object):
    def __init__(self, view):
        self.view = view

    def process_inputs(self, **kwargs):
        return {
            "numbers": bool(kwargs.get("numbers", False)),
            "highlight_selections": bool(kwargs.get("highlight_selections", False)),
            "browser_print": bool(kwargs.get("browser_print", False)),
            "color_scheme": kwargs.get("color_scheme", None),
            "wrap": kwargs.get("wrap", None),
            "multi_select": bool(kwargs.get("multi_select", False)),
            "style_gutter": bool(kwargs.get("style_gutter", True)),
            "no_header": bool(kwargs.get("no_header", False)),
            "date_time_format": kwargs.get("date_time_format", "%m/%d/%y %I:%M:%S"),
            "show_full_path": bool(kwargs.get("show_full_path", True)),
            "toolbar": kwargs.get("toolbar", ["plain_text", "gutter", "wrapping", "print", "annotation", "theme"]),
            "save_location": kwargs.get("save_location", None),
            "time_stamp": kwargs.get("time_stamp", "_%m%d%y%H%M%S"),
            "clipboard_copy": bool(kwargs.get("clipboard_copy", False)),
            "view_open": bool(kwargs.get("view_open", False)),
            "shift_brightness": bool(kwargs.get("shift_brightness", False)),
            "filter": kwargs.get("filter", ""),
        }

    def setup(self, **kwargs):
        # Get get general document preferences from sublime preferences
        eh_settings = sublime.load_settings(PACKAGE_SETTINGS)
        settings = sublime.load_settings("Preferences.sublime-settings")
        alternate_font_size = eh_settings.get("alternate_font_size", False)
        alternate_font_face = eh_settings.get("alternate_font_face", False)
        self.font_size = settings.get("font_size", 10) if alternate_font_size == False else alternate_font_size
        self.font_face = settings.get("font_face", "Consolas") if alternate_font_face == False else alternate_font_face
        self.tab_size = settings.get("tab_size", 4)
        self.padd_top = settings.get("line_padding_top", 0)
        self.padd_bottom = settings.get("line_padding_bottom", 0)
        self.char_limit = int(eh_settings.get("valid_selection_size", 4))
        self.bground = ""
        self.fground = ""
        self.gbground = ""
        self.gfground = ""
        self.sbground = ""
        self.sfground = ""
        self.numbers = kwargs["numbers"]
        self.date_time_format = kwargs["date_time_format"]
        self.time = time.localtime()
        self.show_full_path = kwargs["show_full_path"]
        self.highlight_selections = kwargs["highlight_selections"]
        self.browser_print = kwargs["browser_print"]
        self.auto_wrap = kwargs["wrap"] != None and int(kwargs["wrap"]) > 0
        self.wrap = 900 if not self.auto_wrap else int(kwargs["wrap"])
        self.hl_continue = None
        self.curr_hl = None
        self.sels = []
        self.multi_select = self.check_sel() if kwargs["multi_select"] and not kwargs["highlight_selections"] else False
        self.size = self.view.size()
        self.pt = 0
        self.end = 0
        self.curr_row = 0
        self.tables = 0
        self.curr_annot = None
        self.curr_comment = None
        self.annotations = self.get_annotations()
        self.annot_num = -1
        self.new_annot = False
        self.open_annot = False
        self.no_header = kwargs["no_header"]
        self.annot_tbl = []
        self.toolbar = kwargs["toolbar"]
        self.toolbar_orientation = (
            "block" if eh_settings.get("toolbar_orientation", "horizontal") == "vertical" else "inline-block"
        )
        self.matched = {}
        self.ebground = self.bground
        self.lumens_limit = float(eh_settings.get("bg_min_lumen_threshold", 62))

        self.highlights = []
        if self.highlight_selections:
            for sel in self.view.sel():
                if not sel.empty():
                    self.highlights.append(sel)

        fname = self.view.file_name()
        if fname == None or not path.exists(fname):
            fname = "Untitled"
        self.file_name = fname

        # Get color scheme
        if kwargs["color_scheme"] != None:
            alt_scheme = kwargs["color_scheme"]
        else:
            alt_scheme = eh_settings.get("alternate_scheme", False)
        scheme_file = settings.get("color_scheme") if alt_scheme == False else alt_scheme

        self.csm = ColorSchemeMatcher(
            scheme_file,
            strip_trans=True,
            ignore_gutter=(not kwargs["style_gutter"]),
            track_dark_background=True,
            filter=(lambda x: ColorSchemeTweaker().tweak(x, kwargs["filter"])),
        )
        if kwargs["shift_brightness"]:
            self.csm.shift_background_brightness(self.lumens_limit)
        (
            self.bground,
            self.fground,
            self.sbground,
            self.sfground,
            self.gbground,
            self.gfground,
        ) = self.csm.get_general_colors()

    def get_tools(self, tools, use_annotation, use_wrapping):
        toolbar_options = {
            "gutter": TOOL_GUTTER,
            "print": TOOL_PRINT,
            "plain_text": TOOL_PLAIN_TEXT,
            "annotation": TOOL_ANNOTATION if use_annotation else "",
            "theme": TOOL_DUMP_THEME,
            "wrapping": TOOL_WRAPPING if use_wrapping else "",
        }
        t_opt = ""
        toolbar_element = ""

        if len(tools):
            for t in tools:
                if t in toolbar_options:
                    t_opt += toolbar_options[t]
            toolbar_element = TOOLBAR % {"options": t_opt}
        return toolbar_element

    def setup_print_block(self, curr_sel, multi=False):
        # Determine start and end points and whether to parse whole file or selection
        if not multi and (curr_sel.empty() or self.highlight_selections or curr_sel.size() <= self.char_limit):
            self.size = self.view.size()
            self.pt = 0
            self.end = 1
            self.curr_row = 1
        else:
            self.size = curr_sel.end()
            self.pt = curr_sel.begin()
            self.end = self.pt + 1
            self.curr_row = self.view.rowcol(self.pt)[0] + 1
        self.start_line = self.curr_row

        self.gutter_pad = len(str(self.view.rowcol(self.size)[0])) + 1

    def check_sel(self):
        multi = False
        for sel in self.view.sel():
            if not sel.empty() and sel.size() >= self.char_limit:
                multi = True
                self.sels.append(sel)
        return multi

    def print_line(self, line, num):
        html_line = LINE % {
            "line_id": num,
            "color": self.gfground,
            "bgcolor": self.gbground,
            "line": str(num).rjust(self.gutter_pad).replace(" ", "&nbsp;"),
            "code_id": num,
            "code": line,
            "table": self.tables,
            "pad_color": self.ebground or self.bground,
        }

        return html_line

    def write_header(self, the_html):
        header = HTML_HEADER % {
            "title": path.basename(self.file_name),
            "css": getcss(
                "export.css",
                {
                    "font_size": str(self.font_size),
                    "font_face": '"' + self.font_face + '"',
                    "page_bg": self.bground,
                    "gutter_bg": self.gbground,
                    "body_fg": self.fground,
                    "display_mode": "table-cell" if self.numbers else "none",
                    "dot_color": self.fground,
                    "toolbar_orientation": self.toolbar_orientation,
                },
            ),
            "js": INCLUDE_THEME
            % {
                "jscode": getjs("plist.js"),
                "theme": json.dumps(self.csm.get_plist_file(), sort_keys=True, indent=4, separators=(",", ": ")).encode(
                    "raw_unicode_escape"
                ),
                "name": self.csm.get_scheme_file(),
            },
        }
        the_html.write(header)

    def convert_view_to_html(self, the_html):
        for line in self.view.split_by_newlines(sublime.Region(self.pt, self.size)):
            self.size = line.end()
            empty = not bool(line.size())
            line = self.convert_line_to_html(the_html, empty)
            the_html.write(self.print_line(line, self.curr_row))
            self.curr_row += 1

    def html_encode(self, text):
        # Format text to HTML
        encode_table = {"&": "&amp;", ">": "&gt;", "<": "&lt;", "\t": " " * self.tab_size, "\n": ""}

        return re.sub(
            r"(?!\s($|\S))\s",
            "&nbsp;",
            "".join(encode_table.get(c, c) for c in text).encode("ascii", "xmlcharrefreplace"),
        )

    def get_annotations(self):
        annotations = get_annotations(self.view)
        comments = []
        for x in range(0, int(annotations["count"])):
            region = annotations["annotations"]["html_annotation_%d" % x]["region"]
            comments.append((region, annotations["annotations"]["html_annotation_%d" % x]["comment"]))
        comments.sort()
        return comments

    def annotate_text(self, line, the_colour, the_bgcolour, the_style, empty):
        pre_text = None
        annot_text = None
        post_text = None
        start = None

        # Pretext Check
        if self.pt >= self.curr_annot.begin():
            # Region starts with an annotation
            start = self.pt
        else:
            # Region has text before annoation
            pre_text = self.html_encode(self.view.substr(sublime.Region(self.pt, self.curr_annot.begin())))
            start = self.curr_annot.begin()

        if self.end == self.curr_annot.end():
            # Region ends annotation
            annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.end)))
            self.curr_annot = None
        elif self.end > self.curr_annot.end():
            # Region has text following annotation
            annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.curr_annot.end())))
            post_text = self.html_encode(self.view.substr(sublime.Region(self.curr_annot.end(), self.end)))
            self.curr_annot = None
        else:
            # Region ends but annotation is not finished
            annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.end)))
            self.curr_annot = sublime.Region(self.end, self.curr_annot.end())

        # Print the separate parts pre text, annotation, post text
        if pre_text != None:
            self.format_text(line, pre_text, the_colour, the_bgcolour, the_style, empty)
        if annot_text != None:
            self.format_text(line, annot_text, the_colour, the_bgcolour, the_style, empty, annotate=True)
            if self.curr_annot == None:
                self.curr_comment = None
        if post_text != None:
            self.format_text(line, post_text, the_colour, the_bgcolour, the_style, empty)

    def add_annotation_table_entry(self):
        row, col = self.view.rowcol(self.annot_pt)
        self.annot_tbl.append(
            (
                self.tables,
                self.curr_row,
                "Line %d Col %d" % (row + 1, col + 1),
                self.curr_comment.encode("ascii", "xmlcharrefreplace"),
            )
        )
        self.annot_pt = None

    def format_text(self, line, text, the_colour, the_bgcolour, the_style, empty, annotate=False):
        if empty:
            text = "&nbsp;"
        else:
            the_style += " real_text"

        if the_bgcolour is None:
            the_bgcolour = self.bground

        if annotate:
            code = ANNOTATION_CODE % {
                "highlight": the_bgcolour,
                "color": the_colour,
                "content": text,
                "class": the_style,
            }
        else:
            code = CODE % {"highlight": the_bgcolour, "color": the_colour, "content": text, "class": the_style}

        if annotate:
            if self.curr_annot != None and not self.open_annot:
                # Open an annotation
                if self.annot_pt != None:
                    self.add_annotation_table_entry()
                if self.new_annot:
                    self.annot_num += 1
                    self.new_annot = False
                code = ANNOTATE_OPEN % {"code": code, "comment": str(self.annot_num)}
                self.open_annot = True
            elif self.curr_annot == None:
                if self.open_annot:
                    # Close an annotation
                    code += ANNOTATE_CLOSE
                    self.open_annot = False
                else:
                    # Do a complete annotation
                    if self.annot_pt != None:
                        self.add_annotation_table_entry()
                    if self.new_annot:
                        self.annot_num += 1
                        self.new_annot = False
                    code = ANNOTATE_OPEN % {"code": code, "comment": str(self.annot_num)} + ANNOTATE_CLOSE
        line.append(code)

    def convert_line_to_html(self, the_html, empty):
        line = []
        hl_done = False

        # Continue highlight form last line
        if self.hl_continue != None:
            self.curr_hl = self.hl_continue
            self.hl_continue = None

        while self.end <= self.size:
            # Get next highlight region
            if self.highlight_selections and self.curr_hl == None and len(self.highlights) > 0:
                self.curr_hl = self.highlights.pop(0)

            # See if we are starting a highlight region
            if self.curr_hl != None and self.pt == self.curr_hl.begin():
                # Get text of like scope up to a highlight
                scope_name = self.view.scope_name(self.pt)
                while self.view.scope_name(self.end) == scope_name and self.end < self.size:
                    # Kick out if we hit a highlight region
                    if self.end == self.curr_hl.end():
                        break
                    self.end += 1
                if self.end < self.curr_hl.end():
                    if self.end >= self.size:
                        self.hl_continue = sublime.Region(self.end, self.curr_hl.end())
                    else:
                        self.curr_hl = sublime.Region(self.end, self.curr_hl.end())
                else:
                    hl_done = True
                if hl_done and empty:
                    the_colour, the_style, the_bgcolour, _, _, _ = self.csm.guess_color(self.view, self.pt, scope_name)
                elif self.sfground is None:
                    the_colour, the_style, _, _, _, _ = self.csm.guess_color(self.view, self.pt, scope_name)
                    the_bgcolour = self.sbground
                else:
                    the_colour, the_style = self.sfground, "normal"
                    the_bgcolour = self.sbground
            else:
                # Get text of like scope up to a highlight
                scope_name = self.view.scope_name(self.pt)
                while self.view.scope_name(self.end) == scope_name and self.end < self.size:
                    # Kick out if we hit a highlight region
                    if self.curr_hl != None and self.end == self.curr_hl.begin():
                        break
                    self.end += 1
                the_colour, the_style, the_bgcolour, _, _, _ = self.csm.guess_color(self.view, self.pt, scope_name)

            # Get new annotation
            if (self.curr_annot == None or self.curr_annot.end() < self.pt) and len(self.annotations):
                self.curr_annot, self.curr_comment = self.annotations.pop(0)
                self.annot_pt = self.curr_annot[0]
                while self.pt > self.curr_annot[1]:
                    if len(self.annotations):
                        self.curr_annot, self.curr_comment = self.annotations.pop(0)
                        self.annot_pt = self.curr_annot[0]
                    else:
                        self.curr_annot = None
                        self.curr_comment = None
                        break
                self.new_annot = True
                self.curr_annot = sublime.Region(self.curr_annot[0], self.curr_annot[1])

            region = sublime.Region(self.pt, self.end)
            if self.curr_annot != None and region.intersects(self.curr_annot):
                # Apply annotation within the text and format the text
                self.annotate_text(line, the_colour, the_bgcolour, the_style, empty)
            else:
                # Normal text formatting
                tidied_text = self.html_encode(self.view.substr(region))
                self.format_text(line, tidied_text, the_colour, the_bgcolour, the_style, empty)

            if hl_done:
                # Clear highlight flags and variables
                hl_done = False
                self.curr_hl = None

            # Continue walking through line
            self.pt = self.end
            self.end = self.pt + 1

        # Close annotation if open at end of line
        if self.open_annot:
            line.append(ANNOTATE_CLOSE % {"comment": self.curr_comment})
            self.open_annot = False

        # Get the color for the space at the end of a line
        if self.end < self.view.size():
            end_key = self.view.scope_name(self.pt)
            _, _, self.ebground, _, _, _ = self.csm.guess_color(self.view, self.pt, end_key)

        # Join line segments
        return "".join(line)

    def write_body(self, the_html):
        processed_rows = ""
        the_html.write(BODY_START)

        the_html.write(TABLE_START)
        if not self.no_header:
            # Write file name
            date_time = time.strftime(self.date_time_format, self.time)
            the_html.write(
                FILE_INFO
                % {
                    "bgcolor": self.bground,
                    "color": self.fground,
                    "date_time": date_time,
                    "file": self.file_name if self.show_full_path else path.basename(self.file_name),
                }
            )

        the_html.write(ROW_START)
        the_html.write(TABLE_START)
        # Convert view to HTML
        if self.multi_select:
            count = 0
            total = len(self.sels)
            for sel in self.sels:
                self.setup_print_block(sel, multi=True)
                processed_rows += "[" + str(self.curr_row) + ","
                self.convert_view_to_html(the_html)
                count += 1
                self.tables = count
                processed_rows += str(self.curr_row) + "],"

                if count < total:
                    the_html.write(TABLE_END)
                    the_html.write(ROW_END)
                    the_html.write(ROW_START)
                    the_html.write(DIVIDER % {"color": self.fground})
                    the_html.write(ROW_END)
                    the_html.write(ROW_START)
                    the_html.write(TABLE_START)
        else:
            self.setup_print_block(self.view.sel()[0])
            processed_rows += "[" + str(self.curr_row) + ","
            self.convert_view_to_html(the_html)
            processed_rows += str(self.curr_row) + "],"
            self.tables += 1

        the_html.write(TABLE_END)
        the_html.write(ROW_END)
        the_html.write(TABLE_END)

        js_options = []
        if len(self.annot_tbl):
            self.add_comments_table(the_html)
            js_options.append(HTML_JS_WRAP % {"jscode": getjs("annotation.js")})

        # Write javascript snippets
        js_options.append(HTML_JS_WRAP % {"jscode": getjs("print.js")})
        js_options.append(HTML_JS_WRAP % {"jscode": getjs("plaintext.js")})
        js_options.append(
            TOGGLE_LINE_OPTIONS
            % {
                "jscode": getjs("lines.js"),
                "wrap_size": self.wrap,
                "ranges": processed_rows.rstrip(","),
                "tables": self.tables,
                "header": ("false" if self.no_header else "true"),
                "gutter": ("true" if self.numbers else "false"),
            }
        )
        if self.auto_wrap:
            js_options.append(WRAP)

        if self.browser_print:
            js_options.append(AUTO_PRINT)

        # Write empty line to allow copying of last line and line number without issue
        the_html.write(
            BODY_END
            % {"js": "".join(js_options), "toolbar": self.get_tools(self.toolbar, len(self.annot_tbl), self.auto_wrap)}
        )

    def add_comments_table(self, the_html):
        the_html.write(ANNOTATION_TBL_START)
        the_html.write(
            "".join([ANNOTATION_ROW % {"table": t, "row": r, "link": l, "comment": c} for t, r, l, c in self.annot_tbl])
        )
        the_html.write(ANNOTATION_FOOTER)
        the_html.write(ANNOTATION_TBL_END)

    def run(self, **kwargs):
        inputs = self.process_inputs(**kwargs)
        self.setup(**inputs)

        save_location = inputs["save_location"]
        time_stamp = inputs["time_stamp"]

        if save_location is not None:
            fname = self.view.file_name()
            if (
                ((fname == None or not path.exists(fname)) and save_location == ".")
                or not path.exists(save_location)
                or not path.isdir(save_location)
            ):
                html_file = ".html"
                save_location = None
            elif save_location == ".":
                html_file = "%s%s.html" % (fname, time.strftime(time_stamp, self.time))
            elif fname is None or not path.exists(fname):
                html_file = path.join(save_location, "Untitled%s.html" % time.strftime(time_stamp, self.time))
            else:
                html_file = path.join(
                    save_location, "%s%s.html" % (path.basename(fname), time.strftime(time_stamp, self.time))
                )
        else:
            html_file = ".html"

        if save_location is not None:
            open_html = lambda x: open(x, "w")
        else:
            open_html = lambda x: tempfile.NamedTemporaryFile(delete=False, suffix=x)

        with open_html(html_file) as the_html:
            self.write_header(the_html)
            self.write_body(the_html)
            if inputs["clipboard_copy"]:
                the_html.seek(0)
                sublime.set_clipboard(the_html.read())
                sublime.status_message("Export to HTML: copied to clipboard")

        if inputs["view_open"]:
            self.view.window().open_file(the_html.name)
        else:
            # Open in web browser; check return code, if failed try webbrowser
            status = desktop.open(the_html.name, status=True)
            if not status:
                webbrowser.open(the_html.name, new=2)
Пример #4
0
    def setup(self, **kwargs):
        # Get get general document preferences from sublime preferences
        eh_settings = sublime.load_settings(PACKAGE_SETTINGS)
        settings = sublime.load_settings('Preferences.sublime-settings')
        alternate_font_size = eh_settings.get("alternate_font_size", False)
        alternate_font_face = eh_settings.get("alternate_font_face", False)
        self.font_size = settings.get('font_size', 10) if alternate_font_size == False else alternate_font_size
        self.font_face = settings.get('font_face', 'Consolas') if alternate_font_face == False else alternate_font_face
        self.tab_size = settings.get('tab_size', 4)
        self.padd_top = settings.get('line_padding_top', 0)
        self.padd_bottom = settings.get('line_padding_bottom', 0)
        self.char_limit = int(eh_settings.get("valid_selection_size", 4))
        self.bground = ''
        self.fground = ''
        self.gbground = ''
        self.gfground = ''
        self.sbground = ''
        self.sfground = ''
        self.numbers = kwargs["numbers"]
        self.date_time_format = kwargs["date_time_format"]
        self.time = time.localtime()
        self.show_full_path = kwargs["show_full_path"]
        self.highlight_selections = kwargs["highlight_selections"]
        self.browser_print = kwargs["browser_print"]
        self.auto_wrap = kwargs["wrap"] != None and int(kwargs["wrap"]) > 0
        self.wrap = 900 if not self.auto_wrap else int(kwargs["wrap"])
        self.hl_continue = None
        self.curr_hl = None
        self.sels = []
        self.multi_select = self.check_sel() if kwargs["multi_select"] and not kwargs["highlight_selections"] else False
        self.size = self.view.size()
        self.pt = 0
        self.end = 0
        self.curr_row = 0
        self.tables = 0
        self.curr_annot = None
        self.curr_comment = None
        self.annotations = self.get_annotations()
        self.annot_num = -1
        self.new_annot = False
        self.open_annot = False
        self.no_header = kwargs["no_header"]
        self.annot_tbl = []
        self.toolbar = kwargs["toolbar"]
        self.toolbar_orientation = "block" if eh_settings.get("toolbar_orientation", "horizontal") == "vertical" else "inline-block"
        self.matched = {}
        self.ebground = self.bground
        self.lumens_limit = float(eh_settings.get("bg_min_lumen_threshold", 62))

        self.highlights = []
        if self.highlight_selections:
            for sel in self.view.sel():
                if not sel.empty():
                    self.highlights.append(sel)

        fname = self.view.file_name()
        if fname == None or not path.exists(fname):
            fname = "Untitled"
        self.file_name = fname

        # Get color scheme
        if kwargs["color_scheme"] != None:
            alt_scheme = kwargs["color_scheme"]
        else:
            alt_scheme = eh_settings.get("alternate_scheme", False)
        scheme_file = settings.get('color_scheme') if alt_scheme == False else alt_scheme

        self.csm = ColorSchemeMatcher(
            scheme_file,
            strip_trans=True,
            ignore_gutter=(not kwargs["style_gutter"]),
            track_dark_background=True,
            filter=(lambda x: ColorSchemeTweaker().tweak(x, kwargs["filter"]))
        )
        if kwargs["shift_brightness"]:
            self.csm.shift_background_brightness(self.lumens_limit)
        (
            self.bground, self.fground, self.sbground,
            self.sfground, self.gbground, self.gfground
        ) = self.csm.get_general_colors()
Пример #5
0
class ExportHtml(object):
    def __init__(self, view):
        self.view = view

    def process_inputs(self, **kwargs):
        return {
            "numbers": bool(kwargs.get("numbers", False)),
            "highlight_selections": bool(kwargs.get("highlight_selections", False)),
            "browser_print": bool(kwargs.get("browser_print", False)),
            "color_scheme": kwargs.get("color_scheme", None),
            "wrap": kwargs.get("wrap", None),
            "multi_select": bool(kwargs.get("multi_select", False)),
            "style_gutter": bool(kwargs.get("style_gutter", True)),
            "no_header": bool(kwargs.get("no_header", False)),
            "date_time_format": kwargs.get("date_time_format", "%m/%d/%y %I:%M:%S"),
            "show_full_path": bool(kwargs.get("show_full_path", True)),
            "toolbar": kwargs.get("toolbar", ["plain_text", "gutter", "wrapping", "print", "annotation", "theme"]),
            "save_location": kwargs.get("save_location", None),
            "time_stamp": kwargs.get("time_stamp", "_%m%d%y%H%M%S"),
            "clipboard_copy": bool(kwargs.get("clipboard_copy", False)),
            "view_open": bool(kwargs.get("view_open", False)),
            "shift_brightness": bool(kwargs.get("shift_brightness", False)),
            "filter": kwargs.get("filter", "")
        }

    def setup(self, **kwargs):
        # Get get general document preferences from sublime preferences
        eh_settings = sublime.load_settings(PACKAGE_SETTINGS)
        settings = sublime.load_settings('Preferences.sublime-settings')
        alternate_font_size = eh_settings.get("alternate_font_size", False)
        alternate_font_face = eh_settings.get("alternate_font_face", False)
        self.font_size = settings.get('font_size', 10) if alternate_font_size == False else alternate_font_size
        self.font_face = settings.get('font_face', 'Consolas') if alternate_font_face == False else alternate_font_face
        self.tab_size = settings.get('tab_size', 4)
        self.padd_top = settings.get('line_padding_top', 0)
        self.padd_bottom = settings.get('line_padding_bottom', 0)
        self.char_limit = int(eh_settings.get("valid_selection_size", 4))
        self.bground = ''
        self.fground = ''
        self.gbground = ''
        self.gfground = ''
        self.sbground = ''
        self.sfground = ''
        self.numbers = kwargs["numbers"]
        self.date_time_format = kwargs["date_time_format"]
        self.time = time.localtime()
        self.show_full_path = kwargs["show_full_path"]
        self.highlight_selections = kwargs["highlight_selections"]
        self.browser_print = kwargs["browser_print"]
        self.auto_wrap = kwargs["wrap"] != None and int(kwargs["wrap"]) > 0
        self.wrap = 900 if not self.auto_wrap else int(kwargs["wrap"])
        self.hl_continue = None
        self.curr_hl = None
        self.sels = []
        self.multi_select = self.check_sel() if kwargs["multi_select"] and not kwargs["highlight_selections"] else False
        self.size = self.view.size()
        self.pt = 0
        self.end = 0
        self.curr_row = 0
        self.tables = 0
        self.curr_annot = None
        self.curr_comment = None
        self.annotations = self.get_annotations()
        self.annot_num = -1
        self.new_annot = False
        self.open_annot = False
        self.no_header = kwargs["no_header"]
        self.annot_tbl = []
        self.toolbar = kwargs["toolbar"]
        self.toolbar_orientation = "block" if eh_settings.get("toolbar_orientation", "horizontal") == "vertical" else "inline-block"
        self.matched = {}
        self.ebground = self.bground
        self.lumens_limit = float(eh_settings.get("bg_min_lumen_threshold", 62))

        self.highlights = []
        if self.highlight_selections:
            for sel in self.view.sel():
                if not sel.empty():
                    self.highlights.append(sel)

        fname = self.view.file_name()
        if fname == None or not path.exists(fname):
            fname = "Untitled"
        self.file_name = fname

        # Get color scheme
        if kwargs["color_scheme"] != None:
            alt_scheme = kwargs["color_scheme"]
        else:
            alt_scheme = eh_settings.get("alternate_scheme", False)
        scheme_file = settings.get('color_scheme') if alt_scheme == False else alt_scheme

        self.csm = ColorSchemeMatcher(
            scheme_file,
            strip_trans=True,
            ignore_gutter=(not kwargs["style_gutter"]),
            track_dark_background=True,
            filter=(lambda x: ColorSchemeTweaker().tweak(x, kwargs["filter"]))
        )
        if kwargs["shift_brightness"]:
            self.csm.shift_background_brightness(self.lumens_limit)
        (
            self.bground, self.fground, self.sbground,
            self.sfground, self.gbground, self.gfground
        ) = self.csm.get_general_colors()

    def get_tools(self, tools, use_annotation, use_wrapping):
        toolbar_options = {
            "gutter": TOOL_GUTTER,
            "print": TOOL_PRINT,
            "plain_text": TOOL_PLAIN_TEXT,
            "annotation": TOOL_ANNOTATION if use_annotation else "",
            "theme": TOOL_DUMP_THEME,
            "wrapping": TOOL_WRAPPING if use_wrapping else ""
        }
        t_opt = ""
        toolbar_element = ""

        if len(tools):
            for t in tools:
                if t in toolbar_options:
                    t_opt += toolbar_options[t]
            toolbar_element = TOOLBAR % {"options": t_opt}
        return toolbar_element

    def setup_print_block(self, curr_sel, multi=False):
        # Determine start and end points and whether to parse whole file or selection
        if not multi and (curr_sel.empty() or self.highlight_selections or curr_sel.size() <= self.char_limit):
            self.size = self.view.size()
            self.pt = 0
            self.end = 1
            self.curr_row = 1
        else:
            self.size = curr_sel.end()
            self.pt = curr_sel.begin()
            self.end = self.pt + 1
            self.curr_row = self.view.rowcol(self.pt)[0] + 1
        self.start_line = self.curr_row

        self.gutter_pad = len(str(self.view.rowcol(self.size)[0])) + 1

    def check_sel(self):
        multi = False
        for sel in self.view.sel():
            if not sel.empty() and sel.size() >= self.char_limit:
                multi = True
                self.sels.append(sel)
        return multi

    def print_line(self, line, num):
        html_line = LINE % {
            "line_id": num,
            "color": self.gfground,
            "bgcolor": self.gbground,
            "line": str(num).rjust(self.gutter_pad).replace(" ", '&nbsp;'),
            "code_id": num,
            "code": line,
            "table": self.tables,
            "pad_color": self.ebground or self.bground
        }

        return html_line

    def write_header(self, the_html):
        header = HTML_HEADER % {
            "title": path.basename(self.file_name),
            "css":   getcss(
                'export.css',
                {
                    "font_size":           str(self.font_size),
                    "font_face":           '"' + self.font_face + '"',
                    "page_bg":             self.bground,
                    "gutter_bg":           self.gbground,
                    "body_fg":             self.fground,
                    "display_mode":        'table-cell' if self.numbers else 'none',
                    "dot_color":           self.fground,
                    "toolbar_orientation": self.toolbar_orientation
                }
            ),
            "js": INCLUDE_THEME % {
                "jscode": getjs('plist.js'),
                "theme": json.dumps(self.csm.get_plist_file(), sort_keys=True, indent=4, separators=(',', ': ')).encode('raw_unicode_escape'),
                "name": self.csm.get_scheme_file(),
            }
        }
        the_html.write(header)

    def convert_view_to_html(self, the_html):
        for line in self.view.split_by_newlines(sublime.Region(self.pt, self.size)):
            self.size = line.end()
            empty = not bool(line.size())
            line = self.convert_line_to_html(the_html, empty)
            the_html.write(self.print_line(line, self.curr_row))
            self.curr_row += 1

    def html_encode(self, text):
        # Format text to HTML
        encode_table = {
            '&':  '&amp;',
            '>':  '&gt;',
            '<':  '&lt;',
            '\t': ' ' * self.tab_size,
            '\n': ''
        }

        return re.sub(
            r'(?!\s($|\S))\s',
            '&nbsp;',
            ''.join(
                encode_table.get(c, c) for c in text
            ).encode('ascii', 'xmlcharrefreplace')
        )

    def get_annotations(self):
        annotations = get_annotations(self.view)
        comments = []
        for x in range(0, int(annotations["count"])):
            region = annotations["annotations"]["html_annotation_%d" % x]["region"]
            comments.append((region, annotations["annotations"]["html_annotation_%d" % x]["comment"]))
        comments.sort()
        return comments

    def annotate_text(self, line, the_colour, the_bgcolour, the_style, empty):
        pre_text = None
        annot_text = None
        post_text = None
        start = None

        # Pretext Check
        if self.pt >= self.curr_annot.begin():
            # Region starts with an annotation
            start = self.pt
        else:
            # Region has text before annoation
            pre_text = self.html_encode(self.view.substr(sublime.Region(self.pt, self.curr_annot.begin())))
            start = self.curr_annot.begin()

        if self.end == self.curr_annot.end():
            # Region ends annotation
            annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.end)))
            self.curr_annot = None
        elif self.end > self.curr_annot.end():
            # Region has text following annotation
            annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.curr_annot.end())))
            post_text = self.html_encode(self.view.substr(sublime.Region(self.curr_annot.end(), self.end)))
            self.curr_annot = None
        else:
            # Region ends but annotation is not finished
            annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.end)))
            self.curr_annot = sublime.Region(self.end, self.curr_annot.end())

        # Print the separate parts pre text, annotation, post text
        if pre_text != None:
            self.format_text(line, pre_text, the_colour, the_bgcolour, the_style, empty)
        if annot_text != None:
            self.format_text(line, annot_text, the_colour, the_bgcolour, the_style, empty, annotate=True)
            if self.curr_annot == None:
                self.curr_comment = None
        if post_text != None:
            self.format_text(line, post_text, the_colour, the_bgcolour, the_style, empty)

    def add_annotation_table_entry(self):
        row, col = self.view.rowcol(self.annot_pt)
        self.annot_tbl.append(
            (
                self.tables, self.curr_row, "Line %d Col %d" % (row + 1, col + 1),
                self.curr_comment.encode('ascii', 'xmlcharrefreplace')
            )
        )
        self.annot_pt = None

    def format_text(self, line, text, the_colour, the_bgcolour, the_style, empty, annotate=False):
        if empty:
            text = '&nbsp;'
        else:
            the_style += " real_text"

        if the_bgcolour is None:
            the_bgcolour = self.bground

        if annotate:
            code = ANNOTATION_CODE % {"highlight": the_bgcolour, "color": the_colour, "content": text, "class": the_style}
        else:
            code = CODE % {"highlight": the_bgcolour, "color": the_colour, "content": text, "class": the_style}

        if annotate:
            if self.curr_annot != None and not self.open_annot:
                # Open an annotation
                if self.annot_pt != None:
                    self.add_annotation_table_entry()
                if self.new_annot:
                    self.annot_num += 1
                    self.new_annot = False
                code = ANNOTATE_OPEN % {"code": code, "comment": str(self.annot_num)}
                self.open_annot = True
            elif self.curr_annot == None:
                if self.open_annot:
                    # Close an annotation
                    code += ANNOTATE_CLOSE
                    self.open_annot = False
                else:
                    # Do a complete annotation
                    if self.annot_pt != None:
                        self.add_annotation_table_entry()
                    if self.new_annot:
                        self.annot_num += 1
                        self.new_annot = False
                    code = (
                        ANNOTATE_OPEN % {"code": code, "comment": str(self.annot_num)} +
                        ANNOTATE_CLOSE
                    )
        line.append(code)

    def convert_line_to_html(self, the_html, empty):
        line = []
        hl_done = False

        # Continue highlight form last line
        if self.hl_continue != None:
            self.curr_hl = self.hl_continue
            self.hl_continue = None

        while self.end <= self.size:
            # Get next highlight region
            if self.highlight_selections and self.curr_hl == None and len(self.highlights) > 0:
                self.curr_hl = self.highlights.pop(0)

            # See if we are starting a highlight region
            if self.curr_hl != None and self.pt == self.curr_hl.begin():
                # Get text of like scope up to a highlight
                scope_name = self.view.scope_name(self.pt)
                while self.view.scope_name(self.end) == scope_name and self.end < self.size:
                    # Kick out if we hit a highlight region
                    if self.end == self.curr_hl.end():
                        break
                    self.end += 1
                if self.end < self.curr_hl.end():
                    if self.end >= self.size:
                        self.hl_continue = sublime.Region(self.end, self.curr_hl.end())
                    else:
                        self.curr_hl = sublime.Region(self.end, self.curr_hl.end())
                else:
                    hl_done = True
                if hl_done and empty:
                    the_colour, the_style, the_bgcolour, _, _, _ = self.csm.guess_color(self.view, self.pt, scope_name)
                elif self.sfground is None:
                    the_colour, the_style, _, _, _, _ = self.csm.guess_color(self.view, self.pt, scope_name)
                    the_bgcolour = self.sbground
                else:
                    the_colour, the_style = self.sfground, "normal"
                    the_bgcolour = self.sbground
            else:
                # Get text of like scope up to a highlight
                scope_name = self.view.scope_name(self.pt)
                while self.view.scope_name(self.end) == scope_name and self.end < self.size:
                    # Kick out if we hit a highlight region
                    if self.curr_hl != None and self.end == self.curr_hl.begin():
                        break
                    self.end += 1
                the_colour, the_style, the_bgcolour, _, _, _ = self.csm.guess_color(self.view, self.pt, scope_name)

            # Get new annotation
            if (self.curr_annot == None or self.curr_annot.end() < self.pt) and len(self.annotations):
                self.curr_annot, self.curr_comment = self.annotations.pop(0)
                self.annot_pt = self.curr_annot[0]
                while self.pt > self.curr_annot[1]:
                    if len(self.annotations):
                        self.curr_annot, self.curr_comment = self.annotations.pop(0)
                        self.annot_pt = self.curr_annot[0]
                    else:
                        self.curr_annot = None
                        self.curr_comment = None
                        break
                self.new_annot = True
                self.curr_annot = sublime.Region(self.curr_annot[0], self.curr_annot[1])

            region = sublime.Region(self.pt, self.end)
            if self.curr_annot != None and region.intersects(self.curr_annot):
                # Apply annotation within the text and format the text
                self.annotate_text(line, the_colour, the_bgcolour, the_style, empty)
            else:
                # Normal text formatting
                tidied_text = self.html_encode(self.view.substr(region))
                self.format_text(line, tidied_text, the_colour, the_bgcolour, the_style, empty)

            if hl_done:
                # Clear highlight flags and variables
                hl_done = False
                self.curr_hl = None

            # Continue walking through line
            self.pt = self.end
            self.end = self.pt + 1

        # Close annotation if open at end of line
        if self.open_annot:
            line.append(ANNOTATE_CLOSE % {"comment": self.curr_comment})
            self.open_annot = False

        # Get the color for the space at the end of a line
        if self.end < self.view.size():
            end_key = self.view.scope_name(self.pt)
            _, _, self.ebground, _, _, _ = self.csm.guess_color(self.view, self.pt, end_key)

        # Join line segments
        return ''.join(line)

    def write_body(self, the_html):
        processed_rows = ""
        the_html.write(BODY_START)

        the_html.write(TABLE_START)
        if not self.no_header:
            # Write file name
            date_time = time.strftime(self.date_time_format, self.time)
            the_html.write(
                FILE_INFO % {
                    "bgcolor": self.bground,
                    "color": self.fground,
                    "date_time": date_time,
                    "file": self.file_name if self.show_full_path else path.basename(self.file_name)
                }
            )

        the_html.write(ROW_START)
        the_html.write(TABLE_START)
        # Convert view to HTML
        if self.multi_select:
            count = 0
            total = len(self.sels)
            for sel in self.sels:
                self.setup_print_block(sel, multi=True)
                processed_rows += "[" + str(self.curr_row) + ","
                self.convert_view_to_html(the_html)
                count += 1
                self.tables = count
                processed_rows += str(self.curr_row) + "],"

                if count < total:
                    the_html.write(TABLE_END)
                    the_html.write(ROW_END)
                    the_html.write(ROW_START)
                    the_html.write(DIVIDER % {"color": self.fground})
                    the_html.write(ROW_END)
                    the_html.write(ROW_START)
                    the_html.write(TABLE_START)
        else:
            self.setup_print_block(self.view.sel()[0])
            processed_rows += "[" + str(self.curr_row) + ","
            self.convert_view_to_html(the_html)
            processed_rows += str(self.curr_row) + "],"
            self.tables += 1

        the_html.write(TABLE_END)
        the_html.write(ROW_END)
        the_html.write(TABLE_END)

        js_options = []
        if len(self.annot_tbl):
            self.add_comments_table(the_html)
            js_options.append(HTML_JS_WRAP % {"jscode": getjs('annotation.js')})

        # Write javascript snippets
        js_options.append(HTML_JS_WRAP % {"jscode": getjs('print.js')})
        js_options.append(HTML_JS_WRAP % {"jscode": getjs('plaintext.js')})
        js_options.append(TOGGLE_LINE_OPTIONS % {
                "jscode":    getjs('lines.js'),
                "wrap_size": self.wrap,
                "ranges":    processed_rows.rstrip(','),
                "tables":    self.tables,
                "header":    ("false" if self.no_header else "true"),
                "gutter":    ('true' if self.numbers else 'false')
            }
        )
        if self.auto_wrap:
            js_options.append(WRAP)

        if self.browser_print:
            js_options.append(AUTO_PRINT)

        # Write empty line to allow copying of last line and line number without issue
        the_html.write(BODY_END % {"js": ''.join(js_options), "toolbar": self.get_tools(self.toolbar, len(self.annot_tbl), self.auto_wrap)})

    def add_comments_table(self, the_html):
        the_html.write(ANNOTATION_TBL_START)
        the_html.write(''.join([ANNOTATION_ROW % {"table": t, "row": r, "link": l, "comment": c} for t, r, l, c in self.annot_tbl]))
        the_html.write(ANNOTATION_FOOTER)
        the_html.write(ANNOTATION_TBL_END)

    def run(self, **kwargs):
        inputs = self.process_inputs(**kwargs)
        self.setup(**inputs)

        save_location = inputs["save_location"]
        time_stamp = inputs["time_stamp"]

        if save_location is not None:
            fname = self.view.file_name()
            if (
                ((fname == None or not path.exists(fname)) and save_location == ".") or
                not path.exists(save_location)
                or not path.isdir(save_location)
            ):
                html_file = ".html"
                save_location = None
            elif save_location == ".":
                html_file = "%s%s.html" % (fname, time.strftime(time_stamp, self.time))
            elif fname is None or not path.exists(fname):
                html_file = path.join(save_location, "Untitled%s.html" % time.strftime(time_stamp, self.time))
            else:
                html_file = path.join(save_location, "%s%s.html" % (path.basename(fname), time.strftime(time_stamp, self.time)))
        else:
            html_file = ".html"

        if save_location is not None:
            open_html = lambda x: open(x, "w")
        else:
            open_html = lambda x: tempfile.NamedTemporaryFile(delete=False, suffix=x)

        with open_html(html_file) as the_html:
            self.write_header(the_html)
            self.write_body(the_html)
            if inputs["clipboard_copy"]:
                the_html.seek(0)
                sublime.set_clipboard(the_html.read())
                sublime.status_message("Export to HTML: copied to clipboard")

        if inputs["view_open"]:
            self.view.window().open_file(the_html.name)
        else:
            # Open in web browser; check return code, if failed try webbrowser
            status = desktop.open(the_html.name, status=True)
            if not status:
                webbrowser.open(the_html.name, new=2)
Пример #6
0
class ExportBbcode(object):
    def __init__(self, view):
        self.view = view

    def process_inputs(self, **kwargs):
        return {
            "numbers": bool(kwargs.get("numbers", False)),
            "color_scheme": kwargs.get("color_scheme", None),
            "multi_select": bool(kwargs.get("multi_select", False)),
            "clipboard_copy": bool(kwargs.get("clipboard_copy", True)),
            "view_open": bool(kwargs.get("view_open", False)),
            "filter": kwargs.get("filter", "")
        }

    def setup(self, **kwargs):
        path_packages = sublime.packages_path()

        # Get get general document preferences from sublime preferences
        settings = sublime.load_settings('Preferences.sublime-settings')
        eh_settings = sublime.load_settings(PACKAGE_SETTINGS)
        self.tab_size = settings.get('tab_size', 4)
        self.char_limit = int(eh_settings.get("valid_selection_size", 4))
        self.bground = ''
        self.fground = ''
        self.gbground = ''
        self.gfground = ''
        self.sbground = ''
        self.sfground = ''
        self.numbers = kwargs["numbers"]
        self.hl_continue = None
        self.curr_hl = None
        self.sels = []
        self.multi_select = self.check_sel() if kwargs["multi_select"] else False
        self.size = self.view.size()
        self.pt = 0
        self.end = 0
        self.curr_row = 0
        self.empty_space = None

        # Get color scheme
        if kwargs["color_scheme"] != None:
            alt_scheme = kwargs["color_scheme"]
        else:
            alt_scheme = eh_settings.get("alternate_scheme", False)
        scheme_file = settings.get('color_scheme') if alt_scheme == False else alt_scheme

        self.csm = ColorSchemeMatcher(
            scheme_file,
            strip_trans=True,
            ignore_gutter=True,
            filter=(lambda x: ColorSchemeTweaker().tweak(x, kwargs["filter"]))
        )
        (
            self.bground, self.fground, self.sbground,
            self.sfground, self.gbground, self.gfground
        ) = self.csm.get_general_colors()

    def setup_print_block(self, curr_sel, multi=False):
        # Determine start and end points and whether to parse whole file or selection
        if not multi and (curr_sel.empty() or curr_sel.size() <= self.char_limit):
            self.size = self.view.size()
            self.pt = 0
            self.end = 1
            self.curr_row = 1
        else:
            self.size = curr_sel.end()
            self.pt = curr_sel.begin()
            self.end = self.pt + 1
            self.curr_row = self.view.rowcol(self.pt)[0] + 1
        self.start_line = self.curr_row

        self.gutter_pad = len(str(self.view.rowcol(self.size)[0])) + 1

    def check_sel(self):
        multi = False
        for sel in self.view.sel():
            if not sel.empty() and sel.size() >= self.char_limit:
                multi = True
                self.sels.append(sel)
        return multi

    def print_line(self, line, num):
        if self.numbers:
            bbcode_line = NUMBERED_BBCODE_LINE % {
                "color": self.gfground,
                "line": str(num).rjust(self.gutter_pad),
                "code": line
            }
        else:
            bbcode_line = BBCODE_LINE % {"code": line}

        return bbcode_line

    def convert_view_to_bbcode(self, the_bbcode):
        for line in self.view.split_by_newlines(sublime.Region(self.end, self.size)):
            self.empty_space = None
            self.size = line.end()
            line = self.convert_line_to_bbcode()
            the_bbcode.write(self.print_line(line, self.curr_row))
            self.curr_row += 1

    def repl(self, m, the_colour):
        return m.group(1) + (
            BBCODE_ESCAPE % {
                "color_open": the_colour,
                "color_close": the_colour,
                "content": m.group(2)
            }
        ) + m.group(3)

    def format_text(self, line, text, the_colour, the_style):
        text = text.replace('\t', ' ' * self.tab_size).replace('\n', '')
        if self.empty_space != None:
            text = self.empty_space + text
            self.empty_space = None
        if text.strip(' ') == '':
            self.empty_space = text
        else:
            code = ""
            text = BBCODE_MATCH.sub(lambda m: self.repl(m, the_colour), text)
            bold = False
            italic = False
            for s in the_style:
                if s == "bold":
                    bold = True
                if s == "italic":
                    italic = True
            code += (BBCODE_CODE % {"color": the_colour, "content": text})
            if italic:
                code = (BBCODE_ITALIC % {"color": the_colour, "content": code})
            if bold:
                code = (BBCODE_BOLD % {"color": the_colour, "content": code})
            line.append(code)

    def convert_line_to_bbcode(self):
        line = []

        while self.end <= self.size:
            # Get text of like scope up to a highlight
            scope_name = self.view.scope_name(self.pt)
            while self.view.scope_name(self.end) == scope_name and self.end < self.size:
                self.end += 1
            the_colour, the_style, _, _, _, _ = self.csm.guess_color(self.view, self.pt, scope_name)

            region = sublime.Region(self.pt, self.end)
            # Normal text formatting
            text = self.view.substr(region)
            self.format_text(line, text, the_colour, the_style)

            # Continue walking through line
            self.pt = self.end
            self.end = self.pt + 1

        # Join line segments
        return ''.join(line)

    def write_body(self, the_bbcode):
        the_bbcode.write(POST_START % {"bg_color": self.bground})

        # Convert view to HTML
        if self.multi_select:
            count = 0
            total = len(self.sels)
            for sel in self.sels:
                self.setup_print_block(sel, multi=True)
                self.convert_view_to_bbcode(the_bbcode)
                count += 1

                if count < total:
                    the_bbcode.write("\n" + (BBCODE_CODE % {"color": self.fground, "content": "..."}) + "\n\n")

        else:
            self.setup_print_block(self.view.sel()[0])
            self.convert_view_to_bbcode(the_bbcode)

        the_bbcode.write(POST_END)

    def run(self, **kwargs):
        inputs = self.process_inputs(**kwargs)
        self.setup(**inputs)

        delete = False if inputs["view_open"] else True

        with tempfile.NamedTemporaryFile(delete=delete, suffix='.txt') as the_bbcode:
            self.write_body(the_bbcode)
            if inputs["clipboard_copy"]:
                the_bbcode.seek(0)
                sublime.set_clipboard(the_bbcode.read())
                sublime.status_message("Export to BBCode: copied to clipboard")

        if inputs["view_open"]:
            self.view.window().open_file(the_bbcode.name)