"""
Graphspell
Spellchecker based on a DAWG (Direct Acyclic Word Graph)
"""
# License: MPL 2
import traceback
import re
import json
#import uno
import unohelper
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
import helpers
from grammalecte.graphspell import SpellChecker
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):
"""Spellchecker class: will be loaded by LibreOffice"""
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")
sMainDicName = self.xOptionNode.getPropertyValue("main_dic_name")
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-"+sMainDicName+".json", "", 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:
# Graphspell
lSugg = []
for l in self.oGraphspell.suggest(aWord.rstrip(".")):
lSugg.extend(l)
return SpellAlternatives(aWord, tuple(lSugg))
# 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",),)