2
# vim:fileencoding=utf-8
3
from __future__ import (unicode_literals, division, absolute_import,
7
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
11
from PyQt4.Qt import QTextDocument, QTextCursor, QTextCharFormat, QPlainTextDocumentLayout
13
from calibre.gui2.tweak_book import tprefs
14
from calibre.gui2.tweak_book.editor.text import get_highlighter as calibre_highlighter, SyntaxHighlighter
15
from calibre.gui2.tweak_book.editor.themes import THEMES, default_theme, highlight_to_char_format
18
theme = THEMES.get(tprefs['editor_theme'], None)
20
theme = THEMES[default_theme()]
23
NULL_FMT = QTextCharFormat()
25
class QtHighlighter(QTextDocument):
27
def __init__(self, parent, text, hlclass):
28
QTextDocument.__init__(self, parent)
29
self.l = QPlainTextDocumentLayout(self)
30
self.setDocumentLayout(self.l)
31
self.highlighter = hlclass(self)
32
self.highlighter.apply_theme(get_theme())
33
self.highlighter.setDocument(self)
34
self.setPlainText(text)
36
def copy_lines(self, lo, hi, cursor):
37
''' Copy specified lines from the syntax highlighted buffer into the
38
destination cursor, preserving all formatting created by the syntax
42
block = self.findBlockByNumber(lo)
45
cursor.insertText(block.text())
46
dest_block = cursor.block()
47
c = QTextCursor(dest_block)
48
for af in block.layout().additionalFormats():
49
start = dest_block.position() + af.start
50
c.setPosition(start), c.setPosition(start + af.length, c.KeepAnchor)
51
c.setCharFormat(af.format)
53
cursor.setCharFormat(NULL_FMT)
56
class NullHighlighter(object):
58
def __init__(self, text):
59
self.lines = text.splitlines()
61
def copy_lines(self, lo, hi, cursor):
62
for i in xrange(lo, hi):
63
cursor.insertText(self.lines[i])
66
def pygments_lexer(filename):
68
from pygments.lexers import get_lexer_for_filename
69
from pygments.util import ClassNotFound
72
glff = lambda n: get_lexer_for_filename(n, stripnl=False)
76
if filename.lower().endswith('.recipe'):
84
from pygments.token import Token
87
Token.Comment: 'Comment',
88
Token.Comment.Preproc: 'PreProc',
89
Token.String: 'String',
90
Token.Number: 'Number',
91
Token.Keyword.Type: 'Type',
92
Token.Keyword: 'Keyword',
93
Token.Name.Builtin: 'Identifier',
94
Token.Operator: 'Statement',
95
Token.Name.Function: 'Function',
96
Token.Literal: 'Constant',
101
def format_for_token(theme, cache, token):
106
pmap = pygments_map()
107
while token is not None:
113
cache[token] = ans = theme[name]
115
cache[token] = ans = NULL_FMT
118
class PygmentsHighlighter(object):
120
def __init__(self, text, lexer):
121
theme, cache = get_theme(), {}
122
theme = {k:highlight_to_char_format(v) for k, v in theme.iteritems()}
123
theme[None] = NULL_FMT
125
return format_for_token(theme, cache, token)
127
from pygments import lex
128
lines = self.lines = [[]]
129
current_line = lines[0]
130
for token, val in lex(text, lexer):
131
for v in val.splitlines(True):
132
current_line.append((fmt(token), v))
135
current_line = lines[-1]
138
def copy_lines(self, lo, hi, cursor):
139
for i in xrange(lo, hi):
140
for fmt, text in self.lines[i]:
141
cursor.insertText(text, fmt)
142
cursor.setCharFormat(NULL_FMT)
144
def get_highlighter(parent, text, syntax):
145
hlclass = calibre_highlighter(syntax)
146
if hlclass is SyntaxHighlighter:
147
filename = os.path.basename(parent.headers[-1][1])
148
lexer = pygments_lexer(filename)
150
return NullHighlighter(text)
151
return PygmentsHighlighter(text, lexer)
152
return QtHighlighter(parent, text, hlclass)