Merged the spell checking classes into one file
This commit is contained in:
@@ -1007,7 +1007,7 @@ class GuiDocEditor(QTextEdit):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if self.mainConf.spellTool == "enchant":
|
if self.mainConf.spellTool == "enchant":
|
||||||
from nw.tools.spellenchant import NWSpellEnchant
|
from nw.tools.spellcheck import NWSpellEnchant
|
||||||
self.theDict = NWSpellEnchant()
|
self.theDict = NWSpellEnchant()
|
||||||
else:
|
else:
|
||||||
self.theDict = NWSpellSimple()
|
self.theDict = NWSpellSimple()
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ from nw.tools.analyse import TextAnalysis
|
|||||||
from nw.tools.legacy import projectMaintenance
|
from nw.tools.legacy import projectMaintenance
|
||||||
from nw.tools.optionstate import OptionState
|
from nw.tools.optionstate import OptionState
|
||||||
from nw.tools.spellcheck import NWSpellCheck
|
from nw.tools.spellcheck import NWSpellCheck
|
||||||
from nw.tools.spellenchant import NWSpellEnchant
|
from nw.tools.spellcheck import NWSpellEnchant
|
||||||
from nw.tools.spellsimple import NWSpellSimple
|
from nw.tools.spellcheck import NWSpellSimple
|
||||||
from nw.tools.translate import numberToWord
|
from nw.tools.translate import numberToWord
|
||||||
from nw.tools.wordcount import countWords
|
from nw.tools.wordcount import countWords
|
||||||
|
|
||||||
|
|||||||
+167
-1
@@ -28,7 +28,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path
|
from os import path, listdir
|
||||||
|
from difflib import get_close_matches
|
||||||
|
|
||||||
from nw.constants import isoLanguage
|
from nw.constants import isoLanguage
|
||||||
|
|
||||||
@@ -108,3 +109,168 @@ class NWSpellCheck():
|
|||||||
return
|
return
|
||||||
|
|
||||||
# END Class NWSpellCheck
|
# END Class NWSpellCheck
|
||||||
|
|
||||||
|
# ================================================================================================ #
|
||||||
|
# Enchant Based SpellChecking
|
||||||
|
# ================================================================================================ #
|
||||||
|
|
||||||
|
class NWSpellEnchant(NWSpellCheck):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
NWSpellCheck.__init__(self)
|
||||||
|
logger.debug("Enchant spell checking activated")
|
||||||
|
return
|
||||||
|
|
||||||
|
def setLanguage(self, theLang, projectDict=None):
|
||||||
|
"""Load a dictionary for the language specified in the config.
|
||||||
|
If that fails, we load a dummy dictionary so that lookups don't
|
||||||
|
crash.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
import enchant
|
||||||
|
self.theDict = enchant.Dict(theLang)
|
||||||
|
self.spellLanguage = theLang
|
||||||
|
logger.debug("Enchant spell checking for language %s loaded" % theLang)
|
||||||
|
except:
|
||||||
|
logger.error("Failed to load enchant spell checking for language %s" % theLang)
|
||||||
|
self.theDict = NWSpellEnchantDummy()
|
||||||
|
self.spellLanguage = None
|
||||||
|
|
||||||
|
self._readProjectDictionary(projectDict)
|
||||||
|
for pWord in self.PROJW:
|
||||||
|
self.theDict.add_to_session(pWord)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def checkWord(self, theWord):
|
||||||
|
return self.theDict.check(theWord)
|
||||||
|
|
||||||
|
def suggestWords(self, theWord):
|
||||||
|
return self.theDict.suggest(theWord)
|
||||||
|
|
||||||
|
def addWord(self, newWord):
|
||||||
|
self.theDict.add_to_session(newWord)
|
||||||
|
NWSpellCheck.addWord(self, newWord)
|
||||||
|
return
|
||||||
|
|
||||||
|
def listDictionaries(self):
|
||||||
|
retList = []
|
||||||
|
for spTag, spProvider in enchant.list_dicts():
|
||||||
|
spName = "%s [%s]" % (self.expandLanguage(spTag), spProvider.name)
|
||||||
|
retList.append((spTag, spName))
|
||||||
|
return retList
|
||||||
|
|
||||||
|
# END Class NWSpellEnchant
|
||||||
|
|
||||||
|
class NWSpellEnchantDummy:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def check(self, theWord):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def suggest(self, theWord):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def add_to_session(self, theWord):
|
||||||
|
return
|
||||||
|
|
||||||
|
# END Class NWSpellEnchantDummy
|
||||||
|
|
||||||
|
# ================================================================================================ #
|
||||||
|
# Fallback SpellChecking Using difflib
|
||||||
|
# ================================================================================================ #
|
||||||
|
|
||||||
|
class NWSpellSimple(NWSpellCheck):
|
||||||
|
|
||||||
|
WORDS = []
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
NWSpellCheck.__init__(self)
|
||||||
|
logger.debug("Simple spell checking activated")
|
||||||
|
return
|
||||||
|
|
||||||
|
def setLanguage(self, theLang, projectDict=None):
|
||||||
|
|
||||||
|
self.WORDS = []
|
||||||
|
dictFile = path.join(self.mainConf.dictPath,theLang+".dict")
|
||||||
|
try:
|
||||||
|
with open(dictFile,mode="r",encoding="utf-8") as wordsFile:
|
||||||
|
for theLine in wordsFile:
|
||||||
|
if len(theLine) == 0 or theLine.startswith("#"):
|
||||||
|
continue
|
||||||
|
self.WORDS.append(theLine.strip().lower())
|
||||||
|
logger.debug("Spell check word list for language %s loaded" % theLang)
|
||||||
|
logger.debug("Word list contains %d words" % len(self.WORDS))
|
||||||
|
self.spellLanguage = theLang
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Failed to load spell check word list for language %s" % theLang)
|
||||||
|
logger.error(str(e))
|
||||||
|
self.spellLanguage = None
|
||||||
|
|
||||||
|
self._readProjectDictionary(projectDict)
|
||||||
|
for pWord in self.PROJW:
|
||||||
|
if pWord not in self.WORDS:
|
||||||
|
self.WORDS.append(pWord)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def checkWord(self, theWord):
|
||||||
|
"""Check if a word exists in the word list. Make sure to keep
|
||||||
|
this function as fast as possible as it is called for every
|
||||||
|
word by the syntax highlighter.
|
||||||
|
"""
|
||||||
|
theWord = theWord.replace(self.mainConf.fmtApostrophe,"'").lower()
|
||||||
|
return theWord in self.WORDS
|
||||||
|
|
||||||
|
def suggestWords(self, theWord):
|
||||||
|
"""Get suggestions for correct word from difflib, and make sure
|
||||||
|
the first character is upper case if that was also the case for
|
||||||
|
the word be3ing checked. Also make sure the apostrophe is
|
||||||
|
changed to the one in the dictionary, and then put back in the
|
||||||
|
results.
|
||||||
|
"""
|
||||||
|
theWord = theWord.strip()
|
||||||
|
if len(theWord) == 0:
|
||||||
|
return []
|
||||||
|
|
||||||
|
firstUp = theWord[0] == theWord[0].upper()
|
||||||
|
theWord = theWord.lower()
|
||||||
|
|
||||||
|
theMatches = get_close_matches(theWord, self.WORDS, n=10, cutoff=0.75)
|
||||||
|
theOptions = []
|
||||||
|
for aWord in theMatches:
|
||||||
|
if len(aWord) == 0:
|
||||||
|
continue
|
||||||
|
if firstUp:
|
||||||
|
aWord = aWord[0].upper() + aWord[1:]
|
||||||
|
aWord = aWord.replace("'",self.mainConf.fmtApostrophe)
|
||||||
|
theOptions.append(aWord)
|
||||||
|
|
||||||
|
return theOptions
|
||||||
|
|
||||||
|
def addWord(self, newWord):
|
||||||
|
newWord = newWord.strip().lower()
|
||||||
|
if newWord not in self.WORDS:
|
||||||
|
self.WORDS.append(newWord)
|
||||||
|
NWSpellCheck.addWord(self, newWord)
|
||||||
|
return
|
||||||
|
|
||||||
|
def listDictionaries(self):
|
||||||
|
|
||||||
|
retList = []
|
||||||
|
for dictFile in listdir(self.mainConf.dictPath):
|
||||||
|
|
||||||
|
theBits = path.splitext(dictFile)
|
||||||
|
if len(theBits) != 2:
|
||||||
|
continue
|
||||||
|
if theBits[1] != ".dict":
|
||||||
|
continue
|
||||||
|
|
||||||
|
spName = "%s [Internal]" % self.expandLanguage(theBits[0])
|
||||||
|
retList.append((theBits[0], spName))
|
||||||
|
|
||||||
|
return retList
|
||||||
|
|
||||||
|
# END Class NWSpellSimple
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""novelWriter Spell Check Wrapper : pyEnchant
|
|
||||||
|
|
||||||
novelWriter – Spell Check Wrapper : pyEnchant
|
|
||||||
===============================================
|
|
||||||
Wrapper class for spell checking with pyEnchant
|
|
||||||
|
|
||||||
File History:
|
|
||||||
Created: 2019-06-11 [0.1.5]
|
|
||||||
|
|
||||||
This file is a part of novelWriter
|
|
||||||
Copyright 2020, Veronica Berglyd Olsen
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import nw
|
|
||||||
try:
|
|
||||||
import enchant
|
|
||||||
except:
|
|
||||||
# No need to do anything
|
|
||||||
# setLanguage will fall back to dummy dictionary
|
|
||||||
pass
|
|
||||||
|
|
||||||
from nw.tools.spellcheck import NWSpellCheck
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class NWSpellEnchant(NWSpellCheck):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
NWSpellCheck.__init__(self)
|
|
||||||
logger.debug("Enchant spell checking activated")
|
|
||||||
return
|
|
||||||
|
|
||||||
def setLanguage(self, theLang, projectDict=None):
|
|
||||||
"""Load a dictionary for the language specified in the config.
|
|
||||||
If that fails, we load a dummy dictionary so that lookups don't
|
|
||||||
crash.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.theDict = enchant.Dict(theLang)
|
|
||||||
self.spellLanguage = theLang
|
|
||||||
logger.debug("Enchant spell checking for language %s loaded" % theLang)
|
|
||||||
except:
|
|
||||||
logger.error("Failed to load enchant spell checking for language %s" % theLang)
|
|
||||||
self.theDict = NWSpellEnchantDummy()
|
|
||||||
self.spellLanguage = None
|
|
||||||
|
|
||||||
self._readProjectDictionary(projectDict)
|
|
||||||
for pWord in self.PROJW:
|
|
||||||
self.theDict.add_to_session(pWord)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def checkWord(self, theWord):
|
|
||||||
return self.theDict.check(theWord)
|
|
||||||
|
|
||||||
def suggestWords(self, theWord):
|
|
||||||
return self.theDict.suggest(theWord)
|
|
||||||
|
|
||||||
def addWord(self, newWord):
|
|
||||||
self.theDict.add_to_session(newWord)
|
|
||||||
NWSpellCheck.addWord(self, newWord)
|
|
||||||
return
|
|
||||||
|
|
||||||
def listDictionaries(self):
|
|
||||||
retList = []
|
|
||||||
for spTag, spProvider in enchant.list_dicts():
|
|
||||||
spName = "%s [%s]" % (self.expandLanguage(spTag), spProvider.name)
|
|
||||||
retList.append((spTag, spName))
|
|
||||||
return retList
|
|
||||||
|
|
||||||
# END Class NWSpellEnchant
|
|
||||||
|
|
||||||
class NWSpellEnchantDummy:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
return
|
|
||||||
|
|
||||||
def check(self, theWord):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def suggest(self, theWord):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def add_to_session(self, theWord):
|
|
||||||
return
|
|
||||||
|
|
||||||
# END Class NWSpellEnchantDummy
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""novelWriter Spell Check Simple
|
|
||||||
|
|
||||||
novelWriter – Spell Check Simple
|
|
||||||
==================================
|
|
||||||
Simple spell checker based on difflib
|
|
||||||
|
|
||||||
File History:
|
|
||||||
Created: 2019-06-11 [0.1.5]
|
|
||||||
|
|
||||||
This file is a part of novelWriter
|
|
||||||
Copyright 2020, Veronica Berglyd Olsen
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import nw
|
|
||||||
|
|
||||||
from os import path, listdir
|
|
||||||
from difflib import get_close_matches
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
from nw.tools.spellcheck import NWSpellCheck
|
|
||||||
|
|
||||||
class NWSpellSimple(NWSpellCheck):
|
|
||||||
|
|
||||||
WORDS = []
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
NWSpellCheck.__init__(self)
|
|
||||||
logger.debug("Simple spell checking activated")
|
|
||||||
return
|
|
||||||
|
|
||||||
def setLanguage(self, theLang, projectDict=None):
|
|
||||||
|
|
||||||
self.WORDS = []
|
|
||||||
dictFile = path.join(self.mainConf.dictPath,theLang+".dict")
|
|
||||||
try:
|
|
||||||
with open(dictFile,mode="r",encoding="utf-8") as wordsFile:
|
|
||||||
for theLine in wordsFile:
|
|
||||||
if len(theLine) == 0 or theLine.startswith("#"):
|
|
||||||
continue
|
|
||||||
self.WORDS.append(theLine.strip().lower())
|
|
||||||
logger.debug("Spell check word list for language %s loaded" % theLang)
|
|
||||||
logger.debug("Word list contains %d words" % len(self.WORDS))
|
|
||||||
self.spellLanguage = theLang
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Failed to load spell check word list for language %s" % theLang)
|
|
||||||
logger.error(str(e))
|
|
||||||
self.spellLanguage = None
|
|
||||||
|
|
||||||
self._readProjectDictionary(projectDict)
|
|
||||||
for pWord in self.PROJW:
|
|
||||||
if pWord not in self.WORDS:
|
|
||||||
self.WORDS.append(pWord)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def checkWord(self, theWord):
|
|
||||||
"""Check if a word exists in the word list. Make sure to keep
|
|
||||||
this function as fast as possible as it is called for every
|
|
||||||
word by the syntax highlighter.
|
|
||||||
"""
|
|
||||||
theWord = theWord.replace(self.mainConf.fmtApostrophe,"'").lower()
|
|
||||||
return theWord in self.WORDS
|
|
||||||
|
|
||||||
def suggestWords(self, theWord):
|
|
||||||
"""Get suggestions for correct word from difflib, and make sure
|
|
||||||
the first character is upper case if that was also the case for
|
|
||||||
the word be3ing checked. Also make sure the apostrophe is
|
|
||||||
changed to the one in the dictionary, and then put back in the
|
|
||||||
results.
|
|
||||||
"""
|
|
||||||
theWord = theWord.strip()
|
|
||||||
if len(theWord) == 0:
|
|
||||||
return []
|
|
||||||
|
|
||||||
firstUp = theWord[0] == theWord[0].upper()
|
|
||||||
theWord = theWord.lower()
|
|
||||||
|
|
||||||
theMatches = get_close_matches(theWord, self.WORDS, n=10, cutoff=0.75)
|
|
||||||
theOptions = []
|
|
||||||
for aWord in theMatches:
|
|
||||||
if len(aWord) == 0:
|
|
||||||
continue
|
|
||||||
if firstUp:
|
|
||||||
aWord = aWord[0].upper() + aWord[1:]
|
|
||||||
aWord = aWord.replace("'",self.mainConf.fmtApostrophe)
|
|
||||||
theOptions.append(aWord)
|
|
||||||
|
|
||||||
return theOptions
|
|
||||||
|
|
||||||
def addWord(self, newWord):
|
|
||||||
newWord = newWord.strip().lower()
|
|
||||||
if newWord not in self.WORDS:
|
|
||||||
self.WORDS.append(newWord)
|
|
||||||
NWSpellCheck.addWord(self, newWord)
|
|
||||||
return
|
|
||||||
|
|
||||||
def listDictionaries(self):
|
|
||||||
|
|
||||||
retList = []
|
|
||||||
for dictFile in listdir(self.mainConf.dictPath):
|
|
||||||
|
|
||||||
theBits = path.splitext(dictFile)
|
|
||||||
if len(theBits) != 2:
|
|
||||||
continue
|
|
||||||
if theBits[1] != ".dict":
|
|
||||||
continue
|
|
||||||
|
|
||||||
spName = "%s [Internal]" % self.expandLanguage(theBits[0])
|
|
||||||
retList.append((theBits[0], spName))
|
|
||||||
|
|
||||||
return retList
|
|
||||||
|
|
||||||
# END Class NWSpellSimple
|
|
||||||
Reference in New Issue
Block a user