src/eric7/QScintilla/SpellChecker.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
23 23
24 class SpellChecker(QObject): 24 class SpellChecker(QObject):
25 """ 25 """
26 Class implementing a pyenchant based spell checker. 26 Class implementing a pyenchant based spell checker.
27 """ 27 """
28
28 # class attributes to be used as defaults 29 # class attributes to be used as defaults
29 _spelling_lang = None 30 _spelling_lang = None
30 _spelling_dict = None 31 _spelling_dict = None
31 32
32 def __init__(self, editor, indicator, defaultLanguage=None, 33 def __init__(self, editor, indicator, defaultLanguage=None, checkRegion=None):
33 checkRegion=None):
34 """ 34 """
35 Constructor 35 Constructor
36 36
37 @param editor reference to the editor object (QScintilla.Editor) 37 @param editor reference to the editor object (QScintilla.Editor)
38 @param indicator spell checking indicator 38 @param indicator spell checking indicator
39 @param defaultLanguage the language to be used as the default 39 @param defaultLanguage the language to be used as the default
40 (string). The string should be in language locale format 40 (string). The string should be in language locale format
41 (e.g. en_US, de). 41 (e.g. en_US, de).
42 @param checkRegion reference to a function to check for a valid 42 @param checkRegion reference to a function to check for a valid
43 region 43 region
44 """ 44 """
45 super().__init__(editor) 45 super().__init__(editor)
46 46
47 self.editor = editor 47 self.editor = editor
48 self.indicator = indicator 48 self.indicator = indicator
49 if defaultLanguage is not None: 49 if defaultLanguage is not None:
50 self.setDefaultLanguage(defaultLanguage) 50 self.setDefaultLanguage(defaultLanguage)
51 if checkRegion is not None: 51 if checkRegion is not None:
52 self.__checkRegion = checkRegion 52 self.__checkRegion = checkRegion
53 else: 53 else:
54 self.__checkRegion = lambda r: True 54 self.__checkRegion = lambda r: True
55 self.minimumWordSize = 3 55 self.minimumWordSize = 3
56 self.lastCheckedLine = -1 56 self.lastCheckedLine = -1
57 57
58 self.__ignoreWords = [] 58 self.__ignoreWords = []
59 self.__replaceWords = {} 59 self.__replaceWords = {}
60 60
61 @classmethod 61 @classmethod
62 def getAvailableLanguages(cls): 62 def getAvailableLanguages(cls):
63 """ 63 """
64 Class method to get all available languages. 64 Class method to get all available languages.
65 65
66 @return list of available languages (list of strings) 66 @return list of available languages (list of strings)
67 """ 67 """
68 with contextlib.suppress(NameError): 68 with contextlib.suppress(NameError):
69 return enchant.list_languages() 69 return enchant.list_languages()
70 return [] 70 return []
71 71
72 @classmethod 72 @classmethod
73 def isAvailable(cls): 73 def isAvailable(cls):
74 """ 74 """
75 Class method to check, if spellchecking is available. 75 Class method to check, if spellchecking is available.
76 76
77 @return flag indicating availability (boolean) 77 @return flag indicating availability (boolean)
78 """ 78 """
79 if Preferences.getEditor("SpellCheckingEnabled"): 79 if Preferences.getEditor("SpellCheckingEnabled"):
80 with contextlib.suppress(NameError, AttributeError): 80 with contextlib.suppress(NameError, AttributeError):
81 return len(enchant.list_languages()) > 0 81 return len(enchant.list_languages()) > 0
82 return False 82 return False
83 83
84 @classmethod 84 @classmethod
85 def getDefaultPath(cls, isException=False): 85 def getDefaultPath(cls, isException=False):
86 """ 86 """
87 Class method to get the default path names of the user dictionaries. 87 Class method to get the default path names of the user dictionaries.
88 88
89 @param isException flag indicating to return the name of the default 89 @param isException flag indicating to return the name of the default
90 exception dictionary (boolean) 90 exception dictionary (boolean)
91 @return file name of the default user dictionary or the default user 91 @return file name of the default user dictionary or the default user
92 exception dictionary (string) 92 exception dictionary (string)
93 """ 93 """
94 if isException: 94 if isException:
95 return os.path.join( 95 return os.path.join(Utilities.getConfigDir(), "spelling", "pel.dic")
96 Utilities.getConfigDir(), "spelling", "pel.dic")
97 else: 96 else:
98 return os.path.join( 97 return os.path.join(Utilities.getConfigDir(), "spelling", "pwl.dic")
99 Utilities.getConfigDir(), "spelling", "pwl.dic") 98
100
101 @classmethod 99 @classmethod
102 def getUserDictionaryPath(cls, isException=False): 100 def getUserDictionaryPath(cls, isException=False):
103 """ 101 """
104 Class method to get the path name of a user dictionary file. 102 Class method to get the path name of a user dictionary file.
105 103
106 @param isException flag indicating to return the name of the user 104 @param isException flag indicating to return the name of the user
107 exception dictionary (boolean) 105 exception dictionary (boolean)
108 @return file name of the user dictionary or the user exception 106 @return file name of the user dictionary or the user exception
109 dictionary (string) 107 dictionary (string)
110 """ 108 """
115 else: 113 else:
116 dicFile = Preferences.getEditor("SpellCheckingPersonalWordList") 114 dicFile = Preferences.getEditor("SpellCheckingPersonalWordList")
117 if not dicFile: 115 if not dicFile:
118 dicFile = SpellChecker.getDefaultPath() 116 dicFile = SpellChecker.getDefaultPath()
119 return dicFile 117 return dicFile
120 118
121 @classmethod 119 @classmethod
122 def _getDict(cls, lang, pwl="", pel=""): 120 def _getDict(cls, lang, pwl="", pel=""):
123 """ 121 """
124 Protected class method to get a new dictionary. 122 Protected class method to get a new dictionary.
125 123
126 @param lang the language to be used as the default (string). 124 @param lang the language to be used as the default (string).
127 The string should be in language locale format (e.g. en_US, de). 125 The string should be in language locale format (e.g. en_US, de).
128 @param pwl name of the personal/project word list (string) 126 @param pwl name of the personal/project word list (string)
129 @param pel name of the personal/project exclude list (string) 127 @param pel name of the personal/project exclude list (string)
130 @return reference to the dictionary (enchant.Dict) 128 @return reference to the dictionary (enchant.Dict)
132 if not pwl: 130 if not pwl:
133 pwl = SpellChecker.getUserDictionaryPath() 131 pwl = SpellChecker.getUserDictionaryPath()
134 d = os.path.dirname(pwl) 132 d = os.path.dirname(pwl)
135 if not os.path.exists(d): 133 if not os.path.exists(d):
136 os.makedirs(d) 134 os.makedirs(d)
137 135
138 if not pel: 136 if not pel:
139 pel = SpellChecker.getUserDictionaryPath(False) 137 pel = SpellChecker.getUserDictionaryPath(False)
140 d = os.path.dirname(pel) 138 d = os.path.dirname(pel)
141 if not os.path.exists(d): 139 if not os.path.exists(d):
142 os.makedirs(d) 140 os.makedirs(d)
143 141
144 try: 142 try:
145 d = enchant.DictWithPWL(lang, pwl, pel) 143 d = enchant.DictWithPWL(lang, pwl, pel)
146 except Exception: 144 except Exception:
147 # Catch all exceptions, because if pyenchant isn't available, you 145 # Catch all exceptions, because if pyenchant isn't available, you
148 # can't catch the enchant.DictNotFound error. 146 # can't catch the enchant.DictNotFound error.
149 d = None 147 d = None
150 return d 148 return d
151 149
152 @classmethod 150 @classmethod
153 def setDefaultLanguage(cls, language): 151 def setDefaultLanguage(cls, language):
154 """ 152 """
155 Class method to set the default language. 153 Class method to set the default language.
156 154
157 @param language the language to be used as the default (string). 155 @param language the language to be used as the default (string).
158 The string should be in language locale format (e.g. en_US, de). 156 The string should be in language locale format (e.g. en_US, de).
159 """ 157 """
160 cls._spelling_lang = language 158 cls._spelling_lang = language
161 cls._spelling_dict = cls._getDict(language) 159 cls._spelling_dict = cls._getDict(language)
162 160
163 def setLanguage(self, language, pwl="", pel=""): 161 def setLanguage(self, language, pwl="", pel=""):
164 """ 162 """
165 Public method to set the current language. 163 Public method to set the current language.
166 164
167 @param language the language to be used as the default (string). 165 @param language the language to be used as the default (string).
168 The string should be in language locale format (e.g. en_US, de). 166 The string should be in language locale format (e.g. en_US, de).
169 @param pwl name of the personal/project word list (string) 167 @param pwl name of the personal/project word list (string)
170 @param pel name of the personal/project exclude list (string) 168 @param pel name of the personal/project exclude list (string)
171 """ 169 """
172 self._spelling_lang = language 170 self._spelling_lang = language
173 self._spelling_dict = self._getDict(language, pwl=pwl, 171 self._spelling_dict = self._getDict(language, pwl=pwl, pel=pel)
174 pel=pel) 172
175
176 def getLanguage(self): 173 def getLanguage(self):
177 """ 174 """
178 Public method to get the current language. 175 Public method to get the current language.
179 176
180 @return current language in language locale format (string) 177 @return current language in language locale format (string)
181 """ 178 """
182 return self._spelling_lang 179 return self._spelling_lang
183 180
184 def setMinimumWordSize(self, size): 181 def setMinimumWordSize(self, size):
185 """ 182 """
186 Public method to set the minimum word size. 183 Public method to set the minimum word size.
187 184
188 @param size minimum word size (integer) 185 @param size minimum word size (integer)
189 """ 186 """
190 if size > 0: 187 if size > 0:
191 self.minimumWordSize = size 188 self.minimumWordSize = size
192 189
193 def __getNextWord(self, pos, endPosition): 190 def __getNextWord(self, pos, endPosition):
194 """ 191 """
195 Private method to get the next word in the text after the given 192 Private method to get the next word in the text after the given
196 position. 193 position.
197 194
198 @param pos position to start word extraction (integer) 195 @param pos position to start word extraction (integer)
199 @param endPosition position to stop word extraction (integer) 196 @param endPosition position to stop word extraction (integer)
200 @return tuple of three values (the extracted word (string), 197 @return tuple of three values (the extracted word (string),
201 start position (integer), end position (integer)) 198 start position (integer), end position (integer))
202 """ 199 """
203 if pos < 0 or pos >= endPosition: 200 if pos < 0 or pos >= endPosition:
204 return "", -1, -1 201 return "", -1, -1
205 202
206 ch = self.editor.charAt(pos) 203 ch = self.editor.charAt(pos)
207 # 1. skip non-word characters 204 # 1. skip non-word characters
208 while pos < endPosition and not ch.isalnum(): 205 while pos < endPosition and not ch.isalnum():
209 pos = self.editor.positionAfter(pos) 206 pos = self.editor.positionAfter(pos)
210 ch = self.editor.charAt(pos) 207 ch = self.editor.charAt(pos)
211 if pos == endPosition: 208 if pos == endPosition:
212 return "", -1, -1 209 return "", -1, -1
213 startPos = pos 210 startPos = pos
214 211
215 # 2. extract the word 212 # 2. extract the word
216 word = "" 213 word = ""
217 while pos < endPosition and ch.isalnum(): 214 while pos < endPosition and ch.isalnum():
218 word += ch 215 word += ch
219 pos = self.editor.positionAfter(pos) 216 pos = self.editor.positionAfter(pos)
221 endPos = pos 218 endPos = pos
222 if word.isdigit(): 219 if word.isdigit():
223 return self.__getNextWord(endPos, endPosition) 220 return self.__getNextWord(endPos, endPosition)
224 else: 221 else:
225 return word, startPos, endPos 222 return word, startPos, endPos
226 223
227 def getContext(self, wordStart, wordEnd): 224 def getContext(self, wordStart, wordEnd):
228 """ 225 """
229 Public method to get the context of a faulty word. 226 Public method to get the context of a faulty word.
230 227
231 @param wordStart the starting position of the word (integer) 228 @param wordStart the starting position of the word (integer)
232 @param wordEnd the ending position of the word (integer) 229 @param wordEnd the ending position of the word (integer)
233 @return tuple of the leading and trailing context (string, string) 230 @return tuple of the leading and trailing context (string, string)
234 """ 231 """
235 sline, sindex = self.editor.lineIndexFromPosition(wordStart) 232 sline, sindex = self.editor.lineIndexFromPosition(wordStart)
236 eline, eindex = self.editor.lineIndexFromPosition(wordEnd) 233 eline, eindex = self.editor.lineIndexFromPosition(wordEnd)
237 text = self.editor.text(sline) 234 text = self.editor.text(sline)
238 return (text[:sindex], text[eindex:]) 235 return (text[:sindex], text[eindex:])
239 236
240 def getError(self): 237 def getError(self):
241 """ 238 """
242 Public method to get information about the last error found. 239 Public method to get information about the last error found.
243 240
244 @return tuple of last faulty word (string), starting position of the 241 @return tuple of last faulty word (string), starting position of the
245 faulty word (integer) and ending position of the faulty word 242 faulty word (integer) and ending position of the faulty word
246 (integer) 243 (integer)
247 """ 244 """
248 return (self.word, self.wordStart, self.wordEnd) 245 return (self.word, self.wordStart, self.wordEnd)
249 246
250 def initCheck(self, startPos, endPos): 247 def initCheck(self, startPos, endPos):
251 """ 248 """
252 Public method to initialize a spell check. 249 Public method to initialize a spell check.
253 250
254 @param startPos position to start at (integer) 251 @param startPos position to start at (integer)
255 @param endPos position to end at (integer) 252 @param endPos position to end at (integer)
256 @return flag indicating successful initialization (boolean) 253 @return flag indicating successful initialization (boolean)
257 """ 254 """
258 if startPos == endPos: 255 if startPos == endPos:
259 return False 256 return False
260 257
261 spell = self._spelling_dict 258 spell = self._spelling_dict
262 if spell is None: 259 if spell is None:
263 return False 260 return False
264 261
265 self.editor.clearIndicatorRange( 262 self.editor.clearIndicatorRange(self.indicator, startPos, endPos - startPos)
266 self.indicator, startPos, endPos - startPos) 263
267
268 self.pos = startPos 264 self.pos = startPos
269 self.endPos = endPos 265 self.endPos = endPos
270 self.word = "" 266 self.word = ""
271 self.wordStart = -1 267 self.wordStart = -1
272 self.wordEnd = -1 268 self.wordEnd = -1
273 return True 269 return True
274 270
275 def __checkDocumentPart(self, startPos, endPos): 271 def __checkDocumentPart(self, startPos, endPos):
276 """ 272 """
277 Private method to check some part of the document. 273 Private method to check some part of the document.
278 274
279 @param startPos position to start at (integer) 275 @param startPos position to start at (integer)
280 @param endPos position to end at (integer) 276 @param endPos position to end at (integer)
281 """ 277 """
282 if not self.initCheck(startPos, endPos): 278 if not self.initCheck(startPos, endPos):
283 return 279 return
284 280
285 while True: 281 while True:
286 try: 282 try:
287 next(self) 283 next(self)
288 self.editor.setIndicatorRange(self.indicator, self.wordStart, 284 self.editor.setIndicatorRange(
289 self.wordEnd - self.wordStart) 285 self.indicator, self.wordStart, self.wordEnd - self.wordStart
286 )
290 except StopIteration: 287 except StopIteration:
291 break 288 break
292 289
293 def __incrementalCheck(self): 290 def __incrementalCheck(self):
294 """ 291 """
295 Private method to check the document incrementally. 292 Private method to check the document incrementally.
296 """ 293 """
297 if self.lastCheckedLine < 0: 294 if self.lastCheckedLine < 0:
298 return 295 return
299 296
300 linesChunk = Preferences.getEditor("AutoSpellCheckChunkSize") 297 linesChunk = Preferences.getEditor("AutoSpellCheckChunkSize")
301 self.checkLines(self.lastCheckedLine, 298 self.checkLines(self.lastCheckedLine, self.lastCheckedLine + linesChunk)
302 self.lastCheckedLine + linesChunk)
303 self.lastCheckedLine = self.lastCheckedLine + linesChunk + 1 299 self.lastCheckedLine = self.lastCheckedLine + linesChunk + 1
304 if self.lastCheckedLine >= self.editor.lines(): 300 if self.lastCheckedLine >= self.editor.lines():
305 self.lastCheckedLine = -1 301 self.lastCheckedLine = -1
306 else: 302 else:
307 QTimer.singleShot(0, self.__incrementalCheck) 303 QTimer.singleShot(0, self.__incrementalCheck)
308 304
309 def checkWord(self, pos, atEnd=False): 305 def checkWord(self, pos, atEnd=False):
310 """ 306 """
311 Public method to check the word at position pos. 307 Public method to check the word at position pos.
312 308
313 @param pos position to check at (integer) 309 @param pos position to check at (integer)
314 @param atEnd flag indicating the position is at the end of the word 310 @param atEnd flag indicating the position is at the end of the word
315 to check (boolean) 311 to check (boolean)
316 """ 312 """
317 spell = self._spelling_dict 313 spell = self._spelling_dict
318 if spell is None: 314 if spell is None:
319 return 315 return
320 316
321 if atEnd: 317 if atEnd:
322 pos = self.editor.positionBefore(pos) 318 pos = self.editor.positionBefore(pos)
323 319
324 if pos >= 0 and self.__checkRegion(pos): 320 if pos >= 0 and self.__checkRegion(pos):
325 pos0 = pos 321 pos0 = pos
326 pos1 = 0xffffffff 322 pos1 = 0xFFFFFFFF
327 if not self.editor.charAt(pos).isalnum(): 323 if not self.editor.charAt(pos).isalnum():
328 line, index = self.editor.lineIndexFromPosition(pos) 324 line, index = self.editor.lineIndexFromPosition(pos)
329 self.editor.clearIndicator( 325 self.editor.clearIndicator(self.indicator, line, index, line, index + 1)
330 self.indicator, line, index, line, index + 1)
331 pos1 = self.editor.positionAfter(pos) 326 pos1 = self.editor.positionAfter(pos)
332 pos0 = self.editor.positionBefore(pos) 327 pos0 = self.editor.positionBefore(pos)
333 328
334 for pos in [pos0, pos1]: 329 for pos in [pos0, pos1]:
335 if self.editor.charAt(pos).isalnum(): 330 if self.editor.charAt(pos).isalnum():
336 line, index = self.editor.lineIndexFromPosition(pos) 331 line, index = self.editor.lineIndexFromPosition(pos)
337 word = self.editor.getWord(line, index, useWordChars=False) 332 word = self.editor.getWord(line, index, useWordChars=False)
338 if len(word) >= self.minimumWordSize: 333 if len(word) >= self.minimumWordSize:
341 except enchant.errors.Error: 336 except enchant.errors.Error:
342 ok = True 337 ok = True
343 else: 338 else:
344 ok = True 339 ok = True
345 start, end = self.editor.getWordBoundaries( 340 start, end = self.editor.getWordBoundaries(
346 line, index, useWordChars=False) 341 line, index, useWordChars=False
342 )
347 if ok: 343 if ok:
348 self.editor.clearIndicator( 344 self.editor.clearIndicator(
349 self.indicator, line, start, line, end) 345 self.indicator, line, start, line, end
346 )
350 else: 347 else:
351 # spell check indicated an error 348 # spell check indicated an error
352 self.editor.setIndicator( 349 self.editor.setIndicator(self.indicator, line, start, line, end)
353 self.indicator, line, start, line, end) 350
354
355 def checkLines(self, firstLine, lastLine): 351 def checkLines(self, firstLine, lastLine):
356 """ 352 """
357 Public method to check some lines of text. 353 Public method to check some lines of text.
358 354
359 @param firstLine line number of first line to check (integer) 355 @param firstLine line number of first line to check (integer)
360 @param lastLine line number of last line to check (integer) 356 @param lastLine line number of last line to check (integer)
361 """ 357 """
362 startPos = self.editor.positionFromLineIndex(firstLine, 0) 358 startPos = self.editor.positionFromLineIndex(firstLine, 0)
363 359
364 if lastLine >= self.editor.lines(): 360 if lastLine >= self.editor.lines():
365 lastLine = self.editor.lines() - 1 361 lastLine = self.editor.lines() - 1
366 endPos = self.editor.lineEndPosition(lastLine) 362 endPos = self.editor.lineEndPosition(lastLine)
367 363
368 self.__checkDocumentPart(startPos, endPos) 364 self.__checkDocumentPart(startPos, endPos)
369 365
370 def checkDocument(self): 366 def checkDocument(self):
371 """ 367 """
372 Public method to check the complete document. 368 Public method to check the complete document.
373 """ 369 """
374 self.__checkDocumentPart(0, self.editor.length()) 370 self.__checkDocumentPart(0, self.editor.length())
375 371
376 def checkDocumentIncrementally(self): 372 def checkDocumentIncrementally(self):
377 """ 373 """
378 Public method to check the document incrementally. 374 Public method to check the document incrementally.
379 """ 375 """
380 spell = self._spelling_dict 376 spell = self._spelling_dict
381 if spell is None: 377 if spell is None:
382 return 378 return
383 379
384 if Preferences.getEditor("AutoSpellCheckingEnabled"): 380 if Preferences.getEditor("AutoSpellCheckingEnabled"):
385 self.lastCheckedLine = 0 381 self.lastCheckedLine = 0
386 QTimer.singleShot(0, self.__incrementalCheck) 382 QTimer.singleShot(0, self.__incrementalCheck)
387 383
388 def stopIncrementalCheck(self): 384 def stopIncrementalCheck(self):
389 """ 385 """
390 Public method to stop an incremental check. 386 Public method to stop an incremental check.
391 """ 387 """
392 self.lastCheckedLine = -1 388 self.lastCheckedLine = -1
393 389
394 def checkSelection(self): 390 def checkSelection(self):
395 """ 391 """
396 Public method to check the current selection. 392 Public method to check the current selection.
397 """ 393 """
398 selStartLine, selStartIndex, selEndLine, selEndIndex = ( 394 (
399 self.editor.getSelection() 395 selStartLine,
400 ) 396 selStartIndex,
397 selEndLine,
398 selEndIndex,
399 ) = self.editor.getSelection()
401 self.__checkDocumentPart( 400 self.__checkDocumentPart(
402 self.editor.positionFromLineIndex(selStartLine, selStartIndex), 401 self.editor.positionFromLineIndex(selStartLine, selStartIndex),
403 self.editor.positionFromLineIndex(selEndLine, selEndIndex) 402 self.editor.positionFromLineIndex(selEndLine, selEndIndex),
404 ) 403 )
405 404
406 def checkCurrentPage(self): 405 def checkCurrentPage(self):
407 """ 406 """
408 Public method to check the currently visible page. 407 Public method to check the currently visible page.
409 """ 408 """
410 startLine = self.editor.firstVisibleLine() 409 startLine = self.editor.firstVisibleLine()
411 endLine = startLine + self.editor.linesOnScreen() 410 endLine = startLine + self.editor.linesOnScreen()
412 self.checkLines(startLine, endLine) 411 self.checkLines(startLine, endLine)
413 412
414 def clearAll(self): 413 def clearAll(self):
415 """ 414 """
416 Public method to clear all spelling markers. 415 Public method to clear all spelling markers.
417 """ 416 """
418 self.editor.clearIndicatorRange( 417 self.editor.clearIndicatorRange(self.indicator, 0, self.editor.length())
419 self.indicator, 0, self.editor.length()) 418
420
421 def getSuggestions(self, word): 419 def getSuggestions(self, word):
422 """ 420 """
423 Public method to get suggestions for the given word. 421 Public method to get suggestions for the given word.
424 422
425 @param word word to get suggestions for (string) 423 @param word word to get suggestions for (string)
426 @return list of suggestions (list of strings) 424 @return list of suggestions (list of strings)
427 """ 425 """
428 suggestions = [] 426 suggestions = []
429 spell = self._spelling_dict 427 spell = self._spelling_dict
430 if spell and len(word) >= self.minimumWordSize: 428 if spell and len(word) >= self.minimumWordSize:
431 with contextlib.suppress(enchant.errors.Error): 429 with contextlib.suppress(enchant.errors.Error):
432 suggestions = spell.suggest(word) 430 suggestions = spell.suggest(word)
433 return suggestions 431 return suggestions
434 432
435 def add(self, word=None): 433 def add(self, word=None):
436 """ 434 """
437 Public method to add a word to the personal word list. 435 Public method to add a word to the personal word list.
438 436
439 @param word word to add (string) 437 @param word word to add (string)
440 """ 438 """
441 spell = self._spelling_dict 439 spell = self._spelling_dict
442 if spell: 440 if spell:
443 if word is None: 441 if word is None:
444 word = self.word 442 word = self.word
445 spell.add(word) 443 spell.add(word)
446 444
447 def remove(self, word): 445 def remove(self, word):
448 """ 446 """
449 Public method to add a word to the personal exclude list. 447 Public method to add a word to the personal exclude list.
450 448
451 @param word word to add (string) 449 @param word word to add (string)
452 """ 450 """
453 spell = self._spelling_dict 451 spell = self._spelling_dict
454 if spell: 452 if spell:
455 spell.remove(word) 453 spell.remove(word)
456 454
457 def ignoreAlways(self, word=None): 455 def ignoreAlways(self, word=None):
458 """ 456 """
459 Public method to tell the checker, to always ignore the given word 457 Public method to tell the checker, to always ignore the given word
460 or the current word. 458 or the current word.
461 459
462 @param word word to be ignored (string) 460 @param word word to be ignored (string)
463 """ 461 """
464 if word is None: 462 if word is None:
465 word = self.word 463 word = self.word
466 if word not in self.__ignoreWords: 464 if word not in self.__ignoreWords:
467 self.__ignoreWords.append(word) 465 self.__ignoreWords.append(word)
468 466
469 def replace(self, replacement): 467 def replace(self, replacement):
470 """ 468 """
471 Public method to tell the checker to replace the current word with 469 Public method to tell the checker to replace the current word with
472 the replacement string. 470 the replacement string.
473 471
474 @param replacement replacement string (string) 472 @param replacement replacement string (string)
475 """ 473 """
476 sline, sindex = self.editor.lineIndexFromPosition(self.wordStart) 474 sline, sindex = self.editor.lineIndexFromPosition(self.wordStart)
477 eline, eindex = self.editor.lineIndexFromPosition(self.wordEnd) 475 eline, eindex = self.editor.lineIndexFromPosition(self.wordEnd)
478 self.editor.setSelection(sline, sindex, eline, eindex) 476 self.editor.setSelection(sline, sindex, eline, eindex)
479 self.editor.beginUndoAction() 477 self.editor.beginUndoAction()
480 self.editor.removeSelectedText() 478 self.editor.removeSelectedText()
481 self.editor.insert(replacement) 479 self.editor.insert(replacement)
482 self.editor.endUndoAction() 480 self.editor.endUndoAction()
483 self.pos += len(replacement) - len(self.word) 481 self.pos += len(replacement) - len(self.word)
484 482
485 def replaceAlways(self, replacement): 483 def replaceAlways(self, replacement):
486 """ 484 """
487 Public method to tell the checker to always replace the current word 485 Public method to tell the checker to always replace the current word
488 with the replacement string. 486 with the replacement string.
489 487
490 @param replacement replacement string (string) 488 @param replacement replacement string (string)
491 """ 489 """
492 self.__replaceWords[self.word] = replacement 490 self.__replaceWords[self.word] = replacement
493 self.replace(replacement) 491 self.replace(replacement)
494 492
495 ################################################################## 493 ##################################################################
496 ## Methods below implement the iterator protocol 494 ## Methods below implement the iterator protocol
497 ################################################################## 495 ##################################################################
498 496
499 def __iter__(self): 497 def __iter__(self):
500 """ 498 """
501 Special method to create an iterator. 499 Special method to create an iterator.
502 500
503 @return self 501 @return self
504 """ 502 """
505 return self 503 return self
506 504
507 def __next__(self): 505 def __next__(self):
508 """ 506 """
509 Special method to advance to the next error. 507 Special method to advance to the next error.
510 508
511 @return self 509 @return self
512 @exception StopIteration raised to indicate the end of the iteration 510 @exception StopIteration raised to indicate the end of the iteration
513 """ 511 """
514 spell = self._spelling_dict 512 spell = self._spelling_dict
515 if spell: 513 if spell:
516 while self.pos < self.endPos and self.pos >= 0: 514 while self.pos < self.endPos and self.pos >= 0:
517 word, wordStart, wordEnd = self.__getNextWord( 515 word, wordStart, wordEnd = self.__getNextWord(self.pos, self.endPos)
518 self.pos, self.endPos)
519 self.pos = wordEnd 516 self.pos = wordEnd
520 if ( 517 if (wordEnd - wordStart) >= self.minimumWordSize and self.__checkRegion(
521 (wordEnd - wordStart) >= self.minimumWordSize and 518 wordStart
522 self.__checkRegion(wordStart)
523 ): 519 ):
524 with contextlib.suppress(enchant.errors.Error): 520 with contextlib.suppress(enchant.errors.Error):
525 if spell.check(word): 521 if spell.check(word):
526 continue 522 continue
527 if word in self.__ignoreWords: 523 if word in self.__ignoreWords:
531 self.wordEnd = wordEnd 527 self.wordEnd = wordEnd
532 if word in self.__replaceWords: 528 if word in self.__replaceWords:
533 self.replace(self.__replaceWords[word]) 529 self.replace(self.__replaceWords[word])
534 continue 530 continue
535 return self 531 return self
536 532
537 raise StopIteration 533 raise StopIteration

eric ide

mercurial