DELETED gc_lang/fr/modules/lexicographe.py Index: gc_lang/fr/modules/lexicographe.py ================================================================== --- gc_lang/fr/modules/lexicographe.py +++ /dev/null @@ -1,234 +0,0 @@ -""" -Grammalecte - Lexicographe -""" - -# License: MPL 2 - - -import re -import traceback - - -_dTAGS = { - ':N': (" nom,", "Nom"), - ':A': (" adjectif,", "Adjectif"), - ':M1': (" prénom,", "Prénom"), - ':M2': (" patronyme,", "Patronyme, matronyme, nom de famille…"), - ':MP': (" nom propre,", "Nom propre"), - ':W': (" adverbe,", "Adverbe"), - ':J': (" interjection,", "Interjection"), - ':B': (" nombre,", "Nombre"), - ':T': (" titre,", "Titre de civilité"), - - ':e': (" épicène", "épicène"), - ':m': (" masculin", "masculin"), - ':f': (" féminin", "féminin"), - ':s': (" singulier", "singulier"), - ':p': (" pluriel", "pluriel"), - ':i': (" invariable", "invariable"), - - ':V1': (" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"), - ':V2': (" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"), - ':V3': (" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"), - ':V0e': (" verbe,", "Verbe auxiliaire être"), - ':V0a': (" verbe,", "Verbe auxiliaire avoir"), - - ':Y': (" infinitif,", "infinitif"), - ':P': (" participe présent,", "participe présent"), - ':Q': (" participe passé,", "participe passé"), - ':Ip': (" présent,", "indicatif présent"), - ':Iq': (" imparfait,", "indicatif imparfait"), - ':Is': (" passé simple,", "indicatif passé simple"), - ':If': (" futur,", "indicatif futur"), - ':K': (" conditionnel présent,", "conditionnel présent"), - ':Sp': (" subjonctif présent,", "subjonctif présent"), - ':Sq': (" subjonctif imparfait,", "subjonctif imparfait"), - ':E': (" impératif,", "impératif"), - - ':1s': (" 1ʳᵉ p. sg.,", "verbe : 1ʳᵉ personne du singulier"), - ':1ŝ': (" présent interr. 1ʳᵉ p. sg.,", "verbe : 1ʳᵉ personne du singulier (présent interrogatif)"), - ':1ś': (" présent interr. 1ʳᵉ p. sg.,", "verbe : 1ʳᵉ personne du singulier (présent interrogatif)"), - ':2s': (" 2ᵉ p. sg.,", "verbe : 2ᵉ personne du singulier"), - ':3s': (" 3ᵉ p. sg.,", "verbe : 3ᵉ personne du singulier"), - ':1p': (" 1ʳᵉ p. pl.,", "verbe : 1ʳᵉ personne du pluriel"), - ':2p': (" 2ᵉ p. pl.,", "verbe : 2ᵉ personne du pluriel"), - ':3p': (" 3ᵉ p. pl.,", "verbe : 3ᵉ personne du pluriel"), - ':3p!': (" 3ᵉ p. pl.,", "verbe : 3ᵉ personne du pluriel (prononciation distinctive)"), - - ':G': ("", "Mot grammatical"), - ':X': (" adverbe de négation,", "Adverbe de négation"), - ':U': (" adverbe interrogatif,", "Adverbe interrogatif"), - ':R': (" préposition,", "Préposition"), - ':Rv': (" préposition verbale,", "Préposition verbale"), - ':D': (" déterminant,", "Déterminant"), - ':Dd': (" déterminant démonstratif,", "Déterminant démonstratif"), - ':De': (" déterminant exclamatif,", "Déterminant exclamatif"), - ':Dp': (" déterminant possessif,", "Déterminant possessif"), - ':Di': (" déterminant indéfini,", "Déterminant indéfini"), - ':Dn': (" déterminant négatif,", "Déterminant négatif"), - ':Od': (" pronom démonstratif,", "Pronom démonstratif"), - ':Oi': (" pronom indéfini,", "Pronom indéfini"), - ':On': (" pronom indéfini négatif,", "Pronom indéfini négatif"), - ':Ot': (" pronom interrogatif,", "Pronom interrogatif"), - ':Or': (" pronom relatif,", "Pronom relatif"), - ':Ow': (" pronom adverbial,", "Pronom adverbial"), - ':Os': (" pronom personnel sujet,", "Pronom personnel sujet"), - ':Oo': (" pronom personnel objet,", "Pronom personnel objet"), - ':Ov': (" préverbe,", "Préverbe (pronom personnel objet, +ne)"), - ':O1': (" 1ʳᵉ pers.,", "Pronom : 1ʳᵉ personne"), - ':O2': (" 2ᵉ pers.,", "Pronom : 2ᵉ personne"), - ':O3': (" 3ᵉ pers.,", "Pronom : 3ᵉ personne"), - ':C': (" conjonction,", "Conjonction"), - ':Ĉ': (" conjonction (él.),", "Conjonction (élément)"), - ':Cc': (" conjonction de coordination,", "Conjonction de coordination"), - ':Cs': (" conjonction de subordination,", "Conjonction de subordination"), - ':Ĉs': (" conjonction de subordination (él.),", "Conjonction de subordination (élément)"), - - ':Ñ': (" locution nominale (él.),", "Locution nominale (élément)"), - ':Â': (" locution adjectivale (él.),", "Locution adjectivale (élément)"), - ':Ṽ': (" locution verbale (él.),", "Locution verbale (élément)"), - ':Ŵ': (" locution adverbiale (él.),", "Locution adverbiale (élément)"), - ':Ŕ': (" locution prépositive (él.),", "Locution prépositive (élément)"), - ':Ĵ': (" locution interjective (él.),", "Locution interjective (élément)"), - - ':Zp': (" préfixe,", "Préfixe"), - ':Zs': (" suffixe,", "Suffixe"), - - ':H': ("", ""), - - ':@': ("", ""), - ':@p': ("signe de ponctuation", "Signe de ponctuation"), - ':@s': ("signe", "Signe divers"), - - ';S': (" : symbole (unité de mesure)", "Symbole (unité de mesure)"), - - '/*': ("", "Sous-dictionnaire "), - '/C': (" ", "Sous-dictionnaire "), - '/M': ("", "Sous-dictionnaire "), - '/R': (" ", "Sous-dictionnaire "), - '/A': ("", "Sous-dictionnaire "), - '/X': ("", "Sous-dictionnaire ") -} - -_dPFX = { - 'd': "(de), déterminant épicène invariable", - 'l': "(le/la), déterminant masculin/féminin singulier", - 'j': "(je), pronom personnel sujet, 1ʳᵉ pers., épicène singulier", - 'm': "(me), pronom personnel objet, 1ʳᵉ pers., épicène singulier", - 't': "(te), pronom personnel objet, 2ᵉ pers., épicène singulier", - 's': "(se), pronom personnel objet, 3ᵉ pers., épicène singulier/pluriel", - 'n': "(ne), adverbe de négation", - 'c': "(ce), pronom démonstratif, masculin singulier/pluriel", - 'ç': "(ça), pronom démonstratif, masculin singulier", - 'qu': "(que), conjonction de subordination", - 'lorsqu': "(lorsque), conjonction de subordination", - 'puisqu': "(puisque), conjonction de subordination", - 'quoiqu': "(quoique), conjonction de subordination", - 'jusqu': "(jusque), préposition", -} - -_dAD = { - 'je': " pronom personnel sujet, 1ʳᵉ pers. sing.", - 'tu': " pronom personnel sujet, 2ᵉ pers. sing.", - 'il': " pronom personnel sujet, 3ᵉ pers. masc. sing.", - 'on': " pronom personnel sujet, 3ᵉ pers. sing. ou plur.", - 'elle': " pronom personnel sujet, 3ᵉ pers. fém. sing.", - 'nous': " pronom personnel sujet/objet, 1ʳᵉ pers. plur.", - 'vous': " pronom personnel sujet/objet, 2ᵉ pers. plur.", - 'ils': " pronom personnel sujet, 3ᵉ pers. masc. plur.", - 'elles': " pronom personnel sujet, 3ᵉ pers. masc. plur.", - - "là": " particule démonstrative", - "ci": " particule démonstrative", - - 'le': " COD, masc. sing.", - 'la': " COD, fém. sing.", - 'les': " COD, plur.", - - 'moi': " COI (à moi), sing.", - 'toi': " COI (à toi), sing.", - 'lui': " COI (à lui ou à elle), sing.", - 'nous2': " COI (à nous), plur.", - 'vous2': " COI (à vous), plur.", - 'leur': " COI (à eux ou à elles), plur.", - - 'y': " pronom adverbial", - "m'y": " (me) pronom personnel objet + (y) pronom adverbial", - "t'y": " (te) pronom personnel objet + (y) pronom adverbial", - "s'y": " (se) pronom personnel objet + (y) pronom adverbial", - - 'en': " pronom adverbial", - "m'en": " (me) pronom personnel objet + (en) pronom adverbial", - "t'en": " (te) pronom personnel objet + (en) pronom adverbial", - "s'en": " (se) pronom personnel objet + (en) pronom adverbial", -} - - -class Lexicographe: - "Lexicographer - word analyzer" - - def __init__ (self, oSpellChecker): - self.oSpellChecker = oSpellChecker - self._zElidedPrefix = re.compile("(?i)^([dljmtsncç]|quoiqu|lorsqu|jusqu|puisqu|qu)['’](.+)") - self._zCompoundWord = re.compile("(?i)(\\w+)-((?:les?|la)-(?:moi|toi|lui|[nv]ous|leur)|t-(?:il|elle|on)|y|en|[mts][’'](?:y|en)|les?|l[aà]|[mt]oi|leur|lui|je|tu|ils?|elles?|on|[nv]ous)$") - self._zTag = re.compile("[:;/][\\w*][^:;/]*") - - def analyzeWord (self, sWord): - "returns a tuple (a list of morphologies, a set of verb at infinitive form)" - try: - if not sWord: - return (None, None) - if sWord.count("-") > 4: - return (["élément complexe indéterminé"], None) - if sWord.isdigit(): - return (["nombre"], None) - - aMorph = [] - # préfixes élidés - m = self._zElidedPrefix.match(sWord) - if m: - sWord = m.group(2) - aMorph.append( "{}’ : {}".format(m.group(1), _dPFX.get(m.group(1).lower(), "[?]")) ) - # mots composés - m2 = self._zCompoundWord.match(sWord) - if m2: - sWord = m2.group(1) - # Morphologies - lMorph = self.oSpellChecker.getMorph(sWord) - if len(lMorph) > 1: - # sublist - aMorph.append( (sWord, [ self.formatTags(s) for s in lMorph if ":" in s ]) ) - elif len(lMorph) == 1: - aMorph.append( "{} : {}".format(sWord, self.formatTags(lMorph[0])) ) - else: - aMorph.append( "{} : inconnu du dictionnaire".format(sWord) ) - # suffixe d’un mot composé - if m2: - aMorph.append( "-{} : {}".format(m2.group(2), self._formatSuffix(m2.group(2).lower())) ) - # Verbes - aVerb = { s[1:s.find("/")] for s in lMorph if ":V" in s } - return (aMorph, aVerb) - except (IndexError, TypeError): - traceback.print_exc() - return (["#erreur"], None) - - def formatTags (self, sTags): - "returns string: readable tags" - sRes = "" - sTags = re.sub("(?<=V[1-3])[itpqnmr_eaxz]+", "", sTags) - sTags = re.sub("(?<=V0[ea])[itpqnmr_eaxz]+", "", sTags) - for m in self._zTag.finditer(sTags): - sRes += _dTAGS.get(m.group(0), " [{}]".format(m.group(0)))[0] - if sRes.startswith(" verbe") and not sRes.endswith("infinitif"): - sRes += " [{}]".format(sTags[1:sTags.find("/")]) - return sRes.rstrip(",") - - def _formatSuffix (self, s): - if s.startswith("t-"): - return "“t” euphonique +" + _dAD.get(s[2:], "[?]") - if not "-" in s: - return _dAD.get(s.replace("’", "'"), "[?]") - if s.endswith("ous"): - s += '2' - nPos = s.find("-") - return "%s +%s" % (_dAD.get(s[:nPos], "[?]"), _dAD.get(s[nPos+1:], "[?]")) Index: gc_lang/fr/oxt/ContextMenu/ContextMenu.py ================================================================== --- gc_lang/fr/oxt/ContextMenu/ContextMenu.py +++ gc_lang/fr/oxt/ContextMenu/ContextMenu.py @@ -8,30 +8,28 @@ from com.sun.star.task import XJob 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.graphspell.spellchecker import SpellChecker from grammalecte.graphspell.echo import echo import helpers xDesktop = None oSpellChecker = None -oLexicographe = None class MyContextMenuInterceptor (XContextMenuInterceptor, unohelper.Base): def __init__ (self, ctx): self.ctx = ctx def notifyContextMenuExecute (self, xEvent): sWord = self._getWord() try: - aItem, aVerb = oLexicographe.analyzeWord(sWord) - if not aItem: + lWordAndMorph = oSpellChecker.analyze(sWord) + if not lWordAndMorph: return uno.Enum("com.sun.star.ui.ContextMenuInterceptorAction", "IGNORED") # don’t work on AOO, have to import the value #return IGNORED xContextMenu = xEvent.ActionTriggerContainer if xContextMenu: # entries index @@ -38,30 +36,31 @@ i = xContextMenu.Count nUnoConstantLine = uno.getConstantByName("com.sun.star.ui.ActionTriggerSeparatorType.LINE") # word analysis i = self._addItemToContextMenu(xContextMenu, i, "ActionTriggerSeparator", SeparatorType=nUnoConstantLine) - for item in aItem: - if isinstance(item, str): - i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text=item, CommandURL="service:net.grammalecte.AppLauncher?None") - elif isinstance(item, tuple): - sRoot, lMorph = item + for sWord, lMorph in lWordAndMorph: + if len(lMorph) == 1: + sMorph, sReadableMorph = lMorph[0] + i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text=sWord + " : " + sReadableMorph, CommandURL="service:net.grammalecte.AppLauncher?None") + elif len(lMorph) >= 1: # submenu xSubMenuContainer = xContextMenu.createInstance("com.sun.star.ui.ActionTriggerContainer") - for j, s in enumerate(lMorph): - self._addItemToContextMenu(xSubMenuContainer, j, "ActionTrigger", Text=s, CommandURL="service:net.grammalecte.AppLauncher?None") + for j, (sMorph, sReadableMorph) in enumerate(lMorph): + self._addItemToContextMenu(xSubMenuContainer, j, "ActionTrigger", Text=sReadableMorph, CommandURL="service:net.grammalecte.AppLauncher?None") # create root menu entry - i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text=sRoot, SubContainer=xSubMenuContainer) + i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text=sWord, SubContainer=xSubMenuContainer) else: - i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text="# erreur : {}".format(item)) + i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text=sWord + " : [erreur] aucun résultat trouvé.") # Links to Conjugueur + aVerb = { sMorph[1:sMorph.find("/")] for sMorph in oSpellChecker.getMorph(sWord) if ":V" in sMorph } if aVerb: i = self._addItemToContextMenu(xContextMenu, i, "ActionTriggerSeparator", SeparatorType=nUnoConstantLine) for sVerb in aVerb: - i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text="Conjuguer “{}”…".format(sVerb), - CommandURL="service:net.grammalecte.AppLauncher?CJ/"+sVerb) + i = self._addItemToContextMenu(xContextMenu, i, "ActionTrigger", Text="Conjuguer “{}”…".format(sVerb), \ + CommandURL="service:net.grammalecte.AppLauncher?CJ/"+sVerb) # Search xDoc = xDesktop.getCurrentComponent() xViewCursor = xDoc.CurrentController.ViewCursor if not xViewCursor.isCollapsed(): @@ -116,11 +115,10 @@ class JobExecutor (XJob, unohelper.Base): def __init__ (self, ctx): self.ctx = ctx global xDesktop global oSpellChecker - global oLexicographe try: if not xDesktop: xDesktop = self.ctx.getServiceManager().createInstanceWithContext('com.sun.star.frame.Desktop', self.ctx) if not oSpellChecker: xCurCtx = uno.getComponentContext() @@ -128,12 +126,10 @@ if hasattr(oGC, "getSpellChecker"): # https://bugs.documentfoundation.org/show_bug.cgi?id=97790 oSpellChecker = oGC.getSpellChecker() else: oSpellChecker = SpellChecker("${lang}", "fr-allvars.bdic") - if not oLexicographe: - oLexicographe = lxg.Lexicographe(oSpellChecker) except: traceback.print_exc() def execute (self, args): if not args: Index: grammalecte-cli.py ================================================================== --- grammalecte-cli.py +++ grammalecte-cli.py @@ -152,11 +152,10 @@ xParser.add_argument("-d", "--debug", help="debugging mode (only in interactive mode)", action="store_true") xArgs = xParser.parse_args() grammalecte.load() oSpellChecker = grammalecte.getSpellChecker() - oLexicographer = grammalecte.getLexicographer() if xArgs.personal_dict: oJSON = loadDictionary(xArgs.personal_dict) if oJSON: oSpellChecker.setPersonalDictionary(oJSON) @@ -269,12 +268,14 @@ while True: if sText.startswith("?"): for sWord in sText[1:].strip().split(): if sWord: echo("* " + sWord) - for sMorph in oSpellChecker.getMorph(sWord): - echo(" {:<32} {}".format(sMorph, oLexicographer.formatTags(sMorph))) + for sElem, aRes in oSpellChecker.analyze(sWord): + echo(" - " + sElem) + for sMorph, sMeaning in aRes: + echo(" {:<40} {}".format(sMorph, sMeaning)) elif sText.startswith("!"): for sWord in sText[1:].strip().split(): if sWord: for lSugg in oSpellChecker.suggest(sWord): echo(" | ".join(lSugg)) Index: graphspell/fr.py ================================================================== --- graphspell/fr.py +++ graphspell/fr.py @@ -1,9 +1,23 @@ """ -Default suggestion for French language +Lexicographer for the French language """ +# Note: +# This mode must contains at least: +# : a dictionary for default suggestions. +# : a boolean False +# if the boolean is True, 3 functions are required: +# split(sWord) -> returns a list of string (that will be analyzed) +# analyze(sWord) -> returns a string with the meaning of word +# formatTags(sTags) -> returns a string with the meaning of tags + + +import re + +#### Suggestions + dSugg = { "bcp": "beaucoup", "ca": "ça", "cad": "c’est-à-dire", "cb": "combien|CB", @@ -82,10 +96,11 @@ "XXVIième": "XXVIᵉ", "XXVIIième": "XXVIIᵉ", "XXVIIIième": "XXVIIIᵉ", "XXIXième": "XXIXᵉ", "XXXième": "XXXᵉ", + "Ier": "Iᵉʳ", "Ière": "Iʳᵉ", "IIème": "IIᵉ", "IIIème": "IIIᵉ", "IVème": "IVᵉ", @@ -114,5 +129,226 @@ "XXVIIème": "XXVIIᵉ", "XXVIIIème": "XXVIIIᵉ", "XXIXème": "XXIXᵉ", "XXXème": "XXXᵉ" } + + +#### Lexicographer + +bLexicographer = True + +_dTAGS = { + ':N': (" nom,", "Nom"), + ':A': (" adjectif,", "Adjectif"), + ':M1': (" prénom,", "Prénom"), + ':M2': (" patronyme,", "Patronyme, matronyme, nom de famille…"), + ':MP': (" nom propre,", "Nom propre"), + ':W': (" adverbe,", "Adverbe"), + ':J': (" interjection,", "Interjection"), + ':B': (" nombre,", "Nombre"), + ':T': (" titre,", "Titre de civilité"), + + ':e': (" épicène", "épicène"), + ':m': (" masculin", "masculin"), + ':f': (" féminin", "féminin"), + ':s': (" singulier", "singulier"), + ':p': (" pluriel", "pluriel"), + ':i': (" invariable", "invariable"), + + ':V1': (" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"), + ':V2': (" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"), + ':V3': (" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"), + ':V0e': (" verbe,", "Verbe auxiliaire être"), + ':V0a': (" verbe,", "Verbe auxiliaire avoir"), + + ':Y': (" infinitif,", "infinitif"), + ':P': (" participe présent,", "participe présent"), + ':Q': (" participe passé,", "participe passé"), + ':Ip': (" présent,", "indicatif présent"), + ':Iq': (" imparfait,", "indicatif imparfait"), + ':Is': (" passé simple,", "indicatif passé simple"), + ':If': (" futur,", "indicatif futur"), + ':K': (" conditionnel présent,", "conditionnel présent"), + ':Sp': (" subjonctif présent,", "subjonctif présent"), + ':Sq': (" subjonctif imparfait,", "subjonctif imparfait"), + ':E': (" impératif,", "impératif"), + + ':1s': (" 1ʳᵉ p. sg.,", "verbe : 1ʳᵉ personne du singulier"), + ':1ŝ': (" présent interr. 1ʳᵉ p. sg.,", "verbe : 1ʳᵉ personne du singulier (présent interrogatif)"), + ':1ś': (" présent interr. 1ʳᵉ p. sg.,", "verbe : 1ʳᵉ personne du singulier (présent interrogatif)"), + ':2s': (" 2ᵉ p. sg.,", "verbe : 2ᵉ personne du singulier"), + ':3s': (" 3ᵉ p. sg.,", "verbe : 3ᵉ personne du singulier"), + ':1p': (" 1ʳᵉ p. pl.,", "verbe : 1ʳᵉ personne du pluriel"), + ':2p': (" 2ᵉ p. pl.,", "verbe : 2ᵉ personne du pluriel"), + ':3p': (" 3ᵉ p. pl.,", "verbe : 3ᵉ personne du pluriel"), + ':3p!': (" 3ᵉ p. pl.,", "verbe : 3ᵉ personne du pluriel (prononciation distinctive)"), + + ':G': ("", "Mot grammatical"), + ':X': (" adverbe de négation,", "Adverbe de négation"), + ':U': (" adverbe interrogatif,", "Adverbe interrogatif"), + ':R': (" préposition,", "Préposition"), + ':Rv': (" préposition verbale,", "Préposition verbale"), + ':D': (" déterminant,", "Déterminant"), + ':Dd': (" déterminant démonstratif,", "Déterminant démonstratif"), + ':De': (" déterminant exclamatif,", "Déterminant exclamatif"), + ':Dp': (" déterminant possessif,", "Déterminant possessif"), + ':Di': (" déterminant indéfini,", "Déterminant indéfini"), + ':Dn': (" déterminant négatif,", "Déterminant négatif"), + ':Od': (" pronom démonstratif,", "Pronom démonstratif"), + ':Oi': (" pronom indéfini,", "Pronom indéfini"), + ':On': (" pronom indéfini négatif,", "Pronom indéfini négatif"), + ':Ot': (" pronom interrogatif,", "Pronom interrogatif"), + ':Or': (" pronom relatif,", "Pronom relatif"), + ':Ow': (" pronom adverbial,", "Pronom adverbial"), + ':Os': (" pronom personnel sujet,", "Pronom personnel sujet"), + ':Oo': (" pronom personnel objet,", "Pronom personnel objet"), + ':Ov': (" préverbe,", "Préverbe (pronom personnel objet, +ne)"), + ':O1': (" 1ʳᵉ pers.,", "Pronom : 1ʳᵉ personne"), + ':O2': (" 2ᵉ pers.,", "Pronom : 2ᵉ personne"), + ':O3': (" 3ᵉ pers.,", "Pronom : 3ᵉ personne"), + ':C': (" conjonction,", "Conjonction"), + ':Ĉ': (" conjonction (él.),", "Conjonction (élément)"), + ':Cc': (" conjonction de coordination,", "Conjonction de coordination"), + ':Cs': (" conjonction de subordination,", "Conjonction de subordination"), + ':Ĉs': (" conjonction de subordination (él.),", "Conjonction de subordination (élément)"), + + ':Ñ': (" locution nominale (él.),", "Locution nominale (élément)"), + ':Â': (" locution adjectivale (él.),", "Locution adjectivale (élément)"), + ':Ṽ': (" locution verbale (él.),", "Locution verbale (élément)"), + ':Ŵ': (" locution adverbiale (él.),", "Locution adverbiale (élément)"), + ':Ŕ': (" locution prépositive (él.),", "Locution prépositive (élément)"), + ':Ĵ': (" locution interjective (él.),", "Locution interjective (élément)"), + + ':Zp': (" préfixe,", "Préfixe"), + ':Zs': (" suffixe,", "Suffixe"), + + ':H': ("", ""), + + ':@': ("", ""), + ':@p': ("signe de ponctuation", "Signe de ponctuation"), + ':@s': ("signe", "Signe divers"), + + ';S': (" : symbole (unité de mesure)", "Symbole (unité de mesure)"), + + '/*': ("", "Sous-dictionnaire "), + '/C': (" ", "Sous-dictionnaire "), + '/M': ("", "Sous-dictionnaire "), + '/R': (" ", "Sous-dictionnaire "), + '/A': ("", "Sous-dictionnaire "), + '/X': ("", "Sous-dictionnaire ") +} + +_dValues = { + 'd’': "(de), préposition ou déterminant épicène invariable", + 'l’': "(le/la), déterminant ou pronom personnel objet, masculin/féminin singulier", + 'j’': "(je), pronom personnel sujet, 1ʳᵉ pers., épicène singulier", + 'm’': "(me), pronom personnel objet, 1ʳᵉ pers., épicène singulier", + 't’': "(te), pronom personnel objet, 2ᵉ pers., épicène singulier", + 's’': "(se), pronom personnel objet, 3ᵉ pers., épicène singulier/pluriel", + 'n’': "(ne), adverbe de négation", + 'c’': "(ce), pronom démonstratif, masculin singulier/pluriel", + 'ç’': "(ça), pronom démonstratif, masculin singulier", + 'qu’': "(que), conjonction de subordination", + 'lorsqu’': "(lorsque), conjonction de subordination", + 'puisqu’': "(puisque), conjonction de subordination", + 'quoiqu’': "(quoique), conjonction de subordination", + 'jusqu’': "(jusque), préposition", + + '-je': " pronom personnel sujet, 1ʳᵉ pers. sing.", + '-tu': " pronom personnel sujet, 2ᵉ pers. sing.", + '-il': " pronom personnel sujet, 3ᵉ pers. masc. sing.", + '-on': " pronom personnel sujet, 3ᵉ pers. sing. ou plur.", + '-elle': " pronom personnel sujet, 3ᵉ pers. fém. sing.", + '-t-il': " “t” euphonique + pronom personnel sujet, 3ᵉ pers. masc. sing.", + '-t-on': " “t” euphonique + pronom personnel sujet, 3ᵉ pers. sing. ou plur.", + '-t-elle': " “t” euphonique + pronom personnel sujet, 3ᵉ pers. fém. sing.", + '-nous': " pronom personnel sujet/objet, 1ʳᵉ pers. plur. ou COI (à nous), plur.", + '-vous': " pronom personnel sujet/objet, 2ᵉ pers. plur. ou COI (à vous), plur.", + '-ils': " pronom personnel sujet, 3ᵉ pers. masc. plur.", + '-elles': " pronom personnel sujet, 3ᵉ pers. masc. plur.", + + "-là": " particule démonstrative", + "-ci": " particule démonstrative", + + '-le': " COD, masc. sing.", + '-la': " COD, fém. sing.", + '-les': " COD, plur.", + + '-moi': " COI (à moi), sing.", + '-toi': " COI (à toi), sing.", + '-lui': " COI (à lui ou à elle), sing.", + '-leur': " COI (à eux ou à elles), plur.", + + '-le-moi': " COD, masc. sing. + COI (à moi), sing.", + '-le-toi': " COD, masc. sing. + COI (à toi), sing.", + '-le-lui': " COD, masc. sing. + COI (à lui ou à elle), sing.", + '-le-nous': " COD, masc. sing. + COI (à nous), plur.", + '-le-vous': " COD, masc. sing. + COI (à vous), plur.", + '-le-leur': " COD, masc. sing. + COI (à eux ou à elles), plur.", + + '-la-moi': " COD, fém. sing. + COI (à moi), sing.", + '-la-toi': " COD, fém. sing. + COI (à toi), sing.", + '-la-lui': " COD, fém. sing. + COI (à lui ou à elle), sing.", + '-la-nous': " COD, fém. sing. + COI (à nous), plur.", + '-la-vous': " COD, fém. sing. + COI (à vous), plur.", + '-la-leur': " COD, fém. sing. + COI (à eux ou à elles), plur.", + + '-les-moi': " COD, plur. + COI (à moi), sing.", + '-les-toi': " COD, plur. + COI (à toi), sing.", + '-les-lui': " COD, plur. + COI (à lui ou à elle), sing.", + '-les-nous': " COD, plur. + COI (à nous), plur.", + '-les-vous': " COD, plur. + COI (à vous), plur.", + '-les-leur': " COD, plur. + COI (à eux ou à elles), plur.", + + '-y': " pronom adverbial", + "-m’y": " (me) pronom personnel objet + (y) pronom adverbial", + "-t’y": " (te) pronom personnel objet + (y) pronom adverbial", + "-s’y": " (se) pronom personnel objet + (y) pronom adverbial", + + '-en': " pronom adverbial", + "-m’en": " (me) pronom personnel objet + (en) pronom adverbial", + "-t’en": " (te) pronom personnel objet + (en) pronom adverbial", + "-s’en": " (se) pronom personnel objet + (en) pronom adverbial", +} + + +_zElidedPrefix = re.compile("(?i)^((?:[dljmtsncç]|quoiqu|lorsqu|jusqu|puisqu|qu)’)(.+)") +_zCompoundWord = re.compile("(?i)(\\w+)(-(?:(?:les?|la)-(?:moi|toi|lui|[nv]ous|leur)|t-(?:il|elle|on)|y|en|[mts]’(?:y|en)|les?|l[aà]|[mt]oi|leur|lui|je|tu|ils?|elles?|on|[nv]ous))$") +_zTag = re.compile("[:;/][\\w*][^:;/]*") + +def split (sWord): + "split word in 3 parts: prefix, root, suffix" + sWord = sWord.replace("'", "’") + sPrefix = "" + sSuffix = "" + # préfixe élidé + m = _zElidedPrefix.match(sWord) + if m: + sPrefix = m.group(1) + sWord = m.group(2) + # mots composés + m = _zCompoundWord.match(sWord) + if m: + sWord = m.group(1) + sSuffix = m.group(2) + return sPrefix, sWord, sSuffix + + +def analyze (sWord): + "return meaning of if found else an empty string" + sWord = sWord.lower() + if sWord in _dValues: + return _dValues[sWord] + return "" + + +def formatTags (sTags): + "returns string: readable tags" + sRes = "" + sTags = re.sub("(?<=V[1-3])[itpqnmr_eaxz]+", "", sTags) + sTags = re.sub("(?<=V0[ea])[itpqnmr_eaxz]+", "", sTags) + for m in _zTag.finditer(sTags): + sRes += _dTAGS.get(m.group(0), " [{}]".format(m.group(0)))[0] + if sRes.startswith(" verbe") and not sRes.endswith("infinitif"): + sRes += " [{}]".format(sTags[1:sTags.find("/")]) + return sRes.rstrip(",") Index: graphspell/spellchecker.py ================================================================== --- graphspell/spellchecker.py +++ graphspell/spellchecker.py @@ -34,12 +34,12 @@ self.oPersonalDic = self._loadDictionary(sfPersonalDic) self.bCommunityDic = bool(self.oCommunityDic) self.bPersonalDic = bool(self.oPersonalDic) self.oTokenizer = None # Default suggestions - self.dDefaultSugg = None - self.loadSuggestions(sLangCode) + self.lexicographer = None + self.loadLang(sLangCode) # storage self.bStorage = False self._dMorphologies = {} # key: flexion, value: list of morphologies self._dLemmas = {} # key: flexion, value: list of lemmas @@ -100,18 +100,34 @@ self.bPersonalDic = False # Default suggestions - def loadSuggestions (self, sLangCode): + def loadLang (self, sLangCode): "load default suggestion module for " try: - suggest = importlib.import_module("."+sLangCode, "grammalecte.graphspell") + self.lexicographer = importlib.import_module("."+sLangCode, "grammalecte.graphspell") except ImportError: print("No suggestion module for language <"+sLangCode+">") return - self.dDefaultSugg = suggest.dSugg + + def analyze (self, sWord): + "returns a list of words and their morphologies" + if not self.lexicographer: + return [] + lWordAndMorph = [] + for sElem in self.lexicographer.split(sWord): + if sElem: + lMorph = self.getMorph(sElem) + sLex = self.lexicographer.analyze(sElem) + if sLex: + aRes = [ (" | ".join(lMorph), sLex) ] + else: + aRes = [ (sMorph, self.lexicographer.formatTags(sMorph)) for sMorph in lMorph ] + if aRes: + lWordAndMorph.append((sElem, aRes)) + return lWordAndMorph # Storage def activateStorage (self): @@ -159,10 +175,11 @@ dWord[dToken['sValue']] = dWord.get(dToken['sValue'], 0) + 1 else: for sLemma in self.getLemma(dToken['sValue']): dWord[sLemma] = dWord.get(sLemma, 0) + 1 return dWord + # IBDAWG functions def isValidToken (self, sToken): "checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)" @@ -216,15 +233,15 @@ return self._dLemmas[sWord] return { s[1:s.find("/")] for s in self.getMorph(sWord) } def suggest (self, sWord, nSuggLimit=10): "generator: returns 1, 2 or 3 lists of suggestions" - if self.dDefaultSugg: - if sWord in self.dDefaultSugg: - yield self.dDefaultSugg[sWord].split("|") - elif sWord.istitle() and sWord.lower() in self.dDefaultSugg: - lRes = self.dDefaultSugg[sWord.lower()].split("|") + if self.lexicographer.dSugg: + if sWord in self.lexicographer.dSugg: + yield self.lexicographer.dSugg[sWord].split("|") + elif sWord.istitle() and sWord.lower() in self.lexicographer.dSugg: + lRes = self.lexicographer.dSugg[sWord.lower()].split("|") yield list(map(lambda sSugg: sSugg[0:1].upper()+sSugg[1:], lRes)) else: yield self.oMainDic.suggest(sWord, nSuggLimit, True) else: yield self.oMainDic.suggest(sWord, nSuggLimit, True)