QScintilla/Exporters/ExporterTEX.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2007 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing an exporter for TeX.
8 """
9
10 # This code is a port of the C++ code found in SciTE 1.74
11 # Original code: Copyright 1998-2006 by Neil Hodgson <neilh@scintilla.org>
12
13 import os
14
15 from PyQt4.QtCore import *
16 from PyQt4.QtGui import *
17 from PyQt4.Qsci import QsciScintilla
18
19 from ExporterBase import ExporterBase
20
21 import Preferences
22
23 class ExporterTEX(ExporterBase):
24 """
25 Class implementing an exporter for TeX.
26 """
27 CHARZ = ord('z') - ord('a') + 1
28
29 def __init__(self, editor, parent = None):
30 """
31 Constructor
32
33 @param editor reference to the editor object (QScintilla.Editor.Editor)
34 @param parent parent object of the exporter (QObject)
35 """
36 ExporterBase.__init__(self, editor, parent)
37
38 def __getTexRGB(self, color):
39 """
40 Private method to convert a color object to a TeX color string
41
42 @param color color object to convert (QColor)
43 @return TeX color string (string)
44 """
45 # texcolor[rgb]{0,0.5,0}{....}
46 rf = color.red() / 256.0
47 gf = color.green() / 256.0
48 bf = color.blue() / 256.0
49
50 # avoid breakage due to locale setting
51 r = int(rf * 10 + 0.5)
52 g = int(gf * 10 + 0.5)
53 b = int(bf * 10 + 0.5)
54
55 return "%d.%d, %d.%d, %d.%d" % (r / 10, r % 10, g / 10, g % 10, b / 10, b % 10)
56
57 def __texStyle(self, style):
58 """
59 Private method to calculate a style name string for a given style number.
60
61 @param style style number (integer)
62 @return style name string (string)
63 """
64 buf = ""
65 if style == 0:
66 buf = "a"
67 else:
68 while style > 0:
69 buf += chr(ord('a') + (style % self.CHARZ))
70 style /= self.CHARZ
71 return buf
72
73 def __defineTexStyle(self, font, color, paper, file, istyle):
74 """
75 Private method to define a new TeX style.
76
77 @param font the font to be used (QFont)
78 @param color the foreground color to be used (QColor)
79 @param paper the background color to be used (QColor)
80 @param file reference to the open file to write to (file object)
81 @param istyle style number (integer)
82 """
83 closing_brackets = 3
84 file.write("\\newcommand{\\eric%s}[1]{\\noindent{\\ttfamily{" % \
85 self.__texStyle(istyle))
86 if font.italic():
87 file.write("\\textit{")
88 closing_brackets += 1
89 if font.bold():
90 file.write("\\textbf{")
91 closing_brackets += 1
92 if color != self.defaultColor:
93 file.write("\\textcolor[rgb]{%s}{" % self.__getTexRGB(color))
94 closing_brackets += 1
95 if paper != self.defaultPaper:
96 file.write("\\colorbox[rgb]{%s}{" % self.__getTexRGB(paper))
97 closing_brackets += 1
98 file.write("#1%s\n" % ('}' * closing_brackets))
99
100 def exportSource(self):
101 """
102 Public method performing the export.
103 """
104 filename = self._getFileName(self.trUtf8("TeX Files (*.tex)"))
105 if not filename:
106 return
107
108 try:
109 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
110 QApplication.processEvents()
111
112 self.editor.recolor(0, -1)
113
114 tabSize = Preferences.getEditor("TabWidth")
115 if tabSize == 0:
116 tabSize = 4
117
118 onlyStylesUsed = Preferences.getEditorExporter("TeX/OnlyStylesUsed")
119 titleFullPath = Preferences.getEditorExporter("TeX/FullPathAsTitle")
120
121 lex = self.editor.getLexer()
122 self.defaultPaper = lex and \
123 lex.paper(QsciScintilla.STYLE_DEFAULT) or \
124 self.editor.paper().name()
125 self.defaultColor = lex and \
126 lex.color(QsciScintilla.STYLE_DEFAULT) or \
127 self.editor.color().name()
128 self.defaultFont = lex and \
129 lex.color(QsciScintilla.STYLE_DEFAULT) or \
130 Preferences.getEditorOtherFonts("DefaultFont")
131
132 lengthDoc = self.editor.length()
133 styleIsUsed = {}
134 if onlyStylesUsed:
135 for index in range(QsciScintilla.STYLE_MAX + 1):
136 styleIsUsed[index] = False
137 # check the used styles
138 pos = 0
139 while pos < lengthDoc:
140 styleIsUsed[self.editor.styleAt(pos) & 0x7F] = True
141 pos += 1
142 else:
143 for index in range(QsciScintilla.STYLE_MAX + 1):
144 styleIsUsed[index] = True
145 styleIsUsed[QsciScintilla.STYLE_DEFAULT] = True
146
147 try:
148 f = open(filename, "wb")
149
150 f.write("\\documentclass[a4paper]{article}\n")
151 f.write("\\usepackage[a4paper,margin=1.5cm]{geometry}\n")
152 f.write("\\usepackage[T1]{fontenc}\n")
153 f.write("\\usepackage{color}\n")
154 f.write("\\usepackage{alltt}\n")
155 f.write("\\usepackage{times}\n")
156 if self.editor.isUtf8():
157 f.write("\\usepackage[utf8]{inputenc}\n")
158 else:
159 f.write("\\usepackage[latin1]{inputenc}\n")
160
161 if lex:
162 istyle = 0
163 while istyle <= QsciScintilla.STYLE_MAX:
164 if (istyle <= QsciScintilla.STYLE_DEFAULT or \
165 istyle > QsciScintilla.STYLE_LASTPREDEFINED) and \
166 styleIsUsed[istyle]:
167 if lex.description(istyle) or \
168 istyle == QsciScintilla.STYLE_DEFAULT:
169 font = lex.font(istyle)
170 colour = lex.color(istyle)
171 paper = lex.paper(istyle)
172
173 self.__defineTexStyle(font, colour, paper, f, istyle)
174 istyle += 1
175 else:
176 colour = self.editor.color()
177 paper = self.editor.paper()
178 font = Preferences.getEditorOtherFonts("DefaultFont")
179
180 self.__defineTexStyle(font, colour, paper, f, 0)
181 self.__defineTexStyle(font, colour, paper, f,
182 QsciScintilla.STYLE_DEFAULT)
183
184 f.write("\\begin{document}\n\n")
185 if titleFullPath:
186 title = self.editor.getFileName()
187 else:
188 title = os.path.basename(self.editor.getFileName())
189 f.write("Source File: %s\n\n\\noindent\n\\tiny{\n" % title)
190
191 styleCurrent = self.editor.styleAt(0)
192 f.write("\\eric%s{" % self.__texStyle(styleCurrent))
193
194 lineIdx = 0
195 pos = 0
196
197 while pos < lengthDoc:
198 ch = self.editor.rawCharAt(pos)
199 style = self.editor.styleAt(pos)
200 if style != styleCurrent:
201 # new style
202 f.write("}\n\\eric%s{" % self.__texStyle(style))
203 styleCurrent = style
204
205 if ch == '\t':
206 ts = tabSize - (lineIdx % tabSize)
207 lineIdx += ts - 1
208 f.write("\\hspace*{%dem}" % ts)
209 elif ch == '\\':
210 f.write("{\\textbackslash}")
211 elif ch in ['>', '<', '@']:
212 f.write("$%c$" % ch)
213 elif ch in ['{', '}', '^', '_', '&', '$', '#', '%', '~']:
214 f.write("\\%c" % ch)
215 elif ch in ['\r', '\n']:
216 lineIdx = -1 # because incremented below
217 if ch == '\r' and self.editor.rawCharAt(pos + 1) == '\n':
218 pos += 1 # skip the LF
219 styleCurrent = self.editor.styleAt(pos + 1)
220 f.write("} \\\\\n\\eric%s{" % self.__texStyle(styleCurrent))
221 elif ch == ' ':
222 if self.editor.rawCharAt(pos + 1) == ' ':
223 f.write("{\\hspace*{1em}}")
224 else:
225 f.write(' ')
226 else:
227 f.write(ch)
228 lineIdx += 1
229 pos += 1
230
231 # close last empty style macros and document too
232 f.write("}\n} %end tiny\n\n\\end{document}\n")
233 f.close()
234 except IOError, err:
235 QApplication.restoreOverrideCursor()
236 QMessageBox.critical(self.editor,
237 self.trUtf8("Export source"),
238 self.trUtf8(\
239 """<p>The source could not be exported to <b>{0}</b>.</p>"""
240 """<p>Reason: {1}</p>""")\
241 .format(filename, unicode(err)),
242 QMessageBox.StandardButtons(\
243 QMessageBox.Ok))
244 finally:
245 QApplication.restoreOverrideCursor()

eric ide

mercurial