Added wrapper classes for spell checker so new libraries can be added

This commit is contained in:
Veronica K. B. Olsen
2019-06-11 20:27:29 +02:00
parent 3c2864f161
commit c48b1deb8f
10 changed files with 113 additions and 21 deletions
+8 -3
View File
@@ -29,12 +29,17 @@ except:
print("ERROR: Failed to load dependency python3-appdirs")
exit(1)
spellPack = None
try:
import enchant
spellPack = "enchant"
except:
print("ERROR: Failed to load dependency python3-enchant")
exit(1)
print("WARNING: No spell check library found.")
print("Please install python3-enchant if you want to use spell checking")
if __name__ == "__main__":
import nw
nw.main(sys.argv[1:])
inArgs = sys.argv[1:]
if spellPack is not None:
inArgs.append("--spell=%s" % spellPack)
nw.main(inArgs)
+5
View File
@@ -82,6 +82,7 @@ def main(sysArgs):
"version",
"config=",
"testmode",
"spell=",
]
helpMsg = (
@@ -117,6 +118,7 @@ def main(sysArgs):
confPath = None
testMode = False
debugGUI = False
spellTool = None
# Parse Options
try:
@@ -149,6 +151,8 @@ def main(sysArgs):
confPath = inArg
elif inOpt in ("--testmode"):
testMode = True
elif inOpt in ("--spell"):
spellTool = inArg
elif inOpt in ("-D","--debuggui"):
debugLevel = logging.DEBUG
debugStr = "{name:>20}:{lineno:<4d} {levelname:8} {message:}"
@@ -158,6 +162,7 @@ def main(sysArgs):
CONFIG.showGUI = not testMode
CONFIG.debugGUI = debugGUI
CONFIG.debugInfo = debugLevel < logging.INFO
CONFIG.spellTool = spellTool
# Set Logging
if showTime: debugStr = timeStr+debugStr
+6
View File
@@ -35,6 +35,7 @@ class Config:
self.showGUI = True
self.debugGUI = False
self.debugInfo = False
self.spellTool = None
# Set Paths
self.confPath = None
@@ -124,6 +125,11 @@ class Config:
# If it does not exist, save a copy of the defaults
self.saveConfig()
if self.spellTool is None:
logger.warning("No spell check tool available")
else:
logger.debug("Using spell check tool '%s'" % self.spellTool)
return True
def loadConfig(self):
+3 -3
View File
@@ -28,13 +28,13 @@ class ToHtml(Tokenizer):
def doAutoReplace(self):
Tokenizer.doAutoReplace(self)
theDict = {
repDict = {
"<" : "&lt;",
">" : "&gt;",
"&" : "&amp;",
}
xRep = re.compile("|".join([re.escape(k) for k in theDict.keys()]), flags=re.DOTALL)
self.theText = xRep.sub(lambda x: theDict[x.group(0)], self.theText)
xRep = re.compile("|".join([re.escape(k) for k in repDict.keys()]), flags=re.DOTALL)
self.theText = xRep.sub(lambda x: repDict[x.group(0)], self.theText)
return
+4 -4
View File
@@ -60,11 +60,11 @@ class Tokenizer():
def doAutoReplace(self):
if len(self.theProject.autoReplace) > 0:
theDict = {}
repDict = {}
for aKey, aVal in self.theProject.autoReplace.items():
theDict["<%s>" % aKey] = aVal
xRep = re.compile("|".join([re.escape(k) for k in theDict.keys()]), flags=re.DOTALL)
self.theText = xRep.sub(lambda x: theDict[x.group(0)], self.theText)
repDict["<%s>" % aKey] = aVal
xRep = re.compile("|".join([re.escape(k) for k in repDict.keys()]), flags=re.DOTALL)
self.theText = xRep.sub(lambda x: repDict[x.group(0)], self.theText)
return
def tokenizeText(self):
+2 -3
View File
@@ -11,7 +11,6 @@
"""
import logging
import enchant
import nw
from os import path
@@ -139,8 +138,8 @@ class GuiConfigEditGeneral(QWidget):
self.spellLang.setLayout(self.spellLangForm)
self.spellLangList = QComboBox(self)
for spTag, spProvider in enchant.list_dicts():
self.spellLangList.addItem("%s [%s]" % (spTag, spProvider.name), spTag)
for spTag, spName in self.theParent.docEditor.theDict.listDictionaries():
self.spellLangList.addItem(spName, spTag)
spellIdx = self.spellLangList.findData(self.mainConf.spellLanguage)
if spellIdx != -1:
self.spellLangList.setCurrentIndex(spellIdx)
+12 -7
View File
@@ -12,7 +12,6 @@
import logging
import nw
import enchant
from time import time
@@ -23,6 +22,7 @@ from PyQt5.QtGui import QTextCursor, QTextOption, QIcon, QKeySequence, Q
from nw.project.document import NWDoc
from nw.gui.dochighlight import GuiDocHighlighter
from nw.gui.wordcounter import WordCounter
from nw.tools.spellcheck import NWSpellCheck
from nw.enum import nwDocAction, nwAlert
logger = logging.getLogger(__name__)
@@ -58,7 +58,13 @@ class GuiDocEditor(QTextEdit):
# Core Elements
self.theQDoc = self.document()
self.theDict = enchant.Dict(self.mainConf.spellLanguage)
if self.mainConf.spellTool == "enchant":
from nw.tools.spellenchant import NWSpellEnchant
self.theDict = NWSpellEnchant()
else:
self.theDict = NWSpellCheck()
self.theDict.setLanguage(self.mainConf.spellLanguage)
self.hLight = GuiDocHighlighter(self.theQDoc, self.theParent)
self.hLight.setDict(self.theDict)
@@ -215,8 +221,7 @@ class GuiDocEditor(QTextEdit):
def setPwl(self, pwlFile):
if pwlFile is not None:
self.pwlFile = pwlFile
self.theDict = enchant.DictWithPWL(self.mainConf.spellLanguage,pwlFile)
self.hLight.setDict(self.theDict)
self.theDict.setLanguage(self.mainConf.spellLanguage, pwlFile)
return True
def setSpellCheck(self, theMode):
@@ -314,7 +319,7 @@ class GuiDocEditor(QTextEdit):
theWord = theCursor.selectedText()
if theWord == "":
return
if self.theDict.check(theWord):
if self.theDict.checkWord(theWord):
return
mnuSuggest = QMenu()
@@ -322,7 +327,7 @@ class GuiDocEditor(QTextEdit):
mnuHead = QAction(spIcon,"Spelling Suggestion", mnuSuggest)
mnuSuggest.addAction(mnuHead)
mnuSuggest.addSeparator()
theSuggest = self.theDict.suggest(theWord)
theSuggest = self.theDict.suggestWords(theWord)
if len(theSuggest) > 0:
for aWord in theSuggest:
mnuWord = QAction(aWord, mnuSuggest)
@@ -353,7 +358,7 @@ class GuiDocEditor(QTextEdit):
def _addWord(self, theCursor):
theWord = theCursor.selectedText().strip()
logger.info("Added '%s' to project dictionary" % theWord)
self.theDict.add_to_pwl(theWord)
self.theDict.addWord(theWord)
self.hLight.setDict(self.theDict)
self.hLight.rehighlightBlock(theCursor.block())
return
+1 -1
View File
@@ -234,7 +234,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
rxSpell = self.spellRx.globalMatch(theText.replace("_"," "), 0)
while rxSpell.hasNext():
rxMatch = rxSpell.next()
if not self.theDict.check(rxMatch.captured(0)):
if not self.theDict.checkWord(rxMatch.captured(0)):
if rxMatch.captured(0) == rxMatch.captured(0).upper():
continue
xPos = rxMatch.capturedStart(0)
+20
View File
@@ -18,4 +18,24 @@ logger = logging.getLogger(__name__)
class NWSpellCheck():
theDict = None
def __init__(self):
return
def setLanguage(self, theLang, projectDict=None):
return
def checkWord(self, theWord):
return True
def suggestWords(self, theWord):
return []
def addWord(self, newWord):
return
def listDictionaries(self):
return []
# END Class NWSpellCheck
+52
View File
@@ -0,0 +1,52 @@
# -*- 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]
"""
import logging
import enchant
import nw
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):
if projectDict is None:
self.theDict = enchant.Dict(theLang)
else:
self.theDict = enchant.DictWithPWL(theLang, projectDict)
logger.debug("Enchant spell checking for %s loaded" % theLang)
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_pwl(newWord)
return
def listDictionaries(self):
retList = []
for spTag, spProvider in enchant.list_dicts():
retList.append((spTag, "%s [%s]" % (spTag, spProvider.name)))
return retList
# END Class NWSpellEnchant