Comment: | merge trunk |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | multid |
Files: | files | file ages | folders |
SHA3-256: |
af32e20bdb0bcb20ac7d61d1aa9e467d |
User & Date: | olr on 2018-02-23 21:00:52 |
Other Links: | branch diff | manifest | tags |
2018-02-25
| ||
08:47 | [lo] lexicon editor check-in: 5a1baacbbb user: olr tags: new_feature, lo, multid | |
2018-02-23
| ||
21:00 | merge trunk check-in: af32e20bdb user: olr tags: multid | |
20:46 | [lo][bug] enumerator: valuemax of progressbar check-in: 1cb2c395f6 user: olr tags: trunk, lo | |
2018-02-19
| ||
18:06 | [lo] dictionaries options: remove print check-in: ba7c03de83 user: olr tags: lo, multid | |
Modified compile_rules.py from [9bd1433006] to [b3cfeb04f1].
︙ | ︙ | |||
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | print(" parsing rules...") global dDEF lLine = [] lRuleLine = [] lTest = [] lOpt = [] zBookmark = re.compile("^!!+") for i, sLine in enumerate(lRules, 1): if sLine.startswith('#END'): printBookmark(0, "BREAK BY #END", i) break elif sLine.startswith("#"): pass elif sLine.startswith("DEF:"): m = re.match("DEF: +([a-zA-Z_][a-zA-Z_0-9]*) +(.+)$", sLine.strip()) if m: dDEF["{"+m.group(1)+"}"] = m.group(2) else: print("Error in definition: ", end="") print(sLine.strip()) | > > > > > > | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | print(" parsing rules...") global dDEF lLine = [] lRuleLine = [] lTest = [] lOpt = [] zBookmark = re.compile("^!!+") zGraphLink = re.compile(r"^@@@@GRAPHLINK>(\w+)@@@@") for i, sLine in enumerate(lRules, 1): if sLine.startswith('#END'): printBookmark(0, "BREAK BY #END", i) break elif sLine.startswith("#"): pass elif sLine.startswith("@@@@"): m = re.match(r"^@@@@GRAPHLINK>(\w+)@@@@", sLine.strip()) if m: #lRuleLine.append(["@GRAPHLINK", m.group(1)]) printBookmark(1, "@GRAPHLINK: " + m.group(1), i) elif sLine.startswith("DEF:"): m = re.match("DEF: +([a-zA-Z_][a-zA-Z_0-9]*) +(.+)$", sLine.strip()) if m: dDEF["{"+m.group(1)+"}"] = m.group(2) else: print("Error in definition: ", end="") print(sLine.strip()) |
︙ | ︙ |
Modified gc_core/py/__init__.py from [a7ffc6f8bf] to [aeadedff14].
> > | 1 2 | from .grammar_checker import * |
Added gc_core/py/grammar_checker.py version [79ce1061e8].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # Grammalecte # Main class: wrapper import importlib import json from . import text class GrammarChecker: def __init__ (self, sLangCode, sContext="Python"): self.sLangCode = sLangCode # Grammar checker engine self.gce = importlib.import_module("."+sLangCode, "grammalecte") self.gce.load(sContext) # Spell checker self.oSpellChecker = self.gce.getSpellChecker() # Lexicographer self.oLexicographer = None # Text formatter self.oTextFormatter = None def getGCEngine (self): return self.gce def getSpellChecker (self): return self.oSpellChecker def getTextFormatter (self): if self.oTextFormatter == None: self.tf = importlib.import_module("."+self.sLangCode+".textformatter", "grammalecte") self.oTextFormatter = self.tf.TextFormatter() return self.oTextFormatter def getLexicographer (self): if self.oLexicographer == None: self.lxg = importlib.import_module("."+self.sLangCode+".lexicographe", "grammalecte") self.oLexicographer = self.lxg.Lexicographe(self.oSpellChecker) return self.oLexicographer def displayGCOptions (self): self.gce.displayOptions() def getParagraphErrors (self, sText, dOptions=None, bContext=False, bSpellSugg=False, bDebug=False): "returns a tuple: (grammar errors, spelling errors)" aGrammErrs = self.gce.parse(sText, "FR", bDebug=bDebug, dOptions=dOptions, bContext=bContext) aSpellErrs = self.oSpellChecker.parseParagraph(sText, bSpellSugg) return aGrammErrs, aSpellErrs def generateText (self, sText, bEmptyIfNoErrors=False, bSpellSugg=False, nWidth=100, bDebug=False): pass def generateTextAsJSON (self, sText, bContext=False, bEmptyIfNoErrors=False, bSpellSugg=False, bReturnText=False, bDebug=False): pass def generateParagraph (self, sText, dOptions=None, bEmptyIfNoErrors=False, bSpellSugg=False, nWidth=100, bDebug=False): aGrammErrs, aSpellErrs = self.getParagraphErrors(sText, dOptions, False, bSpellSugg, bDebug) if bEmptyIfNoErrors and not aGrammErrs and not aSpellErrs: return "" return text.generateParagraph(sText, aGrammErrs, aSpellErrs, nWidth) def generateParagraphAsJSON (self, iIndex, sText, dOptions=None, bContext=False, bEmptyIfNoErrors=False, bSpellSugg=False, bReturnText=False, lLineSet=None, bDebug=False): aGrammErrs, aSpellErrs = self.getParagraphErrors(sText, dOptions, bContext, bSpellSugg, bDebug) aGrammErrs = list(aGrammErrs) if bEmptyIfNoErrors and not aGrammErrs and not aSpellErrs: return "" if lLineSet: aGrammErrs, aSpellErrs = text.convertToXY(aGrammErrs, aSpellErrs, lLineSet) return json.dumps({ "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False) if bReturnText: return json.dumps({ "iParagraph": iIndex, "sText": sText, "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False) return json.dumps({ "iParagraph": iIndex, "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False) |
Modified gc_lang/fr/config.ini from [576d6e6c29] to [87fa24eb7e].
︙ | ︙ | |||
90 91 92 93 94 95 96 97 98 99 100 101 | oxt/ContextMenu/ContextMenu.py = ContextMenu.py oxt/ContextMenu/jobs.xcu = config/jobs.xcu # TextFormatter oxt/TextFormatter/TextFormatter.py = pythonpath/TextFormatter.py oxt/TextFormatter/tf_strings.py = pythonpath/tf_strings.py oxt/TextFormatter/tf_options.py = pythonpath/tf_options.py oxt/TextFormatter/tf_tabrep.py = pythonpath/tf_tabrep.py # Conjugueur oxt/Conjugueur/Conjugueur.py = pythonpath/Conjugueur.py # Modify author oxt/ChangeAuthor/Author.py = pythonpath/Author.py oxt/ChangeAuthor/ca_strings.py = pythonpath/ca_strings.py | > > > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | oxt/ContextMenu/ContextMenu.py = ContextMenu.py oxt/ContextMenu/jobs.xcu = config/jobs.xcu # TextFormatter oxt/TextFormatter/TextFormatter.py = pythonpath/TextFormatter.py oxt/TextFormatter/tf_strings.py = pythonpath/tf_strings.py oxt/TextFormatter/tf_options.py = pythonpath/tf_options.py oxt/TextFormatter/tf_tabrep.py = pythonpath/tf_tabrep.py # Lexicographer oxt/Lexicographer/Enumerator.py = pythonpath/Enumerator.py oxt/Lexicographer/enum_strings.py = pythonpath/enum_strings.py # Conjugueur oxt/Conjugueur/Conjugueur.py = pythonpath/Conjugueur.py # Modify author oxt/ChangeAuthor/Author.py = pythonpath/Author.py oxt/ChangeAuthor/ca_strings.py = pythonpath/ca_strings.py |
Modified gc_lang/fr/oxt/AppLauncher.py from [851c2d6eab] to [91f766cacd].
︙ | ︙ | |||
54 55 56 57 58 59 60 61 62 63 64 65 66 67 | import Author xDialog = Author.Author(self.ctx) xDialog.run(self.sLang) elif sCmd == "OP": import Options xDialog = Options.GC_Options(self.ctx) xDialog.run(self.sLang) elif sCmd.startswith("FA/"): findAll(sCmd[6:], (sCmd[3:4] == "y"), (sCmd[4:5] == "y")) # elif sCmd.startswith("URL/"): # # Call from context menu to launch URL? # # http://opengrok.libreoffice.org/xref/core/sw/source/ui/lingu/olmenu.cxx#785 # xSystemShellExecute = self.ctx.getServiceManager().createInstanceWithContext('com.sun.star.system.SystemShellExecute', self.ctx) # xSystemShellExecute.execute(url, "", uno.getConstantByName("com.sun.star.system.SystemShellExecuteFlags.URIS_ONLY")) | > > > > | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | import Author xDialog = Author.Author(self.ctx) xDialog.run(self.sLang) elif sCmd == "OP": import Options xDialog = Options.GC_Options(self.ctx) xDialog.run(self.sLang) elif sCmd == "EN": import Enumerator xDialog = Enumerator.Enumerator(self.ctx) xDialog.run(self.sLang) elif sCmd.startswith("FA/"): findAll(sCmd[6:], (sCmd[3:4] == "y"), (sCmd[4:5] == "y")) # elif sCmd.startswith("URL/"): # # Call from context menu to launch URL? # # http://opengrok.libreoffice.org/xref/core/sw/source/ui/lingu/olmenu.cxx#785 # xSystemShellExecute = self.ctx.getServiceManager().createInstanceWithContext('com.sun.star.system.SystemShellExecute', self.ctx) # xSystemShellExecute.execute(url, "", uno.getConstantByName("com.sun.star.system.SystemShellExecuteFlags.URIS_ONLY")) |
︙ | ︙ |
Added gc_lang/fr/oxt/Lexicographer/Enumerator.py version [753041f6b5].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | # Dictionary Options # by Olivier R. # License: MPL 2 import unohelper import uno import traceback import helpers import enum_strings import grammalecte.graphspell as sc from com.sun.star.task import XJobExecutor from com.sun.star.awt import XActionListener from com.sun.star.beans import PropertyValue def hexToRBG (sHexa): r = int(sHexa[:2], 16) g = int(sHexa[2:4], 16) b = int(sHexa[4:], 16) return (r & 255) << 16 | (g & 255) << 8 | (b & 255) def _waitPointer (funcDecorated): def wrapper (*args, **kwargs): # self is the first parameter if the decorator is applied on a object self = args[0] # before xPointer = self.xSvMgr.createInstanceWithContext("com.sun.star.awt.Pointer", self.ctx) xPointer.setType(uno.getConstantByName("com.sun.star.awt.SystemPointer.WAIT")) xWindowPeer = self.xContainer.getPeer() xWindowPeer.setPointer(xPointer) for x in xWindowPeer.Windows: x.setPointer(xPointer) # processing result = funcDecorated(*args, **kwargs) # after xPointer.setType(uno.getConstantByName("com.sun.star.awt.SystemPointer.ARROW")) xWindowPeer.setPointer(xPointer) for x in xWindowPeer.Windows: x.setPointer(xPointer) self.xContainer.setVisible(True) # seems necessary to refresh the dialog box and text widgets (why?) # return return result return wrapper class Enumerator (unohelper.Base, XActionListener, XJobExecutor): def __init__ (self, ctx): self.ctx = ctx self.xSvMgr = self.ctx.ServiceManager self.xDesktop = self.xSvMgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.ctx) self.xDocument = self.xDesktop.getCurrentComponent() self.xContainer = None self.xDialog = None self.oSpellChecker = None def _addWidget (self, name, wtype, x, y, w, h, **kwargs): xWidget = self.xDialog.createInstance('com.sun.star.awt.UnoControl%sModel' % wtype) xWidget.Name = name xWidget.PositionX = x xWidget.PositionY = y xWidget.Width = w xWidget.Height = h for k, w in kwargs.items(): setattr(xWidget, k, w) self.xDialog.insertByName(name, xWidget) return xWidget def _addGrid (self, name, x, y, w, h, columns, **kwargs): xGridModel = self.xDialog.createInstance('com.sun.star.awt.grid.UnoControlGridModel') xGridModel.Name = name xGridModel.PositionX = x xGridModel.PositionY = y xGridModel.Width = w xGridModel.Height = h xColumnModel = xGridModel.ColumnModel for e in columns: xCol = xColumnModel.createColumn() for k, w in e.items(): setattr(xCol, k, w) xColumnModel.addColumn(xCol) for k, w in kwargs.items(): setattr(xGridModel, k, w) self.xDialog.insertByName(name, xGridModel) return xGridModel def run (self, sLang): self.dUI = enum_strings.getUI(sLang) # dialog self.xDialog = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialogModel', self.ctx) self.xDialog.Width = 240 self.xDialog.Height = 280 self.xDialog.Title = self.dUI.get('title', "#title#") xWindowSize = helpers.getWindowSize() self.xDialog.PositionX = int((xWindowSize.Width / 2) - (self.xDialog.Width / 2)) self.xDialog.PositionY = int((xWindowSize.Height / 2) - (self.xDialog.Height / 2)) # fonts xFDTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor") xFDTitle.Height = 9 xFDTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD") xFDTitle.Name = "Verdana" xFDSubTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor") xFDSubTitle.Height = 8 xFDSubTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD") xFDSubTitle.Name = "Verdana" # widget nX = 10 nY1 = 5 nY2 = nY1 + 225 nWidth = self.xDialog.Width - 20 nHeight = 10 # List self._addWidget("list_section", 'FixedLine', nX, nY1, nWidth, nHeight, Label = self.dUI.get("list_section", "#err"), FontDescriptor = xFDTitle) self._addWidget('count_button', 'Button', nX, nY1+12, 70, 10, Label = self.dUI.get('count_button', "#err")) self._addWidget('count2_button', 'Button', nX+75, nY1+12, 70, 10, Label = self.dUI.get('count2_button', "#err")) self._addWidget('unknown_button', 'Button', nX+150, nY1+12, 70, 10, Label = self.dUI.get('unknown_button', "#err")) self.xGridModel = self._addGrid("list_grid", nX, nY1+25, nWidth, 180, [ {"Title": self.dUI.get("words", "#err"), "ColumnWidth": 175}, {"Title": "Occurrences", "ColumnWidth": 45} ]) self._addWidget('num_of_entries', 'FixedText', nX, nY1+210, 60, nHeight, Label = self.dUI.get('num_of_entries', "#err"), Align = 2) self.xNumWord = self._addWidget('num_of_entries_res', 'FixedText', nX+65, nY1+210, 30, nHeight, Label = "—") self._addWidget('tot_of_entries', 'FixedText', nX+100, nY1+210, 60, nHeight, Label = self.dUI.get('tot_of_entries', "#err"), Align = 2) self.xTotWord = self._addWidget('tot_of_entries_res', 'FixedText', nX+165, nY1+210, 30, nHeight, Label = "—") # Tag # Note: the only way to group RadioButtons is to create them successively self._addWidget("dformat_section", 'FixedLine', nX, nY2, 90, nHeight, Label = self.dUI.get("dformat_section", "#err"), FontDescriptor = xFDTitle) self._addWidget("charstyle_section", 'FixedLine', nX+100, nY2, 90, nHeight, Label = self.dUI.get("charstyle_section", "#err"), FontDescriptor = xFDTitle) self.xUnderline = self._addWidget('underline', 'RadioButton', nX, nY2+12, 40, nHeight, Label = self.dUI.get('underline', "#err")) self.xNoUnderline = self._addWidget('nounderline', 'RadioButton', nX+50, nY2+12, 40, nHeight, Label = self.dUI.get('nounderline', "#err")) self.xAccent = self._addWidget('accentuation', 'RadioButton', nX+100, nY2+12, 50, nHeight, Label = self.dUI.get('accentuation', "#err")) self.xNoAccent = self._addWidget('noaccentuation', 'RadioButton', nX+155, nY2+12, 40, nHeight, Label = self.dUI.get('noaccentuation', "#err")) self.xTag = self._addWidget('tag_button', 'Button', self.xDialog.Width-40, nY2+10, 30, 11, Label = self.dUI.get('tag_button', "#err"), FontDescriptor = xFDTitle, TextColor = 0x005500) # Progress bar self.xProgressBar = self._addWidget('progress_bar', 'ProgressBar', nX, self.xDialog.Height-25, 160, 14) self.xProgressBar.ProgressValueMin = 0 self.xProgressBar.ProgressValueMax = 1 # to calculate # Close self._addWidget('close_button', 'Button', self.xDialog.Width-60, self.xDialog.Height-25, 50, 14, Label = self.dUI.get('close_button', "#err"), FontDescriptor = xFDTitle, TextColor = 0x550000) # container self.xContainer = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialog', self.ctx) self.xContainer.setModel(self.xDialog) self.xGridControl = self.xContainer.getControl('list_grid') self.xContainer.getControl('count_button').addActionListener(self) self.xContainer.getControl('count_button').setActionCommand('Count') self.xContainer.getControl('count2_button').addActionListener(self) self.xContainer.getControl('count2_button').setActionCommand('CountByLemma') self.xContainer.getControl('unknown_button').addActionListener(self) self.xContainer.getControl('unknown_button').setActionCommand('UnknownWords') self.xContainer.getControl('tag_button').addActionListener(self) self.xContainer.getControl('tag_button').setActionCommand('Tag') self.xContainer.getControl('close_button').addActionListener(self) self.xContainer.getControl('close_button').setActionCommand('Close') self.xContainer.setVisible(False) xToolkit = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.ExtToolkit', self.ctx) self.xContainer.createPeer(xToolkit, None) self.xContainer.execute() # XActionListener def actionPerformed (self, xActionEvent): try: if xActionEvent.ActionCommand == "Count": self.count(self.dUI.get("words", "#err")) self.xTag.Enabled = True elif xActionEvent.ActionCommand == "CountByLemma": self.count(self.dUI.get("lemmas", "#err"), bByLemma=True) self.xTag.Enabled = False elif xActionEvent.ActionCommand == "UnknownWords": self.count(self.dUI.get("unknown_words", "#err"), bOnlyUnknownWords=True) self.xTag.Enabled = True elif xActionEvent.ActionCommand == "Tag": nRow = self.xGridControl.getCurrentRow() if nRow == -1: return sWord = self.xGridModel.GridDataModel.getCellData(0, nRow) if not sWord: return sAction = "" if self.xUnderline.State: sAction = "underline" elif self.xNoUnderline.State: sAction = "nounderline" elif self.xAccent.State: sAction = "accentuation" elif self.xNoAccent.State: sAction = "noaccentuation" self.tagText(sWord, sAction) elif xActionEvent.ActionCommand == "Close": self.xContainer.endExecute() except: traceback.print_exc() # XJobExecutor def trigger (self, args): try: xDialog = Enumerator(self.ctx) xDialog.run() except: traceback.print_exc() # Code def _setTitleOfFirstColumn (self, sTitle): xColumnModel = self.xGridModel.ColumnModel xColumn = xColumnModel.getColumn(0) xColumn.Title = sTitle def _getParagraphsFromText (self): "generator: returns full document text paragraph by paragraph" xCursor = self.xDocument.Text.createTextCursor() xCursor.gotoStart(False) xCursor.gotoEndOfParagraph(True) yield xCursor.getString() while xCursor.gotoNextParagraph(False): xCursor.gotoEndOfParagraph(True) yield xCursor.getString() def _countParagraph (self): i = 1 xCursor = self.xDocument.Text.createTextCursor() xCursor.gotoStart(False) while xCursor.gotoNextParagraph(False): i += 1 return i @_waitPointer def count (self, sTitle, bByLemma=False, bOnlyUnknownWords=False): if not self.oSpellChecker: self.oSpellChecker = sc.SpellChecker("fr") self._setTitleOfFirstColumn(sTitle) self.xProgressBar.ProgressValueMax = self._countParagraph() * 2 self.xProgressBar.ProgressValue = 0 xGridDataModel = self.xGridModel.GridDataModel xGridDataModel.removeAllRows() dWord = {} for sParagraph in self._getParagraphsFromText(): dWord = self.oSpellChecker.countWordsOccurrences(sParagraph, bByLemma, bOnlyUnknownWords, dWord) self.xProgressBar.ProgressValue += 1 self.xProgressBar.ProgressValueMax += len(dWord) i = 0 nTotOccur = 0 for k, w in sorted(dWord.items(), key=lambda t: t[1], reverse=True): xGridDataModel.addRow(i, (k, w)) self.xProgressBar.ProgressValue += 1 i += 1 nTotOccur += w self.xProgressBar.ProgressValue = self.xProgressBar.ProgressValueMax self.xNumWord.Label = str(i) self.xTotWord.Label = nTotOccur @_waitPointer def tagText (self, sWord, sAction=""): if not sAction: return self.xProgressBar.ProgressValueMax = self._countParagraph() self.xProgressBar.ProgressValue = 0 xCursor = self.xDocument.Text.createTextCursor() #helpers.xray(xCursor) xCursor.gotoStart(False) xCursor.gotoEndOfParagraph(True) sParagraph = xCursor.getString() if sWord in sParagraph: self._tagParagraph(sWord, xCursor, sAction) self.xProgressBar.ProgressValue += 1 while xCursor.gotoNextParagraph(False): xCursor.gotoEndOfParagraph(True) sParagraph = xCursor.getString() if sWord in sParagraph: self._tagParagraph(sWord, xCursor, sAction) self.xProgressBar.ProgressValue += 1 self.xProgressBar.ProgressValue = self.xProgressBar.ProgressValueMax def _tagParagraph (self, sWord, xCursor, sAction): xCursor.gotoStartOfParagraph(False) while xCursor.gotoNextWord(False): if xCursor.isStartOfWord(): xCursor.gotoEndOfWord(True) if sWord == xCursor.getString(): if sAction == "underline": xCursor.CharBackColor = hexToRBG("AA0000") elif sAction == "nounderline": xCursor.CharBackColor = hexToRBG("FFFFFF") elif sAction == "accentuation": xCursor.CharStyleName = "Emphasis" elif sAction == "noaccentuation": #xCursor.CharStyleName = "Default Style" # doesn’t work xCursor.setPropertyToDefault("CharStyleName") #g_ImplementationHelper = unohelper.ImplementationHelper() #g_ImplementationHelper.addImplementation(Enumerator, 'net.grammalecte.enumerator', ('com.sun.star.task.Job',)) |
Added gc_lang/fr/oxt/Lexicographer/enum_strings.py version [fd05286777].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | def getUI (sLang): if sLang in dStrings: return dStrings[sLang] return dStrings["fr"] dStrings = { "fr": { "title": "Grammalecte · Recenseur de mots", "list_section": "Calcul des occurrences des mots", "count_button": "Compter tout", "count2_button": "Compter par lemme", "unknown_button": "Mots inconnus", "num_of_entries": "Nombre d’entrées :", "tot_of_entries": "Total des entrées :", "words": "Mots", "lemmas": "Lemmes", "unknown_words": "Mots inconnus", "dformat_section": "Formatage direct", "charstyle_section": "Style de caractères", "underline": "Surligner", "nounderline": "Effacer", "accentuation": "Accentuation", "noaccentuation": "Aucun", "tag_button": "Taguer", "close_button": "Fermer", }, "en": { "title": "Grammalecte · Enumerator of Words", "list_section": "Words", "count_button": "Count all", "count2_button": "Count by lemma", "unknown_button": "Unknown words", "num_of_entries": "Number of entries:", "tot_of_entries": "Total of words:", "words": "Words", "lemmas": "Lemmas", "unknown_words": "Unknown words", "dformat_section": "Direct format", "charstyle_section": "Character style", "underline": "Underline", "nounderline": "Erase", "accentuation": "Accentuation", "noaccentuation": "None", "tag_button": "Tag", "close_button": "Close", }, } |
Modified gc_lang/fr/oxt/addons.xcu from [3b803f02e0] to [9b5b4f4c15].
︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | <value>_self</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument,com.sun.star.presentation.PresentationDocument</value> </prop> </node> <node oor:name="m3" oor:op="replace"> <!--<prop oor:name="URL" oor:type="xs:string"> <value>vnd.sun.star.script:basiclib.Module1.EditAuthorField?language=Basic&location=application</value> </prop>--> <prop oor:name="URL" oor:type="xs:string"> <value>service:net.grammalecte.AppLauncher?MA</value> </prop> <prop oor:name="Title" oor:type="xs:string"> <value/> <value xml:lang="fr">~Modifier le champ “Auteur”…</value> <value xml:lang="en-US">~Modify the field “Author”…</value> </prop> <prop oor:name="Target" oor:type="xs:string"> <value>_self</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument</value> </prop> </node> | > > > > > > > > > > > > > > > > | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | <value>_self</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument,com.sun.star.presentation.PresentationDocument</value> </prop> </node> <node oor:name="m3" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>service:net.grammalecte.AppLauncher?EN</value> </prop> <prop oor:name="Title" oor:type="xs:string"> <value/> <value xml:lang="fr">~Recenseur de mots…</value> <value xml:lang="en-US">~Enumerator of words…</value> </prop> <prop oor:name="Target" oor:type="xs:string"> <value>_self</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument,com.sun.star.presentation.PresentationDocument</value> </prop> </node> <node oor:name="m4" oor:op="replace"> <!--<prop oor:name="URL" oor:type="xs:string"> <value>vnd.sun.star.script:basiclib.Module1.EditAuthorField?language=Basic&location=application</value> </prop>--> <prop oor:name="URL" oor:type="xs:string"> <value>service:net.grammalecte.AppLauncher?MA</value> </prop> <prop oor:name="Title" oor:type="xs:string"> <value/> <value xml:lang="fr">~Modifier le champ “Auteur”…</value> <value xml:lang="en-US">~Modify the field “Author”…</value> </prop> <prop oor:name="Target" oor:type="xs:string"> <value>_self</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument</value> </prop> </node> <node oor:name="m5" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>private:separator</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument,com.sun.star.presentation.PresentationDocument</value> </prop> </node> <node oor:name="m6" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>service:net.grammalecte.AppLauncher?OP</value> </prop> <!--<prop oor:name="URL" oor:type="xs:string"> <value>.uno:OptionsTreeDialog?OptionsPageURL:string=%origin%/dialog/fr.xdl</value> </prop>--> <prop oor:name="Title" oor:type="xs:string"> |
︙ | ︙ | |||
115 116 117 118 119 120 121 | <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument</value> </prop> <prop oor:name="ImageIdentifier" oor:type="xs:string"> <value>org.dicollecte.images:Grammalecte</value> </prop> </node> | | | | | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument</value> </prop> <prop oor:name="ImageIdentifier" oor:type="xs:string"> <value>org.dicollecte.images:Grammalecte</value> </prop> </node> <node oor:name="m7" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>service:net.grammalecte.AppLauncher?DI</value> </prop> <prop oor:name="Title" oor:type="xs:string"> <value/> <value xml:lang="fr">~Options des dictionnaires…</value> <value xml:lang="en-US">Dictionaries ~options…</value> </prop> <prop oor:name="Target" oor:type="xs:string"> <value>_self</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument,com.sun.star.presentation.PresentationDocument</value> </prop> <prop oor:name="ImageIdentifier" oor:type="xs:string"> <value>org.dicollecte.images:Frenchflag</value> </prop> </node> <node oor:name="m8" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>service:net.grammalecte.AppLauncher?DS</value> </prop> <prop oor:name="Title" oor:type="xs:string"> <value/> <value xml:lang="fr">~Options orthographiques…</value> <value xml:lang="en-US">Spelling ~options…</value> </prop> <prop oor:name="Target" oor:type="xs:string"> <value>_self</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument,com.sun.star.presentation.PresentationDocument</value> </prop> <prop oor:name="ImageIdentifier" oor:type="xs:string"> <value>org.dicollecte.images:Frenchflag</value> </prop> </node> <node oor:name="m9" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>private:separator</value> </prop> <prop oor:name="Context" oor:type="xs:string"> <value>com.sun.star.text.TextDocument,com.sun.star.text.GlobalDocument,com.sun.star.text.WebDocument,com.sun.star.presentation.PresentationDocument</value> </prop> </node> <node oor:name="m10" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>service:net.grammalecte.AppLauncher?About</value> </prop> <prop oor:name="Title" oor:type="xs:string"> <value/> <value xml:lang="fr">À ~propos de Grammalecte…</value> <value xml:lang="en-US">~About Grammalecte…</value> |
︙ | ︙ |
Modified gc_lang/fr/perf_memo.txt from [15962af16c] to [b880c3770c].
︙ | ︙ | |||
19 20 21 22 23 24 25 | 0.5.12 2016.10.14 18:58 4.51895 1.0843 0.772805 0.22387 0.249411 0.261593 0.628802 0.339303 0.0570326 0.00805416 0.5.15 2017.01.22 11:44 4.85204 1.16134 0.770762 0.227874 0.244574 0.253305 0.58831 0.319987 0.0603996 0.00694786 0.5.15 2017.01.22 11:47 4.85593 1.15248 0.762924 0.22744 0.243461 0.254609 0.586741 0.317503 0.0588827 0.00701016 (unicode normalisation NFC) 0.5.15 2017.01.31 12:06 4.88227 1.18008 0.782217 0.232617 0.247672 0.257628 0.596903 0.32169 0.0603505 0.00695196 0.5.15 2017.02.05 10:10 4.90222 1.18444 0.786696 0.233413 0.25071 0.260214 0.602112 0.325235 0.0609932 0.00706897 0.5.16 2017.05.12 07:41 4.92201 1.19269 0.80639 0.239147 0.257518 0.266523 0.62111 0.33359 0.0634668 0.00757178 0.6.1 2018.02.12 09:58 5.25924 1.2649 0.878442 0.257465 0.280558 0.293903 0.686887 0.391275 0.0672474 0.00824723 | | | 19 20 21 22 23 24 25 26 | 0.5.12 2016.10.14 18:58 4.51895 1.0843 0.772805 0.22387 0.249411 0.261593 0.628802 0.339303 0.0570326 0.00805416 0.5.15 2017.01.22 11:44 4.85204 1.16134 0.770762 0.227874 0.244574 0.253305 0.58831 0.319987 0.0603996 0.00694786 0.5.15 2017.01.22 11:47 4.85593 1.15248 0.762924 0.22744 0.243461 0.254609 0.586741 0.317503 0.0588827 0.00701016 (unicode normalisation NFC) 0.5.15 2017.01.31 12:06 4.88227 1.18008 0.782217 0.232617 0.247672 0.257628 0.596903 0.32169 0.0603505 0.00695196 0.5.15 2017.02.05 10:10 4.90222 1.18444 0.786696 0.233413 0.25071 0.260214 0.602112 0.325235 0.0609932 0.00706897 0.5.16 2017.05.12 07:41 4.92201 1.19269 0.80639 0.239147 0.257518 0.266523 0.62111 0.33359 0.0634668 0.00757178 0.6.1 2018.02.12 09:58 5.25924 1.2649 0.878442 0.257465 0.280558 0.293903 0.686887 0.391275 0.0672474 0.00824723 0.6.2 2018.02.19 19:06 5.51302 1.29359 0.874157 0.260415 0.271596 0.290641 0.684754 0.376905 0.0815201 0.00919633 (spelling normalization) |
Modified gc_lang/fr/webext/gce_worker.js from [c20f81d8f3] to [efd11a103b].
︙ | ︙ | |||
200 201 202 203 204 205 206 | } function parseAndSpellcheck (sText, sCountry, bDebug, bContext, dInfo={}) { let i = 0; sText = sText.replace(//g, "").normalize("NFC"); for (let sParagraph of text.getParagraph(sText)) { let aGrammErr = gc_engine.parse(sParagraph, sCountry, bDebug, bContext); | | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | } function parseAndSpellcheck (sText, sCountry, bDebug, bContext, dInfo={}) { let i = 0; sText = sText.replace(//g, "").normalize("NFC"); for (let sParagraph of text.getParagraph(sText)) { let aGrammErr = gc_engine.parse(sParagraph, sCountry, bDebug, bContext); let aSpellErr = oSpellChecker.parseParagraph(sParagraph); postMessage(createResponse("parseAndSpellcheck", {sParagraph: sParagraph, iParaNum: i, aGrammErr: aGrammErr, aSpellErr: aSpellErr}, dInfo, false)); i += 1; } postMessage(createResponse("parseAndSpellcheck", null, dInfo, true)); } function parseAndSpellcheck1 (sParagraph, sCountry, bDebug, bContext, dInfo={}) { sParagraph = sParagraph.replace(//g, "").normalize("NFC"); let aGrammErr = gc_engine.parse(sParagraph, sCountry, bDebug, bContext); let aSpellErr = oSpellChecker.parseParagraph(sParagraph); postMessage(createResponse("parseAndSpellcheck1", {sParagraph: sParagraph, aGrammErr: aGrammErr, aSpellErr: aSpellErr}, dInfo, true)); } function getOptions (dInfo={}) { postMessage(createResponse("getOptions", gc_engine.getOptions(), dInfo, true)); } |
︙ | ︙ |
Modified grammalecte-cli.py from [d66b04b565] to [150bfbed66].
1 2 3 4 5 6 7 | #!/usr/bin/env python3 import sys import os.path import argparse import json | < | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/env python3 import sys import os.path import argparse import json import grammalecte import grammalecte.text as txt from grammalecte.graphspell.echo import echo _EXAMPLE = "Quoi ? Racontes ! Racontes-moi ! Bon sangg, parles ! Oui. Il y a des menteur partout. " \ "Je suit sidéré par la brutales arrogance de cette homme-là. Quelle salopard ! Un escrocs de la pire espece. " \ "Quant sera t’il châtiés pour ses mensonge ? Merde ! J’en aie marre." |
︙ | ︙ | |||
40 41 42 43 44 45 46 | if sys.platform == "win32": # Apparently, the console transforms «’» in «'». # So we reverse it to avoid many useless warnings. sText = sText.replace("'", "’") return sText | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | > > > > | > | | | | > | | > | > | | > > > > | | < < < < < > | | > > > > > | | | > | | | < < | | | | < > | | < | < < < < < < < | < < < < < < | | | | | | | | | | | | | | | | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | if sys.platform == "win32": # Apparently, the console transforms «’» in «'». # So we reverse it to avoid many useless warnings. sText = sText.replace("'", "’") return sText def readFile (spf): "generator: returns file line by line" if os.path.isfile(spf): with open(spf, "r", encoding="utf-8") as hSrc: for sLine in hSrc: yield sLine else: print("# Error: file <" + spf + ">not found.") def generateParagraphFromFile (spf, bConcatLines=False): "generator: returns text by tuple of (iParagraph, sParagraph, lLineSet)" if not bConcatLines: for iParagraph, sLine in enumerate(readFile(spf), 1): yield iParagraph, sLine, None else: lLine = [] iParagraph = 1 for iLine, sLine in enumerate(readFile(spf), 1): if sLine.strip(): lLine.append((iLine, sLine)) elif lLine: sText, lLineSet = txt.createParagraphWithLines(lLine) yield iParagraph, sText, lLineSet lLine = [] iParagraph += 1 if lLine: sText, lLineSet = txt.createParagraphWithLines(lLine) yield iParagraph, sText, lLineSet def output (sText, hDst=None): if not hDst: echo(sText, end="") else: hDst.write(sText) def main (): xParser = argparse.ArgumentParser() xParser.add_argument("-f", "--file", help="parse file (UTF-8 required!) [on Windows, -f is similar to -ff]", type=str) xParser.add_argument("-ff", "--file_to_file", help="parse file (UTF-8 required!) and create a result file (*.res.txt)", type=str) xParser.add_argument("-owe", "--only_when_errors", help="display results only when there are errors", action="store_true") xParser.add_argument("-j", "--json", help="generate list of errors in JSON (only with option --file or --file_to_file)", action="store_true") xParser.add_argument("-cl", "--concat_lines", help="concatenate lines not separated by an empty paragraph (only with option --file or --file_to_file)", action="store_true") xParser.add_argument("-tf", "--textformatter", help="auto-format text according to typographical rules (not with option --concat_lines)", action="store_true") xParser.add_argument("-tfo", "--textformatteronly", help="auto-format text and disable grammar checking (only with option --file or --file_to_file)", action="store_true") xParser.add_argument("-ctx", "--context", help="return errors with context (only with option --json)", action="store_true") xParser.add_argument("-wss", "--with_spell_sugg", help="add suggestions for spelling errors (only with option --file or --file_to_file)", action="store_true") xParser.add_argument("-w", "--width", help="width in characters (40 < width < 200; default: 100)", type=int, choices=range(40,201,10), default=100) xParser.add_argument("-lo", "--list_options", help="list options", action="store_true") xParser.add_argument("-lr", "--list_rules", nargs="?", help="list rules [regex pattern as filter]", const="*") xParser.add_argument("-sug", "--suggest", help="get suggestions list for given word", type=str) xParser.add_argument("-on", "--opt_on", nargs="+", help="activate options") xParser.add_argument("-off", "--opt_off", nargs="+", help="deactivate options") xParser.add_argument("-roff", "--rule_off", nargs="+", help="deactivate rules") xParser.add_argument("-d", "--debug", help="debugging mode (only in interactive mode)", action="store_true") xArgs = xParser.parse_args() oGrammarChecker = grammalecte.GrammarChecker("fr") oSpellChecker = oGrammarChecker.getSpellChecker() oLexicographer = oGrammarChecker.getLexicographer() oTextFormatter = oGrammarChecker.getTextFormatter() if not xArgs.json: echo("Grammalecte v{}".format(oGrammarChecker.gce.version)) # list options or rules if xArgs.list_options or xArgs.list_rules: if xArgs.list_options: oGrammarChecker.gce.displayOptions("fr") if xArgs.list_rules: oGrammarChecker.gce.displayRules(None if xArgs.list_rules == "*" else xArgs.list_rules) exit() # spell suggestions if xArgs.suggest: for lSugg in oSpellChecker.suggest(xArgs.suggest): if xArgs.json: sText = json.dumps({ "aSuggestions": lSugg }, ensure_ascii=False) else: sText = "Suggestions : " + " | ".join(lSugg) echo(sText) exit() # disable options if not xArgs.json: xArgs.context = False if xArgs.concat_lines: xArgs.textformatter = False # grammar options oGrammarChecker.gce.setOptions({"html": True, "latex": True}) if xArgs.opt_on: oGrammarChecker.gce.setOptions({ opt:True for opt in xArgs.opt_on if opt in oGrammarChecker.gce.getOptions() }) if xArgs.opt_off: oGrammarChecker.gce.setOptions({ opt:False for opt in xArgs.opt_off if opt in oGrammarChecker.gce.getOptions() }) # disable grammar rules if xArgs.rule_off: for sRule in xArgs.rule_off: oGrammarChecker.gce.ignoreRule(sRule) sFile = xArgs.file or xArgs.file_to_file if sFile: # file processing hDst = open(sFile[:sFile.rfind(".")]+".res.txt", "w", encoding="utf-8", newline="\n") if xArgs.file_to_file or sys.platform == "win32" else None bComma = False if xArgs.json: output('{ "grammalecte": "'+oGrammarChecker.gce.version+'", "lang": "'+oGrammarChecker.gce.lang+'", "data" : [\n', hDst) for i, sText, lLineSet in generateParagraphFromFile(sFile, xArgs.concat_lines): if xArgs.textformatter or xArgs.textformatteronly: sText = oTextFormatter.formatText(sText) if xArgs.textformatteronly: output(sText, hDst) continue if xArgs.json: sText = oGrammarChecker.generateParagraphAsJSON(i, sText, bContext=xArgs.context, bEmptyIfNoErrors=xArgs.only_when_errors, \ bSpellSugg=xArgs.with_spell_sugg, bReturnText=xArgs.textformatter, lLineSet=lLineSet) else: sText = oGrammarChecker.generateParagraph(sText, bEmptyIfNoErrors=xArgs.only_when_errors, bSpellSugg=xArgs.with_spell_sugg, nWidth=xArgs.width) if sText: if xArgs.json and bComma: output(",\n", hDst) output(sText, hDst) bComma = True if hDst: echo("§ %d\r" % i, end="", flush=True) if xArgs.json: output("\n]}\n", hDst) else: # pseudo-console sInputText = "\n~==========~ Enter your text [/h /q] ~==========~\n" sText = _getText(sInputText) 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))) elif sText.startswith("!"): for sWord in sText[1:].strip().split(): if sWord: for lSugg in oSpellChecker.suggest(sWord): echo(" | ".join(lSugg)) elif sText.startswith(">"): oSpellChecker.drawPath(sText[1:].strip()) elif sText.startswith("="): for sRes in oSpellChecker.select(sText[1:].strip()): echo(sRes) elif sText.startswith("/+ "): oGrammarChecker.gce.setOptions({ opt:True for opt in sText[3:].strip().split() if opt in oGrammarChecker.gce.getOptions() }) echo("done") elif sText.startswith("/- "): oGrammarChecker.gce.setOptions({ opt:False for opt in sText[3:].strip().split() if opt in oGrammarChecker.gce.getOptions() }) echo("done") elif sText.startswith("/-- "): for sRule in sText[3:].strip().split(): oGrammarChecker.gce.ignoreRule(sRule) echo("done") elif sText.startswith("/++ "): for sRule in sText[3:].strip().split(): oGrammarChecker.gce.reactivateRule(sRule) echo("done") elif sText == "/debug" or sText == "/d": xArgs.debug = not(xArgs.debug) echo("debug mode on" if xArgs.debug else "debug mode off") elif sText == "/textformatter" or sText == "/tf": xArgs.textformatter = not(xArgs.textformatter) echo("textformatter on" if xArgs.debug else "textformatter off") elif sText == "/help" or sText == "/h": echo(_HELP) elif sText == "/lopt" or sText == "/lo": oGrammarChecker.gce.displayOptions("fr") elif sText.startswith("/lr"): sText = sText.strip() sFilter = sText[sText.find(" "):].strip() if sText != "/lr" and sText != "/rules" else None oGrammarChecker.gce.displayRules(sFilter) elif sText == "/quit" or sText == "/q": break elif sText.startswith("/rl"): # reload (todo) pass else: for sParagraph in txt.getParagraph(sText): if xArgs.textformatter: sText = oTextFormatter.formatText(sText) sRes = oGrammarChecker.generateParagraph(sText, bEmptyIfNoErrors=xArgs.only_when_errors, nWidth=xArgs.width, bDebug=xArgs.debug) if sRes: echo("\n" + sRes) else: echo("\nNo error found.") sText = _getText(sInputText) if __name__ == '__main__': main() |
Modified grammalecte-server.py from [3253a2b2ff] to [a5cc9d7be7].
1 2 3 4 5 6 7 8 9 10 11 12 | #!/usr/bin/env python3 import sys import os.path import argparse import json import traceback import configparser import time from bottle import Bottle, run, request, response, template, static_file | < | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/usr/bin/env python3 import sys import os.path import argparse import json import traceback import configparser import time from bottle import Bottle, run, request, response, template, static_file import grammalecte import grammalecte.text as txt from grammalecte.graphspell.echo import echo HOMEPAGE = """ <!DOCTYPE HTML> <html> <head> |
︙ | ︙ | |||
125 126 127 128 129 130 131 | def genUserId (): i = 0 while True: yield str(i) i += 1 | > | | | | < | < < < < | | < < < < < | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | def genUserId (): i = 0 while True: yield str(i) i += 1 if __name__ == '__main__': # initialisation oGrammarChecker = grammalecte.GrammarChecker("fr", "Server") oSpellChecker = oGrammarChecker.getSpellChecker() oLexicographer = oGrammarChecker.getLexicographer() oTextFormatter = oGrammarChecker.getTextFormatter() gce = oGrammarChecker.getGCEngine() echo("Grammalecte v{}".format(gce.version)) dServerOptions = getServerOptions() dGCOptions = getConfigOptions("fr") if dGCOptions: gce.setOptions(dGCOptions) dServerGCOptions = gce.getOptions() echo("Grammar options:\n" + " | ".join([ k + ": " + str(v) for k, v in sorted(dServerGCOptions.items()) ])) dUser = {} userGenerator = genUserId() app = Bottle() # GET @app.route("/") |
︙ | ︙ | |||
176 177 178 179 180 181 182 | # POST @app.route("/gc_text/fr", method="POST") def gcText (): #if len(lang) != 2 or lang != "fr": # abort(404, "No grammar checker available for lang “" + str(lang) + "”") bComma = False | < | | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | # POST @app.route("/gc_text/fr", method="POST") def gcText (): #if len(lang) != 2 or lang != "fr": # abort(404, "No grammar checker available for lang “" + str(lang) + "”") bComma = False dOptions = None sError = "" if request.cookies.user_id: if request.cookies.user_id in dUser: dOptions = dUser[request.cookies.user_id].get("gc_options", None) response.set_cookie("user_id", request.cookies.user_id, path="/", max_age=86400) # we renew cookie for 24h else: response.delete_cookie("user_id", path="/") if request.forms.options: try: dOptions = dict(dServerGCOptions) if not dOptions else dict(dOptions) dOptions.update(json.loads(request.forms.options)) except: sError = "request options not used" sJSON = '{ "program": "grammalecte-fr", "version": "'+gce.version+'", "lang": "'+gce.lang+'", "error": "'+sError+'", "data" : [\n' for i, sText in enumerate(txt.getParagraph(request.forms.text), 1): if bool(request.forms.tf): sText = oTextFormatter.formatText(sText) sText = oGrammarChecker.generateParagraphAsJSON(i, sText, dOptions=dOptions, bEmptyIfNoErrors=True, bReturnText=bool(request.forms.tf)) if sText: if bComma: sJSON += ",\n" sJSON += sText bComma = True sJSON += "\n]}\n" return sJSON |
︙ | ︙ | |||
227 228 229 230 231 232 233 | def resetOptions (): if request.cookies.user_id and request.cookies.user_id in dUser: del dUser[request.cookies.user_id] return "done" @app.route("/format_text/fr", method="POST") def formatText (): | | | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | def resetOptions (): if request.cookies.user_id and request.cookies.user_id in dUser: del dUser[request.cookies.user_id] return "done" @app.route("/format_text/fr", method="POST") def formatText (): return oTextFormatter.formatText(request.forms.text) #@app.route('/static/<filepath:path>') #def server_static (filepath): # return static_file(filepath, root='./views/static') @app.route("/purge_users", method="POST") def purgeUsers (): |
︙ | ︙ |
Modified graphspell-js/spellchecker.js from [e878cd2181] to [7b8a526c88].
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | "use strict"; if (typeof(require) !== 'undefined') { var ibdawg = require("resource://grammalecte/graphspell/ibdawg.js"); } ${map} const dDefaultDictionaries = new Map([ | > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | "use strict"; if (typeof(require) !== 'undefined') { var ibdawg = require("resource://grammalecte/graphspell/ibdawg.js"); var tokenizer = require("resource://grammalecte/graphspell/tokenizer.js"); } ${map} const dDefaultDictionaries = new Map([ |
︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | this.sLangCode = sLangCode; if (!mainDic) { mainDic = dDefaultDictionaries.gl_get(sLangCode, ""); } this.oMainDic = this._loadDictionary(mainDic, sPath, true); this.oExtendedDic = this._loadDictionary(extentedDic, sPath); this.oPersonalDic = this._loadDictionary(personalDic, sPath); } _loadDictionary (dictionary, sPath, bNecessary=false) { // returns an IBDAWG object if (!dictionary) { return null; } try { | > | > > > > > > > > > > > > > > > > > > > > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | this.sLangCode = sLangCode; if (!mainDic) { mainDic = dDefaultDictionaries.gl_get(sLangCode, ""); } this.oMainDic = this._loadDictionary(mainDic, sPath, true); this.oExtendedDic = this._loadDictionary(extentedDic, sPath); this.oPersonalDic = this._loadDictionary(personalDic, sPath); this.oTokenizer = null; } _loadDictionary (dictionary, sPath, bNecessary=false) { // returns an IBDAWG object if (!dictionary) { return null; } try { if (typeof(ibdawg) !== 'undefined') { return new ibdawg.IBDAWG(dictionary); // dictionary can be a filename or a JSON object } else { return new IBDAWG(dictionary, sPath); // dictionary can be a filename or a JSON object } } catch (e) { let sfDictionary = (typeof(dictionary) == "string") ? dictionary : dictionary.sLangName + "/" + dictionary.sFileName; if (bNecessary) { throw "Error: <" + sfDictionary + "> not loaded. " + e.message; } console.log("Error: <" + sfDictionary + "> not loaded.") console.log(e.message); return null; } } loadTokenizer () { if (typeof(tokenizer) !== 'undefined') { this.oTokenizer = new tokenizer.Tokenizer(this.sLangCode); } else { this.oTokenizer = new Tokenizer(this.sLangCode); } } setMainDictionary (dictionary) { // returns true if the dictionary is loaded this.oMainDic = this._loadDictionary(dictionary); return Boolean(this.oMainDic); } setExtendedDictionary (dictionary) { // returns true if the dictionary is loaded this.oExtendedDic = this._loadDictionary(dictionary); return Boolean(this.oExtendedDic); } setPersonalDictionary (dictionary) { // returns true if the dictionary is loaded this.oPersonalDic = this._loadDictionary(dictionary); return Boolean(this.oPersonalDic); } // parse text functions parseParagraph (sText) { if (!this.oTokenizer) { this.loadTokenizer(); } let aSpellErr = []; for (let oToken of this.oTokenizer.genTokens(sText)) { if (oToken.sType === 'WORD' && !this.isValidToken(oToken.sValue)) { aSpellErr.push(oToken); } } return aSpellErr; } // IBDAWG functions isValidToken (sToken) { // checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked) if (this.oMainDic.isValidToken(sToken)) { return true; |
︙ | ︙ |
Modified graphspell-js/tokenizer.js from [c3f0ee8c90] to [bdd895b918].
︙ | ︙ | |||
83 84 85 86 87 88 89 | helpers.logerror(e); } } i += nCut; sText = sText.slice(nCut); } } | < < < < < < < < < < | 83 84 85 86 87 88 89 90 91 92 93 94 95 | helpers.logerror(e); } } i += nCut; sText = sText.slice(nCut); } } } if (typeof(exports) !== 'undefined') { exports.Tokenizer = Tokenizer; } |
Modified graphspell/__init__.py from [a7ffc6f8bf] to [a53bdfb757].
> > | 1 2 | from .spellchecker import * |
Modified graphspell/spellchecker.py from [638f8d8cdf] to [dbd02131cc].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | # Spellchecker # Wrapper for the IBDAWG class. # Useful to check several dictionaries at once. # To avoid iterating over a pile of dictionaries, it is assumed that 3 are enough: # - the main dictionary, bundled with the package # - the extended dictionary, added by an organization # - the personal dictionary, created by the user for its own convenience import traceback from . import ibdawg dDefaultDictionaries = { "fr": "fr.bdic", "en": "en.bdic" } class SpellChecker (): 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, True) self.oExtendedDic = self._loadDictionary(sfExtendedDic) self.oPersonalDic = self._loadDictionary(sfPersonalDic) def _loadDictionary (self, sfDictionary, bNecessary=False): "returns an IBDAWG object" if not sfDictionary: return None try: return ibdawg.IBDAWG(sfDictionary) 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" self.oMainDic = self._loadDictionary(sfDictionary) return bool(self.oMainDic) def setExtendedDictionary (self, sfDictionary): "returns True if the dictionary is loaded" self.oExtendedDic = self._loadDictionary(sfDictionary) return bool(self.oExtendedDic) def setPersonalDictionary (self, sfDictionary): "returns True if the dictionary is loaded" self.oPersonalDic = self._loadDictionary(sfDictionary) return bool(self.oPersonalDic) # IBDAWG functions def isValidToken (self, sToken): "checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)" if self.oMainDic.isValidToken(sToken): return True | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | # Spellchecker # Wrapper for the IBDAWG class. # Useful to check several dictionaries at once. # To avoid iterating over a pile of dictionaries, it is assumed that 3 are enough: # - the main dictionary, bundled with the package # - the extended dictionary, added by an organization # - the personal dictionary, created by the user for its own convenience import traceback from . import ibdawg from . import tokenizer dDefaultDictionaries = { "fr": "fr.bdic", "en": "en.bdic" } class SpellChecker (): 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, True) self.oExtendedDic = self._loadDictionary(sfExtendedDic) self.oPersonalDic = self._loadDictionary(sfPersonalDic) self.oTokenizer = None def _loadDictionary (self, sfDictionary, bNecessary=False): "returns an IBDAWG object" if not sfDictionary: return None try: return ibdawg.IBDAWG(sfDictionary) 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 loadTokenizer (self): self.oTokenizer = tokenizer.Tokenizer(self.sLangCode) def setMainDictionary (self, sfDictionary): "returns True if the dictionary is loaded" self.oMainDic = self._loadDictionary(sfDictionary) return bool(self.oMainDic) def setExtendedDictionary (self, sfDictionary): "returns True if the dictionary is loaded" self.oExtendedDic = self._loadDictionary(sfDictionary) return bool(self.oExtendedDic) def setPersonalDictionary (self, sfDictionary): "returns True if the dictionary is loaded" self.oPersonalDic = self._loadDictionary(sfDictionary) return bool(self.oPersonalDic) # parse text functions def parseParagraph (self, sText, bSpellSugg=False): if not self.oTokenizer: self.loadTokenizer() aSpellErrs = [] for dToken in self.oTokenizer.genTokens(sText): if dToken['sType'] == "WORD" and not self.isValidToken(dToken['sValue']): if bSpellSugg: dToken['aSuggestions'] = [] for lSugg in self.suggest(dToken['sValue']): dToken['aSuggestions'].extend(lSugg) aSpellErrs.append(dToken) return aSpellErrs def countWordsOccurrences (self, sText, bByLemma=False, bOnlyUnknownWords=False, dWord={}): if not self.oTokenizer: self.loadTokenizer() for dToken in self.oTokenizer.genTokens(sText): if dToken['sType'] == "WORD": if bOnlyUnknownWords: if not self.isValidToken(dToken['sValue']): dWord[dToken['sValue']] = dWord.get(dToken['sValue'], 0) + 1 else: if not bByLemma: 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)" if self.oMainDic.isValidToken(sToken): return True |
︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 105 106 107 108 109 | lResult = self.oMainDic.getMorph(sWord) if self.oExtendedDic: lResult.extend(self.oExtendedDic.getMorph(sWord)) if self.oPersonalDic: 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) if self.oExtendedDic: yield self.oExtendedDic.suggest(sWord, nSuggLimit) if self.oPersonalDic: yield self.oPersonalDic.suggest(sWord, nSuggLimit) | > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | lResult = self.oMainDic.getMorph(sWord) if self.oExtendedDic: lResult.extend(self.oExtendedDic.getMorph(sWord)) if self.oPersonalDic: lResult.extend(self.oPersonalDic.getMorph(sWord)) return lResult def getLemma (self, sWord): return set([ 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" yield self.oMainDic.suggest(sWord, nSuggLimit) if self.oExtendedDic: yield self.oExtendedDic.suggest(sWord, nSuggLimit) if self.oPersonalDic: yield self.oPersonalDic.suggest(sWord, nSuggLimit) |
︙ | ︙ |
Modified tests/fr/horla.res.txt from [036f6beeea] to [0417945727].
1 2 3 4 5 6 7 8 9 10 | Guy de Maupassant Le Horla (1887) °°°°° Le Horla, P. Ollendorff, 1895 [trente-cinquième édition] (pp. 3-68). °°°°° °°°°°°°°°° 8 mai. – Quelle journée admirable ! J’ai passé toute la matinée étendu sur ^^^^^^ | > | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Guy de Maupassant Le Horla (1887) °°°°° Le Horla, P. Ollendorff, 1895 [trente-cinquième édition] (pp. 3-68). °°°°° °°°°°°°°°° 8 mai. – Quelle journée admirable ! J’ai passé toute la matinée étendu sur ^^^^^^ * 64:70 # 6628s / gn_2m_la: Accord de genre erroné : « matinée » est féminin, « étendu » est masculin. > Suggestions : étendue l’herbe, devant ma maison, sous l’énorme platane qui la couvre, l’abrite et l’ombrage tout entière. J’aime ce pays, et j’aime y vivre parce que j’y ai mes racines, ces profondes et délicates racines, qui attachent un homme à la terre où sont nés et morts ses aïeux, qui l’attachent à ce qu’on pense et à ce qu’on mange, aux usages comme aux nourritures, aux locutions locales, aux intonations |
︙ | ︙ | |||
107 108 109 110 111 112 113 | tomberait pour s’y noyer, dans un gouffre d’eau stagnante. Je ne le sens pas venir, comme autrefois, ce sommeil perfide, caché près de moi, qui me guette, qui va me saisir par la tête, me fermer les yeux, m’anéantir. Je dors – longtemps – deux ou trois heures – puis un rêve – non – un cauchemar m’étreint. Je sens bien que je suis couché et que je dors,… je le sens et je le ^^ | > | < | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | tomberait pour s’y noyer, dans un gouffre d’eau stagnante. Je ne le sens pas venir, comme autrefois, ce sommeil perfide, caché près de moi, qui me guette, qui va me saisir par la tête, me fermer les yeux, m’anéantir. Je dors – longtemps – deux ou trois heures – puis un rêve – non – un cauchemar m’étreint. Je sens bien que je suis couché et que je dors,… je le sens et je le ^^ * 136:138 # 704p / virg_virgule_avant_points_suspension: Typographie : pas de virgule avant les points de suspension. > Suggestions : … sais… et je sens aussi que quelqu’un s’approche de moi, me regarde, me palpe, monte sur mon lit, s’agenouille sur ma poitrine, me prend le cou entre ses mains et serre… serre… de toute sa force pour m’étrangler. Moi, je me débats, lié par cette impuissance atroce, qui nous paralyse dans les |
︙ | ︙ | |||
475 476 477 478 479 480 481 | — Oui, moi, ou plutôt mon mari, qui me charge de les trouver. J’étais tellement stupéfait, que je balbutiais mes réponses. Je me demandais si vraiment elle ne s’était pas moquée de moi avec le docteur Parent, si ce n’était pas là une simple farce préparée d’avance et fort bien jouée. ^^^^^^^^^^^^^^^^^ | > | | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | — Oui, moi, ou plutôt mon mari, qui me charge de les trouver. J’étais tellement stupéfait, que je balbutiais mes réponses. Je me demandais si vraiment elle ne s’était pas moquée de moi avec le docteur Parent, si ce n’était pas là une simple farce préparée d’avance et fort bien jouée. ^^^^^^^^^^^^^^^^^ * 185:202 # 3020s / pleo_verbe_à_l_avance: Pléonasme. > Suggestions : préparée Mais, en la regardant avec attention, tous mes doutes se dissipèrent. Elle tremblait d’angoisse, tant cette démarche lui était douloureuse, et je compris qu’elle avait la gorge pleine de sanglots. |
︙ | ︙ | |||
584 585 586 587 588 589 590 | Puis il la réveilla. Je tirai de ma poche un portefeuille : — Voici, ma chère cousine, ce que vous m’avez demandé ce matin. Elle fut tellement surprise que je n’osai pas insister. J’essayai cependant de ranimer sa mémoire, mais elle nia avec force, crut que je me moquais d’elle, et faillit, à la fin, se fâcher. | | | > > > | 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | Puis il la réveilla. Je tirai de ma poche un portefeuille : — Voici, ma chère cousine, ce que vous m’avez demandé ce matin. Elle fut tellement surprise que je n’osai pas insister. J’essayai cependant de ranimer sa mémoire, mais elle nia avec force, crut que je me moquais d’elle, et faillit, à la fin, se fâcher. · · · · · · · · · · · · · · · · · · · · · · · · Voilà ! je viens de rentrer ; et je n’ai pu déjeuner, tant cette expérience m’a bouleversé. 19 juillet. – Beaucoup de personnes à qui j’ai raconté cette aventure se sont moquées de moi. Je ne sais plus que penser. Le sage dit : Peut-être ? 21 juillet. – J’ai été dîner à Bougival, puis j’ai passé la soirée au bal des ^^^^^^ °°°°°°°° * 16:22 # 9891s / ppas_avoir_été: Tournure familière. Utilisez « être allé » plutôt que « avoir été ». canotiers. Décidément, tout dépend des lieux et des milieux. Croire au surnaturel dans l’île de la Grenouillère, serait le comble de la folie… mais au sommet du mont Saint-Michel ?… mais dans les Indes ? Nous subissons effroyablement l’influence de ce qui nous entoure. Je rentrerai chez moi la semaine prochaine. 30 juillet. – Je suis revenu dans ma maison depuis hier. Tout va bien. |
︙ | ︙ | |||
810 811 812 813 814 815 816 | s’éteignit, et ma fenêtre se ferma comme si un malfaiteur surpris se fût élancé dans la nuit, en prenant à pleines mains les battants. Donc, il s’était sauvé ; il avait eu peur, peur de moi, lui ! Alors,… alors… demain… ou après,… ou un jour quelconque,… je pourrai donc le ^^ ^^ ^^ | > | > | > | > | | > | > > | | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 | s’éteignit, et ma fenêtre se ferma comme si un malfaiteur surpris se fût élancé dans la nuit, en prenant à pleines mains les battants. Donc, il s’était sauvé ; il avait eu peur, peur de moi, lui ! Alors,… alors… demain… ou après,… ou un jour quelconque,… je pourrai donc le ^^ ^^ ^^ * 5:7 # 704p / virg_virgule_avant_points_suspension: Typographie : pas de virgule avant les points de suspension. > Suggestions : … * 31:33 # 704p / virg_virgule_avant_points_suspension: Typographie : pas de virgule avant les points de suspension. > Suggestions : … * 55:57 # 704p / virg_virgule_avant_points_suspension: Typographie : pas de virgule avant les points de suspension. > Suggestions : … tenir sous mes poings, et l’écraser contre le sol ! Est-ce que les chiens, quelquefois, ne mordent point et n’étranglent pas leurs maîtres ? 18 août. – J’ai songé toute la journée. Oh ! oui, je vais lui obéir, suivre ses impulsions, accomplir toutes ses volontés, me faire humble, soumis, lâche. Il est le plus fort. Mais une heure viendra… 19 août. – Je sais… je sais… je sais tout ! Je viens de lire ceci dans la Revue du Monde scientifique : « Une nouvelle assez curieuse nous arrive de Rio de Janeiro. Une folie, une épidémie de folie, comparable aux démences contagieuses qui atteignirent les peuples d’Europe au moyen âge, sévit en ce moment dans la ^^^^^^^^^ * 277:286 # 8968s / maj_Moyen_Âge: Le « Moyen Âge ». > Suggestions : Moyen Âge province de San-Paulo. Les habitants éperdus quittent leurs maisons, désertent leurs villages, abandonnent leurs cultures, se disant poursuivis, possédés, gouvernés comme un bétail humain par des êtres invisibles bien que tangibles, des sortes de vampires qui se nourrissent de leur vie, pendant leur sommeil, et qui boivent en outre de l’eau et du lait sans paraître toucher à aucun autre aliment. « M. le professeur Don Pedro Henriquez, accompagné de plusieurs savants °°°°°°°°° médecins, est parti pour la province de San-Paulo, afin d’étudier sur place les origines et les manifestations de cette surprenante folie, et de proposer à l’Empereur les mesures qui lui paraîtront le plus propres à rappeler à la ^^ ^^^^^^^ * 270:272 # 5835s / gn_le_accord2: Accord de nombre erroné : « propres » est au pluriel. > Suggestions : les * 278:285 # 5835s / gn_le_accord2: Accord de nombre erroné : « propres » devrait être au singulier. > Suggestions : propre raison ces populations en délire. » Ah ! Ah ! je me rappelle, je me rappelle le beau trois-mâts brésilien qui passa sous mes fenêtres en remontant la Seine, le 8 mai dernier ! Je le trouvai si joli, si blanc, si gai ! L’Être était dessus, venant de là-bas, où sa race est |
︙ | ︙ | |||
935 936 937 938 939 940 941 | Mais direz-vous, le papillon ! une fleur qui vole ! J’en rêve un qui serait grand comme cent univers, avec des ailes dont je ne puis même exprimer la forme, la beauté, la couleur et le mouvement. Mais je le vois… il va d’étoile en étoile, les rafraîchissant et les embaumant au souffle harmonieux et léger de sa course !… Et les peuples de là-haut le regardent passer, extasiés et ravis !… | | | 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 | Mais direz-vous, le papillon ! une fleur qui vole ! J’en rêve un qui serait grand comme cent univers, avec des ailes dont je ne puis même exprimer la forme, la beauté, la couleur et le mouvement. Mais je le vois… il va d’étoile en étoile, les rafraîchissant et les embaumant au souffle harmonieux et léger de sa course !… Et les peuples de là-haut le regardent passer, extasiés et ravis !… · · · · · · · · · · · · · · · · · · · · · · · · Qu’ai-je donc ? C’est lui, lui, le Horla, qui me hante, qui me fait penser ces °°°°° folies ! Il est en moi, il devient mon âme ; je le tuerai ! 19 août. – Je le tuerai. Je l’ai vu ! je me suis assis hier soir, à ma table ; et je fis semblant d’écrire avec une grande attention. Je savais bien qu’il |
︙ | ︙ | |||
994 995 996 997 998 999 1000 | alors ?… 21 août. – J’ai fait venir un serrurier de Rouen, et lui ai commandé pour ma chambre des persiennes de fer, comme en ont, à Paris, certains hôtels particuliers, au rez-de-chaussée, par crainte des voleurs. Il me fera, en outre, une porte pareille. Je me suis donné pour un poltron, mais je m’en moque !… | | | 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 | alors ?… 21 août. – J’ai fait venir un serrurier de Rouen, et lui ai commandé pour ma chambre des persiennes de fer, comme en ont, à Paris, certains hôtels particuliers, au rez-de-chaussée, par crainte des voleurs. Il me fera, en outre, une porte pareille. Je me suis donné pour un poltron, mais je m’en moque !… · · · · · · · · · · · · · · · · · · · · · · · · 10 septembre. – Rouen, hôtel continental. C’est fait… c’est fait… mais est-il mort ? J’ai l’âme bouleversée de ce que j’ai vu. Hier donc, le serrurier ayant posé ma persienne et ma porte de fer, j’ai laissé tout ouvert jusqu’à minuit, bien qu’il commençât à faire froid. |
︙ | ︙ | |||
1024 1025 1026 1027 1028 1029 1030 | bien refermé, à double tour, la grande porte d’entrée. Et j’allai me cacher au fond de mon jardin, dans un massif de lauriers. Comme ce fut long ! comme ce fut long ! Tout était noir, muet, immobile ; pas un souffle d’air, pas une étoile, des montagnes de nuages qu’on ne voyait point, mais qui pesaient sur mon âme si lourds, si lourds. ^^^^^^ | > | < | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 | bien refermé, à double tour, la grande porte d’entrée. Et j’allai me cacher au fond de mon jardin, dans un massif de lauriers. Comme ce fut long ! comme ce fut long ! Tout était noir, muet, immobile ; pas un souffle d’air, pas une étoile, des montagnes de nuages qu’on ne voyait point, mais qui pesaient sur mon âme si lourds, si lourds. ^^^^^^ * 264:270 # 6602s / gn_2m_mon_ton_son: Accord de nombre erroné avec « âme » : « lourds » devrait être au singulier. > Suggestions : lourd Je regardais ma maison, et j’attendais. Comme ce fut long ! Je croyais déjà que le feu s’était éteint tout seul, ou qu’il l’avait éteint, Lui, quand une des fenêtres d’en bas creva sous la poussée de l’incendie, et une flamme, une grande flamme rouge et jaune, longue, molle, caressante, monta le long du mur |
︙ | ︙ |
Modified tests/fr/horla.txt from [4cbaa54e8b] to [44498933b9].
︙ | ︙ | |||
291 292 293 294 295 296 297 | — Votre mari n’a plus besoin de cinq mille francs ! Vous allez donc oublier que vous avez prié votre cousin de vous les prêter, et, s’il vous parle de cela, vous ne comprendrez pas. Puis il la réveilla. Je tirai de ma poche un portefeuille : — Voici, ma chère cousine, ce que vous m’avez demandé ce matin. Elle fut tellement surprise que je n’osai pas insister. J’essayai cependant de ranimer sa mémoire, mais elle nia avec force, crut que je me moquais d’elle, et faillit, à la fin, se fâcher. | | | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | — Votre mari n’a plus besoin de cinq mille francs ! Vous allez donc oublier que vous avez prié votre cousin de vous les prêter, et, s’il vous parle de cela, vous ne comprendrez pas. Puis il la réveilla. Je tirai de ma poche un portefeuille : — Voici, ma chère cousine, ce que vous m’avez demandé ce matin. Elle fut tellement surprise que je n’osai pas insister. J’essayai cependant de ranimer sa mémoire, mais elle nia avec force, crut que je me moquais d’elle, et faillit, à la fin, se fâcher. · · · · · · · · · · · · · · · · · · · · · · · · Voilà ! je viens de rentrer ; et je n’ai pu déjeuner, tant cette expérience m’a bouleversé. 19 juillet. – Beaucoup de personnes à qui j’ai raconté cette aventure se sont moquées de moi. Je ne sais plus que penser. Le sage dit : Peut-être ? 21 juillet. – J’ai été dîner à Bougival, puis j’ai passé la soirée au bal des canotiers. Décidément, tout dépend des lieux et des milieux. Croire au surnaturel dans l’île de la Grenouillère, serait le comble de la folie… mais au sommet du mont Saint-Michel ?… mais dans les Indes ? Nous subissons effroyablement l’influence de ce qui nous entoure. Je rentrerai chez moi la semaine prochaine. |
︙ | ︙ | |||
404 405 406 407 408 409 410 | Un être nouveau ! pourquoi pas ? Il devait venir assurément ! pourquoi serions-nous les derniers ! Nous ne le distinguons point, ainsi que tous les autres créés avant nous ? C’est que sa nature est plus parfaite, son corps plus fin et plus fini que le nôtre, que le nôtre si faible, si maladroitement conçu, encombré d’organes toujours fatigués, toujours forcés comme des ressorts trop complexes, que le nôtre, qui vit comme une plante et comme une bête, en se nourrissant péniblement d’air, d’herbe et de viande, machine animale en proie aux maladies, aux déformations, aux putréfactions, poussive, mal réglée, naïve et bizarre, ingénieusement mal faite, œuvre grossière et délicate, ébauche d’être qui pourrait devenir intelligent et superbe. Nous sommes quelques-uns, si peu sur ce monde, depuis l’huître jusqu’à l’homme. Pourquoi pas un de plus, une fois accomplie la période qui sépare les apparitions successives de toutes les espèces diverses ? Pourquoi pas un de plus ? Pourquoi pas aussi d’autres arbres aux fleurs immenses, éclatantes et parfumant des régions entières ? Pourquoi pas d’autres éléments que le feu, l’air, la terre et l’eau ? – Ils sont quatre, rien que quatre, ces pères nourriciers des êtres ! Quelle pitié ! Pourquoi ne sont-ils pas quarante, quatre cents, quatre mille ! Comme tout est pauvre, mesquin, misérable ! avarement donné, sèchement inventé, lourdement fait ! Ah ! l’éléphant, l’hippopotame, que de grâce ! Le chameau que d’élégance ! Mais direz-vous, le papillon ! une fleur qui vole ! J’en rêve un qui serait grand comme cent univers, avec des ailes dont je ne puis même exprimer la forme, la beauté, la couleur et le mouvement. Mais je le vois… il va d’étoile en étoile, les rafraîchissant et les embaumant au souffle harmonieux et léger de sa course !… Et les peuples de là-haut le regardent passer, extasiés et ravis !… | | | 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | Un être nouveau ! pourquoi pas ? Il devait venir assurément ! pourquoi serions-nous les derniers ! Nous ne le distinguons point, ainsi que tous les autres créés avant nous ? C’est que sa nature est plus parfaite, son corps plus fin et plus fini que le nôtre, que le nôtre si faible, si maladroitement conçu, encombré d’organes toujours fatigués, toujours forcés comme des ressorts trop complexes, que le nôtre, qui vit comme une plante et comme une bête, en se nourrissant péniblement d’air, d’herbe et de viande, machine animale en proie aux maladies, aux déformations, aux putréfactions, poussive, mal réglée, naïve et bizarre, ingénieusement mal faite, œuvre grossière et délicate, ébauche d’être qui pourrait devenir intelligent et superbe. Nous sommes quelques-uns, si peu sur ce monde, depuis l’huître jusqu’à l’homme. Pourquoi pas un de plus, une fois accomplie la période qui sépare les apparitions successives de toutes les espèces diverses ? Pourquoi pas un de plus ? Pourquoi pas aussi d’autres arbres aux fleurs immenses, éclatantes et parfumant des régions entières ? Pourquoi pas d’autres éléments que le feu, l’air, la terre et l’eau ? – Ils sont quatre, rien que quatre, ces pères nourriciers des êtres ! Quelle pitié ! Pourquoi ne sont-ils pas quarante, quatre cents, quatre mille ! Comme tout est pauvre, mesquin, misérable ! avarement donné, sèchement inventé, lourdement fait ! Ah ! l’éléphant, l’hippopotame, que de grâce ! Le chameau que d’élégance ! Mais direz-vous, le papillon ! une fleur qui vole ! J’en rêve un qui serait grand comme cent univers, avec des ailes dont je ne puis même exprimer la forme, la beauté, la couleur et le mouvement. Mais je le vois… il va d’étoile en étoile, les rafraîchissant et les embaumant au souffle harmonieux et léger de sa course !… Et les peuples de là-haut le regardent passer, extasiés et ravis !… · · · · · · · · · · · · · · · · · · · · · · · · Qu’ai-je donc ? C’est lui, lui, le Horla, qui me hante, qui me fait penser ces folies ! Il est en moi, il devient mon âme ; je le tuerai ! 19 août. – Je le tuerai. Je l’ai vu ! je me suis assis hier soir, à ma table ; et je fis semblant d’écrire avec une grande attention. Je savais bien qu’il viendrait rôder autour de moi, tout près, si près que je pourrais peut-être le toucher, le saisir ? Et alors !… alors, j’aurais la force des désespérés ; j’aurais mes mains, mes genoux, ma poitrine, mon front, mes dents pour l’étrangler, l’écraser, le mordre, le déchirer. Et je le guettais avec tous mes organes surexcités. |
︙ | ︙ | |||
429 430 431 432 433 434 435 | Je pus enfin me distinguer complètement, ainsi que je le fais chaque jour en me regardant. Je l’avais vu ! L’épouvante m’en est restée, qui me fait encore frissonner. 20 août. – Le tuer, comment ? puisque je ne peux l’atteindre ? Le poison ? mais il me verrait le mêler à l’eau ; et nos poisons, d’ailleurs, auraient-ils un effet sur son corps imperceptible ? Non… non… sans aucun doute… Alors ?… alors ?… 21 août. – J’ai fait venir un serrurier de Rouen, et lui ai commandé pour ma chambre des persiennes de fer, comme en ont, à Paris, certains hôtels particuliers, au rez-de-chaussée, par crainte des voleurs. Il me fera, en outre, une porte pareille. Je me suis donné pour un poltron, mais je m’en moque !… | | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | Je pus enfin me distinguer complètement, ainsi que je le fais chaque jour en me regardant. Je l’avais vu ! L’épouvante m’en est restée, qui me fait encore frissonner. 20 août. – Le tuer, comment ? puisque je ne peux l’atteindre ? Le poison ? mais il me verrait le mêler à l’eau ; et nos poisons, d’ailleurs, auraient-ils un effet sur son corps imperceptible ? Non… non… sans aucun doute… Alors ?… alors ?… 21 août. – J’ai fait venir un serrurier de Rouen, et lui ai commandé pour ma chambre des persiennes de fer, comme en ont, à Paris, certains hôtels particuliers, au rez-de-chaussée, par crainte des voleurs. Il me fera, en outre, une porte pareille. Je me suis donné pour un poltron, mais je m’en moque !… · · · · · · · · · · · · · · · · · · · · · · · · 10 septembre. – Rouen, hôtel continental. C’est fait… c’est fait… mais est-il mort ? J’ai l’âme bouleversée de ce que j’ai vu. Hier donc, le serrurier ayant posé ma persienne et ma porte de fer, j’ai laissé tout ouvert jusqu’à minuit, bien qu’il commençât à faire froid. Tout à coup, j’ai senti qu’il était là, et une joie, une joie folle m’a saisi. Je me suis levé lentement, et j’ai marché à droite, à gauche, longtemps pour qu’il ne devinât rien ; puis j’ai ôté mes bottines et mis mes savates avec négligence ; puis j’ai fermé ma persienne de fer, et revenant à pas tranquilles vers la porte, j’ai fermé la porte aussi à double tour. Retournant alors vers la fenêtre, je la fixai par un cadenas, dont je mis la clef dans ma poche. |
︙ | ︙ |
Modified tests/fr/text2.res.txt from [4c753a53e0] to [56d437d0e0].
|
| | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { "grammalecte": "0.6.2", "lang": "fr", "data" : [ {"lGrammarErrors": [{"sLineId": "885p", "sRuleId": "apostrophe_typographique", "sType": "apos", "aSuggestions": ["Lorsqu’"], "sMessage": "Apostrophe typographique.", "URL": "", "nEndY": 1, "nEndX": 7, "nStartY": 1, "nStartX": 0}, {"sLineId": "11404s", "sRuleId": "conj_il", "sType": "conj", "aSuggestions": ["arriva"], "sMessage": "Conjugaison erronée. Accord avec « il ». Le verbe devrait être à la 3ᵉ personne du singulier.", "URL": "", "nEndY": 1, "nEndX": 17, "nStartY": 1, "nStartX": 10}], "lSpellingErrors": []}, {"lGrammarErrors": [], "lSpellingErrors": []}, {"lGrammarErrors": [], "lSpellingErrors": [{"sType": "WORD", "sValue": "Horla", "nEndY": 5, "nEndX": 8, "nStartY": 5, "nStartX": 3}, {"sType": "WORD", "sValue": "Horla", "nEndY": 6, "nEndX": 8, "nStartY": 6, "nStartX": 3}, {"sType": "WORD", "sValue": "Ollendorff", "nEndY": 6, "nEndX": 23, "nStartY": 6, "nStartX": 13}]}, {"lGrammarErrors": [{"sLineId": "885p", "sRuleId": "apostrophe_typographique", "sType": "apos", "aSuggestions": ["J’"], "sMessage": "Apostrophe typographique.", "URL": "", "nEndY": 9, "nEndX": 39, "nStartY": 9, "nStartX": 37}, {"sLineId": "6265s", "sRuleId": "gn_quelle_accord", "sType": "gn", "aSuggestions": ["Quelles"], "sMessage": "Accord de nombre erroné : « journées » est au pluriel.", "URL": "", "nEndY": 9, "nEndX": 15, "nStartY": 9, "nStartX": 9}, {"sLineId": "6265s", "sRuleId": "gn_quelle_accord", "sType": "gn", "aSuggestions": ["journée"], "sMessage": "Accord de nombre erroné : « Quelle » est au singulier.", "URL": "", "nEndY": 9, "nEndX": 24, "nStartY": 9, "nStartX": 16}, {"sLineId": "6628s", "sRuleId": "gn_2m_la", "sType": "gn", "aSuggestions": ["étendue"], "sMessage": "Accord de genre erroné : « matinée » est féminin, « étendu » est masculin.", "URL": "", "nEndY": 9, "nEndX": 72, "nStartY": 9, "nStartX": 66}, {"sLineId": "10365s", "sRuleId": "ppas_pronom_avoir", "sType": "ppas", "aSuggestions": ["passé"], "sMessage": "Ce verbe devrait être un participe passé au masculin singulier.", "URL": "http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais", "nEndY": 9, "nEndX": 48, "nStartY": 9, "nStartX": 42}], "lSpellingErrors": []}, {"lGrammarErrors": [{"sLineId": "11348s", "sRuleId": "conj_j", "sType": "conj", "aSuggestions": ["aime"], "sMessage": "Conjugaison erronée. Accord avec « je ». Le verbe devrait être à la 1ʳᵉ personne du singulier.", "URL": "", "nEndY": 17, "nEndX": 7, "nStartY": 17, "nStartX": 2}], "lSpellingErrors": []}, {"lGrammarErrors": [], "lSpellingErrors": []}, {"lGrammarErrors": [], "lSpellingErrors": []}, {"lGrammarErrors": [{"sLineId": "6199s", "sRuleId": "gn_nombre_lettres_accord", "sType": "gn", "aSuggestions": ["heures"], "sMessage": "Accord de nombre erroné avec « onze » : « heure » devrait être au pluriel.", "URL": "", "nEndY": 30, "nEndX": 15, "nStartY": 30, "nStartX": 10}], "lSpellingErrors": []}, {"lGrammarErrors": [{"sLineId": "11353s", "sRuleId": "conj_je", "sType": "conj", "aSuggestions": ["saluais"], "sMessage": "Conjugaison erronée. Accord avec « Je ». Le verbe devrait être à la 1ʳᵉ personne du singulier.", "URL": "", "nEndY": 36, "nEndX": 22, "nStartY": 36, "nStartX": 15}], "lSpellingErrors": [{"sType": "WORD", "sValue": "goëlettes", "nEndY": 34, "nEndX": 20, "nStartY": 34, "nStartX": 11}]}, {"lGrammarErrors": [{"sLineId": "6108s", "sRuleId": "gn_det_pluriel_accord", "sType": "gn", "aSuggestions": ["jours"], "sMessage": "Accord de nombre erroné : « jour » devrait être au pluriel.", "URL": "", "nEndY": 39, "nEndX": 80, "nStartY": 39, "nStartX": 76}], "lSpellingErrors": []}, {"lGrammarErrors": [{"sLineId": "6053s", "sRuleId": "gn_notre_votre_chaque_accord", "sType": "gn", "aSuggestions": ["confiance"], "sMessage": "Accord de nombre erroné : « confiances » devrait être au singulier.", "URL": "", "nEndY": 43, "nEndX": 27, "nStartY": 43, "nStartX": 17}, {"sLineId": "11353s", "sRuleId": "conj_je", "sType": "conj", "aSuggestions": ["descends"], "sMessage": "Conjugaison erronée. Accord avec « Je ». Le verbe devrait être à la 1ʳᵉ personne du singulier.", "URL": "", "nEndY": 46, "nEndX": 32, "nStartY": 46, "nStartX": 25}, {"sLineId": "12117s", "sRuleId": "inte_ce", "sType": "inte", "aSuggestions": ["est"], "sMessage": "Forme interrogative : « Es » n’est pas un verbe à la 3ᵉ personne du singulier.", "URL": "http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132", "nEndY": 48, "nEndX": 22, "nStartY": 48, "nStartX": 20}], "lSpellingErrors": []}, {"lGrammarErrors": [{"sLineId": "10836s", "sRuleId": "imp_va", "sType": "imp", "aSuggestions": ["Va"], "sMessage": "S’il s’agit d’un impératif, pas de “s”.", "URL": "", "nEndY": 57, "nEndX": 3, "nStartY": 57, "nStartX": 0}, {"sLineId": "10836s", "sRuleId": "imp_va", "sType": "imp", "aSuggestions": ["Va"], "sMessage": "S’il s’agit d’un impératif, pas de “s”.", "URL": "", "nEndY": 58, "nEndX": 3, "nStartY": 58, "nStartX": 0}], "lSpellingErrors": []} ]} |