Index: compile_rules_js_convert.py ================================================================== --- compile_rules_js_convert.py +++ compile_rules_js_convert.py @@ -25,10 +25,11 @@ sCode = sCode.replace("False", "false") sCode = sCode.replace("True", "true") sCode = sCode.replace("None", "null") sCode = sCode.replace("bool", "Boolean") # methods + sCode = sCode.replace("_oSpellChecker", "gc_engine.oSpellChecker") sCode = sCode.replace(".__len__()", ".length") sCode = sCode.replace(".endswith", ".endsWith") sCode = sCode.replace(".find", ".indexOf") sCode = sCode.replace(".startswith", ".startsWith") sCode = sCode.replace(".lower", ".toLowerCase") @@ -43,10 +44,11 @@ sCode = sCode.replace(".lstrip", ".gl_trimLeft") sCode = sCode.replace(".rstrip", ".gl_trimRight") sCode = sCode.replace('.replace("."', r".replace(/\./g") sCode = sCode.replace('.replace("..."', r".replace(/\.\.\./g") sCode = re.sub(r'.replace\("([^"]+)" ?,', ".replace(/\\1/g,", sCode) + # regex sCode = re.sub('m\\.group\\((\\d+)\\) +in +(a[a-zA-Z]+)', "\\2.has(m[\\1])", sCode) sCode = re.sub('(lToken\\S+) +in +(a[a-zA-Z]+)', "\\2.has(\\1)", sCode) # slices sCode = sCode.replace("[:m.start()]", ".slice(0,m.index)") 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 @@ -28,25 +28,16 @@ aNew[i] = aArray[i].slice(0,1).toUpperCase() + aArray[i].slice(1); } return aNew; } - -// data -let _sAppContext = ""; // what software is running -let _dOptions = null; -let _dOptionsColors = null; -let _oSpellChecker = null; -let _oTokenizer = null; -let _aIgnoredRules = new Set(); - - function echo (x) { console.log(x); return true; } +var _sAppContext = ""; var gc_engine = { //// Informations @@ -55,36 +46,41 @@ pkg: "${implname}", name: "${name}", version: "${version}", author: "${author}", + //// Tools + oSpellChecker: null, + oTokenizer: null, + + //// Data + aIgnoredRules: new Set(), + oOptionsColors: null, + //// Initialization load: function (sContext="JavaScript", sColorType="aRGB", sPath="") { try { - if(typeof(process) !== 'undefined') { + _sAppContext = sContext; + if (typeof(process) !== 'undefined') { var spellchecker = require("../graphspell/spellchecker.js"); - _oSpellChecker = new spellchecker.SpellChecker("${lang}", "", "${dic_main_filename_js}", "${dic_community_filename_js}", "${dic_personal_filename_js}"); - } else if (typeof(require) !== 'undefined') { - var spellchecker = require("resource://grammalecte/graphspell/spellchecker.js"); - _oSpellChecker = new spellchecker.SpellChecker("${lang}", "", "${dic_main_filename_js}", "${dic_community_filename_js}", "${dic_personal_filename_js}"); + this.oSpellChecker = new spellchecker.SpellChecker("${lang}", "", "${dic_main_filename_js}", "${dic_community_filename_js}", "${dic_personal_filename_js}"); } else { - _oSpellChecker = new SpellChecker("${lang}", sPath, "${dic_main_filename_js}", "${dic_community_filename_js}", "${dic_personal_filename_js}"); + this.oSpellChecker = new SpellChecker("${lang}", sPath, "${dic_main_filename_js}", "${dic_community_filename_js}", "${dic_personal_filename_js}"); } - _sAppContext = sContext; - _dOptions = gc_options.getOptions(sContext).gl_shallowCopy(); // duplication necessary, to be able to reset to default - _dOptionsColors = gc_options.getOptionsColors(sContext, sColorType); - _oTokenizer = _oSpellChecker.getTokenizer(); - _oSpellChecker.activateStorage(); + this.oSpellChecker.activateStorage(); + this.oTokenizer = this.oSpellChecker.getTokenizer(); + gc_options.load(sContext) + this.oOptionsColors = gc_options.getOptionsColors(sContext, sColorType); } catch (e) { console.error(e); } }, getSpellChecker: function () { - return _oSpellChecker; + return this.oSpellChecker; }, //// Rules getRules: function (bParagraph) { @@ -93,19 +89,19 @@ } return gc_rules.lParagraphRules; }, ignoreRule: function (sRuleId) { - _aIgnoredRules.add(sRuleId); + this.aIgnoredRules.add(sRuleId); }, resetIgnoreRules: function () { - _aIgnoredRules.clear(); + this.aIgnoredRules.clear(); }, reactivateRule: function (sRuleId) { - _aIgnoredRules.delete(sRuleId); + this.aIgnoredRules.delete(sRuleId); }, listRules: function* (sFilter=null) { // generator: returns tuple (sOption, sLineId, sRuleId) try { @@ -130,29 +126,27 @@ }, //// Options setOption: function (sOpt, bVal) { - if (_dOptions.has(sOpt)) { - _dOptions.set(sOpt, bVal); - } + gc_options.setOption(sOpt, bVal); }, setOptions: function (dOpt) { - _dOptions.gl_updateOnlyExistingKeys(dOpt); + gc_options.setOptions(dOpt); }, getOptions: function () { - return _dOptions; + return gc_options.getOptions(); }, getDefaultOptions: function () { - return gc_options.getOptions(_sAppContext).gl_shallowCopy(); + return gc_options.getDefaultOptions(); }, resetOptions: function () { - _dOptions = gc_options.getOptions(_sAppContext).gl_shallowCopy(); + gc_options.resetOptions(); }, //// Parsing parse: function (sText, sCountry="${country_default}", bDebug=false, dOptions=null, bContext=false, bFullInfo=false) { @@ -196,11 +190,11 @@ return s; } parse (sCountry="${country_default}", bDebug=false, dOptions=null, bContext=false, bFullInfo=false) { // analyses and returns an iterable of errors or (with option ) a list of sentences with tokens and errors - let dOpt = dOptions || _dOptions; + let dOpt = dOptions || gc_options.dOptions; let bShowRuleId = option('idrule'); // parse paragraph try { this.parseText(this.sText, this.sText0, true, 0, sCountry, dOpt, bShowRuleId, bDebug, bContext); } @@ -219,11 +213,11 @@ for (let [iStart, iEnd] of text.getSentenceBoundaries(sText)) { try { this.sSentence = sText.slice(iStart, iEnd); this.sSentence0 = this.sText0.slice(iStart, iEnd); this.nOffsetWithinParagraph = iStart; - this.lToken = Array.from(_oTokenizer.genTokens(this.sSentence, true)); + this.lToken = Array.from(gc_engine.oTokenizer.genTokens(this.sSentence, true)); this.dTokenPos.clear(); for (let dToken of this.lToken) { if (dToken["sType"] != "INFO") { this.dTokenPos.set(dToken["nStart"], dToken); } @@ -230,11 +224,11 @@ } if (bFullInfo) { oSentence = { "nStart": iStart, "nEnd": iEnd, "sSentence": this.sSentence, "lToken": Array.from(this.lToken) }; for (let oToken of oSentence["lToken"]) { if (oToken["sType"] == "WORD") { - oToken["bValidToken"] = _oSpellChecker.isValidToken(oToken["sValue"]); + oToken["bValidToken"] = gc_engine.oSpellChecker.isValidToken(oToken["sValue"]); } } // the list of tokens is duplicated, to keep all tokens from being deleted when analysis } this.parseText(this.sSentence, this.sSentence0, false, iStart, sCountry, dOpt, bShowRuleId, bDebug, bContext); @@ -300,11 +294,11 @@ } } } else if (!sOption || option(sOption)) { for (let [zRegex, bUppercase, sLineId, sRuleId, nPriority, lActions, lGroups, lNegLookBefore] of lRuleGroup) { - if (!_aIgnoredRules.has(sRuleId)) { + if (!gc_engine.aIgnoredRules.has(sRuleId)) { while ((m = zRegex.gl_exec2(sText, lGroups, lNegLookBefore)) !== null) { let bCondMemo = null; for (let [sFuncCond, cActionType, sWhat, ...eAct] of lActions) { // action in lActions: [ condition, action type, replacement/suggestion/action[, iGroup[, message, URL]] ] try { @@ -371,11 +365,11 @@ } update (sSentence, bDebug=false) { // update and retokenize this.sSentence = sSentence; - let lNewToken = Array.from(_oTokenizer.genTokens(sSentence, true)); + let lNewToken = Array.from(gc_engine.oTokenizer.genTokens(sSentence, true)); for (let oToken of lNewToken) { if (this.dTokenPos.gl_get(oToken["nStart"], {}).hasOwnProperty("lMorph")) { oToken["lMorph"] = this.dTokenPos.get(oToken["nStart"])["lMorph"]; } if (this.dTokenPos.gl_get(oToken["nStart"], {}).hasOwnProperty("aTags")) { @@ -469,11 +463,11 @@ } // analysable tokens if (oToken["sType"].slice(0,4) == "WORD") { // token lemmas if (oNode.hasOwnProperty("")) { - for (let sLemma of _oSpellChecker.getLemma(oToken["sValue"])) { + for (let sLemma of gc_engine.oSpellChecker.getLemma(oToken["sValue"])) { if (oNode[""].hasOwnProperty(sLemma)) { if (bDebug) { console.log(" MATCH: >" + sLemma); } yield { "iToken1": iToken1, "iNode": oNode[""][sLemma] }; @@ -481,11 +475,11 @@ } } } // morph arcs if (oNode.hasOwnProperty("")) { - let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : _oSpellChecker.getMorph(oToken["sValue"]); + let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken["sValue"]); if (lMorph.length > 0) { for (let sSearch in oNode[""]) { if (!sSearch.includes("¬")) { // no anti-pattern if (lMorph.some(sMorph => (sMorph.includes(sSearch)))) { @@ -525,11 +519,11 @@ } } } // regex morph arcs if (oNode.hasOwnProperty("")) { - let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : _oSpellChecker.getMorph(oToken["sValue"]); + let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken["sValue"]); if (lMorph.length > 0) { for (let sRegex in oNode[""]) { if (!sRegex.includes("¬")) { // no anti-pattern if (lMorph.some(sMorph => (sMorph.search(sRegex) !== -1))) { @@ -838,11 +832,11 @@ "nStart": nStart, "nEnd": nEnd, "sLineId": sLineId, "sRuleId": sRuleId, "sType": sOption || "notype", - "aColor": _dOptionsColors[sOption], + "aColor": gc_engine.oOptionsColors[sOption], "sMessage": sMessage, "aSuggestions": lSugg, "URL": sURL } if (bContext) { @@ -1031,11 +1025,11 @@ //////// Common functions function option (sOpt) { // return true if option sOpt is active - return _dOptions.get(sOpt); + return gc_options.dOptions.gl_get(sOpt, false); } var re = { search: function (sRegex, sText) { if (sRegex.startsWith("(?i)")) { @@ -1121,11 +1115,11 @@ // for debugging: info of word if (!aWord) { console.log("> nothing to find"); return true; } - let lMorph = _oSpellChecker.getMorph(aWord[1]); + let lMorph = gc_engine.oSpellChecker.getMorph(aWord[1]); if (lMorph.length === 0) { console.log("> not in dictionary"); return true; } if (dTokenPos.has(aWord[0])) { @@ -1138,11 +1132,11 @@ function morph (dTokenPos, aWord, sPattern, sNegPattern, bNoWord=false) { // analyse a tuple (position, word), returns true if not sNegPattern in word morphologies and sPattern in word morphologies (disambiguation on) if (!aWord) { return bNoWord; } - let lMorph = (dTokenPos.has(aWord[0]) && dTokenPos.get(aWord[0]))["lMorph"] ? dTokenPos.get(aWord[0])["lMorph"] : _oSpellChecker.getMorph(aWord[1]); + let lMorph = (dTokenPos.has(aWord[0]) && dTokenPos.get(aWord[0]))["lMorph"] ? dTokenPos.get(aWord[0])["lMorph"] : gc_engine.oSpellChecker.getMorph(aWord[1]); if (lMorph.length === 0) { return false; } if (sNegPattern) { // check negative condition @@ -1160,11 +1154,11 @@ return lMorph.some(sMorph => (sMorph.search(sPattern) !== -1)); } function analyse (sWord, sPattern, sNegPattern) { // analyse a word, returns True if not sNegPattern in word morphologies and sPattern in word morphologies (disambiguation off) - let lMorph = _oSpellChecker.getMorph(sWord); + let lMorph = gc_engine.oSpellChecker.getMorph(sWord); if (lMorph.length === 0) { return false; } if (sNegPattern) { // check negative condition @@ -1218,16 +1212,16 @@ lMorph = oToken["lMorph"]; } else { if (nLeft !== null) { let sValue = (nRight !== null) ? oToken["sValue"].slice(nLeft, nRight) : oToken["sValue"].slice(nLeft); - lMorph = _oSpellChecker.getMorph(sValue); + lMorph = gc_engine.oSpellChecker.getMorph(sValue); if (bMemorizeMorph) { oToken["lMorph"] = lMorph; } } else { - lMorph = _oSpellChecker.getMorph(oToken["sValue"]); + lMorph = gc_engine.oSpellChecker.getMorph(oToken["sValue"]); } } if (lMorph.length == 0) { return false; } @@ -1250,16 +1244,16 @@ function g_analyse (oToken, sPattern, sNegPattern="", nLeft=null, nRight=null, bMemorizeMorph=true) { // analyse a token, return True if not in morphologies and in morphologies let lMorph; if (nLeft !== null) { let sValue = (nRight !== null) ? oToken["sValue"].slice(nLeft, nRight) : oToken["sValue"].slice(nLeft); - lMorph = _oSpellChecker.getMorph(sValue); + lMorph = gc_engine.oSpellChecker.getMorph(sValue); if (bMemorizeMorph) { oToken["lMorph"] = lMorph; } } else { - lMorph = _oSpellChecker.getMorph(oToken["sValue"]); + lMorph = gc_engine.oSpellChecker.getMorph(oToken["sValue"]); } if (lMorph.length == 0) { return false; } // check negative condition @@ -1278,11 +1272,11 @@ return lMorph.some(sMorph => (sMorph.search(sPattern) !== -1)); } function g_merged_analyse (oToken1, oToken2, cMerger, sPattern, sNegPattern="", bSetMorph=true) { // merge two token values, return True if not in morphologies and in morphologies (disambiguation off) - let lMorph = _oSpellChecker.getMorph(oToken1["sValue"] + cMerger + oToken2["sValue"]); + let lMorph = gc_engine.oSpellChecker.getMorph(oToken1["sValue"] + cMerger + oToken2["sValue"]); if (lMorph.length == 0) { return false; } // check negative condition if (sNegPattern) { @@ -1362,11 +1356,11 @@ } if (!dTokenPos.has(nPos)) { console.log("Error. There should be a token at this position: ", nPos); return true; } - let lMorph = _oSpellChecker.getMorph(sWord); + let lMorph = gc_engine.oSpellChecker.getMorph(sWord); if (lMorph.length === 0 || lMorph.length === 1) { return true; } let lSelect = lMorph.filter( sMorph => sMorph.search(sPattern) !== -1 ); if (lSelect.length > 0) { @@ -1385,11 +1379,11 @@ } if (!dTokenPos.has(nPos)) { console.log("Error. There should be a token at this position: ", nPos); return true; } - let lMorph = _oSpellChecker.getMorph(sWord); + let lMorph = gc_engine.oSpellChecker.getMorph(sWord); if (lMorph.length === 0 || lMorph.length === 1) { return true; } let lSelect = lMorph.filter( sMorph => sMorph.search(sPattern) === -1 ); if (lSelect.length > 0) { @@ -1410,11 +1404,11 @@ //// Disambiguation for graph rules function g_select (oToken, sPattern, lDefault=null) { // select morphologies for according to , always return true - let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : _oSpellChecker.getMorph(oToken["sValue"]); + let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken["sValue"]); if (lMorph.length === 0 || lMorph.length === 1) { if (lDefault) { oToken["lMorph"] = lDefault; } return true; @@ -1430,11 +1424,11 @@ return true; } function g_exclude (oToken, sPattern, lDefault=null) { // select morphologies for according to , always return true - let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : _oSpellChecker.getMorph(oToken["sValue"]); + let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken["sValue"]); if (lMorph.length === 0 || lMorph.length === 1) { if (lDefault) { oToken["lMorph"] = lDefault; } return true; @@ -1450,19 +1444,19 @@ return true; } function g_add_morph (oToken, sNewMorph) { // Disambiguation: add a morphology to a token - let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : _oSpellChecker.getMorph(oToken["sValue"]); + let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken["sValue"]); lMorph.push(...sNewMorph.split("|")); oToken["lMorph"] = lMorph; return true; } function g_rewrite (oToken, sToReplace, sReplace) { // Disambiguation: rewrite morphologies - let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : _oSpellChecker.getMorph(oToken["sValue"]); + let lMorph = (oToken.hasOwnProperty("lMorph")) ? oToken["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken["sValue"]); oToken["lMorph"] = lMorph.map(s => s.replace(sToReplace, sReplace)); return true; } function g_define (oToken, sMorphs) { @@ -1474,11 +1468,11 @@ function g_define_from (oToken, nLeft=null, nRight=null) { let sValue = oToken["sValue"]; if (nLeft !== null) { sValue = (nRight !== null) ? sValue.slice(nLeft, nRight) : sValue.slice(nLeft); } - oToken["lMorph"] = _oSpellChecker.getMorph(sValue); + oToken["lMorph"] = gc_engine.oSpellChecker.getMorph(sValue); return true; } function g_change_meta (oToken, sType) { // Disambiguation: change type of token Index: gc_core/js/lang_core/gc_options.js ================================================================== --- gc_core/js/lang_core/gc_options.js +++ gc_core/js/lang_core/gc_options.js @@ -1,58 +1,103 @@ -// Options for Grammalecte +// Grammar checker options manager /* jshint esversion:6 */ /* jslint esversion:6 */ /* global exports */ ${map} var gc_options = { - getOptions: function (sContext="JavaScript") { - if (this.dOpt.hasOwnProperty(sContext)) { - return this.dOpt[sContext]; + + dOptions: new Map(), + + sAppContext: "JavaScript", + + load: function (sContext="JavaScript") { + this.sAppContext = sContext; + this.dOptions = this.getDefaultOptions(sContext); + }, + + setOption: function (sOpt, bVal) { + if (this.dOptions.has(sOpt)) { + this.dOptions.set(sOpt, bVal); + } + }, + + setOptions: function (dOpt) { + this.dOptions.gl_updateOnlyExistingKeys(dOpt); + }, + + getOptions: function () { + return this.dOptions.gl_shallowCopy(); + }, + + resetOptions: function () { + this.dOptions = this.getDefaultOptions(this._sAppContext); + }, + + getDefaultOptions: function (sContext="") { + if (!sContext) { + sContext = this.sAppContext; + } + if (this.oDefaultOpt.hasOwnProperty(sContext)) { + return this.oDefaultOpt[sContext].gl_shallowCopy(); + } + return this.oDefaultOpt["JavaScript"].gl_shallowCopy(); + }, + + getOptionLabels: function (sLang="${sLang}") { + if (this.oOptLabel.hasOwnProperty(sLang)) { + return this.oOptLabel[sLang]; } - return this.dOpt["JavaScript"]; + return this.oOptLabel["{$sLang}"]; }, getOptionsColors: function (sTheme="Default", sColorType="aRGB") { - let dOptColor = (this.dOptColor.hasOwnProperty(sTheme)) ? this.dOptColor[sTheme] : this.dOptColor["Default"]; - let dColorType = (this.dColorType.hasOwnProperty(sColorType)) ? this.dColorType[sColorType] : this.dColorType["aRGB"]; - let dColor = {}; + let oOptColor = (this.oOptColor.hasOwnProperty(sTheme)) ? this.oOptColor[sTheme] : this.oOptColor["Default"]; + let oColorType = (this.oColorType.hasOwnProperty(sColorType)) ? this.oColorType[sColorType] : this.oColorType["aRGB"]; + let oColor = {}; try { - for (let [sOpt, sColor] of Object.entries(dOptColor)) { - dColor[sOpt] = dColorType[sColor]; + for (let [sOpt, sColor] of Object.entries(oOptColor)) { + oColor[sOpt] = oColorType[sColor]; } - return dColor; + return oColor; } catch (e) { console.error(e); return {}; } }, lStructOpt: ${lStructOpt}, - dOpt: { + oDefaultOpt: { "JavaScript": new Map (${dOptJavaScript}), "Firefox": new Map (${dOptFirefox}), "Thunderbird": new Map (${dOptThunderbird}), }, - dColorType: ${dColorType}, + oColorType: ${dColorType}, - dOptColor: ${dOptColor}, + oOptColor: ${dOptColor}, - dOptLabel: ${dOptLabel} + oOptLabel: ${dOptLabel} }; if (typeof(exports) !== 'undefined') { + exports.dOptions = gc_options.dOptions; + exports.sAppContext = gc_options.sAppContext; + exports.load = gc_options.load; + exports.setOption = gc_options.setOption; + exports.setOptions = gc_options.setOptions; + exports.resetOptions = gc_options.resetOptions; + exports.getDefaultOptions = gc_options.getDefaultOptions; exports.getOptions = gc_options.getOptions; exports.getOptionsColors = gc_options.getOptionsColors; exports.lStructOpt = gc_options.lStructOpt; - exports.dOpt = gc_options.dOpt; + exports.oDefaultOpt = gc_options.oDefaultOpt; exports.dColorType = gc_options.dColorType; - exports.dOptColor = gc_options.dOptColor; - exports.dOptLabel = gc_options.dOptLabel; + exports.oOptColor = gc_options.oOptColor; + exports.oOptLabel = gc_options.oOptLabel; } 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 @@ -43,19 +43,20 @@ # Modules _rules = None # module gc_rules _rules_graph = None # module gc_rules_graph -# Data -_sAppContext = "" # what software is running -_dOptions = None -_dOptionsColors = None +# Tools _oSpellChecker = None _oTokenizer = None + +# Data +_sAppContext = "" # what software is running _aIgnoredRules = set() # Writer underlining style +_dOptionsColors = None _bMulticolor = True _nUnderliningStyle = 0 #### Initialization @@ -62,20 +63,19 @@ def load (sContext="Python", sColorType="aRGB"): "initialization of the grammar checker" global _oSpellChecker global _sAppContext - global _dOptions global _dOptionsColors global _oTokenizer try: - _oSpellChecker = SpellChecker("${lang}", "${dic_main_filename_py}", "${dic_community_filename_py}", "${dic_personal_filename_py}") _sAppContext = sContext - _dOptions = gc_options.getOptions(sContext).copy() # duplication necessary, to be able to reset to default - _dOptionsColors = gc_options.getOptionsColors(sContext, sColorType) + _oSpellChecker = SpellChecker("${lang}", "${dic_main_filename_py}", "${dic_community_filename_py}", "${dic_personal_filename_py}") + _oSpellChecker.activateStorage() _oTokenizer = _oSpellChecker.getTokenizer() - _oSpellChecker.activateStorage() + gc_options.load(sContext) + _dOptionsColors = gc_options.getOptionsColors(sContext, sColorType) except: traceback.print_exc() def getSpellChecker (): @@ -156,51 +156,45 @@ echo("List of rules. Filter: << " + str(sFilter) + " >>") for sOption, sLineId, sRuleId, sType in listRules(sFilter): echo("{:<8} {:<10} {:<10} {}".format(sOption, sLineId, sRuleId, sType)) -#### Options +#### Options (just calls to gc_options, to keep for compatibility) def setOption (sOpt, bVal): "set option with if it exists" - if sOpt in _dOptions: - _dOptions[sOpt] = bVal + gc_options.setOption(sOpt, bVal) def setOptions (dOpt): "update the dictionary of options with " - for sKey, bVal in dOpt.items(): - if sKey in _dOptions: - _dOptions[sKey] = bVal + gc_options.setOptions(dOpt) def getOptions (): "return the dictionary of current options" - return _dOptions + return gc_options.getOptions() def getDefaultOptions (): "return the dictionary of default options" - return gc_options.getOptions(_sAppContext).copy() + return gc_options.getDefaultOptions() -def getOptionsLabels (sLang): +def getOptionsLabels (sLang="${lang}"): "return options labels" - return gc_options.getUI(sLang) + return gc_options.getOptionLabels(sLang) def displayOptions (sLang="${lang}"): - "display the list of grammar checking options" - echo("Options:") - echo("\n".join( [ k+":\t"+str(v)+"\t"+gc_options.getUI(sLang).get(k, ("?", ""))[0] for k, v in sorted(_dOptions.items()) ] )) - echo("") + "print options" + gc_options.displayOptions(sLang) def resetOptions (): "set options to default values" - global _dOptions - _dOptions = getDefaultOptions() + gc_options.resetOptions() def setWriterUnderliningStyle (sStyle="BOLDWAVE", bMulticolor=True): "set underlining style for Writer (WAVE, BOLDWAVE, BOLD)" global _nUnderliningStyle @@ -262,11 +256,11 @@ return s def parse (self, sCountry="${country_default}", bDebug=False, dOptions=None, bContext=False, bFullInfo=False): "analyses and returns an iterable of errors or (with option ) paragraphs errors and sentences with tokens and errors" #sText = unicodedata.normalize("NFC", sText) - dOpt = dOptions or _dOptions + dOpt = dOptions or gc_options.dOptions bShowRuleId = option('idrule') # parse paragraph try: self.parseText(self.sText, self.sText0, True, 0, sCountry, dOpt, bShowRuleId, bDebug, bContext) except: @@ -881,11 +875,11 @@ #### common functions def option (sOpt): "return True if option is active" - return _dOptions.get(sOpt, False) + return gc_options.dOptions.get(sOpt, False) #### Functions to get text outside pattern scope # warning: check compile_rules.py to understand how it works Index: gc_core/py/lang_core/gc_options.py ================================================================== --- gc_core/py/lang_core/gc_options.py +++ gc_core/py/lang_core/gc_options.py @@ -1,42 +1,91 @@ """ -Grammar checker default options +Grammar checker options manager """ # generated code, do not edit +# template: +# variables generated in + import traceback -def getUI (sLang): + +dOptions = {} + +_sAppContext = "Python" + + +def load (sContext="Python"): + global dOptions + global _sAppContext + _sAppContext = sContext + dOptions = getDefaultOptions(sContext) + + +def setOption (sOpt, bVal): + "set option with if it exists" + if sOpt in dOptions: + dOptions[sOpt] = bVal + + +def setOptions (dOpt): + "update the dictionary of options with , only known options are updated" + for sKey, bVal in dOpt.items(): + if sKey in dOptions: + dOptions[sKey] = bVal + + +def getOptions (): + "return a copy of options as dictionary" + return dOptions.copy() + + +def resetOptions (): + "set options to default values" + global dOptions + dOptions = getDefaultOptions() + + +def displayOptions (sLang="${lang}"): + "display the list of grammar checking options" + print("Options:") + print("\n".join( [ k+":\t"+str(v)+"\t"+getOptionLabels(sLang).get(k, ("?", ""))[0] for k, v in sorted(dOptions.items()) ] )) + print("") + + +def getOptionLabels (sLang="${sLang}"): "returns dictionary of UI labels" if sLang in _dOptLabel: return _dOptLabel[sLang] - return _dOptLabel["fr"] + return _dOptLabel["${sLang}"] -def getOptions (sContext="Python"): +def getDefaultOptions (sContext=""): "returns dictionary of options" - if sContext in _dOpt: - return _dOpt[sContext] - return _dOpt["Python"] + if not sContext: + sContext = _sAppContext + if sContext in _dDefaultOpt: + return _dDefaultOpt[sContext].copy() # duplication necessary, to be able to reset to default + return _dDefaultOpt["Python"].copy() # duplication necessary, to be able to reset to default def getOptionsColors (sTheme="Default", sColorType="aRGB"): "returns dictionary of options colors" dOptColor = _dOptColor[sTheme] if sTheme in _dOptColor else _dOptColor["Default"] dColorType = _dColorType[sColorType] if sColorType in _dColorType else _dColorType["aRGB"] try: - return { sOpt: dColorType[sColor] for sOpt, sColor in dOptColor.items() } + return { sOpt: dColorType[sColor] for sOpt, sColor in dOptColor.items() } except KeyError: traceback.print_exc() return {} lStructOpt = ${lStructOpt} -_dOpt = { +_dDefaultOpt = { "Python": ${dOptPython}, "Server": ${dOptServer}, "Writer": ${dOptWriter} } Index: gc_core/py/oxt/Options.py ================================================================== --- gc_core/py/oxt/Options.py +++ gc_core/py/oxt/Options.py @@ -21,11 +21,11 @@ def loadOptions (sLang): "load options from Grammalecte and change them according to LibreOffice settings, returns a dictionary {option_name: boolean}" try: xNode = helpers.getConfigSetting("/org.openoffice.Lightproof_${implname}/Leaves", False) xChild = xNode.getByName(sLang) - dOpt = gce.gc_options.getOptions("Writer") + dOpt = gce.gc_options.getOptions() for sKey in dOpt: sValue = xChild.getPropertyValue(sKey) if sValue != '': dOpt[sKey] = bool(int(sValue)) return dOpt @@ -70,11 +70,11 @@ return xWidget def run (self, sUI): try: dUI = op_strings.getUI(sUI) - dOptionUI = gce.gc_options.getUI(sUI) + dOptionUI = gce.gc_options.getOptionLabels(sUI) # fonts xFDTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor") xFDTitle.Height = 9 xFDTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD") Index: gc_lang/fr/modules-js/gce_analyseur.js ================================================================== --- gc_lang/fr/modules-js/gce_analyseur.js +++ gc_lang/fr/modules-js/gce_analyseur.js @@ -16,20 +16,20 @@ return g_morph(oToken, sPattern, sNegPattern, 0, nEnd, false); } function apposition (sWord1, sWord2) { // returns true if nom + nom (no agreement required) - return sWord2.length < 2 || (cregex.mbNomNotAdj(_oSpellChecker.getMorph(sWord2)) && cregex.mbPpasNomNotAdj(_oSpellChecker.getMorph(sWord1))); + return sWord2.length < 2 || (cregex.mbNomNotAdj(gc_engine.oSpellChecker.getMorph(sWord2)) && cregex.mbPpasNomNotAdj(gc_engine.oSpellChecker.getMorph(sWord1))); } function g_checkAgreement (oToken1, oToken2, bNotOnlyNames=true) { // check agreement between and - let lMorph1 = oToken1.hasOwnProperty("lMorph") ? oToken1["lMorph"] : _oSpellChecker.getMorph(oToken1["sValue"]); + let lMorph1 = oToken1.hasOwnProperty("lMorph") ? oToken1["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken1["sValue"]); if (lMorph1.length === 0) { return true; } - let lMorph2 = oToken2.hasOwnProperty("lMorph") ? oToken2["lMorph"] : _oSpellChecker.getMorph(oToken2["sValue"]); + let lMorph2 = oToken2.hasOwnProperty("lMorph") ? oToken2["lMorph"] : gc_engine.oSpellChecker.getMorph(oToken2["sValue"]); if (lMorph2.length === 0) { return true; } if (bNotOnlyNames && !(cregex.mbAdj(lMorph2) || cregex.mbAdjNb(lMorph1))) { return false; @@ -46,12 +46,12 @@ } return false; } function queryNamesPOS (sWord1, sWord2) { - let lMorph1 = _oSpellChecker.getMorph(sWord1); - let lMorph2 = _oSpellChecker.getMorph(sWord2); + let lMorph1 = gc_engine.oSpellChecker.getMorph(sWord1); + let lMorph2 = gc_engine.oSpellChecker.getMorph(sWord2); if (lMorph1.length == 0 || lMorph2.length == 0) { return ":N:e:p"; } let sGender1 = cregex.getGender(lMorph1); let sGender2 = cregex.getGender(lMorph2); Index: gc_lang/fr/modules-js/gce_suggestions.js ================================================================== --- gc_lang/fr/modules-js/gce_suggestions.js +++ gc_lang/fr/modules-js/gce_suggestions.js @@ -34,16 +34,16 @@ let sSfx; if (bVC) { [sFlex, sSfx] = splitVerb(sFlex); } let aSugg = new Set(); - for (let sStem of _oSpellChecker.getLemma(sFlex)) { + for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) { let tTags = conj._getTags(sStem); if (tTags) { // we get the tense let aTense = new Set(); - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { let m; let zVerb = new RegExp (">"+sStem+"/.*?(:(?:Y|I[pqsf]|S[pq]|K|P|Q))", "g"); while ((m = zVerb.exec(sMorph)) !== null) { // stem must be used in regex to prevent confusion between different verbs (e.g. sauras has 2 stems: savoir and saurer) if (m) { @@ -84,11 +84,11 @@ return ""; } function suggVerbPpas (sFlex, sWhat=null) { let aSugg = new Set(); - for (let sStem of _oSpellChecker.getLemma(sFlex)) { + for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) { let tTags = conj._getTags(sStem); if (tTags) { if (!sWhat) { aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")); aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")); @@ -134,11 +134,11 @@ return ""; } function suggVerbTense (sFlex, sTense, sWho) { let aSugg = new Set(); - for (let sStem of _oSpellChecker.getLemma(sFlex)) { + for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) { if (conj.hasConj(sStem, sTense, sWho)) { aSugg.add(conj.getConj(sStem, sTense, sWho)); } } if (aSugg.size > 0) { @@ -151,11 +151,11 @@ let sSfx; if (bVC) { [sFlex, sSfx] = splitVerb(sFlex); } let aSugg = new Set(); - for (let sStem of _oSpellChecker.getLemma(sFlex)) { + for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) { let tTags = conj._getTags(sStem); if (tTags) { if (conj._hasConjWithTags(tTags, ":E", ":2s")) { aSugg.add(conj._getConjWithTags(sStem, tTags, ":E", ":2s")); } @@ -175,11 +175,11 @@ } return ""; } function suggVerbInfi (sFlex) { - return _oSpellChecker.getLemma(sFlex).filter(sStem => conj.isVerb(sStem)).join("|"); + return gc_engine.oSpellChecker.getLemma(sFlex).filter(sStem => conj.isVerb(sStem)).join("|"); } const _dQuiEst = new Map ([ ["je", ":1s"], ["j’", ":1s"], ["j’en", ":1s"], ["j’y", ":1s"], @@ -206,11 +206,11 @@ return ""; } sWho = ":3s"; } let aSugg = new Set(); - for (let sStem of _oSpellChecker.getLemma(sFlex)) { + for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) { let tTags = conj._getTags(sStem); if (tTags) { for (let sTense of lMode) { if (conj._hasConjWithTags(tTags, sTense, sWho)) { aSugg.add(conj._getConjWithTags(sStem, tTags, sTense, sWho)); @@ -227,11 +227,11 @@ //// Nouns and adjectives function suggPlur (sFlex, sWordToAgree=null, bSelfSugg=false) { // returns plural forms assuming sFlex is singular if (sWordToAgree) { - let lMorph = _oSpellChecker.getMorph(sWordToAgree); + let lMorph = gc_engine.oSpellChecker.getMorph(sWordToAgree); if (lMorph.length === 0) { return ""; } let sGender = cregex.getGender(lMorph); if (sGender == ":m") { @@ -240,37 +240,37 @@ return suggFemPlur(sFlex); } } let aSugg = new Set(); if (sFlex.endsWith("l")) { - if (sFlex.endsWith("al") && sFlex.length > 2 && _oSpellChecker.isValid(sFlex.slice(0,-1)+"ux")) { + if (sFlex.endsWith("al") && sFlex.length > 2 && gc_engine.oSpellChecker.isValid(sFlex.slice(0,-1)+"ux")) { aSugg.add(sFlex.slice(0,-1)+"ux"); } - if (sFlex.endsWith("ail") && sFlex.length > 3 && _oSpellChecker.isValid(sFlex.slice(0,-2)+"ux")) { + if (sFlex.endsWith("ail") && sFlex.length > 3 && gc_engine.oSpellChecker.isValid(sFlex.slice(0,-2)+"ux")) { aSugg.add(sFlex.slice(0,-2)+"ux"); } } if (sFlex.endsWith("L")) { - if (sFlex.endsWith("AL") && sFlex.length > 2 && _oSpellChecker.isValid(sFlex.slice(0,-1)+"UX")) { + if (sFlex.endsWith("AL") && sFlex.length > 2 && gc_engine.oSpellChecker.isValid(sFlex.slice(0,-1)+"UX")) { aSugg.add(sFlex.slice(0,-1)+"UX"); } - if (sFlex.endsWith("AIL") && sFlex.length > 3 && _oSpellChecker.isValid(sFlex.slice(0,-2)+"UX")) { + if (sFlex.endsWith("AIL") && sFlex.length > 3 && gc_engine.oSpellChecker.isValid(sFlex.slice(0,-2)+"UX")) { aSugg.add(sFlex.slice(0,-2)+"UX"); } } if (sFlex.slice(-1).gl_isLowerCase()) { - if (_oSpellChecker.isValid(sFlex+"s")) { + if (gc_engine.oSpellChecker.isValid(sFlex+"s")) { aSugg.add(sFlex+"s"); } - if (_oSpellChecker.isValid(sFlex+"x")) { + if (gc_engine.oSpellChecker.isValid(sFlex+"x")) { aSugg.add(sFlex+"x"); } } else { - if (_oSpellChecker.isValid(sFlex+"S")) { + if (gc_engine.oSpellChecker.isValid(sFlex+"S")) { aSugg.add(sFlex+"s"); } - if (_oSpellChecker.isValid(sFlex+"X")) { + if (gc_engine.oSpellChecker.isValid(sFlex+"X")) { aSugg.add(sFlex+"x"); } } if (mfsp.hasMiscPlural(sFlex)) { mfsp.getMiscPlural(sFlex).forEach(function(x) { aSugg.add(x); }); @@ -287,26 +287,26 @@ function suggSing (sFlex, bSelfSugg=false) { // returns singular forms assuming sFlex is plural let aSugg = new Set(); if (sFlex.endsWith("ux")) { - if (_oSpellChecker.isValid(sFlex.slice(0,-2)+"l")) { + if (gc_engine.oSpellChecker.isValid(sFlex.slice(0,-2)+"l")) { aSugg.add(sFlex.slice(0,-2)+"l"); } - if (_oSpellChecker.isValid(sFlex.slice(0,-2)+"il")) { + if (gc_engine.oSpellChecker.isValid(sFlex.slice(0,-2)+"il")) { aSugg.add(sFlex.slice(0,-2)+"il"); } } if (sFlex.endsWith("UX")) { - if (_oSpellChecker.isValid(sFlex.slice(0,-2)+"L")) { + if (gc_engine.oSpellChecker.isValid(sFlex.slice(0,-2)+"L")) { aSugg.add(sFlex.slice(0,-2)+"L"); } - if (_oSpellChecker.isValid(sFlex.slice(0,-2)+"IL")) { + if (gc_engine.oSpellChecker.isValid(sFlex.slice(0,-2)+"IL")) { aSugg.add(sFlex.slice(0,-2)+"IL"); } } - if ((sFlex.endsWith("s") || sFlex.endsWith("x") || sFlex.endsWith("S") || sFlex.endsWith("X")) && _oSpellChecker.isValid(sFlex.slice(0,-1))) { + if ((sFlex.endsWith("s") || sFlex.endsWith("x") || sFlex.endsWith("S") || sFlex.endsWith("X")) && gc_engine.oSpellChecker.isValid(sFlex.slice(0,-1))) { aSugg.add(sFlex.slice(0,-1)); } if (bSelfSugg && aSugg.size == 0) { aSugg.add(sFlex); } @@ -318,11 +318,11 @@ } function suggMasSing (sFlex, bSuggSimil=false) { // returns masculine singular forms let aSugg = new Set(); - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (!sMorph.includes(":V")) { // not a verb if (sMorph.includes(":m") || sMorph.includes(":e")) { aSugg.add(suggSing(sFlex)); } else { @@ -354,11 +354,11 @@ } function suggMasPlur (sFlex, bSuggSimil=false) { // returns masculine plural forms let aSugg = new Set(); - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (!sMorph.includes(":V")) { // not a verb if (sMorph.includes(":m") || sMorph.includes(":e")) { aSugg.add(suggPlur(sFlex)); } else { @@ -395,11 +395,11 @@ function suggFemSing (sFlex, bSuggSimil=false) { // returns feminine singular forms let aSugg = new Set(); - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (!sMorph.includes(":V")) { // not a verb if (sMorph.includes(":f") || sMorph.includes(":e")) { aSugg.add(suggSing(sFlex)); } else { @@ -429,11 +429,11 @@ } function suggFemPlur (sFlex, bSuggSimil=false) { // returns feminine plural forms let aSugg = new Set(); - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (!sMorph.includes(":V")) { // not a verb if (sMorph.includes(":f") || sMorph.includes(":e")) { aSugg.add(suggPlur(sFlex)); } else { @@ -461,11 +461,11 @@ } return ""; } function hasFemForm (sFlex) { - for (let sStem of _oSpellChecker.getLemma(sFlex)) { + for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) { if (mfsp.isMasForm(sStem) || conj.hasConj(sStem, ":PQ", ":Q3")) { return true; } } if (phonet.hasSimil(sFlex, ":f")) { @@ -473,11 +473,11 @@ } return false; } function hasMasForm (sFlex) { - for (let sStem of _oSpellChecker.getLemma(sFlex)) { + for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) { if (mfsp.isMasForm(sStem) || conj.hasConj(sStem, ":PQ", ":Q1")) { // what has a feminine form also has a masculine form return true; } } @@ -488,11 +488,11 @@ } function switchGender (sFlex, bPlur=null) { let aSugg = new Set(); if (bPlur === null) { - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (sMorph.includes(":f")) { if (sMorph.includes(":s")) { aSugg.add(suggMasSing(sFlex)); } else if (sMorph.includes(":p")) { aSugg.add(suggMasPlur(sFlex)); @@ -507,19 +507,19 @@ aSugg.add(suggFemPlur(sFlex)); } } } } else if (bPlur) { - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (sMorph.includes(":f")) { aSugg.add(suggMasPlur(sFlex)); } else if (sMorph.includes(":m")) { aSugg.add(suggFemPlur(sFlex)); } } } else { - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (sMorph.includes(":f")) { aSugg.add(suggMasSing(sFlex)); } else if (sMorph.includes(":m")) { aSugg.add(suggFemSing(sFlex)); } @@ -531,11 +531,11 @@ return ""; } function switchPlural (sFlex) { let aSugg = new Set(); - for (let sMorph of _oSpellChecker.getMorph(sFlex)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sFlex)) { if (sMorph.includes(":s")) { aSugg.add(suggPlur(sFlex)); } else if (sMorph.includes(":p")) { aSugg.add(suggSing(sFlex)); } @@ -556,11 +556,11 @@ if (bVC) { [sWord, sSfx] = splitVerb(sWord); } let aSugg = phonet.selectSimil(sWord, sPattern); if (aSugg.size === 0 || !bSubst) { - for (let sMorph of _oSpellChecker.getMorph(sWord)) { + for (let sMorph of gc_engine.oSpellChecker.getMorph(sWord)) { for (let e of conj.getSimil(sWord, sMorph, bSubst)) { aSugg.add(e); } } } @@ -582,11 +582,11 @@ } return "ce"; } function suggLesLa (sWord) { - if (_oSpellChecker.getMorph(sWord).some(s => s.includes(":p"))) { + if (gc_engine.oSpellChecker.getMorph(sWord).some(s => s.includes(":p"))) { return "les|la"; } return "la"; }