Ejemplo n.º 1
0
    def __init__(self, plgmgr):
        """Initializes the LaTeX object
        @param plgmgr: pluginmanger for this object

        """
        plugin.Plugin.__init__(self, plgmgr)
        self._stc = None
        self._id = ed_glob.ID_TEX_GEN
        self._dstyle = StyleItem()
        self._cmds = dict()
Ejemplo n.º 2
0
def DuplicateStyleDict(style_dict):
    """Duplicates the style dictionary to make a true copy of
    it, as simply assigning the dictionary to two different variables
    only copies a reference leaving both variables pointing to the
    same object.
    @param style_dict: dictionary of tags->StyleItems
    @return: a copy of the given styleitem dictionary

    """
    new_dict = dict()
    for tag in style_dict:
        new_dict[tag] = StyleItem()
        is_ok = new_dict[tag].SetAttrFromStr(unicode(style_dict[tag]))
        if not is_ok:
            new_dict[tag].null = True
    return new_dict
Ejemplo n.º 3
0
    def GenerateStyleSheet(self):
        """Generates a style sheet from the dialogs style data
        @return: The dictionary of L{StyleItem} in self.styles_new transformed
                 into a string that is in Editra Style Sheet format.

        """
        sty_sheet = list()
        ditem = self.styles_new.get('default_style', StyleItem())
        dvals = ';\n\t\t'.join(
            [item.replace(',', ' ') for item in ditem.GetAsList()]) + ';'
        sty_sheet.append(''.join(['default_style {\n\t\t', dvals,
                                  '\n\n}\n\n']))
        for tag, item in self.styles_new.iteritems():
            if item.IsNull() or tag == 'default_style':
                continue

            stage1 = wx.EmptyString
            for attr in ('fore', 'back', 'face', 'size'):
                ival = item.GetNamedAttr(attr)
                if ival is None or ival == ditem.GetNamedAttr(attr):
                    continue

                stage1 = ''.join((stage1, attr, u':', ival.replace(',',
                                                                   ' '), u';'))

            if len(stage1):
                sty_sheet.append(tag + u" {\n")
                stage2 = u"\t\t" + stage1[0:-1].replace(u";",
                                                        u";\n\t\t") + u";"
                sty_sheet.append(stage2)
                sty_sheet.append(u"\n}\n\n")

        return u"".join(sty_sheet)
Ejemplo n.º 4
0
def DuplicateStyleDict(style_dict):
    """Duplicates the style dictionary to make a true copy of
    it, as simply assigning the dictionary to two different variables
    only copies a reference leaving both variables pointing to the
    same object.
    @param style_dict: dictionary of tags->StyleItems
    @return: a copy of the given styleitem dictionary

    """
    new_dict = dict()
    for tag in style_dict:
        new_dict[tag] = StyleItem()
        is_ok = new_dict[tag].SetAttrFromStr(unicode(style_dict[tag]))
        if not is_ok:
            new_dict[tag].null = True
    return new_dict
Ejemplo n.º 5
0
    def GenerateStyleSheet(self):
        """Generates a style sheet from the dialogs style data
        @return: The dictionary of L{StyleItem} in self.styles_new transformed
                 into a string that is in Editra Style Sheet format.

        """
        sty_sheet = list()
        ditem = self.styles_new.get('default_style', StyleItem())
        dvals = ';\n\t\t'.join(
            [item.replace(',', ' ') for item in ditem.GetAsList()]) + ';'
        sty_sheet.append(''.join(['default_style {\n\t\t', dvals,
                                  '\n\n}\n\n']))

        tags = sorted(self.styles_new.keys())
        for tag in tags:
            item = self.styles_new[tag]
            if item.IsNull() or tag == 'default_style':
                continue

            stage1 = wx.EmptyString
            for attr in ('fore', 'back', 'face', 'size'):
                ival = item.GetNamedAttr(attr)
                if attr in ('fore', 'back'):
                    ival = ival.upper()

                if ival is None or ival == ditem.GetNamedAttr(attr):
                    continue

                stage1 = ''.join((stage1, attr, u':', ival.replace(',',
                                                                   ' '), u';'))

            # Add any modifiers to the modifier tag
            modifiers = item.GetModifiers()
            if len(modifiers):
                stage1 += (u"modifiers:" + modifiers + u";").replace(',', ' ')

            # If the StyleItem had any set attributes add it to the stylesheet
            if len(stage1):
                sty_sheet.append(tag + u" {\n")
                stage2 = u"\t\t" + stage1[0:-1].replace(u";",
                                                        u";\n\t\t") + u";"
                sty_sheet.append(stage2)
                sty_sheet.append(u"\n}\n\n")

        return u"".join(sty_sheet)
Ejemplo n.º 6
0
class LaTeX(plugin.Plugin):
    """Creates a LaTeX document object from the contents of the
    supplied document reference.
    @todo: performance improvements and wordwrap in generated document

    """
    plugin.Implements(GeneratorI)

    def __init__(self, plgmgr):
        """Initializes the LaTeX object
        @param plgmgr: pluginmanger for this object

        """
        plugin.Plugin.__init__(self)

        # Attributes
        self._stc = None
        self._id = ed_glob.ID_TEX_GEN
        self._dstyle = StyleItem()
        self._cmds = dict()

    def CreateCmdName(self, name):
        """Creates and returns a proper cmd name
        @param name: name to construct command from
        @return: latex formated command string

        """
        name = name.replace('_', '')
        tmp = list()
        alpha = "ABCDEFGHIJ"
        for char in name:
            if char.isdigit():
                tmp.append(alpha[int(char)])
            else:
                tmp.append(char)
        return "".join(tmp)

    def GenDoc(self):
        """Generates the document body of the LaTeX document
        @returns: the main body of the reference document marked up with latex

        """
        tex = list()
        tmp = u''
        start = parse_pos = 0
        last_pos = self._stc.GetLineEndPosition(self._stc.GetLineCount())

        # Define the default style
        self.RegisterStyleCmd('default_style', \
                              self._stc.GetItemByName('default_style'))

        # Get Document start point info
        last_id = self._stc.GetStyleAt(parse_pos)
        tmp = self.TransformText(
            self._stc.GetTextRange(parse_pos, parse_pos + 1))
        tag = self._stc.FindTagById(last_id)
        if tag != wx.EmptyString:
            self.RegisterStyleCmd(tag, self._stc.GetItemByName(tag))

        # Optimizations
        stc = self._stc
        GetStyleAt = stc.GetStyleAt
        GetTextRange = stc.GetTextRange
        TransformText = self.TransformText

        # Build LaTeX
        for parse_pos in xrange(last_pos + 1):
            curr_id = GetStyleAt(parse_pos)
            if parse_pos > 1:
                # This is the performance bottleneck, changeing the text
                # collection to when the style changes is much faster as
                # it only needs to be done once per style section instead
                # of once per character. Doing that however causes problems
                # with the style and resulting document formatting.
                tmp = TransformText(GetTextRange((parse_pos - 1), parse_pos))

            if curr_id == 0 and GetStyleAt(parse_pos + 1) == last_id:
                curr_id = last_id

            # If style region has changed close section
            if curr_id != last_id or tmp[-1] == "\n":
                tmp_tex = TransformText(GetTextRange(start, parse_pos))
                #                 tmp_tex = u"".join(tmp)
                if tag == "operator_style" or \
                   (tag == "default_style" and \
                    tmp_tex.isspace() and len(tmp_tex) <= 2):
                    tex.append(tmp_tex)
                else:
                    if "\\\\\n" in tmp_tex:
                        tmp_tex = tmp_tex.replace("\\\\\n", "")
                        tmp2 = "\\%s{%s}\\\\\n"
                    else:
                        tmp2 = "\\%s{%s}"

                    cmd = self.CreateCmdName(tag)
                    if cmd in [None, wx.EmptyString]:
                        cmd = "defaultstyle"
                    tex.append(tmp2 % (cmd, tmp_tex))

                last_id = curr_id
                tag = stc.FindTagById(last_id)
                if tag not in [None, wx.EmptyString]:
                    self.RegisterStyleCmd(tag, stc.GetItemByName(tag))
                tmp = list()
                start = parse_pos

        # Case for unstyled documents
        if tex == wx.EmptyString:
            tex.append(self.TransformText(stc.GetText()))
        return "\\begin{document}\n%s\n\\end{document}" % "".join(tex)

    def Generate(self, stc_doc):
        """Generates the LaTeX document
        @param stc_doc: text control to generate latex from
        @return: the reference document marked up in LaTeX.

        """
        self._stc = stc_doc
        default_si = self._stc.GetItemByName('default_style')
        self._dstyle.SetBack(default_si.GetBack().split(',')[0])
        self._dstyle.SetFore(default_si.GetFore().split(',')[0])
        self._dstyle.SetFace(default_si.GetFace().split(',')[0])
        self._dstyle.SetSize(default_si.GetSize().split(',')[0])
        body = self.GenDoc()
        preamble = self.GenPreamble()
        return ("tex", u"".join([preamble, body]))

    def GenPreamble(self):
        """Generates the Preamble of the document
        @return: the LaTeX document preamble

        """
        # Preamble template
        pre = (
            "%% \iffalse meta-comment\n"
            "%%\n%% Generated by Editra %s\n"
            "%% This is generator is Very Experimental.\n"
            "%% The code should compile in most cases but there may\n"
            "%% be some display issues when rendered.\n"
            "%%\n%%\n\n"
            "\\documentclass[11pt, a4paper]{article}\n"
            "\\usepackage[a4paper, margin=2cm]{geometry}\n"
            "\\usepackage[T1]{fontenc}\n"
            #               "\\usepackage{ucs}\n"
            #               "\\usepackage[utf8]{inputenc}\n"
            "\\usepackage{color}\n"
            "\\usepackage{alltt}\n"
            "\\usepackage{times}\n") % ed_glob.VERSION

        # Set the background color
        pre += ("\\pagecolor[rgb]{%s}\n" % \
                self.HexToRGB(self._dstyle.GetBack()))
        pre += "\\parindent=0in\n\n"

        # Insert all styling commands
        pre += "%% Begin Styling Command Definitions"
        for cmd in self._cmds:
            pre += ("\n" + self._cmds[cmd])
        pre += "\n%% End Styling Command Definitions\n\n"
        return pre

    def GetId(self):
        """Returns the menu identifier for the LaTeX generator
        @return: id of that identifies this generator

        """
        return self._id

    def GetMenuEntry(self, menu):
        """Returns the Menu control for the LaTeX generator
        @param menu: menu to create MenuItem for

        """
        return wx.MenuItem(menu, self._id, _("Generate %s") % u"LaTeX",
                           _("Generate an %s version of the " \
                             "current document") % u"LaTeX")

    def HexToRGB(self, hex_str):
        """Returns a comma separated rgb string representation
        of the input hex string. 1.0 = White, 0.0 = Black.
        @param hex_str: hex string to convert to latex rgb format

        """
        r_hex = hex_str
        if r_hex[0] == u"#":
            r_hex = r_hex[1:]
        ldiff = 6 - len(r_hex)
        r_hex += ldiff * u"0"
        # Convert hex values to integer
        red = round(float(float(int(r_hex[0:2], 16)) / 255), 2)
        green = round(float(float(int(r_hex[2:4], 16)) / 255), 2)
        blue = round(float(float(int(r_hex[4:], 16)) / 255), 2)
        return "%s,%s,%s" % (str(red), str(green), str(blue))

    def RegisterStyleCmd(self, cmd_name, s_item):
        """Registers and generates a command from the
        supplied StyleItem.
        @param cmd_name: name of command
        @param s_item: style item to create command for
        @postcondition: new styling command is created and registered for use

        """
        cmd_name = self.CreateCmdName(cmd_name)

        # If we already made a command for this style return
        if cmd_name in self._cmds:
            return

        # Templates
        uline_tmp = u"\\underline{%s}"
        ital_tmp = u"\\emph{%s}"
        bold_tmp = u"\\textbf{%s}"
        fore_tmp = u"\\textcolor[rgb]{%s}{%s}"
        back_tmp = u"\\colorbox[rgb]{%s}{#1}"
        cmd_tmp = u"\\newcommand{%s}[1]{%s}"

        # Get Style Attributes
        fore = s_item.GetFore()
        if fore == wx.EmptyString:
            fore = self._dstyle.GetFore()
        back = s_item.GetBack()
        if back == wx.EmptyString:
            back = self._dstyle.GetBack()
        face = s_item.GetFace()
        if face == wx.EmptyString:
            face = self._dstyle.GetFace()
        size = s_item.GetSize()
        if size == wx.EmptyString:
            size = self._dstyle.GetSize()

        back = back_tmp % self.HexToRGB(back.split(u',')[0])
        fore = fore_tmp % (self.HexToRGB(fore.split(u',')[0]), back)
        if u"bold" in unicode(s_item):
            fore = bold_tmp % fore
        if u"underline" in unicode(s_item):
            fore = uline_tmp % fore
        if u"italic" in unicode(s_item):
            fore = ital_tmp % fore
        cmd = cmd_tmp % (
            (u"\\" + cmd_name), u"\\texttt{\\ttfamily{%s}}" % fore)
        self._cmds[cmd_name] = cmd

    def TransformText(self, txt):
        """Transforms the given text into LaTeX format, by
        escaping all special characters and sequences.
        @param txt: text to transform
        @return: txt with all special characters transformed

        """
        ch_map = {
            "#": "\\#",
            "$": "\\$",
            "^": "\\^",
            "%": "\\%",
            "&": "\\&",
            "_": "\\_",
            "{": "\\{",
            "}": "\\}",
            "~": "\\~",
            "\\": "$\\backslash$",
            "\n": "\\\\\n",
            "@": "$@$",
            "<": "$<$",
            ">": "$>$",
            "-": "$-$",
            "|": "$|$"
        }
        tmp = list()
        for char in txt:
            tmp.append(ch_map.get(char, char))
        return u''.join(tmp)
Ejemplo n.º 7
0
    def GenerateBody(self):
        """Generates the body of the html from the stc's content. To do
        this it does a character by character parse of the stc to determine
        style regions and generate css and and styled spans of html in order
        to generate an 'exact' html reqresentation of the stc's window.
        @return: the body section of the html generated from the text control

        """
        html = list()
        parse_pos = 0
        style_start = 0
        style_end = 0
        last_pos = self.stc.GetLineEndPosition(self.stc.GetLineCount()) + 1

        # Get Document start point info
        last_id = self.stc.GetStyleAt(parse_pos)
        tag = self.stc.FindTagById(last_id)
        if tag != wx.EmptyString:
            s_item = StyleItem()
            s_item.SetAttrFromStr(self.stc.GetStyleByName(tag))
            self.css[tag] = CssItem(tag.split('_')[0], s_item)

        # Optimizations
        stc = self.stc
        GetStyleAt = stc.GetStyleAt

        # Build Html
        while parse_pos < last_pos:
            parse_pos += 1
            curr_id = GetStyleAt(parse_pos)
            style_end = parse_pos
            # If style region has changed close section
            if curr_id == 0 and GetStyleAt(parse_pos + 1) == last_id:
                curr_id = last_id

            if curr_id != last_id or parse_pos == last_pos:
                tmp = stc.GetTextRange(style_start, style_end)
                tmp = self.TransformText(tmp)
                if tmp.isspace() or tag in ["default_style", "operator_style"]:
                    html.append(tmp)
                else:
                    tmp2 = "<span class=\"%s\">%s</span>"
                    html.append(tmp2 % (tag.split('_')[0], tmp))

                last_id = curr_id
                style_start = style_end
                tag = stc.FindTagById(last_id)
                if tag not in self.css:
                    s_item = StyleItem()
                    s_item.SetAttrFromStr(stc.GetStyleByName(tag))
                    self.css[tag] = CssItem(tag.split('_')[0], s_item)

        # Case for unstyled documents
        if len(html) == 0:
            s_item = StyleItem()
            s_item.SetAttrFromStr(stc.GetStyleByName('default_style'))
            self.css['default_style'] = CssItem('default', s_item)
            html.append(self.TransformText(stc.GetText()))
        else:
            self.OptimizeCss()

        return "<body class=\"default\">\n<pre>\n%s\n</pre>\n</body>" % \
                                                                   "".join(html)