# Graphspell
#
# Spellchecker based on a DAWG (Direct Acyclic Word Graph)
import uno
import unohelper
import traceback
import re
import json
import helpers
from grammalecte.graphspell import SpellChecker
from com.sun.star.linguistic2 import XSupportedLocales, XSpellChecker, XSpellAlternatives
from com.sun.star.lang import XServiceInfo, XServiceName, XServiceDisplayName
from com.sun.star.lang import Locale
lLocale = {
# List of locales in LibreOffice
# https://cgit.freedesktop.org/libreoffice/core/tree/i18nlangtag/source/isolang/isolang.cxx
#('la', 'VA', ''), # Latin (for testing purpose)
('fr', 'FR', ''), # France
('fr', 'BE', ''), # Belgique
('fr', 'CA', ''), # Canada
('fr', 'CH', ''), # Suisse
('fr', 'LU', ''), # Luxembourg
#('fr', 'MC', ''), # Monaco
('fr', 'BF', ''), # Burkina Faso
('fr', 'BJ', ''), # Benin
('fr', 'CD', ''), # Congo
('fr', 'CI', ''), # Côte d’Ivoire
('fr', 'CM', ''), # Cameroun
('fr', 'MA', ''), # Maroc
('fr', 'ML', ''), # Mali
('fr', 'MU', ''), # Île Maurice
('fr', 'NE', ''), # Niger
('fr', 'RE', ''), # Réunion
('fr', 'SN', ''), # Sénégal
('fr', 'TG', '') # Togo
}
zElidedWords = re.compile("(?i)^(?:[ldnmtsjcçy]|qu|lorsqu|quoiqu|puisqu|jusqu)['’`‘]")
class Graphspell (unohelper.Base, XSpellChecker, XServiceInfo, XServiceName, XServiceDisplayName, XSupportedLocales):
def __init__ (self, ctx, *args):
try:
self.ctx = ctx
self.sServiceName = "com.sun.star.linguistic2.SpellChecker"
self.sImplementationName = "net.grammalecte.graphspell"
self.tSupportedServiceNames = (self.sServiceName, )
self.xSvMgr = ctx.ServiceManager
self.locales = tuple([ Locale(t[0], t[1], t[2]) for t in lLocale ])
self.xSettingNode = helpers.getConfigSetting("/org.openoffice.Lightproof_grammalecte/Other/", False)
self.xOptionNode = self.xSettingNode.getByName("o_fr")
personal_dic = ""
if (self.xOptionNode.getPropertyValue("use_personal_dic")):
sPersonalDicJSON = self.xOptionNode.getPropertyValue("personal_dic")
if sPersonalDicJSON:
try:
personal_dic = json.loads(sPersonalDicJSON)
except:
print("Graphspell: wrong personal_dic")
traceback.print_exc()
self.oGraphspell = SpellChecker("fr", "fr-allvars.bdic", "", "", personal_dic)
self.loadHunspell()
# print("Graphspell: init done")
except:
print("Graphspell: init failed")
traceback.print_exc()
def loadHunspell (self):
# Hunspell is a fallback spellchecker
try:
self.xHunspell = self.xSvMgr.createInstance("org.openoffice.lingu.MySpellSpellChecker")
except:
print("Hunspell: init failed")
traceback.print_exc()
self.xHunspell = False
self.bHunspell = False
else:
self.xHunspellLocale = Locale('fr', 'MC', '')
self.bHunspell = not bool(self.xOptionNode.getPropertyValue("use_graphspell_sugg"))
# XServiceName
def getServiceName (self):
return self.sImplementationName #self.sServiceName
# XServiceInfo
def getImplementationName (self):
return self.sImplementationName
def supportsService (self, sServiceName):
return (sServiceName in self.tSupportedServiceNames)
def getSupportedServiceNames (self):
return self.tSupportedServiceNames
# XSupportedLocales
def hasLocale (self, aLocale):
if aLocale in self.locales:
return True
for e in self.locales:
if aLocale.Language == e.Language and (e.Country == aLocale.Country or e.Country == ""):
return True
return False
def getLocales (self):
return self.locales
# XSpellChecker
# http://www.openoffice.org/api/docs/common/ref/com/sun/star/linguistic2/XSpellChecker.html
def isValid (self, aWord, rLocale, aProperties):
try:
aWord = zElidedWords.sub("", aWord.rstrip("."), count=1)
return self.oGraphspell.isValidToken(aWord)
# return self.xHunspell.isValid(aWord, self.xHunspellLocale, aProperties)
except:
traceback.print_exc()
return False
def spell (self, aWord, aLocale, aProperties):
"returns an object SpellAlternatives"
try:
if not self.bHunspell:
lSugg = []
for l in self.oGraphspell.suggest(aWord):
lSugg.extend(l)
return SpellAlternatives(aWord, tuple(lSugg))
else:
# fallback dictionary suggestions (Hunspell)
return self.xHunspell.spell(aWord, self.xHunspellLocale, aProperties)
except:
traceback.print_exc()
return None
# XServiceDisplayName
def getServiceDisplayName(self, aLocale):
return "Graphspell (fr)"
# Other
def listSpellChecker (self):
xLinguServiceManager = self.xSvMgr.createInstance("com.sun.star.linguistic2.LinguServiceManager")
lService = xLinguServiceManager.getAvailableServices('com.sun.star.linguistic2.SpellChecker', Locale("fr", "MC", ""))
for sSpellchecker in lService:
print(repr(sSpellchecker))
#if sSpellchecker == self.ImplementationName:
# continue
#self.xFallbackSpellChecker = self.xSvMgr.createInstance(sSpellchecker)
#if self.xFallbackSpellChecker:
# print("Spell checker: %s" % xSpellChecker)
# break
class SpellAlternatives (unohelper.Base, XSpellAlternatives):
def __init__ (self, sWord, lSugg):
try:
self.sWord = sWord
self.lSugg = lSugg
self.xLocale = Locale('fr', 'FR', '')
except:
traceback.print_exc()
# XSpellAlternatives
# http://www.openoffice.org/api/docs/common/ref/com/sun/star/linguistic2/XSpellAlternatives.html
def getWord (self):
return self.sWord
def getLocale (self):
return self.xLocale
def getFailureType (self):
return 4
# IS_NEGATIVE_WORD = 2
# The word is a negative one, that is, it should not be used.
# CAPTION_ERROR = 3
# The capitalization of the word is wrong.
# SPELLING_ERROR = 4
# The spelling of the word is wrong (or at least not known to be correct).
# No difference -> red underline
def getAlternativesCount (self):
return len(self.lSugg)
def getAlternatives (self):
return self.lSugg
g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(Graphspell, "net.grammalecte.graphspell", ("com.sun.star.linguistic2.SpellChecker",),)