Index: gc_core/js/lang_core/gc_engine.js ================================================================== --- gc_core/js/lang_core/gc_engine.js +++ gc_core/js/lang_core/gc_engine.js @@ -323,11 +323,11 @@ try { if (typeof(require) !== 'undefined') { var spellchecker = require("resource://grammalecte/graphspell/spellchecker.js"); _oSpellChecker = new spellchecker.SpellChecker("${lang}", "", "${dic_filename}.json"); } else { - _oSpellChecker = new SpellChecker("${lang}", sPath, "${dic_filename}.json"); + _oSpellChecker = new SpellChecker("${lang}", sPath, "${dic_main_filename_js}", "${dic_extended_filename_js}", "${dic_personal_filename_js}"); } _sAppContext = sContext; _dOptions = gc_options.getOptions(sContext).gl_shallowCopy(); // duplication necessary, to be able to reset to default } catch (e) { Index: gc_core/py/lang_core/gc_engine.py ================================================================== --- gc_core/py/lang_core/gc_engine.py +++ gc_core/py/lang_core/gc_engine.py @@ -290,11 +290,11 @@ def load (sContext="Python"): global _oSpellChecker global _sAppContext global _dOptions try: - _oSpellChecker = SpellChecker("${lang}", "${dic_filename}.bdic") + _oSpellChecker = SpellChecker("${lang}", "${dic_main_filename_py}", "${dic_extended_filename_py}", "${dic_personal_filename_py}") _sAppContext = sContext _dOptions = dict(gc_options.getOptions(sContext)) # duplication necessary, to be able to reset to default except: traceback.print_exc() Index: gc_core/py/oxt/Grammalecte.py ================================================================== --- gc_core/py/oxt/Grammalecte.py +++ gc_core/py/oxt/Grammalecte.py @@ -41,10 +41,12 @@ # store for results of big paragraphs self.dResult = {} self.nMaxRes = 1500 self.lLastRes = deque(maxlen=self.nMaxRes) self.nRes = 0 + #oSpellChecker = gce.getSpellChecker(); + #oSpellChecker.setPersonalDictionary("fr.personal.json") # XServiceName method implementations def getServiceName (self): return self.ImplementationName @@ -130,14 +132,14 @@ # XServiceDisplayName def getServiceDisplayName (self, aLocale): return gce.name # Grammalecte - def getDictionary (self): - return gce.getDictionary() + def getSpellChecker (self): + return gce.getSpellChecker() g_ImplementationHelper = unohelper.ImplementationHelper() g_ImplementationHelper.addImplementation(Grammalecte, "org.openoffice.comp.pyuno.Lightproof."+gce.pkg, ("com.sun.star.linguistic2.Proofreader",),) # g_ImplementationHelper.addImplementation( opt_handler.LightproofOptionsEventHandler, \ # "org.openoffice.comp.pyuno.LightproofOptionsEventHandler." + gce.pkg, ("com.sun.star.awt.XContainerWindowEventHandler",),) Index: gc_lang/fr/config.ini ================================================================== --- gc_lang/fr/config.ini +++ gc_lang/fr/config.ini @@ -12,23 +12,29 @@ link = http://grammalecte.net description = Correcteur grammatical pour le français. extras = README_fr.txt logo = logo.png -# lexicon source +# main dictionary lexicon_src = lexicons/French.lex -# binary dictionary file name dic_filename = fr -# binary dictionary name dic_name = French +# extended dictionary +lexicon_extended_src = lexicons/French.extended.lex +dic_extended_filename = fr.extended +dic_extended_name = Français - dictionnaire étendu +# personal dictionary +lexicon_personal_src = lexicons/French.personal.lex +dic_personal_filename = fr.personal +dic_personal_name = Français - dictionnaire personnel # Finite state automaton compression: 1, 2 (experimental) or 3 (experimental) fsa_method = 1 # stemming method: S for suffixes only, A for prefixes and suffixes stemming_method = S # LibreOffice -unopkg = C:/Program Files/LibreOffice 5/program/unopkg.com +unopkg = C:/Program Files/LibreOffice/program/unopkg.com oxt_version = 6.2 oxt_identifier = French.linguistic.resources.from.Dicollecte.by.OlivierR # Firefox fx_identifier = French-GC@grammalecte.net Index: gc_lang/fr/oxt/ContextMenu/ContextMenu.py ================================================================== --- gc_lang/fr/oxt/ContextMenu/ContextMenu.py +++ gc_lang/fr/oxt/ContextMenu/ContextMenu.py @@ -10,17 +10,17 @@ from com.sun.star.ui import XContextMenuInterceptor #from com.sun.star.ui.ContextMenuInterceptorAction import IGNORED #from com.sun.star.ui.ContextMenuInterceptorAction import EXECUTE_MODIFIED import grammalecte.fr.lexicographe as lxg -from grammalecte.ibdawg import IBDAWG -from grammalecte.echo import echo +from grammalecte.graphspell.spellchecker import SpellChecker +from grammalecte.graphspell.echo import echo import helpers xDesktop = None -oDict = None +oSpellChecker = None oLexicographe = None class MyContextMenuInterceptor (XContextMenuInterceptor, unohelper.Base): def __init__ (self, ctx): @@ -117,25 +117,25 @@ class JobExecutor (XJob, unohelper.Base): def __init__ (self, ctx): self.ctx = ctx global xDesktop - global oDict + global oSpellChecker global oLexicographe try: if not xDesktop: xDesktop = self.ctx.getServiceManager().createInstanceWithContext('com.sun.star.frame.Desktop', self.ctx) - if not oDict: + if not oSpellChecker: xCurCtx = uno.getComponentContext() oGC = self.ctx.ServiceManager.createInstanceWithContext("org.openoffice.comp.pyuno.Lightproof.grammalecte", self.ctx) - if hasattr(oGC, "getDictionary"): + if hasattr(oGC, "getSpellChecker"): # https://bugs.documentfoundation.org/show_bug.cgi?id=97790 - oDict = oGC.getDictionary() + oSpellChecker = oGC.getSpellChecker() else: - oDict = IBDAWG("French.bdic") + oSpellChecker = SpellChecker("${lang}", "${dic_filename}.bdic") if not oLexicographe: - oLexicographe = lxg.Lexicographe(oDict) + oLexicographe = lxg.Lexicographe(oSpellChecker) except: traceback.print_exc() def execute (self, args): if not args: Index: gc_lang/fr/webext/panel/lex_editor.js ================================================================== --- gc_lang/fr/webext/panel/lex_editor.js +++ gc_lang/fr/webext/panel/lex_editor.js @@ -617,10 +617,10 @@ }, export: function () { let xBlob = new Blob([ JSON.stringify(this.oIBDAWG.getJSON()) ], {type: 'application/json'}); let sURL = URL.createObjectURL(xBlob); - browser.downloads.download({ filename: "grammalecte_dictionnaire_personnel.json", url: sURL, saveAs: true }); + browser.downloads.download({ filename: "fr.personal.json", url: sURL, saveAs: true }); } } oBinaryDict.load(); Index: graphspell-js/spellchecker.js ================================================================== --- graphspell-js/spellchecker.js +++ graphspell-js/spellchecker.js @@ -49,14 +49,16 @@ } else { return new IBDAWG(dictionary, sPath); // dictionary can be a filename or a JSON object } } catch (e) { - console.log(e.message); + let sfDictionary = (typeof(dictionary) == "string") ? dictionary : dictionary.sLangName + "/" + dictionary.sFileName; if (bNecessary) { - throw e.message; + throw "Error: <" + sfDictionary + "> not loaded. " + e.message; } + console.log("Error: <" + sfDictionary + "> not loaded.") + console.log(e.message); return null; } } setMainDictionary (dictionary) { Index: graphspell/spellchecker.py ================================================================== --- graphspell/spellchecker.py +++ graphspell/spellchecker.py @@ -24,22 +24,24 @@ def __init__ (self, sLangCode, sfMainDic="", sfExtendedDic="", sfPersonalDic=""): "returns True if the main dictionary is loaded" self.sLangCode = sLangCode if not sfMainDic: sfMainDic = dDefaultDictionaries.get(sLangCode, "") - self.oMainDic = self._loadDictionary(sfMainDic) + self.oMainDic = self._loadDictionary(sfMainDic, True) self.oExtendedDic = self._loadDictionary(sfExtendedDic) self.oPersonalDic = self._loadDictionary(sfPersonalDic) - def _loadDictionary (self, sfDictionary): + def _loadDictionary (self, sfDictionary, bNecessary=False): "returns an IBDAWG object" if not sfDictionary: return None try: return ibdawg.IBDAWG(sfDictionary) - except: - print("Error: <" + sDicName + "> not loaded.") + except Exception as e: + if bNecessary: + raise Exception(str(e), "Error: <" + sfDictionary + "> not loaded.") + print("Error: <" + sfDictionary + "> not loaded.") traceback.print_exc() return None def setMainDictionary (self, sfDictionary): "returns True if the dictionary is loaded" @@ -91,13 +93,13 @@ def getMorph (self, sWord): "retrieves morphologies list, different casing allowed" lResult = self.oMainDic.getMorph(sWord) if self.oExtendedDic: - lResult.extends(self.oExtendedDic.getMorph(sWord)) + lResult.extend(self.oExtendedDic.getMorph(sWord)) if self.oPersonalDic: - lResult.extends(self.oPersonalDic.getMorph(sWord)) + lResult.extend(self.oPersonalDic.getMorph(sWord)) return lResult def suggest (self, sWord, nSuggLimit=10): "generator: returns 1, 2 or 3 lists of suggestions" yield self.oMainDic.suggest(sWord, nSuggLimit) Index: make.py ================================================================== --- make.py +++ make.py @@ -76,11 +76,11 @@ print("Building extension for Writer") spfZip = "_build/" + dVars['name'] + "-"+ dVars['lang'] +"-v" + dVars['version'] + '.oxt' hZip = zipfile.ZipFile(spfZip, mode='w', compression=zipfile.ZIP_DEFLATED) # Package and parser - copyGrammalectePyPackageInZipFile(hZip, spLangPack, dVars['dic_filename']+".bdic", "pythonpath/") + copyGrammalectePyPackageInZipFile(hZip, spLangPack, "pythonpath/") hZip.write("grammalecte-cli.py", "pythonpath/grammalecte-cli.py") # Extension files hZip.writestr("META-INF/manifest.xml", helpers.fileFile("gc_core/py/oxt/manifest.xml", dVars)) hZip.writestr("description.xml", helpers.fileFile("gc_core/py/oxt/description.xml", dVars)) @@ -154,26 +154,28 @@ def createPackageZip (sLang, dVars, spLangPack): "create server zip" spfZip = "_build/" + dVars['name'] + "-"+ dVars['lang'] +"-v" + dVars['version'] + '.zip' hZip = zipfile.ZipFile(spfZip, mode='w', compression=zipfile.ZIP_DEFLATED) - copyGrammalectePyPackageInZipFile(hZip, spLangPack, dVars['dic_filename']+".bdic") + copyGrammalectePyPackageInZipFile(hZip, spLangPack) for spf in ["grammalecte-cli.py", "grammalecte-server.py", "bottle.py", \ "grammalecte-server-options._global.ini", "grammalecte-server-options."+sLang+".ini", \ "README.txt", "LICENSE.txt", "LICENSE.fr.txt"]: hZip.write(spf) hZip.writestr("setup.py", helpers.fileFile("gc_lang/fr/setup.py", dVars)) -def copyGrammalectePyPackageInZipFile (hZip, spLangPack, sfDict, sAddPath=""): +def copyGrammalectePyPackageInZipFile (hZip, spLangPack, sAddPath=""): for sf in os.listdir("grammalecte"): if not os.path.isdir("grammalecte/"+sf): hZip.write("grammalecte/"+sf, sAddPath+"grammalecte/"+sf) for sf in os.listdir("grammalecte/graphspell"): if not os.path.isdir("grammalecte/graphspell/"+sf): hZip.write("grammalecte/graphspell/"+sf, sAddPath+"grammalecte/graphspell/"+sf) - hZip.write("grammalecte/graphspell/_dictionaries/"+sfDict, sAddPath+"grammalecte/graphspell/_dictionaries/"+sfDict) + for sf in os.listdir("grammalecte/graphspell/_dictionaries"): + if not os.path.isdir("grammalecte/graphspell/_dictionaries/"+sf): + hZip.write("grammalecte/graphspell/_dictionaries/"+sf, sAddPath+"grammalecte/graphspell/_dictionaries/"+sf) for sf in os.listdir(spLangPack): if not os.path.isdir(spLangPack+"/"+sf): hZip.write(spLangPack+"/"+sf, sAddPath+spLangPack+"/"+sf) @@ -302,24 +304,50 @@ if not os.path.isdir("graphspell-js/"+sf): file_util.copy_file("graphspell-js/"+sf, "grammalecte-js/graphspell") helpers.copyAndFileTemplate("graphspell-js/"+sf, "grammalecte-js/graphspell/"+sf, dVars) -def copyGraphspellDictionary (dVars, bJavaScript=False): - spfPyDic = "graphspell/_dictionaries/"+dVars['dic_filename']+".bdic" - spfJSDic = "graphspell-js/_dictionaries/"+dVars['dic_filename']+".json" - if not os.path.isfile(spfPyDic) or (bJavaScript and not os.path.isfile(spfJSDic)): - buildDictionary(dVars, bJavaScript) - file_util.copy_file(spfPyDic, "grammalecte/graphspell/_dictionaries") - file_util.copy_file(spfPyDic[:-5]+".info.txt", "grammalecte/graphspell/_dictionaries") - if bJavaScript: - file_util.copy_file(spfJSDic, "grammalecte-js/graphspell/_dictionaries") +def copyGraphspellDictionaries (dVars, bJavaScript=False, bExtendedDict=False, bPersonalDict=False): + dVars["dic_main_filename_py"] = "" + dVars["dic_main_filename_js"] = "" + dVars["dic_extended_filename_py"] = "" + dVars["dic_extended_filename_js"] = "" + dVars["dic_personal_filename_py"] = "" + dVars["dic_personal_filename_js"] = "" + lDict = [ ("main", dVars['dic_filename']) ] + if bExtendedDict: + lDict.append(("extended", dVars['dic_extended_filename'])) + if bPersonalDict: + lDict.append(("personal", dVars['dic_personal_filename'])) + for sType, sFileName in lDict: + spfPyDic = "graphspell/_dictionaries/" + sFileName + ".bdic" + spfJSDic = "graphspell-js/_dictionaries/" + sFileName + ".json" + if not os.path.isfile(spfPyDic) or (bJavaScript and not os.path.isfile(spfJSDic)): + buildDictionary(dVars, sType, bJavaScript) + print(spfPyDic) + file_util.copy_file(spfPyDic, "grammalecte/graphspell/_dictionaries") + dVars['dic_'+sType+'_filename_py'] = sFileName + '.bdic' + if bJavaScript: + file_util.copy_file(spfJSDic, "grammalecte-js/graphspell/_dictionaries") + dVars['dic_'+sType+'_filename_js'] = sFileName + '.json' -def buildDictionary (dVars, bJavaScript): - lex_build.build(dVars['lexicon_src'], dVars['lang'], dVars['lang_name'], dVars['dic_filename'], \ - bJavaScript, dVars['dic_name'], dVars['stemming_method'], int(dVars['fsa_method'])) +def buildDictionary (dVars, sType, bJavaScript=False): + if sType == "main": + spfLexSrc = dVars['lexicon_src'] + sfDictDst = dVars['dic_filename'] + sDicName = dVars['dic_name'] + elif sType == "extended": + spfLexSrc = dVars['lexicon_extended_src'] + sfDictDst = dVars['dic_extended_filename'] + sDicName = dVars['dic_extended_name'] + elif sType == "personal": + spfLexSrc = dVars['lexicon_personal_src'] + sfDictDst = dVars['dic_personal_filename'] + sDicName = dVars['dic_personal_name'] + lex_build.build(spfLexSrc, dVars['lang'], dVars['lang_name'], sfDictDst, bJavaScript, sDicName, dVars['stemming_method'], int(dVars['fsa_method'])) + def main (): print("Python: " + sys.version) xParser = argparse.ArgumentParser() @@ -330,10 +358,12 @@ xParser.add_argument("-d", "--dict", help="generate FSA dictionary", action="store_true") xParser.add_argument("-t", "--tests", help="run unit tests", action="store_true") xParser.add_argument("-p", "--perf", help="run performance tests", action="store_true") xParser.add_argument("-pm", "--perf_memo", help="run performance tests and store results in perf_memo.txt", action="store_true") xParser.add_argument("-js", "--javascript", help="JavaScript build for Firefox", action="store_true") + xParser.add_argument("-aed", "--add_extended_dictionary", help="add extended dictionary to the build", action="store_true") + xParser.add_argument("-apd", "--add_personal_dictionary", help="add personal dictionary to the build", action="store_true") xParser.add_argument("-fx", "--firefox", help="Launch Firefox Developper for WebExtension testing", action="store_true") xParser.add_argument("-we", "--web_ext", help="Launch Firefox Nightly for WebExtension testing", action="store_true") xParser.add_argument("-tb", "--thunderbird", help="Launch Thunderbird", action="store_true") xParser.add_argument("-i", "--install", help="install the extension in Writer (path of unopkg must be set in config.ini)", action="store_true") xArgs = xParser.parse_args() @@ -352,10 +382,15 @@ for sLang in xArgs.lang: if os.path.exists("gc_lang/"+sLang) and os.path.isdir("gc_lang/"+sLang): xConfig = getConfig(sLang) dVars = xConfig._sections['args'] + if not dVars["lexicon_extended_src"]: + xArgs.add_extended_dictionary = False + if not dVars["lexicon_personal_src"]: + xArgs.add_personal_dictionary = False + # build data build_data_module = None if xArgs.build_data_before or xArgs.build_data_after: # lang data try: @@ -363,16 +398,20 @@ except ImportError: print("# Error. Couldn’t import file build_data.py in folder gc_lang/"+sLang) if build_data_module and xArgs.build_data_before: build_data_module.before('gc_lang/'+sLang, dVars, xArgs.javascript) if xArgs.dict: - buildDictionary(dVars, xArgs.javascript) + buildDictionary(dVars, "main", xArgs.javascript) + if xArgs.add_extended_dictionary: + buildDictionary(dVars, "extended", xArgs.javascript) + if xArgs.add_personal_dictionary: + buildDictionary(dVars, "personal", xArgs.javascript) if build_data_module and xArgs.build_data_after: build_data_module.after('gc_lang/'+sLang, dVars, xArgs.javascript) # copy dictionaries from Graphspell - copyGraphspellDictionary(dVars, xArgs.javascript) + copyGraphspellDictionaries(dVars, xArgs.javascript, xArgs.add_extended_dictionary, xArgs.add_personal_dictionary) # make sVersion = create(sLang, xConfig, xArgs.install, xArgs.javascript, ) # tests Index: misc/wconsole.bat ================================================================== --- misc/wconsole.bat +++ misc/wconsole.bat @@ -1,9 +1,9 @@ Rem Create console for LibreOffice at launch -"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe" /subsystem:console "C:\Program Files\LibreOffice 5\program\soffice.exe" -"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe" /subsystem:console "C:\Program Files\LibreOffice 5\program\soffice.bin" +"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe" /subsystem:console "C:\Program Files\LibreOffice\program\soffice.exe" +"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe" /subsystem:console "C:\Program Files\LibreOffice\program\soffice.bin" Rem "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe" /subsystem:console "C:\cygwin64\home\Z7\bibisect-win32-5.3\instdir\program\soffice.exe" Rem "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe" /subsystem:console "C:\cygwin64\home\Z7\bibisect-win32-5.3\instdir\program\soffice.bin"