|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2003 - 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the lexer base class. |
|
8 """ |
|
9 |
|
10 import Preferences |
|
11 |
|
12 class Lexer(object): |
|
13 """ |
|
14 Class to implement the lexer mixin class. |
|
15 """ |
|
16 def __init__(self): |
|
17 """ |
|
18 Constructor |
|
19 """ |
|
20 self.commentString = '' |
|
21 self.streamCommentString = { |
|
22 'start' : '', |
|
23 'end' : '' |
|
24 } |
|
25 self.boxCommentString = { |
|
26 'start' : '', |
|
27 'middle' : '', |
|
28 'end' : '' |
|
29 } |
|
30 |
|
31 # last indented line wrapper |
|
32 self.lastIndented = -1 |
|
33 self.lastIndentedIndex = -1 |
|
34 |
|
35 # always keep tabs (for languages where tabs are esential |
|
36 self._alwaysKeepTabs = False |
|
37 |
|
38 def initProperties(self): |
|
39 """ |
|
40 Public slot to initialize the properties. |
|
41 """ |
|
42 # default implementation is a do nothing |
|
43 return |
|
44 |
|
45 def commentStr(self): |
|
46 """ |
|
47 Public method to return the comment string. |
|
48 |
|
49 @return comment string (string) |
|
50 """ |
|
51 return self.commentString |
|
52 |
|
53 def canBlockComment(self): |
|
54 """ |
|
55 Public method to determine, whether the lexer language supports a block comment. |
|
56 |
|
57 @return flag (boolean) |
|
58 """ |
|
59 return self.commentString != "" |
|
60 |
|
61 def streamCommentStr(self): |
|
62 """ |
|
63 Public method to return the stream comment strings. |
|
64 |
|
65 @return stream comment strings (dictionary with two strings) |
|
66 """ |
|
67 return self.streamCommentString |
|
68 |
|
69 def canStreamComment(self): |
|
70 """ |
|
71 Public method to determine, whether the lexer language supports a stream comment. |
|
72 |
|
73 @return flag (boolean) |
|
74 """ |
|
75 return \ |
|
76 (self.streamCommentString['start'] != "") and \ |
|
77 (self.streamCommentString['end'] != "") |
|
78 |
|
79 def boxCommentStr(self): |
|
80 """ |
|
81 Public method to return the box comment strings. |
|
82 |
|
83 @return box comment strings (dictionary with three QStrings) |
|
84 """ |
|
85 return self.boxCommentString |
|
86 |
|
87 def canBoxComment(self): |
|
88 """ |
|
89 Public method to determine, whether the lexer language supports a box comment. |
|
90 |
|
91 @return flag (boolean) |
|
92 """ |
|
93 return \ |
|
94 (self.boxCommentString['start'] != "") and \ |
|
95 (self.boxCommentString['middle'] != "") and \ |
|
96 (self.boxCommentString['end'] != "") |
|
97 |
|
98 def alwaysKeepTabs(self): |
|
99 """ |
|
100 Public method to check, if tab conversion is allowed. |
|
101 |
|
102 @return flag indicating to keep tabs (boolean) |
|
103 """ |
|
104 return self._alwaysKeepTabs |
|
105 |
|
106 def hasSmartIndent(self): |
|
107 """ |
|
108 Public method indicating whether lexer can do smart indentation. |
|
109 |
|
110 @return flag indicating availability of smartIndentLine and |
|
111 smartIndentSelection methods (boolean) |
|
112 """ |
|
113 return hasattr(self, 'getIndentationDifference') |
|
114 |
|
115 def smartIndentLine(self, editor): |
|
116 """ |
|
117 Public method to handle smart indentation for a line. |
|
118 |
|
119 @param editor reference to the QScintilla editor object |
|
120 """ |
|
121 cline, cindex = editor.getCursorPosition() |
|
122 |
|
123 # get leading spaces |
|
124 lead_spaces = editor.indentation(cline) |
|
125 |
|
126 # get the indentation difference |
|
127 indentDifference = self.getIndentationDifference(cline, editor) |
|
128 |
|
129 if indentDifference != 0: |
|
130 editor.setIndentation(cline, lead_spaces + indentDifference) |
|
131 editor.setCursorPosition(cline, cindex + indentDifference) |
|
132 |
|
133 self.lastIndented = cline |
|
134 |
|
135 def smartIndentSelection(self, editor): |
|
136 """ |
|
137 Public method to handle smart indentation for a selection of lines. |
|
138 |
|
139 Note: The assumption is, that the first line determines the new |
|
140 indentation level. |
|
141 |
|
142 @param editor reference to the QScintilla editor object |
|
143 """ |
|
144 if not editor.hasSelectedText(): |
|
145 return |
|
146 |
|
147 # get the selection |
|
148 lineFrom, indexFrom, lineTo, indexTo = editor.getSelection() |
|
149 if lineFrom != self.lastIndented: |
|
150 self.lastIndentedIndex = indexFrom |
|
151 |
|
152 if indexTo == 0: |
|
153 endLine = lineTo - 1 |
|
154 else: |
|
155 endLine = lineTo |
|
156 |
|
157 # get the indentation difference |
|
158 indentDifference = self.getIndentationDifference(lineFrom, editor) |
|
159 |
|
160 editor.beginUndoAction() |
|
161 # iterate over the lines |
|
162 for line in range(lineFrom, endLine+1): |
|
163 editor.setIndentation(line, |
|
164 editor.indentation(line) + indentDifference) |
|
165 editor.endUndoAction() |
|
166 |
|
167 if self.lastIndentedIndex != 0: |
|
168 indexStart = indexFrom + indentDifference |
|
169 else: |
|
170 indexStart = 0 |
|
171 if indexStart < 0: |
|
172 indexStart = 0 |
|
173 indexEnd = indexTo != 0 and (indexTo + indentDifference) or 0 |
|
174 if indexEnd < 0: |
|
175 indexEnd = 0 |
|
176 editor.setSelection(lineFrom, indexStart, lineTo, indexEnd) |
|
177 |
|
178 self.lastIndented = lineFrom |
|
179 |
|
180 def autoCompletionWordSeparators(self): |
|
181 """ |
|
182 Public method to return the list of separators for autocompletion. |
|
183 |
|
184 @return list of separators (list of strings) |
|
185 """ |
|
186 return [] |
|
187 |
|
188 def isCommentStyle(self, style): |
|
189 """ |
|
190 Public method to check, if a style is a comment style. |
|
191 |
|
192 @return flag indicating a comment style (boolean) |
|
193 """ |
|
194 return True |
|
195 |
|
196 def isStringStyle(self, style): |
|
197 """ |
|
198 Public method to check, if a style is a string style. |
|
199 |
|
200 @return flag indicating a string style (boolean) |
|
201 """ |
|
202 return True |