diff options
author | László Németh <nemeth@numbertext.org> | 2012-02-02 12:17:44 +0100 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2012-02-02 12:17:44 +0100 |
commit | 1a46fc1103856acae202f047528d1bbd837220e4 (patch) | |
tree | f78ec351f747ecfc76c685547f2bd97fe0a4be5b |
Initial release
51 files changed, 4201 insertions, 0 deletions
@@ -0,0 +1,11 @@ +GPL 2.0/LGPL 2.1/MPL 1.1 tri-license + +The contents of this software may be used under the terms of +the GNU General Public License Version 2 or later (the "GPL"), or +the GNU Lesser General Public License Version 2.1 or later (the "LGPL") +or the Mozilla Public License Version 1.1 or later (the "MPL"). + +Software distributed under these licenses is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the licences on +http://www.fsf.org and http://www.opensource.org for the specific language +governing rights and limitations under the licenses. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..8c9392f --- /dev/null +++ b/ChangeLog @@ -0,0 +1,160 @@ +2012-02-02 László Németh <nemeth@numbertext.org>: + - Lightproof editor (rule development extension for LibreOffice) + - use template and config system, based on + the work of Olivier Ronez, author of French + grammar checker Dicollecte. + - code cleanups + - move user code to different module to speed up + its load (submodules use Python pyc format) + +2011-12-16 László Németh <nemeth@numbertext.org>: + - add FullCommentURL support + - remove " [" from reversed space and punctuation + - remove traceback.print_exc (problems on Windows reported by Olivier Ronez) + - license: LGPL -> MPL/GPL/LGPL + - remove tabulators for LibreOffice Git + - options only in extension manager (temporarily) + - help separator in dlg: now "\n" instead of "/" + - long comments (\n), eg. # Did you mean:\nExplanation... + - expressions in comments, eg. # =expression({word}) + - \u00AD (soft hyphen is not word boundary) + - print traceback in LibreOffice + - LOCALE, TEXT in rules, see doc. + + * lightproof_py.py: fix hasLocale() for LibreOffice 3.5 + + - data/en_US.dat: improved English rules (a/an) rules + + * Complile.py: support "_" in pattern names. + - add ^ for sentence beginning + +2011-07-12 László Németh <nemeth@numbertext.org>: + * lightproof_handler_py.py: fix for LibreOffice + Problem with option settings reported by Péter Benedek on + openscope.org and others + + * Dialog.py: support for multiple options in a line. + syntax in dlg files: space and comma separated list, comma means new line: + item1 item2 ..., itemx itemz ..., itemA itemB ... + + * Dialog.py: tooltip support, syntax in dlg files: slash separation + item = option caption/tooltip + + * Dialog.py: fix localization of the extension name in the Options + + * lightproof_py.py: + - stem(): new function for stemming, see doc/syntax.txt. + Problems with the experimental version reported by Olivier Ronez. + - generate(): new function for morphological generation, see doc/syntax.txt + - extended functions: optional "all" parameter of functions morph() and affix(), + see doc/syntax.txt + + * Compile.py: fix for [code] (handling "\n" in strings) + +2010-02-19 László Németh <nemeth@numbertext.org>: + * Compile.py, make.py: add user code support + by [code] sections in the rule files, + see end of the doc/manual.txt + + * Lightproof_handler.py: fix Mac OS X PyUNO problem + (problem with helper classes in the same file) + +2009-12-16 László Németh <nemeth@numbertext.org>: + * make.py: vendor/language specific grammar checker generator + * *_{py,xcu,xml}.py: + - template files for code generation + * Makefile, Compile.py: + - modified for code generation + + * Dialog.py: + - Options dialog data generator (see doc/dialog.txt) + + * data/{en_US,hu_HU}.dat: + - optional rules: word duplication etc. + + * Lightproof.py: + - fix getAlternatives() handling (morphological analysis of unknown + words resulted in unchecked sentences) + + - extended, simplified syntax: + + rule sections ([Word], [word], [Char], [char]): see NEWS + + - expressions in suggestions: specified by a starting equal sign + (see doc/syntax.txt): + + - new library functions (see doc/syntax.txt): + option(): return the value of the option (see doc/dialog.txt) + spell(): spelling (Boolean function) + suggest(): suggestion + affix(): morph variant (only with affix fields) + calc(): Calc function access + +2009-10-23 László Németh <nemeth@numbertext.org>: + * data/hu_HU.dat: + - fix rule article "a". The problem with "13-a óta" reported by kiazaki + at openscope.hu. + +2009-10-20 László Németh <nemeth@numbertext.org>: + * data/hu_HU.dat: + - add the rule "mellet" for irregular nouns, too (eg. "a ház mellet") + + - add -ban/-ben affixes to the rule "helyett kap", reported by + József Barna. + + - fix digit separator rules for decimal digits, reported by joghurt at + OOo Wiki. + + * Lightproof.py: + - add words with dots to word(). The problem with version numbers + (eg. in OpenOffice.org 3.1) reported by Kami. + +2009-10-19 László Németh <nemeth@numbertext.org>: + * Lightproof.py: + - Hunspell integration + + - processing conditional rules by eval() + + - helper functions: morph() and word() (see doc/syntax.txt) + + - add try-except for proofing rule compiling (bad regexes of the + conditional rules detected only in loading phase yet, see stdout + of OpenOffice.org) + + * Compile.py: + + - conditional rules (see doc/syntax.txt and hu_HU.dat) + + - multi-line rules + + * data/hu_HU.dat: + - new Hungarian rules + +2009-09-03 László Németh <nemeth@numbertext.org>: + * Lightproof.py: + + - fix: multiple space detection beetween sentences + - data/*.dat: modified rule for space detection beetween sentences + + * data/en*.dat: + + - fix: de *juro -> de jure, also extended by "de luxe" + + - using "typographic apostrophe" message instead of "apostrophe". + Ambiguous warning message reported by Dave Pitts (davidmpitts at gmail) + + * data/hu_HU.dat: + - add "döntetlenre" to the suggestions for "egyelőre" + + * doc/manual.txt: reported by Olivier Ronez <dico dot savant at free dot fr> + + - replace Convert.py with Compile.py + + - suggesting yourname.dat argument instead of parameter substitution + for manual compilation under Windows + +2009-09-01 Yakov Reztsov <yr at myooo dot ru> + * data/ru_RU.dat: Russian translation of template.dat + +2009-04-25 László Németh <nemeth@numbertext.org>: + * first release diff --git a/Dialog.py b/Dialog.py new file mode 100644 index 0000000..b652618 --- /dev/null +++ b/Dialog.py @@ -0,0 +1,220 @@ +# -*- encoding: UTF-8 -*- +import sys +import re +from string import split +import os +import codecs + +comment = re.compile(ur"[\n#]") +ids = re.compile(ur"\w+:\s*\*?\w+(,\s*\*?\w+)*") +langu = re.compile(ur"\[.+=.+\]\s*") +titl = re.compile(ur"\w+\s*=\s*") +helptexts = [] + +xdl_header = """<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE dlg:window PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "dialog.dtd"> +<dlg:window xmlns:dlg="http://openoffice.org/2000/dialog" xmlns:script="http://openoffice.org/2000/script" dlg:id="%s" dlg:left="101" dlg:top="52" dlg:width="196" dlg:height="72" dlg:closeable="true" dlg:moveable="true" dlg:withtitlebar="false"> + <dlg:bulletinboard> +""" +xdl_footer = """</dlg:bulletinboard> +</dlg:window> +""" +xdl_group = '<dlg:fixedline dlg:id="%s" dlg:tab-index="%d" dlg:left="5" dlg:top="%d" dlg:width="240" dlg:height="10" dlg:value="&%s"/>\n' +xdl_item = '<dlg:checkbox dlg:id="%s" dlg:tab-index="%d" dlg:left="%d" dlg:top="%d" dlg:width="%d" dlg:height="10" dlg:value="&%s" dlg:checked="%s" %s/>\n' + +xcs_header = """<?xml version="1.0" encoding="UTF-8"?> +<oor:component-schema xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +oor:name="%s" oor:package="org.openoffice" xml:lang="en-US"> +<info> +<desc>Contains the options data used for the test extensions.</desc> +</info> +<templates> +""" +xcs_leaf_header = ur""" + <group oor:name="%s"> + <info> + <desc>The data for one leaf.</desc> + </info> +""" +xcs_leaf = ur"""<prop oor:name="%s" oor:type="xs:string"> + <value></value> +</prop> +""" +xcs_leaf_footer = ur""" </group> +""" +xcs_component_header = """ </templates> + <component> + <group oor:name="Leaves"> +""" +xcs_component = """ + <node-ref oor:name="%s" oor:node-type="%s"/> +""" +xcs_footer = """ </group> + </component> + +</oor:component-schema> +""" +xcu_header = u"""<?xml version='1.0' encoding='UTF-8'?> +<!DOCTYPE oor:component-data SYSTEM "../../../../component-update.dtd"> +<oor:component-data oor:name="OptionsDialog" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <node oor:name="Nodes"> + <node oor:name="org.openoffice.lightproof" oor:op="fuse"> + <prop oor:name="Label"> + <value xml:lang="en">Dictionaries</value> + <value xml:lang="hu">Szótárak</value> + </prop> + <node oor:name="Leaves"> +""" +xcu_node_header = """ + <node oor:name="org.openoffice.lightproof.%s" oor:op="fuse"> + + <prop oor:name="Id"> + <value>org.openoffice.comp.pyuno.lightproof.oxt.%s</value> + </prop> + + <prop oor:name="Label"> +""" +xcu_node = """ + <value xml:lang="%s">%s</value> +""" +xcu_node_footer = """ + </prop> + + <prop oor:name="OptionsPage"> + <value>%%origin%%/%s.xdl</value> + </prop> + + <prop oor:name="EventHandlerService"> + <value>org.openoffice.comp.pyuno.LightproofOptionsEventHandler.%s</value> + </prop> + + </node> +""" +xcu_footer = """ + </node> + </node> + </node> +</oor:component-data> +""" + +indexes = {} +indexes_def = {} +modules = {} + +def create_xdl(pkg, lines, target, lang): + global indexes + global indexes_def + global modules + indexes[lang] = [] + indexes_def[lang] = [] + modules[lang] = [] + f2 = "" + state = 0 + f2n = "dialog/" + lang + ".xdl" + f2 = f2 + xdl_header%lang + + k = 0 + k2 = 0 + lin = 0 + ok = False + for i in lines: + i = i.strip() + if "=" in i and r"\n" in i: + helptexts.append(i.split("=")[0]) + for i in lines: + i = unicode(i.strip().replace(r"\n", "@#@") + "\n", "UTF-8") + lin = lin + 1 + if not comment.match(i): + if state == 0: + ok = True + if ids.match(i.strip()): + j = split(i.strip(),":") + f2 = f2 + xdl_group%(j[0].strip(), k, k2 * 10 + 5, j[0].strip()) + for l in split(j[1],","): + k = k + 1 + k2 = k2 + 1 + l = l.strip() + la = split(l, " ") + l3 = 0 + itemlen = int(240 / len(la)) + for l2 in la: + if l2 != "-": + checked = "false" + if l2[0] == '*': + checked = "true" + l2 = l2[1:] + indexes_def[lang] += [l2] + indexes[lang] += [l2] + helptext = "" + if l2 in helptexts: + helptext = "dlg:help-text=\"&hlp_" + l2 + "\"" + f2 = f2 + xdl_item%(l2, k, 10 + itemlen * l3, k2 * 10 + 5, itemlen, l2, checked, helptext) + l3 = l3 + 1 + k = k + 1 + k2 = k2 + 1 + k = k + 1 + else: + ok = False + if langu.match(i.strip()): + if "xdl" in f2n: + f2 = f2 + xdl_footer + target.writestr(f2n, f2) + f2 = "" + i = i.strip() + langname = i[1:i.find("=")] + modules[lang] += [langname[:langname.find("_")], i[i.find("=")+1:-1]] + f2n = "dialog/" + lang + "_" + langname + ".properties" + state = state + 1 + if state == 1: + target.writestr("dialog/" + lang + "_" + langname + ".default", "") + elif titl.match(i.strip()): + hlp = i.encode("unicode-escape").replace(r"\n","\n").replace(r"\t","\t").replace(r"\x","\\u00").split("@#@", 1) + if len(hlp) > 1: + helptexts.append(hlp[0].split("=")[0]) + f2 = f2 + "hlp_" + hlp[0].split("=")[0] + "=" + hlp[1] + hlp[0] = hlp[0] + "\n" + f2 = f2 + hlp[0] + elif not ok: + print "Syntax error in line %d: %s" %(lin, i) + if "xdl" in f2n: + f2 = f2 + xdl_footer + target.writestr(f2n, f2) + +#def c(pkg, author, language, inpdir, target, prgtarget, dlg): + +def c(pkg, dlgdata, target, lang): + + # create xdl dialog data files + create_xdl(pkg, dlgdata, target, lang) + + s = xcs_header% ("Lightproof_" + pkg) + for i in indexes: + s = s + xcs_leaf_header%i + \ + xcs_leaf*len(indexes[i])%tuple(indexes[i]) + \ + xcs_leaf_footer + s = s + xcs_component_header + for i in indexes: + s = s + xcs_component%(i,i) + + target.writestr("dialog/OptionsDialog.xcs", s + xcs_footer) + + s = "" + for i in indexes: + s = s + xcu_node_header%(pkg, pkg) + \ + xcu_node*(len(modules[i])/2)%tuple(modules[i]) + \ + xcu_node_footer%(i, pkg) + target.writestr("dialog/OptionsDialog.xcu", (xcu_header + s + xcu_footer).encode("utf-8")) + + # python resource file + + s = """lopts = {} +lopts_default = {} +""" + for i in indexes: + s = s + "lopts['" + i + "'] = " + str(indexes[i]) + "\n" + for i in indexes: + s = s + "lopts_default['" + i + "'] = " + str(indexes_def[i]) + "\n" + target.writestr("pythonpath/lightproof_opts_%s.py"%pkg, s) + + + diff --git a/Lightproof.py b/Lightproof.py new file mode 100644 index 0000000..a0c703f --- /dev/null +++ b/Lightproof.py @@ -0,0 +1,153 @@ +# -*- encoding: UTF-8 -*- +# Lightproof grammar checker for LibreOffice and OpenOffice.org +# 2009-2012 (c) László Németh (nemeth at numbertext org), license: MPL 1.1 / GPLv3+ / LGPLv3+ + +import uno, unohelper, sys, traceback +from lightproof_impl_${implname} import locales +from lightproof_impl_${implname} import pkg +import lightproof_impl_${implname} +import lightproof_handler_${implname} + +from com.sun.star.linguistic2 import XProofreader, XSupportedLocales +from com.sun.star.linguistic2 import ProofreadingResult, SingleProofreadingError +from com.sun.star.lang import XServiceInfo, XServiceName, XServiceDisplayName +from com.sun.star.lang import Locale +# reload in obj.reload in Python 3 +try: + from obj import reload +except: + pass + +class Lightproof( unohelper.Base, XProofreader, XServiceInfo, XServiceName, XServiceDisplayName, XSupportedLocales): + + def __init__( self, ctx, *args ): + self.ctx = ctx + self.ServiceName = "com.sun.star.linguistic2.Proofreader" + self.ImplementationName = "org.openoffice.comp.pyuno.Lightproof." + pkg + self.SupportedServiceNames = (self.ServiceName, ) + self.locales = [] + for i in locales: + l = locales[i] + self.locales += [Locale(l[0], l[1], l[2])] + self.locales = tuple(self.locales) + currentContext = uno.getComponentContext() + lightproof_impl_${implname}.SMGR = currentContext.ServiceManager + lightproof_impl_${implname}.spellchecker = \ + lightproof_impl_${implname}.SMGR.createInstanceWithContext("com.sun.star.linguistic2.SpellChecker", currentContext) + lightproof_handler_${implname}.load(currentContext) + + # XServiceName method implementations + def getServiceName(self): + return self.ImplementationName + + # XServiceInfo method implementations + def getImplementationName (self): + return self.ImplementationName + + def supportsService(self, ServiceName): + return (ServiceName in self.SupportedServiceNames) + + def getSupportedServiceNames (self): + return self.SupportedServiceNames + + # XSupportedLocales + def hasLocale(self, aLocale): + if aLocale in self.locales: + return True + for i in self.locales: + if (i.Country == aLocale.Country or i.Country == "") and aLocale.Language == i.Language: + return True + return False + + def getLocales(self): + return self.locales + + # XProofreader + def isSpellChecker(self): + return False + + def doProofreading(self, nDocId, rText, rLocale, nStartOfSentencePos, \ + nSuggestedSentenceEndPos, rProperties): + aRes = uno.createUnoStruct( "com.sun.star.linguistic2.ProofreadingResult" ) + aRes.aDocumentIdentifier = nDocId + aRes.aText = rText + aRes.aLocale = rLocale + aRes.nStartOfSentencePosition = nStartOfSentencePos + aRes.nStartOfNextSentencePosition = nSuggestedSentenceEndPos + aRes.aProperties = () + aRes.xProofreader = self + aRes.aErrors = () + if len(rProperties) > 0 and rProperties[0].Name == "Update": + try: + import lightproof_compile_${implname} + try: + code = lightproof_compile_${implname}.c(rProperties[0].Value, rLocale.Language, True) + except Exception as e: + aRes.aText, aRes.nStartOfSentencePosition = e + return aRes + path = lightproof_impl_${implname}.get_path() + f = open(path.replace("_impl", ""), "w") + f.write("dic = %s" % code["rules"]) + f.close() + if pkg in lightproof_impl_${implname}.langrule: + mo = lightproof_impl_${implname}.langrule[pkg] + reload(mo) + lightproof_impl_${implname}.compile_rules(mo.dic) + lightproof_impl_${implname}.langrule[pkg] = mo + if "code" in code: + f = open(path, "r") + ft = f.read() + f.close() + f = open(path, "w") + f.write(ft[:ft.find("# [code]") + 8] + "\n" + code["code"]) + f.close() + try: + reload(lightproof_impl_${implname}) + except Exception as e: + aRes.aText = e.args[0] + if e.args[1][3] == "": # "expected an indented block" (end of file) + aRes.nStartOfSentencePosition = len(rText.split("\n")) + else: + aRes.nStartOfSentencePosition = rText.split("\n").index(e.args[1][3][:-1]) + 1 + return aRes + aRes.aText = "" + return aRes + except: + print traceback.format_exc() + + l = rText[nSuggestedSentenceEndPos:nSuggestedSentenceEndPos+1] + while l == " ": + aRes.nStartOfNextSentencePosition = aRes.nStartOfNextSentencePosition + 1 + l = rText[aRes.nStartOfNextSentencePosition:aRes.nStartOfNextSentencePosition+1] + if aRes.nStartOfNextSentencePosition == nSuggestedSentenceEndPos and l!="": + aRes.nStartOfNextSentencePosition = nSuggestedSentenceEndPos + 1 + aRes.nBehindEndOfSentencePosition = aRes.nStartOfNextSentencePosition + + try: + aRes.aErrors = lightproof_impl_${implname}.proofread( nDocId, rText, rLocale, \ + nStartOfSentencePos, aRes.nBehindEndOfSentencePosition, rProperties) + except Exception as e: + if len(rProperties) > 0 and rProperties[0].Name == "Debug" and len(e.args) == 2: + aRes.aText, aRes.nStartOfSentencePosition = e + else: + print traceback.format_exc() + return aRes + + def ignoreRule(self, rid, aLocale): + lightproof_impl_${implname}.ignore[rid] = 1 + + def resetIgnoreRules(self): + lightproof_impl_${implname}.ignore = {} + + # XServiceDisplayName + def getServiceDisplayName(self, aLocale): + return lightproof_impl_${implname}.name + +g_ImplementationHelper = unohelper.ImplementationHelper() +g_ImplementationHelper.addImplementation( Lightproof, \ + "org.openoffice.comp.pyuno.Lightproof." + pkg, + ("com.sun.star.linguistic2.Proofreader",),) + +g_ImplementationHelper.addImplementation( lightproof_handler_${implname}.LightproofOptionsEventHandler, \ + "org.openoffice.comp.pyuno.LightproofOptionsEventHandler." + pkg, + ("com.sun.star.awt.XContainerWindowEventHandler",),) diff --git a/Linguistic.xcu b/Linguistic.xcu new file mode 100644 index 0000000..00ae15e --- /dev/null +++ b/Linguistic.xcu @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<oor:component-data oor:name="Linguistic" + oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <node oor:name="ServiceManager"> + <node oor:name="GrammarCheckers"> + <node oor:name="org.openoffice.comp.pyuno.Lightproof.${implname}" oor:op="fuse"> + <prop oor:name="Locales" oor:type="oor:string-list"> + <value>${locales}</value> + </prop> + </node> + </node> + </node> +</oor:component-data> diff --git a/META-INF/manifest.xml b/META-INF/manifest.xml new file mode 100644 index 0000000..a3a40d2 --- /dev/null +++ b/META-INF/manifest.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<manifest:manifest> + <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcs" + manifest:media-type="application/vnd.sun.star.configuration-schema" /> + <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcu" + manifest:media-type="application/vnd.sun.star.configuration-data" /> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python" + manifest:full-path="Lightproof.py"/> + <manifest:file-entry + manifest:media-type="application/vnd.sun.star.configuration-data" + manifest:full-path="Linguistic.xcu" /> +</manifest:manifest>
\ No newline at end of file @@ -0,0 +1,86 @@ +2012-02-02: Version 1.5 beta 2 +- rule editor (Writer extension) +- code cleanups, only Python dependency in config system + +2011-12-05: Version 1.5 beta (1.4.3) +- Improved English and Hungarian rules +- See ChangeLog + +2011-07-12: Version 1.4.1 +- fix option saving in LibreOffice + +- fix localization of the name of the grammar checker in OpenOffice.org/LibreOffice Options + +- multiple options in the same line in the Options dialog + +- new functions: stem(), generate() + +- improved Hungarian rules + +2010-02-19 Version 1.4 +- user code support ([code] sections in the rule files) + +- fix Mac OS X PyUNO problem + +2009-12-16 Version 1.3 +- Lightproof is a grammar checker extension generator (see doc/manual.txt): + the result of the generation is a single Lightproof or vendor specific + grammar checker language package, eg. lightproof-en_US.oxt or + your-grammar-checker-en_US.oxt. + +- native OpenOffice.org Options support (see Options->Language Settings + after the installation of en_US or hu_HU oxt packages of the Lightproof + distribution). Documentation: doc/dialog.txt + +- new, simplified rule syntax: + - rule sections ([Word], [word], [Char], [char]): + - word rules: patterns with default word boundaries + - [Word]: ignore case + - [word]: case sensitive + + simplified syntax: + + [Word] (default) + + foo -> bar # bar is far better + + instead of the old + + (?i)\bfoo\b -> bar # bar is far better + + - character rules: old default + - [Char]: ignore case + - [case]: case sensitive + + - expressions in suggestions: specified by a starting equal sign + + foo\w+ -> =\0.upper() # suggest with uppercase letters + + - new library functions: + spell: spelling (Boolean function) + suggest: suggestion + affix: morph variant (only with affix fields) + calc: Calc function access (see NUMBERTEXT example in data/hu_HU.dat) + +2009-10-23 Version 1.2.2 + - a small improvement in Hungarian grammar checking + +2009-10-20 Version 1.2.1 + - small improvements in Hungarian grammar checking + +2009-10-19 Version 1.2 + - Hunspell integration and + + - extended syntax for grammar checking based on + morphological analysis (see data/hu_HU.dat) + + - multi-line rules + + - extended Hungarian rules + +2009-09-03 Version 1.1 + - fixed multiple space detection beetween sentences + + - Translated and extended Russian rule sets from Yakov Reztsov + + - small improvements (see ChangeLog) @@ -0,0 +1,68 @@ +Lightproof grammar checker framework for Libreoffice/OpenOffice.org + +source: git://anongit.freedesktop.org/libreoffice/lightproof + +or see cgit.freedesktop.org/libreoffice + +version 1.5 beta 2 (2012-02-02) + +2009–2012 (c) László Németh (nemeth at numbertext dot org), license: MPL 1.1 / GPLv3+ / LGPLv3+ + +This software was developed with support from FSF.hu Foundation, Hungary. +(For more information, see http://www.fsf.hu/index.php/About_us.) + +== Build OOo/LibO extension == + +python make.py [config_file] + +For example: + +python make.py src/en/en.cfg + +or with own Python of LibreOffice on Windows: + +[install_path]\program\python make.py src\en\en.cfg + +The result is an oxt (OpenOffice.org/LibreOffice) extension. + +== Compile development tool == + +python make.py src/editor/editor.cfg + +== Installation == + +1. Via Tools -> Extension manager in OOo/LibreOffice + +2. or with unopkg tool, for example + +[install_path\program\]unopkg add -f lightproof_en-0.4.2.oxt + +== Features == + +- Lightproof is a grammar checker extension generator (see doc/manual.txt): + the result of the generation is a single Lightproof or vendor specific + grammar checker language package, eg. lightproof-en.oxt or + your-grammar-checker-en_US.oxt. + +- language-neutral proofreading tool (see data/ for language data) +- OpenOffice.org grammar checker extension generator +- Lightproof editor (rule development tool / LibreOffice toolbar) +- high-level regex-based rule definition language +- optional Python conditions in the rules +- integration with Hunspell morphological analyzer +- written in Python using fast regex module of CPython +- lazy loading of language modules +- template (data/template.dat) for new languages + +== Rule compilation == + +For the default language modules (en_US, hu_HU, ru_RU): + +make + +See doc/manual.txt to add a new language module or develop a +new grammar checker extension for your language + +== Documentation == + +doc/manual.txt @@ -0,0 +1,7 @@ +Thanks to + +András Tímár +Olivier Ronez +Michael Meeks + +See ChangeLog for other contributors. @@ -0,0 +1 @@ +1.5b2 diff --git a/description.xml b/description.xml new file mode 100644 index 0000000..b6e548c --- /dev/null +++ b/description.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:d="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.comp.pyuno.lightproof.oxt.${implname}" /> + <display-name> + <name lang="en-US">${name}</name> + </display-name> + <version value="${version}" /> + <publisher> + <name lang="en" xlink:href="${link}">${provider}</name> + </publisher> + <icon> + <default xlink:href="img/logo.png" /> + </icon> + <dependencies> + <OpenOffice.org-minimal-version value="3.2" d:name="OpenOffice.org 3.2" /> + </dependencies> +</description> diff --git a/doc/dialog.txt b/doc/dialog.txt new file mode 100644 index 0000000..e67f4aa --- /dev/null +++ b/doc/dialog.txt @@ -0,0 +1,52 @@ +# 1. Copy this template to the data folder, under the name of your locale +# eg. en_US.dlg. +# +# 2. Define your group ids and option ids and the localized title +# texts (see later for the syntax). +# +# Syntax of the dialog data file: +# +# Options and title texts for the Settings and conditional rules +# +# The Lightproof dialogs contain only grouped checkboxes. +# +# Format of the dialog definition: +# +# GroupID: OptionID [OptionsInTheSameLines_or_hyphen_placeholder], OptionID ... +# Group2ID: OptionID, OptionID ... +# ... +# [Language_code=title of the window] +# GroupID=title of the group +# OptionID=title of the option [\n tooltip] +# Option2ID=title of the option [\n tooltip] +# +# The first language is the default language for the other locales +# (use en_US or the common language of your country) +# +# The OptionIDs are used in the rules, too. For example: +# +# foo <- option("style") -> bar # bar is far better +# +# this rule depends from the state of the "style" checkbox. + +# options + +spelling: comma, hyphen +proofreading: style, moregrammar + +# titles + +[en_US=Hungarian grammar checking] + +spelling=Spelling +comma=Comma usage +hyphen=Check compound words with hyphen +proofreading=Proofreading +style=Style checking +moregrammar=Use grammar rules with ambiguous word analysis + +[yourlocale=yourtitle] + +spelling=... +wordpart=... +... diff --git a/doc/manual.txt b/doc/manual.txt new file mode 100644 index 0000000..96cd096 --- /dev/null +++ b/doc/manual.txt @@ -0,0 +1,69 @@ += Making a new grammar checker for LibreOffice/OpenOffice.org = + +== Rule development == + +Use Lightproof editor (LibreOffice Writer toolbar extension) to create a rule +(Lightproof .dat) file. See doc/syntax.txt for more informations. + +After LibreOffice integration (see later) switch off the integrated grammar +checker component in the Tools » Options » Language Settings » Writing Aids » +Available language modules, eg. "Lightproof Grammar Checker (en)", and switch +on the component "Lightproof editor" and *restart* LibreOffice for rule +development. + +There is no visual editor for optional features, yet (dlg file), but you can +compile and test all optional rules in the editor with the Apply all rules icon. +Also copying your rule and dialog definition files to the src/editor folder, +you can compile an extended editor extension with the +following command: python make.py src/editor/editor.cfg + +Note: the default locales of the editor (supported languages of the edited rule +document) cover only the languages with Hunspell dictionaries. Choose such +languages for editing in Writer (eg. Esperanto), or add your language to the +"locales" section of the src/editor/editor.cfg and compile the editor extension. + +== Extension development == + +1. Copy src/en/en.cfg, dat and dlg files under the name src/your_locale/your_locale.cfg, dat and dlg. + +2. Set cfg, translate messages, dat and dlg files (see doc/dialog.txt). + +3. Compile and install your data (see README) + +== LibreOffice integration == + +Short description about the Lightproof integration with the dictionary +extensions (it is not an automatic process yet): + +1. Copy dialog/* and pythonpath/* directories and Lightproof.py, Linguistic.xcu +of your Lightproof extension to the dictionaries/your_language/ directory of +LibreOffice. (Note: pythonpath/lightproof_compiler* doesn't need for the +integration.) + +2. Extend COMPONENT_FILES variable of makefile.mk with these new files. + +3. Extend manifest.xml with the following elements: + + <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcs" + +manifest:media-type="application/vnd.sun.star.configuration-schema" /> + <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcu" + +manifest:media-type="application/vnd.sun.star.configuration-data" /> + <manifest:file-entry +manifest:media-type="application/vnd.sun.star.uno-component;type=Python" + manifest:full-path="Lightproof.py"/> + <manifest:file-entry + +manifest:media-type="application/vnd.sun.star.configuration-data" + manifest:full-path="Linguistic.xcu" /> + +4. Change extension ID of dialog/OptionsDialog.xcu to the ID of the dictionary +extension (see in description.xml): + +<prop oor:name="Id"> + <value>org.openoffice.en.hunspell.dictionaries</value> +</prop> + + + diff --git a/doc/syntax.txt b/doc/syntax.txt new file mode 100644 index 0000000..12da666 --- /dev/null +++ b/doc/syntax.txt @@ -0,0 +1,296 @@ += Encoding = + +UTF-8 + += Rule syntax = + +pattern -> replacement # message + +or (see Conditions) + +pattern <- condition -> replacement # message + +or + +pattern <- condition -> = replacement # = expression_for_message +pattern <- condition -> = expression_to_generate_replacement_string # message +pattern <- condition -> = expression_to_generate_replacement_string # = expression_for_message + + +Basically pattern and replacement will be the parameters of the +standard Python re.sub() regular expression function (see also +Python regex module documentation for regular expression syntax: +http://docs.python.org/library/re.html). + +Example 0. Report "foo" in the text and suggest "bar": + +foo -> bar # Use bar instead of foo. + +Example 1. Recognize and suggest missing hyphen: + +foo bar -> foo-bar # Missing hyphen. + += Rule Sections = + +Example 2. Recognize double or more spaces and suggests a single space: + +[char] + +" +" -> " " # Extra space. + +The line [char] changes the default word-level rules to character-level ones. +Use [Word] to change back to the (case-insensitive) word-level rules. +Also [word] is for the case-sensitive word-level rules, and [Char] for the +case-insensitive character-level rules. + +ASCII " characters protect spaces in the pattern and in the replacement text. +Plus sign means 1 or more repetitions of the previous space. + += Other examples = + +Example 3. Suggest a word with correct quotation marks: + +\"(\w+)\" -> “\1” # Correct quotation marks. + +(Here \" is an ASCII quotation mark, \w means an arbitrary letter, ++ means 1 or more repetitions of the previous object, +The parentheses define a regex group (the word). In the +replacement, \1 is a reference to the (first) group of the pattern.) + +Example 4. Suggest the missing space after the !, ? or . signs: + +\b([?!.])([a-zA-Z]+) -> \1 \2 # Missing space? + +\b is the zero-length word boundary regex notation, so +\b signs the end and the begin of the words. + +The [ and ] define a character pattern, the replacement will contain +the actual matching character (?, ! or .), a space and the word after +the punctuation character. +Note: ? and . characters have special meanings in regular expressions, +use [?] or [.] patterns to check "?" and "." signs in the text. + +== Multiple suggestions == + +Use \n (new line) in the replacement text to add multiple suggestions: + +foo -> Foo\nFOO\nBar\nBAR # Did you mean: + +(Foo, FOO, Bar and BAR suggestions for the input word "foo") + += Expressions in the suggestions = + +Suggestions (and warning messages) started by an equal sign are Python string expressions +extended with possible back references and named definitions: + +Example: + +foo\w+ -> = '"' + \0.upper() + '"' # With uppercase letters and quoation marks + +All words beginning with "foo" will be recognized, and the suggestion is +the uppercase form of the string with ASCII quoation marks: eg. foom -> "FOOM". + +== Longer explanations == + +Warning messages can contain optional URLs for longer explanations separated by "\n": + +(your|her|our|their)['’]s -> \1s # Possessive pronoun: \n http://en.wikipedia.org/wiki/Possessive_pronoun + +== Default variables == + +LOCALE + +It contains the current locale of the checked paragraph. Its fields: +For en-US LOCALE.Language = "en" and LOCALE.Country = "US", eg. + +colour <- LOCALE.Language == "US" -> color # Use American English spelling. + +TEXT + +Full text of the checked paragraph. + +== Name definitions == + +Lightproof supports name definitions to simplify the +description of the complex rules. + +Definition: + +name pattern # name definition + +Usage in the rules: + +"{name} " -> "{name}. " # Missing dot? + +{Name}s in the first part of the rules mean +subpatterns (groups). {Name}s in the second +part of the rules mean back references to the +matched texts of the subpatterns. + +Example: thousand markers (10000 -> 10,000 or 10 000) + +# definitions +d \d\d\d # name definition: 3 digits +d2 \d\d # 2 digits +D \d{1,3} # 1, 2 or 3 digits + +# rules +# ISO thousand marker: space, here: no-break space (U+00A0) +{d2}{d} -> {d2},{d}\n{d2} {d} # Use thousand marker (common or ISO). +{D}{d}{d} -> {D},{d},{d}\n{D} {d} {d} # Use thousand markers (common or ISO). + +Note: Lightproof uses named groups for name definitions and +their references, adding a hidden number to the group names +in the form of "_n". You can use these explicit names in the replacement: + +{d2}{d} -> {d2_1},{d_1}\n{d2_1} {d_1} # Use thousand marker (common or ISO). +{D}{d}{d} -> {D_1},{d_1},{d_2}\n{D_1} {d_1} {d_2} # Use thousand markers (common or ISO). + +Note: back references of name definitions are zeroed after new line +characters, see this and the following example: + +E ( |$) # name definition: space or end of sentence +"\b[.][.]{E}" -> .{E}\n…{E} # Period or ellipsis? + +See src/en/en.dat for more examples. + += Conditions = + +A Lightproof condition is a Python condition with some modifications: +the \0..\9 regex notations and the Lightproof {name} notations in the condition will be +replaced by the matched subpatterns. For example, the rule + +\w+ <- \0 == "foo" -> Foo # Foo is a capitalized word. + +is equivalent of the following rule: + +foo -> Foo # Foo is a capitalized word. + +== Standard functions == + +There are some default function for the rule conditions. + + +word(n) or word(-n): + +The function word(n) returns the Nth word (separated only by white spaces) +before or after the matching pattern, or None, if this word doesn't exist. + + +morph(word, regex pattern): +morph(word, regex pattern, all): + +The function morph returns a matching subpattern of the morphological analysis +of the input word or None, if the pattern won't match all items of the +analysis of the input word. For example, the rule + +\ban ([a-z]\w+) <- morph(\1, "(po:verb|is:plural)") -> and \1 # Missing letter? + +will find the word "an" followed by a not capitalized verb or a plural noun (the notation depends from the morphological data of +the Hunspell dictionary). + +The optional argument can modify the default "all" mode to "if exists", using +the False value: + +morph(word, regex pattern, False): + +stem(word): + +The function returns an arraw with the stems of the input word. + +Usage: + +(\w+) <- "foo" in stem(\1) -> bar # One of the stem of the word is "foo" + +(\w+) <- stem(\1) == ["foo"] -> bar # The word has got only one stem, "foo". + + + +affix(word, regex pattern): +affix(word, regex pattern, all): + +Variant of morph: it filters the affix fields from the result of the analysis +before matching the pattern. + +The optional argument can modify the default "all" mode to "if exists", using +the False value: + +affix(word, regex pattern, False): + + +calc(functionname, functionparameters): + +Access to the Calc functions. Functionparameters is a tuple with the parameter +of the Calc function: + +calc("CONCATENATE", ("string1", "string2")) + + +generate(word, example_word): + +Morphological generation by example, eg. the result of generate("mouse", +"rodents") is ["mice"] with the en_US English dictionary. (See also +Hunspell (4) manual page for morphological generation.) + +option(optionname): + +Return the Boolean value of the option (see doc/dialog.txt). + +== Multi-line rules == + +Rules can be break to multiple lines by leading tabulators: + +pattern <- condition + # only comment + -> replacement + # message (last comment) + +== User code support == + +Use [code] sections to add your own Python functions for the rules: + +Example (suggesting uppercase form for all words with underline character, +for example hello_world -> HELLO_WORLD) + +[code] + +def u(s): + return s.upper() + +[Word] + +# suggest uppercase form for all words with underline character + +\w+_\w+ -> =u(\0) # Use uppercase form + +(In fact, this is equivalent of the following rule: + +\w+_\w+ -> =\0.upper() # Use uppercase form) + +See English rules (src/en/en.dat) for more examples, eg. precompiled regular +expressions for sentence checking, sets to handle more irregular words etc. + += Typical problems = + +== Encoding == + +Python expressions (< Python 3.0) need explicit Unicode declaration for non-ASCII +characters: + +fó -> bár # example + +is equivalent of the following rule (see u'string' instead of 'string') + +fó -> = u'bár' # example + +== Pattern matching == + +Repeating pattern matching of a single rule continues after the previous matching, so +instead of general multiword patterns, like + +(\w+) (\w+) <- some_check(\1, \2) -> \1, \2 # foo + +use + +(\w+) <- some_check(\1, word(1)) -> \1, # foo + @@ -0,0 +1,45 @@ +# -*- encoding: UTF-8 -*- +import sys, os, zipfile, traceback, Dialog +import ConfigParser as cp # configparser in Python 3 +import pythonpath.lightproof_compile___implname__ +from string import Template + +def dist(fn, a): + a['locales'] = a["locales"].replace("_", "-") + a['loc'] = str(dict([[i, [i[0:2], i[3:5], ""]] for i in a["locales"].split(" ")])) + distname = a['implname'] + "-" + a['version'] + '.oxt' + z = zipfile.ZipFile(distname, mode='w', compression = zipfile.ZIP_DEFLATED) + f = open(fn + ".dat",'r') + code = pythonpath.lightproof_compile___implname__.c(unicode(f.read(), "UTF-8"), a['lang']) + a["code"] = code["code"] + a['data'] = code["rules"] + + for i in ["META-INF/manifest.xml", "description.xml", "Linguistic.xcu", "Lightproof.py", \ + "pythonpath/lightproof_handler___implname__.py", "pythonpath/lightproof_impl___implname__.py", \ + "pythonpath/lightproof___implname__.py" ]: + z.writestr(i.replace("__implname__", a["implname"]), Template(open(i, "r").read()).safe_substitute(a)) + + for i in a["extras"].split(","): + z.writestr(i.strip().replace("../", "").replace("__implname__", a["implname"]), \ + open(fn[:fn.rfind("/")+1] + i.strip()).read()) + + try: + d = open(fn + ".dlg", "r").readlines() + Dialog.c(a["implname"], d, z, a["lang"]) + except: + z.writestr("pythonpath/lightproof_opts_%s.py"%a["implname"], "") + +if len(sys.argv) == 1: + print """Synopsis: python make.py config_file +eg. python make.py src/en/en.cfg""" + sys.exit(0) + +fArgs = cp.SafeConfigParser() +for i in sys.argv[1:]: + try: + fArgs.read(i) + dist(i[:-4], fArgs._sections['args']) + except: + print traceback.format_exc() + print "missing config file or options: ", i + sys.exit(0) diff --git a/pythonpath/__init__.py b/pythonpath/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pythonpath/__init__.py diff --git a/pythonpath/lightproof___implname__.py b/pythonpath/lightproof___implname__.py new file mode 100644 index 0000000..c1fe0ce --- /dev/null +++ b/pythonpath/lightproof___implname__.py @@ -0,0 +1,3 @@ +# -*- encoding: UTF-8 -*- +dic = ${data} + diff --git a/pythonpath/lightproof_compile___implname__.py b/pythonpath/lightproof_compile___implname__.py new file mode 100644 index 0000000..7c37bf4 --- /dev/null +++ b/pythonpath/lightproof_compile___implname__.py @@ -0,0 +1,276 @@ +import sys, re, traceback +from string import split + +repl = {} +tests = [] +comp = [] +modes = ["[Word]", "[word]", "[Char]", "[char]", "[code]"] +mode = "[Word]" +code = u"" +language = "" +oldlinenums = {} + +def prepare_for_eval(s): + s = re.sub("(affix|spell|morph|stem|option|suggest|generate)\(", r'\1(LOCALE,', s) + s = re.sub(r"word\(\s*(\d)", r'word(s[m.end():],\1', s) # word(n) + s = re.sub(r"word\(\s*-(\d)", r'wordmin(s[:m.start()],\1', s) # word(-n) + s = re.sub(r"[\\](\d)", r'm.group(\1)', s) + s = re.sub("[{]([^}]+)}", r'm.group("\1_1")', s) + return s + + +def mysplit(s, line, oldline, debug): + global repl + global tests + global comp + global modes + global mode + orig = s + if s[0:1] == '[': + if s.strip() in modes: + mode = s.strip() + return None + elif re.match(r"\[\w+\]$", s.strip()): + #sys.stderr.write("Unknown mode: " + s + "\n") + return oldline + dec = 0 + exprep = 0 # replacement is a Python expression (beginning with sign =) + condition = False + # description + c = re.search("\s#\s", s) + com = u"" + if c: + try: + c = c.start(c.lastindex - 1) + except: + c = c.start() + com = prepare_for_eval(s[c+2:].strip()) + s = s[:c] + m1 = re.search("<-", s) + m2 = re.search("->", s) + if m1 and m2: + condition = prepare_for_eval(s[m1.end(0): m2.start(0)].strip()) + s = s[0:m1.start(0)] + s[m2.start(0):] + if s[0:1] == '"': + # quoted + pos = s[1:].find('"') + while pos > 0 and s[pos] == '\\': + pos = s[pos:].find('"') + s1 = s[1:pos+1] + s2 = s[pos+2:].strip() + else: + m = re.compile("->").search(s) + if not m: + m = re.compile("[_a-zA-Z][_a-zA-Z0-9]*").match(s) + if not m: + # syntax error + return oldline + s1 = m.group(0) + s2 = s[m.end(0):].strip() + # replace previous definitions + for i in repl: + ire = re.compile("[{]" + i + "}") + if re.search(ire, s2): + s2 = ire.sub(repl[i], s2) + # make named group + s2 = "(?P<" + m.group(0) + ">" + s2 + ")" + dec = 1 + else: + s1 = s[0:m.start(0)].strip() + if re.match("TEST: ", s1): # deprecated + tests += [[s1[5:].strip(), s[m.end(0):].strip(), oldline]] + return None + s2 = s[m.start(0):].strip() + m = re.compile("->").match(s2) + if dec!= 1 and m: + s2 = s2[m.end(0):].strip() + elif dec!=1: + # syntax error + return oldline + if s2[0:1] == '=': + exprep = 1 + if s2[0:1] == '"' and s2[-1:]=='"': + s2 = s2[1:-1] + if dec==1: + repl[s1] = s2 + return None + else: + for i in repl: + s1 = re.sub("[{]" + i + "}", repl[i], s1) + # modes + if mode == "[Word]" or mode == "[word]": + if s1[0] == '^': + s1 = ur"((?<=[!?.] )|^)" + s1[1:] + ur"(?![-\w\u2013\u00AD])" + else: + s1 = ur"(?<![-\w\u2013.,\u00AD])" + s1 + ur"(?![-\w\u2013\u00AD])" + # modes with casing ([Word] or [Char]) + if mode == "[Word]" or mode == "[Char]": + s1 = "(?i)" + s1 + # add Unicode flag to the regex by (?u) + s1 = re.sub("[(][?][iI][)]", "(?iu)", s1) + if not re.match("[(][?][iI][uU][)]", s1): + s1 = "(?u)" + s1 + else: + # casing + lu = re.compile("(?u)\w") + s3 = u"" + state = 0 + for i in range(0, len(s1)): + c = s1[i] + if c == "[": + state = 1 + if state == 1 and c == "]": + state = 0 + if c == "<" and i > 3 and s1[i-3:i]=="(?P": + state = 2 + if state == 2 and c == ">": + state = 0 + if c == "?" and i > 0 and s1[i-1:i]=="(": + state = 5 + if state == 5 and c == ")": + state = 0 + if lu.match(c) and c.islower() and state == 0: + if c=="i" and (language == "tr" or language == "az"): + s3 += u"[\u0130" + c + "]" + else: + s3 += "[" + c.upper() + c + "]" + elif lu.match(c) and c.islower() and state == 1 and s1[i+1:i+2] != "-": + if s1[i-1:i] == "-" and s1[i-2:i-1].islower(): # [a-z] -> [a-zA-Z] + s3 += c + s1[i-2:i-1].upper() + "-" + c.upper() + elif c=="i" and (language == "tr" or language == "az"): + s3 += u"\u0130" + c + else: + s3 += c.upper() + c + else: + s3 += c + if c == "\\": + state = 4 + elif state == 4: + state = 0 + s1 = s3 + s1 = renum("[?]P<([^<_]*)>", s1, "?P<") + if exprep == 0: + s2 = re.sub("[{]([_a-zA-Z][_a-zA-Z0-9]*)}", r"\\g<\1>", s2) + s2 = renum(r"\\g<([^<_]*)>", s2, r"\\g<") + else: + s2 = prepare_for_eval(s2) + # check + if re.compile("[(][?]iu[)]").match(s1): + cap = True + sc = re.sub("[(][?]iu[)]", "(?u)", s1) + else: + cap = False + sc = s1 + try: + compr = re.compile(sc) + if not condition: + comp += [[compr, s2, com, cap, line]] + except Exception as e: + raise Exception(str(e), oldline) + if debug: + return [s1, s2, com, condition, oldline] + return [s1, s2, com, condition] + +# group renum (<groupname> -> <groupname_1> etc.) +def renum(regex, s1, beg): + j={} + mr = re.compile(regex) + m = mr.search(s1) + nl = s1.find("\\n") + while m: + # restart numbering in new lines + if nl > -1 and m.start(0) > (nl + 1): + j={} + nl = s1[m.start(0):].find("\\n") + if nl > -1: + nl = m.start(0) + nl + n = m.group(1) + if n in j: + j[n] += 1 + else: + j[n] = 1 + s1 = re.sub(mr, beg + n + "_" + str(j[n]) + ">", s1, 1) + m = mr.search(s1) + return s1 + +def cap(a, iscap): + global language + if iscap: + for i in range(0, len(a)): + if a[i][0:1] == "i": + if language == "tr" or language == "az": + a[i] = u"\u0130" + a[i][1:] + elif a[i][1:2] == "j" and language == "nl": + a[i] = "IJ" + a[i][2:] + else: + a[i] = "I" + a[i][1:] + else: + a[i] = a[i].capitalize() + return a + +def c(rules, lang, debug = False): + global language + global code + global oldlinenums + language = lang + r = re.compile("[\n#]") + code = "" + dic = [] + oldlinenums = {} + + lines = rules.split("\n") + lines2 = [] + result = {} + + + cm = 0 + lnums = 1 + for i in lines: + if i.strip() in modes: + if i.strip() == "[code]": + cm = 1 + continue + else: + cm = 0 + if cm == 1: + code = code + i + "\n" + elif len(i.strip()) > 0: + lines2 = lines2 + [i] + oldlinenums[i] = lnums + lnums = lnums + 1 + + lines = lines2 + + # concatenate multiline commands + # last tabulator + comment is the message + l = u"" + comment = 0 + for i in range(len(lines)-1, -1, -1): + if re.match("\t", lines[i]): + if not (comment and re.match("\t+#", lines[i])): + l = lines[i].strip() + " " + l + if re.search("#", lines[i]): + comment = 1 + del lines[i] + elif l != "": + lnums = oldlinenums[lines[i]] + lines[i] = lines[i].strip() + " " + l + oldlinenums[lines[i]] = lnums + l = "" + comment = 0 + + # processing + for i in range(0, len(lines)): + if not r.match(lines[i]): + item = mysplit(lines[i].strip(), i + 1, oldlinenums[lines[i]], debug) + if item != None: + if type(item) == type(1): + raise Exception("Syntax error in line ", item) + dic = dic + [item] + + result["rules"] = dic + code = re.sub(r"(?<![\\])\\n", "\n", code.encode("unicode-escape")) + + result["code"] = re.sub(r"(?<![\\])\\t", "\t", code).replace(r"\\n", r"\n").replace(r"\\t", r"\t") + + return result diff --git a/pythonpath/lightproof_handler___implname__.py b/pythonpath/lightproof_handler___implname__.py new file mode 100644 index 0000000..3e5a284 --- /dev/null +++ b/pythonpath/lightproof_handler___implname__.py @@ -0,0 +1,119 @@ +import uno +import unohelper +import lightproof_opts_${implname} +from lightproof_impl_${implname} import pkg + +from com.sun.star.lang import XServiceInfo +from com.sun.star.awt import XContainerWindowEventHandler + +# options +options = {} + +def load(context): + try: + l = LightproofOptionsEventHandler(context) + for i in lightproof_opts_${implname}.lopts: + l.load(i) + except: + pass + +def get_option(page, option): + try: + return options[page + "," + option] + except: + try: + return options[page[:2] + "," + option] + except: + return 0 + +def set_option(page, option, value): + options[page + "," + option] = int(value) + +class LightproofOptionsEventHandler( unohelper.Base, XServiceInfo, XContainerWindowEventHandler ): + def __init__( self, ctx ): + p = uno.createUnoStruct( "com.sun.star.beans.PropertyValue" ) + p.Name = "nodepath" + p.Value = "/org.openoffice.Lightproof_%s/Leaves"%pkg + self.xConfig = ctx.ServiceManager.createInstance( 'com.sun.star.configuration.ConfigurationProvider' ) + self.node = self.xConfig.createInstanceWithArguments( 'com.sun.star.configuration.ConfigurationUpdateAccess', (p, ) ) + self.service = "org.openoffice.comp.pyuno.LightproofOptionsEventHandler." + pkg + self.ImplementationName = self.service + self.services = (self.service, ) + + # XContainerWindowEventHandler + def callHandlerMethod(self, aWindow, aEventObject, sMethod): + if sMethod == "external_event": + return self.handleExternalEvent(aWindow, aEventObject) + + def getSupportedMethodNames(self): + return ("external_event", ) + + def handleExternalEvent(self, aWindow, aEventObject): + sMethod = aEventObject + if sMethod == "ok": + self.saveData(aWindow) + elif sMethod == "back" or sMethod == "initialize": + self.loadData(aWindow) + return True + + def load(self, sWindowName): + child = self.getChild(sWindowName) + for i in lightproof_opts_${implname}.lopts[sWindowName]: + sValue = child.getPropertyValue(i) + if sValue == '': + if i in lightproof_opts_${implname}.lopts_default[sWindowName]: + sValue = 1 + else: + sValue = 0 + set_option(sWindowName, i, sValue) + + def loadData(self, aWindow): + sWindowName = self.getWindowName(aWindow) + if (sWindowName == None): + return + child = self.getChild(sWindowName) + for i in lightproof_opts_${implname}.lopts[sWindowName]: + sValue = child.getPropertyValue(i) + if sValue == '': + if i in lightproof_opts_${implname}.lopts_default[sWindowName]: + sValue = 1 + else: + sValue = 0 + xControl = aWindow.getControl(i) + xControl.State = sValue + set_option(sWindowName, i, sValue) + + def saveData(self, aWindow): + sWindowName = self.getWindowName(aWindow) + if (sWindowName == None): + return + child = self.getChild(sWindowName) + for i in lightproof_opts_${implname}.lopts[sWindowName]: + xControl = aWindow.getControl(i) + sValue = xControl.State + child.setPropertyValue(i, str(sValue)) + set_option(sWindowName, i, sValue) + self.commitChanges() + + def getWindowName(self, aWindow): + sName = aWindow.getModel().Name + if sName in lightproof_opts_${implname}.lopts: + return sName + return None + + # XServiceInfo method implementations + def getImplementationName (self): + return self.ImplementationName + + def supportsService(self, ServiceName): + return (ServiceName in self.services) + + def getSupportedServiceNames (self): + return self.services + + def getChild(self, name): + return self.node.getByName(name) + + def commitChanges(self): + self.node.commitChanges() + return True diff --git a/pythonpath/lightproof_impl___implname__.py b/pythonpath/lightproof_impl___implname__.py new file mode 100644 index 0000000..2344a77 --- /dev/null +++ b/pythonpath/lightproof_impl___implname__.py @@ -0,0 +1,229 @@ +# -*- encoding: UTF-8 -*- +import uno, re, sys, os, traceback +from string import join +from com.sun.star.text.TextMarkupType import PROOFREADING +from com.sun.star.beans import PropertyValue + +pkg = "${implname}" +lang = "${lang}" +locales = ${loc} +version = "${version}" +author = "${author}" +name = "${name}" + +import lightproof_handler_${implname} + +# loaded rules (check for Update mechanism of the editor) +try: + langrule +except NameError: + langrule = {} + +# ignored rules +ignore = {} + +# cache for morphogical analyses +analyses = {} +stems = {} +suggestions = {} + +# assign Calc functions +calcfunc = None + +# check settings +def option(lang, opt): + return lightproof_handler_${implname}.get_option(lang.Language + "_" + lang.Country, opt) + +# filtering affix fields (ds, is, ts etc.) +def onlymorph(st): + if st != None: + st = re.sub(r"^.*(st:|po:)", r"\\1", st) # keep last word part + st = re.sub(r"\\b(?=[dit][sp]:)","@", st) # and its affixes + st = re.sub(r"(?<!@)\\b\w\w:\w+","", st).replace('@','').strip() + return st + +# if the pattern matches all analyses of the input word, +# return the last matched substring +def _morph(rLoc, word, pattern, all, onlyaffix): + global analyses + if word == None: + return None + if word not in analyses: + x = spellchecker.spell(u"<?xml?><query type='analyze'><word>" + word + "</word></query>", rLoc, ()) + if not x: + return None + t = x.getAlternatives() + if not t: + t = [""] + analyses[word] = t[0] + a = analyses[word].split("</a>")[:-1] + result = None + p = re.compile(pattern) + for i in a: + if onlyaffix: + i = onlymorph(i) + result = p.search(i) + if result: + result = result.group(0) + if not all: + return result + elif all: + return None + return result + +def morph(rLoc, word, pattern, all=True): + return _morph(rLoc, word, pattern, all, False) + +def affix(rLoc, word, pattern, all=True): + return _morph(rLoc, word, pattern, all, True) + +def spell(rLoc, word): + if word == None: + return None + return spellchecker.isValid(word, rLoc, ()) + +# get the tuple of the stem of the word or an empty array +def stem(rLoc, word): + global stems + if word == None: + return [] + if not word in stems: + x = spellchecker.spell(u"<?xml?><query type='stem'><word>" + word + "</word></query>", rLoc, ()) + if not x: + return [] + t = x.getAlternatives() + if not t: + t = [] + stems[word] = list(t) + return stems[word] + +# get the tuple of the morphological generation of a word or an empty array +def generate(rLoc, word, example): + if word == None: + return [] + x = spellchecker.spell(u"<?xml?><query type='generate'><word>" + word + "</word><word>" + example + "</word></query>", rLoc, ()) + if not x: + return [] + t = x.getAlternatives() + if not t: + t = [] + return list(t) + +# get suggestions +def suggest(rLoc, word): + global suggestions + if word == None: + return word + if word not in suggestions: + x = spellchecker.spell("_" + word, rLoc, ()) + if not x: + return word + t = x.getAlternatives() + suggestions[word] = join(t, "\\n") + return suggestions[word] + +# get the nth word of the input string or None +def word(s, n): + a = re.match("(?u)( [-.\w%%]+){" + str(n-1) + "}( [-.\w%%]+)", s) + if not a: + return None + return a.group(2)[1:] + +# get the (-)nth word of the input string or None +def wordmin(s, n): + a = re.search("(?u)([-.\w%%]+ )([-.\w%%]+ ){" + str(n-1) + "}$", s) + if not a: + return None + return a.group(1)[:-1] + +def calc(funcname, par): + global calcfunc + global SMGR + if calcfunc == None: + calcfunc = SMGR.createInstance( "com.sun.star.sheet.FunctionAccess") + if calcfunc == None: + return None + return calcfunc.callFunction(funcname, par) + +def proofread( nDocId, TEXT, LOCALE, nStartOfSentencePos, nSuggestedSentenceEndPos, rProperties ): + global ignore + aErrs = [] + s = TEXT[nStartOfSentencePos:nSuggestedSentenceEndPos] + for i in get_rule(LOCALE).dic: + if i[0] and not str(i[0]) in ignore: + for m in i[0].finditer(s): + try: + if not i[3] or eval(i[3]): + aErr = uno.createUnoStruct( "com.sun.star.linguistic2.SingleProofreadingError" ) + aErr.nErrorStart = nStartOfSentencePos + m.start(0) # nStartOfSentencePos + aErr.nErrorLength = m.end(0) - m.start(0) + aErr.nErrorType = PROOFREADING + aErr.aRuleIdentifier = str(i[0]) + iscap = (i[-1] and m.group(0)[0:1].isupper()) + if i[1][0:1] == "=": + aErr.aSuggestions = tuple(cap(eval(i[1][1:]).split("\\n"), iscap, LOCALE)) + else: + aErr.aSuggestions = tuple(cap(m.expand(i[1]).split("\\n"), iscap, LOCALE)) + comment = i[2] + if comment[0:1] == "=": + comment = eval(comment[1:]) + aErr.aShortComment = comment.split("\\n")[0].strip() + aErr.aFullComment = comment.split("\\n")[-1].strip() + if "://" in aErr.aFullComment: + p = PropertyValue() + p.Name = "FullCommentURL" + p.Value = aErr.aFullComment + aErr.aFullComment = aErr.aShortComment + aErr.aProperties = (p,) + else: + aErr.aProperties = () + aErrs = aErrs + [aErr] + except Exception as e: + if len(i) == 6: + raise Exception(str(e), i[4]) + raise + + return tuple(aErrs) + +def cap(a, iscap, rLoc): + if iscap: + for i in range(0, len(a)): + if a[i][0:1] == "i": + if rLoc.Language == "tr" or rLoc.Language == "az": + a[i] = u"\u0130" + a[i][1:] + elif a[i][1:2] == "j" and rLoc.Language == "nl": + a[i] = "IJ" + a[i][2:] + else: + a[i] = "I" + a[i][1:] + else: + a[i] = a[i].capitalize() + return a + +def compile_rules(dic): + # compile regular expressions + for i in dic: + try: + if re.compile("[(][?]iu[)]").match(i[0]): + i += [True] + i[0] = re.sub("[(][?]iu[)]", "(?u)", i[0]) + else: + i += [False] + i[0] = re.compile(i[0]) + except: + print "Lightproof: bad regular expression: ", traceback.format_exc() + i[0] = None + +def get_rule(loc): + try: + return langrule[pkg] + except: + langrule[pkg] = __import__("lightproof_" + pkg) + compile_rules(langrule[pkg].dic) + return langrule[pkg] + +def get_path(): + return os.path.join(os.path.dirname(sys.modules[__name__].__file__), __name__ + ".py") + +# [code] + +${code} diff --git a/src/editor/Addons.xcu b/src/editor/Addons.xcu new file mode 100644 index 0000000..958adc7 --- /dev/null +++ b/src/editor/Addons.xcu @@ -0,0 +1,97 @@ +<?xml version='1.0' encoding='UTF-8'?> +<oor:component-data + xmlns:oor="http://openoffice.org/2001/registry" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + oor:name="Addons" + oor:package="org.openoffice.Office"> + <node oor:name="AddonUI"> + <node oor:name="OfficeToolBar"> + <node oor:name="lightproof_editor.OfficeToolBar" oor:op="replace"> + <node oor:name="m0" oor:op="replace"> + <prop oor:name="Context" oor:type="xs:string"> + <value>com.sun.star.text.TextDocument</value> + </prop> + <prop oor:name="URL" oor:type="xs:string"> + <value>macro:///lightproof_editor.General.Compile</value> + </prop> + <prop oor:name="Title" oor:type="xs:string"> + <value>Apply rules (Alt-R)</value> + </prop> + <prop oor:name="Target" oor:type="xs:string"> + <value>_self</value> + </prop> + </node> + <node oor:name="m1" oor:op="replace"> + <prop oor:name="Context" oor:type="xs:string"> + <value>com.sun.star.text.TextDocument</value> + </prop> + <prop oor:name="URL" oor:type="xs:string"> + <value>macro:///lightproof_editor.General.CompileAll</value> + </prop> + <prop oor:name="Title" oor:type="xs:string"> + <value>Apply all (also optional) rules (Alt-C)</value> + </prop> + <prop oor:name="Target" oor:type="xs:string"> + <value>_self</value> + </prop> + </node> + <node oor:name="m2" oor:op="replace"> + <prop oor:name="Context" oor:type="xs:string"> + <value>com.sun.star.text.TextDocument</value> + </prop> + <prop oor:name="URL" oor:type="xs:string"> + <value>macro:///lightproof_editor.General.Debug</value> + </prop> + <prop oor:name="Title" oor:type="xs:string"> + <value>Debug rules (Alt-D)</value> + </prop> + <prop oor:name="Target" oor:type="xs:string"> + <value>_self</value> + </prop> + </node> + </node> + </node> + + <node oor:name="Images"> + <node oor:name="lightproof_editor-image-comp" oor:op="replace"> + <prop oor:name="URL" oor:type="xs:string"> + <value>macro:///lightproof_editor.General.Compile</value> + </prop> + <node oor:name="UserDefinedImages"> + <prop oor:name="ImageSmallURL"> + <value>%origin%/icons/comp16.png</value> + </prop> + <prop oor:name="ImageBigURL"> + <value>%origin%/icons/comp.png</value> + </prop> + </node> + </node> + <node oor:name="lightproof_editor-image-compall" oor:op="replace"> + <prop oor:name="URL" oor:type="xs:string"> + <value>macro:///lightproof_editor.General.CompileAll</value> + </prop> + <node oor:name="UserDefinedImages"> + <prop oor:name="ImageSmallURL"> + <value>%origin%/icons/compall16.png</value> + </prop> + <prop oor:name="ImageBigURL"> + <value>%origin%/icons/compall.png</value> + </prop> + </node> + </node> + <node oor:name="lightproof_editor-image-debug" oor:op="replace"> + <prop oor:name="URL" oor:type="xs:string"> + <value>macro:///lightproof_editor.General.Debug</value> + </prop> + <node oor:name="UserDefinedImages"> + <prop oor:name="ImageSmallURL"> + <value>%origin%/icons/debug16.png</value> + </prop> + <prop oor:name="ImageBigURL"> + <value>%origin%/icons/debug.png</value> + </prop> + </node> + </node> + </node> + </node> +</oor:component-data> diff --git a/src/editor/META-INF/manifest.xml b/src/editor/META-INF/manifest.xml new file mode 100644 index 0000000..6c50439 --- /dev/null +++ b/src/editor/META-INF/manifest.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<manifest:manifest> + <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcs" + manifest:media-type="application/vnd.sun.star.configuration-schema" /> + <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcu" + manifest:media-type="application/vnd.sun.star.configuration-data" /> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python" + manifest:full-path="Lightproof.py"/> + <manifest:file-entry + manifest:media-type="application/vnd.sun.star.configuration-data" + manifest:full-path="Linguistic.xcu" /> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" manifest:full-path ="Office/Accelerators.xcu"/> + <manifest:file-entry manifest:full-path="lightproof_editor/" manifest:media-type="application/vnd.sun.star.basic-library"/> + <manifest:file-entry manifest:full-path="pkg-desc/pkg-description.txt" manifest:media-type="application/vnd.sun.star.package-bundle-description"/> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" manifest:full-path ="Office/Events.xcu"/> + <manifest:file-entry manifest:full-path="Office/UI/StartModuleWindowState.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/> + <manifest:file-entry manifest:full-path="Office/UI/WriterWindowState.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/> + <manifest:file-entry manifest:full-path="Addons.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/> +</manifest:manifest>
\ No newline at end of file diff --git a/src/editor/Office/Accelerators.xcu b/src/editor/Office/Accelerators.xcu new file mode 100644 index 0000000..9492e4c --- /dev/null +++ b/src/editor/Office/Accelerators.xcu @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Accelerators" oor:package="org.openoffice.Office"> + <node oor:name="PrimaryKeys"> + <node oor:name="Modules"> + <node oor:name="com.sun.star.text.TextDocument"> + <node oor:name="R_MOD2" oor:op="replace"> + <prop oor:name="Command"> + <value xml:lang="hu">macro:///lightproof_editor.General.Compile</value> + </prop> + </node> + <node oor:name="C_MOD2" oor:op="replace"> + <prop oor:name="Command"> + <value xml:lang="hu">macro:///lightproof_editor.General.CompileAll</value> + </prop> + </node> + <node oor:name="D_MOD2" oor:op="replace"> + <prop oor:name="Command"> + <value xml:lang="hu">macro:///lightproof_editor.General.Debug</value> + </prop> + </node> + </node> + </node> + </node> + <node oor:name="SecondaryKeys"> + <node oor:name="Modules"> + <node oor:name="com.sun.star.text.TextDocument"> + </node> + </node> + </node> +</oor:component-data>
\ No newline at end of file diff --git a/src/editor/Office/UI/StartModuleWindowState.xcu b/src/editor/Office/UI/StartModuleWindowState.xcu new file mode 100644 index 0000000..19bcabe --- /dev/null +++ b/src/editor/Office/UI/StartModuleWindowState.xcu @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + oor:name="StartModuleWindowState" + oor:package="org.openoffice.Office.UI"> + <node oor:name="UIElements"> + <node oor:name="States"> + <node oor:name="private:resource/toolbar/addon_lightproof_editor.OfficeToolBar" oor:op="replace"> + <prop oor:name="UIName" oor:type="xs:string"> + <value>Lightproof editor + </value> + </prop> + <prop oor:name="Locked" oor:type="xs:boolean"> + <value>false</value> + </prop> + </node> + </node> + </node> +</oor:component-data> diff --git a/src/editor/Office/UI/WriterWindowState.xcu b/src/editor/Office/UI/WriterWindowState.xcu new file mode 100644 index 0000000..14f4ed9 --- /dev/null +++ b/src/editor/Office/UI/WriterWindowState.xcu @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + oor:name="WriterWindowState" + oor:package="org.openoffice.Office.UI"> + <node oor:name="UIElements"> + <node oor:name="States"> + <node oor:name="private:resource/toolbar/addon_lightproof_editor.OfficeToolBar" oor:op="replace"> + <prop oor:name="UIName" oor:type="xs:string"> + <value>Lightproof editor</value> + </prop> + <prop oor:name="Locked" oor:type="xs:boolean"> + <value>false</value> + </prop> + </node> + </node> + </node> +</oor:component-data> diff --git a/src/editor/README b/src/editor/README new file mode 100644 index 0000000..dfca312 --- /dev/null +++ b/src/editor/README @@ -0,0 +1,75 @@ +Lightproof grammar checker rule editor for LibreOffice + +source: git://anongit.freedesktop.org/libreoffice/lightproof + +or see cgit.freedesktop.org/libreoffice + +version 0.1 (2012-02-02) + +2009–2012 (c) László Németh (nemeth at numbertext dot org), license: MPL 1.1 / GPLv3+ / LGPLv3+ + +This software was developed with support from FSF.hu Foundation, Hungary. + +Introduction: http://libreoffice.hu/2011/12/08/grammar-checking-in-libreoffice/ + +== Installation == + +1. Via Tools -> Extension manager in OOo/LibreOffice + +2. or with unopkg tool, for example + +[install_path\program\]unopkg add -f lightproof_editor-0.1.oxt + +== Usage == + +Note: there is a huge starting time (seconds) starting LibreOffice with the +Lightproof editor. [Removing the unnecessary locales from src/editor/editor.cfg +of Lightproof source and generating a new editor extension can solve this problem.] + +The Lightproof editor extension contains a special grammar checker component and +a LibreOffice Writer toolbar. The editor can update its grammar checker component based +on the Lightproof rules in the current Writer document. + +Note: for languages without 'official LibreOffice' Hunspell dictionaries or languages +with default LibreOffice grammar checking (English, Russian and Hungarian in LibO 3.5) +have to modify some settings, too, see doc/manual.txt in the zipped extension, or you +can choose a neutral language (eg. Esperanto) for your Writer document during the rule +development. Only the Hunspell-related Lightproof functions, eg. spell(), morph() need +the correct language. + +After the successful installation (and settings), you can check the work of the grammar +checking component of the editor with the following text: + +a a + +The repeating letters will be underlined with blue wavy line (thanks to the default +a a -> a # Did you mean +rule of the grammar checker component of the editor). + +Write the following Lightproof rule in an empty Writer document: + +b b -> b # suggestion + +Click on the first icon on the Lightproof editor toolbar. The 'b b' text will be +underlined with blue wavy line as a grammar mistake with the 'b' suggestion and +'suggestion' explanation. + +Load and modify the English Lightproof rules (src/en/en.dat) or decribe new rules +based on doc/syntax.txt (these files can be found in the oxt (zipped) file of the +Lightproof editor extension, too). See also doc/manual.txt and +http://libreoffice.hu/2011/12/08/grammar-checking-in-libreoffice/ + += Toolbar icons = + +1. Apply rules + +Compile and the default Lightproof rules in the current document and update the Lightproof +editor grammar checker component. + +2. Apply all rules + +Compile and apply all (including optional) Lightproof rules in the current document and update the relevant component. + +3. Debug rules + +Check the current text and report run time errors (eg. in the Python conditions of the rules). diff --git a/src/editor/editor.cfg b/src/editor/editor.cfg new file mode 100644 index 0000000..2145943 --- /dev/null +++ b/src/editor/editor.cfg @@ -0,0 +1,11 @@ +[args] +lang = editor +locales = af_ZA an_ES ar be_BY bg_BG bn_BD br_FR ca cs_CZ da_DK de_DE el_GR en_AU en_CA en_GB en_US en_ZA es_ES et_EE eo fr gd_GB gl_ES gu_IN he_IL hi_IN hr_HR hu_HU it_IT ku_TR lt_LT lv_LV ne_NP nl_NL nb_NO nn_NO oc_FR pl_PL pt_BR pt_PT ro_RO ru_RU si_LK sk_SK sl_SI sh sr sv_SE sw_TZ te_IN th_TH uk_UA vi_VN +name = Lightproof editor +version = 0.1 +author = László Németh +provider = FSF.hu Foundation +implname = lightproof_editor +link = http://www.fsf.hu/about-us/ +description = Grammar checker rule editor for LibreOffice +extras = ../../pythonpath/lightproof_compile___implname__.py, README, ../../doc/syntax.txt, ../../doc/manual.txt, ../../src/en/en.dat, lightproof_editor/script.xlb, lightproof_editor/RegisteredFlag, lightproof_editor/General.xba, lightproof_editor/dialog.xlb, Office/UI/StartModuleWindowState.xcu, Office/UI/WriterWindowState.xcu, Office/Accelerators.xcu, icons/comp.png, icons/compall.png, icons/comp16.png, icons/compall16.png, icons/debug16.png, icons/debug.png, META-INF/manifest.xml, Addons.xcu diff --git a/src/editor/editor.dat b/src/editor/editor.dat new file mode 100644 index 0000000..8dd5d64 --- /dev/null +++ b/src/editor/editor.dat @@ -0,0 +1 @@ +a a -> a # Did you mean: diff --git a/src/editor/icons/comp.png b/src/editor/icons/comp.png Binary files differnew file mode 100644 index 0000000..2a91ef5 --- /dev/null +++ b/src/editor/icons/comp.png diff --git a/src/editor/icons/comp16.png b/src/editor/icons/comp16.png Binary files differnew file mode 100644 index 0000000..dfa593f --- /dev/null +++ b/src/editor/icons/comp16.png diff --git a/src/editor/icons/compall.png b/src/editor/icons/compall.png Binary files differnew file mode 100644 index 0000000..723a723 --- /dev/null +++ b/src/editor/icons/compall.png diff --git a/src/editor/icons/compall16.png b/src/editor/icons/compall16.png Binary files differnew file mode 100644 index 0000000..1e6fd39 --- /dev/null +++ b/src/editor/icons/compall16.png diff --git a/src/editor/icons/debug.png b/src/editor/icons/debug.png Binary files differnew file mode 100644 index 0000000..d1859e3 --- /dev/null +++ b/src/editor/icons/debug.png diff --git a/src/editor/icons/debug16.png b/src/editor/icons/debug16.png Binary files differnew file mode 100644 index 0000000..f11270b --- /dev/null +++ b/src/editor/icons/debug16.png diff --git a/src/editor/lightproof_editor/General.xba b/src/editor/lightproof_editor/General.xba new file mode 100644 index 0000000..3dc048e --- /dev/null +++ b/src/editor/lightproof_editor/General.xba @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd"> +<script:module xmlns:script="http://openoffice.org/2000/script" script:name="General" script:language="StarBasic">' László Németh (c) 2012, License: MPL/LGPL/GPL + +Sub Compile() + Update(False) +End Sub + +Sub CompileAll() + Update(True) +End Sub + +Sub Update(all) + c = ThisComponent.CurrentController.getViewCursor() + Dim prop + prop = ThisComponent.getDocumentProperties() + locale = ThisComponent.StyleFamilies.getByName("ParagraphStyles").getByName("Standard").CharLocale + Dim values(1) As New com.sun.star.beans.PropertyValue + rules = ThisComponent.Text.getString() + if InStr(rules, "→") Then Replace("→", "->") + if InStr(rules, "←") Then Replace("←", "<-") + rules = ThisComponent.Text.getString() + if all Then Replace("\<option\([^)]*\)", "True") + values(0).Name = "Update" + values(0).Value = ThisComponent.Text.getString() + 'spellchecker = createUnoService("com.sun.star.linguistic2.SpellChecker") + proofreader = createUnoService("org.openoffice.comp.pyuno.Lightproof.lightproof_editor") + result = proofreader.doProofreading(0, rules, locale, 0, len(rules), values()) + ThisComponent.Text.setString(rules) + SetStyle() + Replace("\n", "\n") ' convert new lines to paragraph breaks + If result.aText <> "" Then + If result.aText <> rules Then + MsgBox result.aText + " in line " + result.nStartOfSentencePosition + SetLine(result.nStartOfSentencePosition) + End If + End If +End Sub + +Sub Debug() + c = ThisComponent.CurrentController.getViewCursor() + Dim prop + prop = ThisComponent.getDocumentProperties() + locale = ThisComponent.StyleFamilies.getByName("ParagraphStyles").getByName("Standard").CharLocale + Dim values(1) As New com.sun.star.beans.PropertyValue + rules = ThisComponent.Text.getString() + 'if InStr(rules, "→") Then Replace("→", "->") + 'if InStr(rules, "←") Then Replace("←", "<-") + 'if all Then Replace("\<option\([^)]*\)", "True") + values(0).Name = "Debug" + values(0).Value = ThisComponent.Text.getString() + 'spellchecker = createUnoService("com.sun.star.linguistic2.SpellChecker") + proofreader = createUnoService("org.openoffice.comp.pyuno.Lightproof.lightproof_editor") + result = proofreader.doProofreading(0, rules, locale, 0, len(rules), values()) + ThisComponent.Text.setString(rules) + SetStyle() + Replace("\n", "\n") ' convert new lines to paragraph breaks + If result.aText <> "" Then + If result.aText <> rules Then + MsgBox result.aText + " in line " + result.nStartOfSentencePosition + SetLine(result.nStartOfSentencePosition) + Else + MsgBox "Ok" + End If + End If +End Sub + + + +Sub SetStyle() + target = ThisComponent.StyleFamilies.getByName("ParagraphStyles").getByName("Standard") + source = ThisComponent.StyleFamilies.getByName("ParagraphStyles").getByName("Preformatted Text") + if target.CharFontName <> source.CharFontName or target.CharHeight <> source.CharHeight then + target.CharFontName = source.CharFontName + target.CharHeight = source.CharHeight + end if +End Sub + +Sub SetLine(n) +' MsgBox "hello" + c = ThisComponent.Text.createTextCursor() +' c = ThisComponent.CurrentController.getViewCursor + c.GoToStart(False) + For i = 2 to n + c.gotoNextParagraph(False) +' c.gotoEndOfLine(False) +' c.goRight(1, False) +' c.setString("M") +' MsgBox c.getString() + Next + ThisComponent.CurrentController.getViewCursor.gotoRange(c, False) +End Sub + + +sub Replace(s, s2) +rem ---------------------------------------------------------------------- +rem define variables +dim document as object +dim dispatcher as object +rem ---------------------------------------------------------------------- +rem get access to the document +document = ThisComponent.CurrentController.Frame +dispatcher = createUnoService("com.sun.star.frame.DispatchHelper") + +rem ---------------------------------------------------------------------- +dispatcher.executeDispatch(document, ".uno:GoToStartOfDoc", "", 0, Array()) + +rem ---------------------------------------------------------------------- +dim args2(18) as new com.sun.star.beans.PropertyValue +args2(0).Name = "SearchItem.StyleFamily" +args2(0).Value = 2 +args2(1).Name = "SearchItem.CellType" +args2(1).Value = 0 +args2(2).Name = "SearchItem.RowDirection" +args2(2).Value = true +args2(3).Name = "SearchItem.AllTables" +args2(3).Value = false +args2(4).Name = "SearchItem.Backward" +args2(4).Value = false +args2(5).Name = "SearchItem.Pattern" +args2(5).Value = false +args2(6).Name = "SearchItem.Content" +args2(6).Value = false +args2(7).Name = "SearchItem.AsianOptions" +args2(7).Value = false +args2(8).Name = "SearchItem.AlgorithmType" +args2(8).Value = 1 +args2(9).Name = "SearchItem.SearchFlags" +args2(9).Value = 65536 +args2(10).Name = "SearchItem.SearchString" +args2(10).Value = s +args2(11).Name = "SearchItem.ReplaceString" +args2(11).Value = s2 +args2(12).Name = "SearchItem.Locale" +args2(12).Value = 255 +args2(13).Name = "SearchItem.ChangedChars" +args2(13).Value = 2 +args2(14).Name = "SearchItem.DeletedChars" +args2(14).Value = 2 +args2(15).Name = "SearchItem.InsertedChars" +args2(15).Value = 2 +args2(16).Name = "SearchItem.TransliterateFlags" +args2(16).Value = 1280 +args2(17).Name = "SearchItem.Command" +args2(17).Value = 3 +args2(18).Name = "Quiet" +args2(18).Value = true + +dispatcher.executeDispatch(document, ".uno:ExecuteSearch", "", 0, args2()) + + +end sub +</script:module>
\ No newline at end of file diff --git a/src/editor/lightproof_editor/RegisteredFlag b/src/editor/lightproof_editor/RegisteredFlag new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/editor/lightproof_editor/RegisteredFlag diff --git a/src/editor/lightproof_editor/dialog.xlb b/src/editor/lightproof_editor/dialog.xlb new file mode 100644 index 0000000..1fe87d3 --- /dev/null +++ b/src/editor/lightproof_editor/dialog.xlb @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd"> +<library:library xmlns:library="http://openoffice.org/2000/library" library:name="lightproof_editor" library:readonly="false" library:passwordprotected="false"> +</library:library>
\ No newline at end of file diff --git a/src/editor/lightproof_editor/script.xlb b/src/editor/lightproof_editor/script.xlb new file mode 100644 index 0000000..68e8364 --- /dev/null +++ b/src/editor/lightproof_editor/script.xlb @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd"> +<library:library xmlns:library="http://openoffice.org/2000/library" library:name="lightproof_editor" library:readonly="false" library:passwordprotected="false"> + <library:element library:name="General"/> +</library:library>
\ No newline at end of file diff --git a/src/en/README_lightproof_en.txt b/src/en/README_lightproof_en.txt new file mode 100644 index 0000000..43c91fe --- /dev/null +++ b/src/en/README_lightproof_en.txt @@ -0,0 +1,3 @@ +English sentence checker for LibreOffice +see git://anongit.freedesktop.org/libreoffice/lightproof +2011-2012 (c) László Németh, license: MPL 1.1 / GPLv3+ / LGPLv3+ diff --git a/src/en/en.cfg b/src/en/en.cfg new file mode 100644 index 0000000..0844e90 --- /dev/null +++ b/src/en/en.cfg @@ -0,0 +1,13 @@ +[args] +lang = en +locales = en_GB en_US en_PH en_ZA en_NA en_ZW en_AU en_CA en_IE en_IN en_BZ en_BS en_GH en_JM en_NZ en_TT +name = Lightproof grammar checker (English) +version = 0.4.2 +author = László Németh +provider = LibreOffice +implname = lightproof_en +link = http://www.libreoffice.org +description = English grammar checker for LibreOffice +extras = README_lightproof_en.txt +# logo = +# sourcefiles =
\ No newline at end of file diff --git a/src/en/en.dat b/src/en/en.dat new file mode 100644 index 0000000..dd8ec6a --- /dev/null +++ b/src/en/en.dat @@ -0,0 +1,382 @@ +# English sentence checking + +# word-level rules (case-sensitive) + +[word] + +# basic syntax of the rules: +# +# pattern -> suggestion # warning message +# pattern <- condition -> suggestion # warning message +# + +# duplicates + +and and -> and # Did you mean: +or or -> or # Did you mean: +for for -> for # Did you mean: +the the -> the # Did you mean: + +# word-level rules (case-insensitive) + +[Word] + +# multiword expressions + +ying and yang -> yin and yang # Did you mean: + +# multiple suggestions separated by "\n" + +scot free -> scot-free\nscotfree # Did you mean: + +# possessive pronouns + +# Your's -> Yours +(your|her|our|their)['’]s -> \1s # Possessive pronoun: \n http://en.wikipedia.org/wiki/Possessive_pronoun + +# a or an (rules for articles)# +############################### + +[word] + +# pattern "a" matches "a" or "A": +a [Aa] + +# pattern "_" matches space and optional quotation marks: +_ [ ]['‘"“]? + +# pattern "vow" matches words beginning with vowels: +vow [aeiouAEIOU]\w* + +# pattern "con" matches words beginning with consonants: +con [bcdfghj-np-tv-zBCDFGHJ-NP-TV-Z]\w* + +# pattern "etc" matches other word parts separated by hyphen, endash or apostrophes: +etc [-–'’\w]* + +# rules ("aA", "aAN", "aB" sets are defined at the end of the file) + +{a}n{_}{vow}{etc} <- {vow} in aA or {vow}.lower() in aA -> {a}{_}{vow}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +a{_}{vow}{etc} <- ({vow} <> {vow}.upper()) and not ({vow} in aA or + {vow}.lower() in aA) and spell({vow}) -> an{_}{vow}{etc} # Bad article? \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +a{_}{con}{etc} <- {con} in aAN or {con}.lower() in aAN -> an{_}{con}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +{a}n{_}{con}{etc} <- ({con} <> {con}.upper()) and not ({con} in aA or + {con}.lower() in aAN) and not {con} in aB and spell({con}) -> {a}{_}{con}{etc} # Bad article? \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +# rules for sentences beginning with "A" + +^A{_}{vow}{etc} <- ({vow} <> {vow}.upper()) and not ({vow} in aA or + {vow}.lower() in aA) and spell({vow}) -> An{_}{vow}{etc} # Bad article? \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +^A{_}{con}{etc} <- {con} in aAN or {con}.lower() in aAN -> An{_}{con}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +# check numbers + +nvow (8[0-9]*|1[18](000)*)(th)? # 8, 8th, 11, 11th, 18, 18th, 11000, 11000th... + +a{_}{nvow}{etc} -> an{_}{nvow}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an +^A{_}{nvow}{etc} -> An{_}{nvow}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +ncon [0-79][0-9]* + +{a}n{_}{ncon}{etc} <- not {ncon}[:2] in ["11", "18"] -> {a}{_}{ncon}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an + +# paragraph capitalization + +[code] +# pattern matching for common English abbreviations +abbrev = re.compile("(?i)\b([a-z]|acct|approx|appt|apr|apt|assoc|asst|aug|ave|avg|co(nt|rp)?|ct|dec|defn|dept|dr|eg|equip|esp|est|etc|excl|ext|feb|fri|ft|govt?|hrs?|ib(id)?|ie|in(c|t)?|jan|jr|jul|lit|ln|mar|max|mi(n|sc)?|mon|Mrs?|mun|natl?|neg?|no(rm|s|v)?|nw|obj|oct|org|orig|pl|pos|prev|proj|psi|qty|rd|rec|rel|reqd?|resp|rev|sat|sci|se(p|pt)?|spec(if)?|sq|sr|st|subj|sun|sw|temp|thurs|tot|tues|univ|var|vs)\.") + +# pattern for paragraph checking +paralcap = re.compile(u"(?u)^[a-z].*[.?!] [A-Z].*[.?!][)”]?$") + +[word] + +# condition: the paragraph begins with a lowercase letter and it contains real sentence boundaries. + +low [a-z]+ + +(^){low} <- paralcap.search(TEXT) and not abbrev.search(TEXT) -> = {low}.capitalize() # Missing capitalization? + +# optional sentence capitalization + +^{low} <- option("cap") and not abbrev.search(TEXT) -> = {low}.capitalize() # Missing capitalization? + +# punctuation + +[code] + +punct = { "?": "question mark", "!": "exclamation mark", + ",": "comma", ":": "colon", ";": "semicolon", + "(": "opening parenthesis", ")": "closing parenthesis", + "[": "opening square bracket", "]": "closing square bracket", + u"“": "opening quotation mark", u"”": "closing quotation mark"} + +[char] + +" ([.?!,:;)”\]])\b" -> "\1 " # Reversed space and punctuation? +" +[.]" <- LOCALE.Country == "US" -> . # Extra space before the period? +" +[.]" <- LOCALE.Country != "US" -> . # Extra space before the full stop? +" +([?!,:;)”\]])" -> \1 # = "Extra space before the " + punct[\1] + "?" +"([([“]) " -> \1 # = "Extra space after the " + punct[\1] + "?" + +# ( item ) -> (item) +# A small - but important - example. -> A small – but important – example. + +# En dash and em dash + +\b(---?| --? )\b <- not option("ndash") and not option("mdash") -> " – \n—" # En dash or em dash: +\b(---?| --? |—)\b <- option("ndash") and not option("mdash") -> " – " # En dash: +\b(---?| --? | – )\b <- option("mdash") -> — # Em dash: + +# multiplication sign + +number \d+([.]\d+)? + +{number}(x| x ){number} <- option("times") -> {number}×{number} # Multiplication sign. \n http://en.wikipedia.org/wiki/Multiplication_sign +# 800x600 -> 800×600 + +# missing space + +abc [a-z]+ +ABC [A-Z]+ +Abc [a-zA-Z]+ +pun [?!,:;%‰‱˚“”‘] + +{Abc}{pun}{Abc} -> {Abc}{pun} {Abc} # Missing space? +{abc}[.]{ABC} -> {abc}. {ABC} # Missing space? +# missing,space -> missing, space +# missing.Space -> missing. Space + +[)] <- option("pair") and not "(" in TEXT -> # Extra closing parenthesis? +[(] <- option("pair") and TEXT[-1] in u"?!;:”’" and not ")" in TEXT -> # Extra opening parenthesis? +(?<![0-9])” <- option("pair") and not u"“" in TEXT -> # Extra quotation mark? +(?<=[0-9])” <- option("apostrophe") and not u"“" in TEXT -> ″\n # Bad double prime or extra quotation mark? +“ <- option("pair") and TEXT[-1] in u"?!;:”’" and not u"”" in TEXT -> # Extra quotation mark? + +"[.]{3}" <- option("ellipsis") -> "…" # Ellipsis. + +\b {2,3}(\b|$) <- option("spaces") -> "\1 " # Extra space. +# Extra space -> Extra space +# End... -> End… + +(^|\b|{pun}|[.]) {2,3}(\b|$) <- option("spaces2") -> "\1 " # Extra space. +# Extra space -> Extra space +# End... -> End… + +(^|\b|{pun}|[.]) {4,}(\b|$) <- option("spaces3") -> "\1 \n " # Change multiple spaces to a single space or a tabulator: + +# quotation + +# Using typographic quotation marks is the + +(?i)[\"“”‟„]({abc}[^\"“”‟„]*)[\"“‟] <- option("quotation") -> “\1” # Quotation marks. +(?i)[\"”‟„]({abc}[^\"“”‟„]*)[\"“”‟] <- option("quotation") -> “\1” # Quotation marks. + +(?i)'{abc}' <- option("apostrophe") -> ‘{abc}’ # Quotation marks. +(?i)[\"”‟„]({abc}[^\"“”‟„]*)[\"“”‟] <- option("apostrophe") -> “\1” # Quotation marks. + +# apostrophe + +w \w* +(?i){Abc}'{w} <- option("apostrophe") -> {Abc}’{w} # Replace typewriter apostrophe or quotation mark: +# o'clock -> o’clock +# singers' voices -> singers’ voices + +(?<= )'{Abc} <- option("apostrophe") -> ‘{Abc}\n’{Abc} # Replace typewriter quotation mark or apostrophe: +^'{Abc} <- option("apostrophe") -> ‘{Abc}\n’{Abc} # Replace typewriter quotation mark or apostrophe: + +# formats + +# Thousand separators: 10000 -> 10,000 (common) or 10 000 (ISO standard) + +# definitions +d \d\d\d # name definition: 3 digits +d2 \d\d # 2 digits +D \d{1,3} # 1, 2 or 3 digits + +# ISO thousand separators: space, here: narrow no-break space (U+202F) +\b{d2}{d}\b <- option("numsep") -> {d2},{d}\n{d2} {d} # Use thousand separator (common or ISO). +\b{D}{d}{d}\b <- option("numsep") -> {D},{d},{d}\n{D} {d} {d} # Use thousand separators (common or ISO). +\b{D}{d}{d}{d}\b <- option("numsep") -> {D},{d},{d},{d}\n{D} {d} {d} {d} # Use thousand separators (common or ISO). +# 1234567890 -> 1,234,567,890\n1 234 567 890 + +# word duplication + +[word] + +{Abc} \1 <- option("dup") -> {Abc} # Word duplication? + +# Optional grammar checking + +([Tt])his {abc} <- option("grammar") and morph({abc}, "Ns") -> \1hese {abc}\n\1his, {abc} # Did you mean: + +with it['’]s <- option("grammar") -> with its\nwith, it’s # Did you mean: + +[Word] + +(it|s?he) don['’]t <- option("grammar") -> \1 doesn’t # Did you mean: + +################### measurements ########################## + +[word] + +# Temperature + +([-−]?\d+(?:[,.]\d+)*) (°F|Fahrenheit) <- option("metric") -> = measurement(\1, "F", "C", u" °C", ".", ",") # Convert to Celsius: +([-−]?\d+(?:[,.]\d+)*) (°C|Celsius) <- option("nonmetric") -> = measurement(\1, "C", "F", u" °F", ".", ",") # Convert to Fahrenheit: + +# Length + +([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) (ft|foot|feet)(?! [1-9]) <- option("metric") -> = + measurement(\1, "ft", "cm", " cm", ".", ",") + "\n" + + measurement(\1, "ft", "m", " m", ".", ",") # Convert to metric: + +([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) ft[.]? ([0-9]+(?: 1/2| ?½)?) in <- option("metric") -> = + measurement(\1 + "*12+" + \2, "in", "cm", " cm", ".", ",") + "\n" + + measurement(\1 + "*12+" + \2, "in", "m", " m", ".", ",") # Convert to metric: + +([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) in <- option("metric") -> = + measurement(\1, "in", "mm", " mm", ".", ",") + "\n" + + measurement(\1, "in", "cm", " cm", ".", ",") + "\n" + + measurement(\1, "in", "m", " m", ".", ",") # Convert to metric: + +([-−]?\d+(?:[,.]\d+)*) mm <- option("nonmetric") -> = + measurement(\1, "mm", "in", " in", ".", ",") # Convert from metric: + +([-−]?\d+(?:[,.]\d+)*) cm <- option("nonmetric") -> = + measurement(\1, "cm", "in", " in", ".", ",") + "\n" + + measurement(\1, "cm", "ft", " ft", ".", ",") # Convert from metric: + +([-−]?\d+(?:[,.]\d+)*) (m|meter|metre) <- option("nonmetric") -> = + measurement(\1, "m", "in", " in", ".", ",") + "\n" + + measurement(\1, "m", "ft", " ft", ".", ",") + "\n" + + measurement(\1, "m", "mi", " mi", ".", ",") # Convert from metric: + +([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) miles? <- option("metric") -> = + measurement(\1, "mi", "m", " m", ".", ",") + "\n" + + measurement(\1, "mi", "km", " km", ".", ",") # Convert to metric: + +([-−]?\d+(?:[,.]\d+)*) km <- option("nonmetric") -> = + measurement(\1, "km", "mi", " mi", ".", ",") # Convert to miles: + +([-−]?\d+(?:,\d+)?) (yd|yards?) <- option("metric") -> = measurement(\1, "yd", "m", " m", ".", ",") # Convert to metric: + +# Volume + +([-−]?\d+(?:,\d+)?) (gal(lons?)?) <- option("metric") -> = + measurement(\1, "gal", "l", " l", ".", ",") + "\n" + + measurement(\1, "uk_gal", "l", " l (in UK)", ".", ",") # Convert to metric: + +([-−]?\d+(?:,\d+)?) (pint) <- option("metric") -> = + measurement(\1, "pt", "dl", " dl", ".", ",") + "\n" + + measurement(\1, "uk_pt", "dl", " dl (in UK)", ".", ",") + "\n" + + measurement(\1, "pt", "l", " l", ".", ",") + "\n" + + measurement(\1, "uk_pt", "l", " l (in UK)", ".", ",") # Convert to metric: + +([-−]?\d+(?:,\d+)?) (l|L|litres?|liters?) <- option("nonmetric") -> = + measurement(\1, "l", "gal", " gal", ".", ",") + "\n" + + measurement(\1, "l", "gal", " gal (in UK)", ".", ",") # Convert to gallons: + +# Weight + +([-−]?\d+(?:[,.]\d+)*) lbs?[.]? <- option("metric") -> = + measurement(\1, "lbm", "kg", " kg", ".", ",") # Convert to metric: +([-−]?\d+(?:[,.]\d+)*) kg[.]? <- option("nonmetric") -> = + measurement(\1, "kg", "lbm", " lb", ".", ",") # Convert to pounds: + +# Speed + +([-−]?\d+(?:[,.]\d+)*) mph <- option("metric") -> = measurement(\1, "mph", "km/h", " km/h", ".", ",") # Convert to km/hour: +([-−]?\d+(?:[,.]\d+)*) km/h <- option("nonmetric") -> = measurement(\1, "km/h", "mph", " mph", ".", ",") # Convert to miles/hour: + +[code] + +aA = set(["eucalypti", "eucalyptus", "Eucharist", "Eucharistic", +"euchre", "euchred", "euchring", "Euclid", "euclidean", "Eudora", +"eugene", "Eugenia", "eugenic", "eugenically", "eugenicist", +"eugenicists", "eugenics", "Eugenio", "eukaryote", "Eula", "eulogies", +"eulogist", "eulogists", "eulogistic", "eulogized", "eulogizer", +"eulogizers", "eulogizing", "eulogy", "eulogies", "Eunice", "eunuch", +"eunuchs", "Euphemia", "euphemism", "euphemisms", "euphemist", +"euphemists", "euphemistic", "euphemistically", "euphonious", +"euphoniously", "euphonium", "euphony", "euphoria", "euphoric", +"Euphrates", "euphuism", "Eurasia", "Eurasian", "Eurasians", "eureka", +"eurekas", "eurhythmic", "eurhythmy", "Euridyce", "Euripides", "euripus", +"Euro", "Eurocentric", "Euroclydon", "Eurocommunism", "Eurocrat", +"eurodollar", "Eurodollar", "Eurodollars", "Euromarket", "Europa", +"Europe", "European", "Europeanisation", "Europeanise", "Europeanised", +"Europeanization", "Europeanize", "Europeanized", "Europeans", "europium", +"Eurovision", "Eustace", "Eustachian", "Eustacia", "euthanasia", +"Ewart", "ewe", "Ewell", "ewer", "ewers", "Ewing", "once", "one", +"oneness", "ones", "oneself", "onetime", "oneway", "oneyear", "u", +"U", "UART", "ubiquitous", "ubiquity", "Udale", "Udall", "UEFA", +"Uganda", "Ugandan", "ugric", "UK", "ukase", "Ukraine", "Ukrainian", +"Ukrainians", "ukulele", "Ula", "ululated", "ululation", "Ulysses", +"UN", "unanimity", "unanimous", "unanimously", "unary", "Unesco", +"UNESCO", "UNHCR", "uni", "unicameral", "unicameralism", "Unicef", +"UNICEF", "unicellular", "Unicode", "unicorn", "unicorns", "unicycle", +"unicyclist", "unicyclists", "unidimensional", "unidirectional", +"unidirectionality", "unifiable", "unification", "unified", "unifier", +"unifilar", "uniform", "uniformally", "uniformed", "uniformer", +"uniforming", "uniformisation", "uniformise", "uniformitarian", +"uniformitarianism", "uniformity", "uniformly", "uniformness", "uniforms", +"unify", "unifying", "unijugate", "unilateral", "unilateralisation", +"unilateralise", "unilateralism", "unilateralist", "unilaterally", +"unilinear", "unilingual", "uniliteral", "uniliteralism", "uniliteralist", +"unimodal", "union", "unionism", "unionist", "unionists", "unionisation", +"unionise", "unionised", "unionising", "unionization", "unionize", +"unionized", "unionizing", "unions", "unipolar", "uniprocessor", +"unique", "uniquely", "uniqueness", "uniquer", "Uniroyal", "unisex", +"unison", "Unisys", "unit", "Unitarian", "Unitarianism", "Unitarians", +"unitary", "unite", "united", "unitedly", "uniter", "unites", "uniting", +"unitize", "unitizing", "unitless", "units", "unity", "univ", "Univac", +"univalent", "univalve", "univariate", "universal", "universalisation", +"universalise", "universalised", "universaliser", "universalisers", +"universalising", "universalism", "universalist", "universalistic", +"universality", "universalisation", "universalization", "universalize", +"universalized", "universalizer", "universalizers", "universalizing", +"universally", "universalness", "universe", "universes", "universities", +"university", "univocal", "Unix", "uracil", "Urals", "uranium", "Uranus", +"uranyl", "urate", "urea", "uremia", "uremic", "ureter", "urethane", +"urethra", "urethral", "urethritis", "Urey", "Uri", "uric", "urinal", +"urinalysis", "urinary", "urinated", "urinating", "urination", "urine", +"urogenital", "urokinase", "urologist", "urologists", "urology", +"Uruguay", "Uruguayan", "Uruguayans", "US", "USA", "usable", "usage", +"usages", "use", "used", "useful", "usefulness", "usefully", "useless", +"uselessly", "uselessness", "Usenet", "user", "users", "uses", "using", +"usual", "usually", "usurer", "usurers", "usuress", "usurial", "usurious", +"usurp", "usurpation", "usurped", "usurper", "usurping", "usurps", +"usury", "Utah", "utensil", "utensils", "uterine", "uterus", "Utica", +"utilitarian", "utilitarianism", "utilities", "utility", "utilizable", +"utilization", "utilize", "utilized", "utilizes", "utilizing", "utopia", +"utopian", "utopians", "utopias", "Utrecht", "Uttoxeter", "uvula", +"uvular"]) + +aAN = set(["f", "F", "FBI", "FDA", "heir", "heirdom", "heired", +"heirer", "heiress", "heiring", "heirloom", "heirship", "honest", +"honester", "honestly", "honesty", "honor", "honorable", "honorableness", +"honorably", "honorarium", "honorary", "honored", "honorer", "honorific", +"honoring", "honors", "honour", "honourable", "honourableness", +"honourably", "honourarium", "honourary", "honoured", "honourer", +"honourific", "honouring", "Honours", "hors", "hour", "hourglass", "hourlong", +"hourly", "hours", "l", "L", "LCD", "m", "M", "MBA", "MP", "mpg", "mph", +"MRI", "MSc", "MTV", "n", "N", "NBA", "NBC", "NFL", "NGO", "NHL", "r", +"R", "s", "S", "SMS", "sos", "SOS", "SPF", "std", "STD", "SUV", "x", +"X", "XML"]) + +aB = set(["H", "hallucination", "haute", "hauteur", "herb", "herbaceous", "herbal", +"herbalist", "herbalism", "heroic", "hilarious", "historian", "historic", "historical", +"homage", "homophone", "horrendous", "hospitable", "horrific", "hotel", "hypothesis", "Xmas"]) + +def measurement(mnum, min, mout, mstr, decimal, remove): + if min == "ft" or min == "in" or min == "mi": + mnum = mnum.replace(" 1/2", ".5").replace(u" ½", ".5").replace(u"½",".5") + m = calc("CONVERT_ADD", (float(eval(mnum.replace(remove, "").replace(decimal, ".").replace(u"−", "-"))), min, mout)) + a = list(set([str(calc("ROUND", (m, 0)))[:-2], str(calc("ROUND", (m, 1))), str(calc("ROUND", (m, 2))), str(m)])) # remove duplicated rounded items + a.sort(lambda x, y: len(x) - len(y)) # sort by string length + return join(a, mstr + "\n").replace(".", decimal).replace("-", u"−") + mstr + diff --git a/src/en/en.dlg b/src/en/en.dlg new file mode 100644 index 0000000..ca35c61 --- /dev/null +++ b/src/en/en.dlg @@ -0,0 +1,53 @@ +# Options and title texts for the Settings and conditional rules +# +# THe dialog windows contain only grouped checkboxes. +# +# Format of the dialog definition: +# +# GroupID: OptionID, OptionID ... +# Group2ID: OptionID, OptionID ... +# ... +# [Language_code=[title of the node/]title of the window] +# OptionID=title of the option +# Option2ID=title of the option +# +# The first language is the default language for other locales +# (use en_US or the common language of your country) +# +# The OptionIDs declared here are used in the rules, too. For example: +# +# foo <- option("style") -> bar # bar is far better +# +# this rule depends from the state of the "style" checkbox. + +# options (starred options are checked) + +spelling: grammar cap dup pair +punctuation: *spaces mdash quotation *times, spaces2 ndash apostrophe ellipsis, spaces3 minus - - +others: metric numsep, nonmetric + +# titles + +[en_US=English sentence checking] + +spelling=Grammar checking +grammar=Possible mistakes \n Check more grammar errors. +cap=Capitalization \n Check missing capitalization of sentences. +dup=Word duplication \n Check repeated words. +pair=Parentheses \n Check missing or extra parentheses and quotation marks. +punctuation=Punctuation +spaces=Word spacing\nCheck single spaces between words. +mdash=Em dash\nForce unspaced em dash instead of spaced en dash. +ndash=En dash\nForce spaced en dash instead of unspaced em dash. +quotation=Quotation marks\nCheck double quotation marks: "x" → “x” +times=Multiplication sign\nCheck true multipliction sign: 5x5 → 5×5 +spaces2=Sentence spacing\nCheck single spaces between sentences. +spaces3=More spaces\nCheck more than two extra space characters between words and sentences. +minus=Minus sign\nChange hyphen characters to real minus signs. +apostrophe=Apostrophe\nChange typewriter apostrophe, single quotation marks and correct double primes. +ellipsis=Ellipsis\nChange three dots with ellipsis. +others=Others +metric=Convert to metric (°C, km/h, m, kg, l)\nMeasurement conversion from °F, mph, ft, in, lb, gal and miles. +numsep=Thousand separation of large numbers\nCommon (1000000 → 1,000,000) or ISO (1000000 → 1 000 000). +nonmetric=Convert to non-metric (°F, mph, ft, lb, gal)\nMeasurement conversion from °C; km/h; cm, m, km; kg; l. + diff --git a/src/hu_HU/ChangeLog b/src/hu_HU/ChangeLog new file mode 100644 index 0000000..a546f1a --- /dev/null +++ b/src/hu_HU/ChangeLog @@ -0,0 +1,124 @@ +2012-02-02 László Németh <nemeth@numbertext.org>: +- rövidebb magyarázat a „több mint” esetén + URL +- "-szám" alakoknál nem feltételez kötőjeles felsorolást + +2011-12-16 László Németh <nemeth@numbertext.org>: +- beállítások csak a kiterjesztéskezelőben hozzáférhetők ideiglenesen + +- webes bővebb magyarázatok támogatása (FullCommentURL) a LibO 3.5-ben, + pl. Fertő-tavi -> AkH. a Wikipédiában. + +- új opciók: + - nagy kezdőbetű: mondatok kis kezdőbetűjének keresése + - zárójelpárok és idézőjelek ellenőrzése + - nem elválasztott szavak elválasztását kínálja fel (pl. + megint -> me-gint, meg-int) + +- új szabályok: + - időről-időre, egytől-egyig -> időről időre, egytől egyig + - földrajzi nevek (Dél-Ázsiai -> Dél-ázsiai, Árpád-híd -> Árpád híd stb.) + - 1-e -> 1-je + - egyel kevesebb/több -> eggyel + - előre hátra -> előre-hátra + - ex-alelnök -> exalelnök stb. + - "kell hogy" esetén nem erőlteti az esetenként hibás vesszőt + +- javított szabályok: + - a/az névelőt csak a helyesírási szótárban meglévő szavak előtt ellenőriz + +- új licenc: MPL/GPL/LGPL + +2011-07-11 László Németh <nemeth@numbertext.org>: + +- javított csomagnév (Magyar nyelvi ellenőrzés) + +- új opciók: + - három pont + - dupla szóköz, sok szóköz + - idézőjelek, nagykötőjel + - törtek, indexek + - mínuszjel + - szóismétlés (egymást közvetlenül követő szavak) + - mértékegységek + +- 2003. Március -> 2003. március: hónap neve kisbetűvel jelenik meg a javaslatban is +- javaslat: a Unikum -> nagybetűvel jelenik meg, ahogy a szövegben szerepelt +- 2005 március-júniusa már nem hibásnak jelezve +- a Unicode, a Unix most már nem hibás a névelővel sem +- illetve hogy, illetve ha vessző nélkül +- áld meg, mond el -> áldd meg, mondd el, ha a felszólítás felismerhető (mondat, + tagmondathatár, esetleg "ne" szócskával bevezetve) +- jó kedvel, rossz kedvel -> jó kedvvel, rossz kedvvel +- halott róla, nem halottunk semmit -> hallott róla, nem hallottunk semmit +- C-vitamin hiány -> C-vitamin-hiány +- C-vitaminhiány -> C-vitamin-hiány (minden egybeírt összetételnél) +- médiák, unszimpatikus kijelzése az opcionális stílusellenőrzésbe került +- Budapest Liszt Ferenc Nemzetközi Repülőtér -> a többszörös helyesírási hiba kijelzése +- felsorolások kötőjele, nagykötőjele aláhúzva egybeírás esetén: -Egy -> – Egy +- 2011 július -> 2011. július (a július hiányzott az ellenőrzőtt hónapnevek közül) +- kellet -> kellett (*nem kellet volna, *meg kellet ezt csinálnom, *várni is kellet +- mértékegységek (mérföld, yard, láb, hüvelyk, °F, font súlyú, gallon, pint) átalakítása + +2010-05-06 László Németh <nemeth@openoffice.org>: + - alapértelmezett ezreselválasztó-ellenőrzés kikapcsolása (Magyar + Linux Libertine G Graphite automatikus ezreselválasztása miatt) + +2010-02-19 László Németh <nemeth@openoffice.org>: + * hu_HU.dat: + - "a" névelő + szám szabály javítása ("a 10") + a regex match hiányzó $ jelének pótlásával + - nem törő szóköz beillesztése a Celsius fok elé + - a törtekre és egyéb jelekre vonatkozó tipográfiai opció bekapcsolása + esetén nem törő szóköz helyett nem törő keskeny szóközt javasol a számok + ezrestagolójaként, és ezt felismeri a pénzegység + konzisztenciaellenőrzésénél is, valamint a régi nem törő szóközök + cseréjét is javasolja. + - Unicode vessző ékezet felvétele a valódi aposztrófot javasló szabályba + (U+00B4 kódja miatt elöl van, és emiatt tévedésből könnyen beilleszthető) + - idézőjeles szabályok bővítése: + - ASCII idézőjelek cseréje: + ,,valami >>volt<< ott.'' -> „valami »volt« ott.” + - felcserélt belső idézőjelek cseréje + - angolszász nem dupla idézőjelek cseréje + - számok konzisztencia-ellenőrzésénél nem törő szóközök helyes felismerése + +2010-02-12 László Németh <nemeth@openoffice.org>: + * hu_HU.dat: + - sorszámok névelőjének ellenőrzése ("az" esetén alapból még szükséges + az "oldal" stb. a sorszám után: pl. *"az 2. oldalon") + + * lightproof_handler.py: segédosztály megszüntetése a Mac OS X PyUNO hiba + lehetséges okának kiküszöbölésére + +2010-02-09 László Németh <nemeth@openoffice.org>: + * hu_HU.dat: + - mínuszjel + - szorzásjel javítása szóközök esetén is: 5 x 6 -> 5×6 + - hibás névelőjavaslat tiltása római számoknál (a II., a III. stb.) + - új feltételes szabályok: ligatúrák javaslata és elutasítása + - nem törő szóköz és toldalékolás esetén is javasolva van a százalékjel + tapadása; + - javaslat évszámok előtti aposztróf esetén is ('76-ban) + - pénznemek 1234,00 Ft és sima szóköz elfogadása, mint ezres tagoló + (nem törő szóköz már korábban így volt kezelve): 34 500 Ft + - fokjel javítása és egybeírása + - törtek (ha van csak Unicode karakterrel, pl. 1/2, + egyébként ha 1/x-ed, akkor "1/" Unicode karakterrel és alsó index + Unicode karakterrel, különben felső index, törtjel és alsó index + karakterekkel), indexek (H2O, H2SO4 stb.), fokok (Celsius, Fahrenheit + jele külön Unicode karakterrel (szebb tipográfiájú pl. a Linux Libertine + betűtípusban) + + * hu_HU.dlg: új feltételes szabályok: + - ligatúrák javaslata és elutasítása + - törtek, indexek, fokok menüpont + + - átcsoportosítás + +2009-12-16 László Németh <nemeth@openoffice.org>: + * hu_HU.dlg: + - Beállítások menü a magyar nyelvi ellenőrzéshez + + * hu_HU.dat: + - opcionális szabályok: szóismétlés, képzett + összetett szavak, (tizedes)vesszők ellenőrzése, stb. diff --git a/src/hu_HU/README_lightproof_hu_HU.txt b/src/hu_HU/README_lightproof_hu_HU.txt new file mode 100644 index 0000000..6c9f4f8 --- /dev/null +++ b/src/hu_HU/README_lightproof_hu_HU.txt @@ -0,0 +1,3 @@ +Hungarian sentence checker for LibreOffice +see git://anongit.freedesktop.org/libreoffice/lightproof +2009-2012 (c) László Németh, license: MPL 1.1 / GPLv3+ / LGPLv3+ diff --git a/src/hu_HU/hu_HU.cfg b/src/hu_HU/hu_HU.cfg new file mode 100644 index 0000000..3e8db39 --- /dev/null +++ b/src/hu_HU/hu_HU.cfg @@ -0,0 +1,10 @@ +[args] +lang = hu_HU +locales = hu_HU +name = Lightproof grammar checker (magyar) +version = 1.4.3 +author = László Németh +provider = FSF.hu +implname = lightproof_hu +link = http://www.fsf.hu +extras = README_lightproof_hu_HU.txt, ChangeLog diff --git a/src/hu_HU/hu_HU.dat b/src/hu_HU/hu_HU.dat new file mode 100644 index 0000000..cbc1a8c --- /dev/null +++ b/src/hu_HU/hu_HU.dat @@ -0,0 +1,908 @@ +# magyar szabályok (írta: Németh László) + +###################### szóismétlés ################### + +a a -> a # Szóismétlés. +és és -> és # Szóismétlés. + +############## hogy (l. még vesszőhasználat) ######### + +hogy[ -]hogy nem -> hogyhogy nem/hogy, hogy nem # Hiányzó vessző vagy egybeírás +hogy-hogy -> hogyhogy # Egybeírás. + +[char] + +# hogy előtt vessző (csak igékre és főnevekre, vessző ne kövesse, mint a hogy, hogy nemben +([-\w]+) hogy\b(?![-]) <- word(1) and morph(\1, r"po:(vrb|noun)\b") and not \1 in [u"feltéve", "kell"] -> \1, hogy # Hiányzó vessző? + +[word] + +# még több vessző + +([-\w]+) hogy <- option("comma") and + not re.match(u"(feltéve|ahelyett|anélkül|aszerint|hogy)$", \1) + -> \1, hogy # Hiányzó vessző? + +# túl sok vessző +([-\w]+), (ahelyett|anélkül|aszerint), hogy -> \1, \2 hogy\n\1 \2, hogy # Kötőszószerű kapcsolat esetén nem írunk a „hogy” elé vesszőt. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#243. +([-\w]+), illetve, (ha|hogy) -> \1, illetve \2 # Kötőszószerű kapcsolat esetén nem írunk az „illetve” után vesszőt. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#243. + +###################### nagybetűsítés ################# +[code] + +abbrev=re.compile(ur"(?i)\b([a-zöüóőúéáűíÖÜÓŐÚÉÁŰÍ]|Áe|Áht|AkH|al|ált|ápr|aug|Avtv|bek|Bp|br|bt|Btk|cca|ci(i|ii|v|x)?|cl(i|ii|iii|iv|ix|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii|xx|xxi|xxii|xxiii|xxiv|xxix|xxv|xxvi|xxvii|xxviii|xxx|xxxi|xxxii|xxxiii|xxxiv|xxxix|xxxv|xxxvi|xxxvii|xxxviii)?|Co|cv(i|ii|iii)?|cx(c|ci|cii|ciii|civ|cix|cv|cvi|cvii|cviii|i|ii|iii|iv|ix|l|li|lii|liii|liv|lix|lv|lvi|lvii|lviii|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii|xx|xxi|xxii|xxiii|xxiv|xxix|xxv|xxvi|xxvii|xxviii)?|cs|Csjt|Cstv|csüt|dec|dk|dny|dr|du|dz(s)?|egy|ék|ÉKsz|em|ény|Épt|érk|etc|Etv|eü|ev|évf|febr|felv|Flt|ford|főisk|fsz(la|t)?|Ftv|gimn|gör|gr|Gt|gy|Gyvt|habil|hg|hiv|Hjt|honv|Hpt|hrsz|hsz|Hszt|htb|id|ifj|ig(h)?|ii(i)?|ill|Inc|ind|isk|iv|ix|izr|jan|jegyz|júl|jún|kat|kb|Kbt|ker|kft|kgy|kht|kir|kiv|Kjt|kk(t)?|koll|korm|köv|kp|Kr|krt|Kt(v)?|ld|li(i|ii|v|x)?|Ltd|ltp|Ltv|luth|lv(i|ii|iii)?|lx(i|ii|iii|iv|ix|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii|xx|xxi|xxii|xxiii|xxiv|xxix|xxv|xxvi|xxvii|xxviii)?|ly|máj|márc|mat|max|mb|megh|megj|MHSz|min|mk|Mo|Mt|NB|nov|ny(á)?|Nyilv|nyrt|okl|okt|olv|op|orsz|ort|ov(h)?|össz|Ötv|özv|Pf|pl(d)?|prof|prot|Ptk|pu|ref|rk(p)?|róm|röv|rt|sgt|spec|stb|sz(ept|erk)?|Szjt|szoc|Szt(v)?|szül|Tbj|tc|tel|tkp|tszf|tvr|ty|ua|ui|úm|ún|uo|Ve|Vhr|vi(i|ii)?|vö|vsz|Vt(v)?|xc(i|ii|iii|iv|ix|v|vi|vii|viii)?|xi(i|ii|v|x)?|xl(i|ii|iii|iv|ix|v|vi|vii|viii)?|xv(i|ii|iii)?|xx(i|ii|iii|iv|ix|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii)?|zrt)\.") + +# pattern for paragraph checking +paralcap = re.compile(u"(?u)^[a-zöüóőúéáűí].*[.?!] [A-ZÖÜÓŐÚÉÁŰÍ].*[.?!][)”]?$") + +[word] + +low [a-zöüóőúéáűí]+ + +^{low} <- paralcap.search(TEXT) and not abbrev.search(TEXT) -> = {low}.capitalize() # Hiányzó nagy kezdőbetű? + +# optional sentence capitalization + +^{low} <- option("cap") and not abbrev.search(TEXT) -> = {low}.capitalize() # Hiányzó nagy kezdőbetű? + +###################### központozás ################### + +[char] + +abc [a-zöüóűőúéáí] +ABC [A-ZÖÜÓŰŐÚÉÁÍ] +Abc {abc}|{ABC} +abc [a-zöüóűőúéáíA-ZÖÜÓŰŐÚÉÁÍ]+ +word [a-záéíóöőúüűA-ZÉÍÓÖŐÚÜŰ]\w* + +punct [?!,:;%‰‱°„”] + +"^[-—] " <- option("dash") -> "– " # A gondolatjel nagykötőjel \n http://hu.wikipedia.org/wiki/Nagykötőjel +" [-—]([ ,;])" <- option("dash") -> " –\1" # A gondolatjel nagykötőjel \n http://hu.wikipedia.org/wiki/Nagykötőjel +# És - hogy is mondjam -, jó. -> És – hogy is mondjam –, jó. + +^[-–]{word} <- option("dash") -> – {word} # Gondolatjel szóközzel a felsorolásnál \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#258. + +"[[][.][.][.]]" <- option("elli") -> […] # Három pont \n http://hu.wikipedia.org/wiki/Három_pont +# [...] -> […] +[.][.][.] <- option("elli") -> … # Három pont \n http://hu.wikipedia.org/wiki/Három_pont +# Vége... -> Vége… + +" +([.?!,:;)”])\b" -> "\1 " # Felcserélt szóköz és írásjel? +" +([.?!,:;)”])" -> \1 # Szóköz nélkül tapadó írásjel \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#239. +# A ( kicsit ) más. -> A (kicsit) más. + +E ( |$) # space or end of sentence +"[:,;]([.?!,;:]){E}" -> \1{E} # Felesleges írásjel. +"\b[.][.]{E}" -> .{E}\n…{E} # Pont vagy három pont? \n http://hu.wikipedia.org/wiki/Három_pont +#"\b[.]([?!]){E}" -> \1{E} # Felesleges írásjel. +# És,, stb.? -> És, stb.? +# És.. -> És.\n… + +(\w){punct}{Abc} -> \1{punct} {Abc} # Hiányzó szóköz? +{abc}[.]{ABC} -> {abc}. {ABC} # Hiányzó szóköz? +# macska,bár -> macska, bár +# macska.Bár -> macska. Bár + +(^|\b|{punct}|[.]) {2,3}(\b|$) <- option("spaces") -> "\1 " # Felesleges szóköz. +# dupla szóköz. Itt három. -> dupla szóköz. Itt három. + +(^|\b|{punct}|[.]) {4,}(\b|$) <- option("spaces2") -> "\1 \n\1 " # Szóközök cseréje egy szóközre vagy tabulátorra: + +(?i)(\d+)(x| x )(\d+(-\w+)?) -> \1×\3\n\1 · \3 # Szorzásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#275. +# 5 x 6 -> 5 × 6 +# 800x600-as -> 800×600-as + +a {abc}+ +b {abc}* +(?i){a}['´]{b} <- option("apost") -> {a}’{b} # Valódi aposztróf. \n http://hu.wikipedia.org/wiki/Aposztróf +# biz' isten -> biz’ isten + +# ’79-ben + +['´](\d\d(-\w+)?) <- option("apost") -> ’\1 # Valódi aposztróf. \n http://hu.wikipedia.org/wiki/Aposztróf + +[)] <- option("par") and not "(" in TEXT -> # Felesleges zárójel? + +######################## idézés ###################### + +(?i)[\"“”‟„]({abc}[^\"“”‟„]*)[\"“‟] <- option("quot") -> „\1” # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel +(?i)[\"“”‟]({abc}[^\"“”‟„]*)[\"“”‟] <- option("quot") -> „\1” # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel +# A "kicsi" macska. -> A „kicsi” macska. + +# ASCII idézőjelek cseréje (,,vmi'', >>vmi<<) + +(?i),,({abc}[^\"“”‟„><']*)'' -> „\1” # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel +(?i)>>({abc}[^\"“”‟„><']*)<< -> »\1« # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel + +# angolszász idézőjelek cseréje + +(?i)‘+({abc}[^\"“”‟„’]*)’+ -> „\1”\n»\1« # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel + +[Word] + +"([(„»]) +" -> \1 # Szóköz nélkül tapadó írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#239. + +" +([«])" -> \1 # Szóköz nélkül tapadó írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#239. + +(?i)«({abc}[^\"“”‟„’]*)» -> »\1« # Felcserélt belső idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel + +############### pénz ################################# + +[Word] + +# 1 Ft (azaz két forint) -> 1 Ft (azaz egy forint) +# 200.000,- Ft, azaz egyszázezer forint -> 100.000,- Ft, azaz kétszázezer forint + +(\d[\d .]*)(,?(?:[-–]|00?)? Ft(?:-\w+)?(?: \(|, )(?:azaz|vagyis) )([-\w]+)( forint\w*\)?) <- option("money") and + # test NUMBERTEXT function access + calc("NUMBERTEXT", ("1", "hu")) and + calc("NUMBERTEXT", (re.sub(u"[ .]", "", \1), "hu")).replace(u"kettő", u"két").replace(u"ezeregyszáz", u"ezerszáz") != + # változatok: száz vagy egyszáz, ezer vagy egyezer, kettő vagy két + re.sub(ur"\begy(száz|ezer)", r"\g<1>", \3).replace(u"ezeregyszáz", u"ezerszáz").replace(u"kettő", u"két") + -> = \1 + \2 + calc("NUMBERTEXT", (re.sub(u"[ .]", "", \1), "hu")) + \4 + # A két összeg nem egyezik. + +######################## számok ###################### + +[Word] + +# nagy számok tagolása nem törő szóközökkel (U+00A0) +d1 −?\d{1,3} # 1, 2 vagy 3 számjegy (opcionális mínusszal) +d2 −?\d{2,3} # 2 vagy 3 számjegy (opcionális mínusszal) +d3 \d{3} # 3 számjegy +dn \d{3}(,\w{1,4})?[%‰‱°]?(-\w+)? # 3 számjegy, toldalékkal is +{d2}{dn} <- option("numpart") and not option("thou") -> {d2} {dn} # Nagy számok tagolása. (AkH. 274.) +{d1}{d3}{dn} <- option("numpart") and not option("thou") -> {d1} {d3} {dn} # Nagy számok tagolása. (AkH. 274.) +{d1}{d3}{d3}{dn} <- option("numpart") and not option("thou") -> {d1} {d3} {d3} {dn} # Nagy számok tagolása. (AkH. 274.) +# Az 1234567890 -> Az 1 234 567 890 + +# nagy számok tagolása nem törő keskeny szóközökkel (U+202F) (thou opciótól függően) +{d2} ?{dn} <- option("numpart") and option("thou") -> {d2} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.) +{d1} ?{d3} ?{dn} <- option("numpart") and option("thou") -> {d1} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.) +{d1} ?{d3} ?{d3} ?{dn} <- option("numpart") and option("thou") -> {d1} {d3} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.) + +# nagy számok tagolása nem törő szóközökkel (U+00A0) +d1 \d{1,3} # 1, 2 vagy 3 számjegy (opcionális mínusszal) +d2 \d{2,3} # 2 vagy 3 számjegy (opcionális mínusszal) +d3 \d{3} # 3 számjegy +dn \d{3}(,\w+)?[%‰‱°]?(-\w+)? # 3 számjegy, toldalékkal is +-{d2}{dn} <- option("numpart") and not option("thou") -> −{d2} {dn} # Nagy számok tagolása. (AkH. 274.) +-{d1}{d3}{dn} <- option("numpart") and not option("thou") -> −{d1} {d3} {dn} # Nagy számok tagolása. (AkH. 274.) +-{d1}{d3}{d3}{dn} <- option("numpart") and not option("thou") -> −{d1} {d3} {d3} {dn} # Nagy számok tagolása. (AkH. 274.) + +# nagy számok tagolása nem törő keskeny szóközökkel (U+202F) +-{d2} ?{dn} <- option("numpart") and option("thou") -> −{d2} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.) +-{d1} ?{d3} ?{dn} <- option("numpart") and option("thou") -> −{d1} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.) +-{d1} ?{d3} ?{d3} ?{dn} <- option("numpart") and option("thou") -> −{d1} {d3} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.) + + +([-−]?\d[\d,]*)[ ]([%‰‱°](-\w*)?) + -> \1\2 # Szóköz nélkül tapadó írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#275. +([-−]?\d\d*)[.](\d\d*)([%‰‱°](-\w*)?) <- option("comma") + -> \1,\2\3 # Tizedesvessző a helyes írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#291. +(\d\d*)[.](\d) + # kivéve, ha tulajdonnév előzi meg (pl. Firefox 3.5 + <- option("comma") and (not word(-1) or not re.match("[A-Z]", word(-1))) + -> \1,\2\n\1.\2. # Tizedestört (AkH. 291.) vagy sorszám? +((\d\d*[.]){2}\d) + # kivéve, ha tulajdonnév előzi meg (pl. Hunspell 1.2.8 + <- option("comma") and not word(-1) or not re.match("[A-Z]", word(-1)) + -> \1. # A sorszámot pont követi. +(\d\d\d+)[.](\d\d) <- option("comma") + -> \1,\2\n\1.\2. # Tizedestört (AkH. 291.) vagy sorszám? +# 25.30˚, de 10.20-kor -> 25,30˚, de 10.20-kor +# 1.5 -> 1,5\n1.5. +# 123.5 -> 123,5\n123.5. + +# mínuszjel + +-(\d+([ ]\d\d\d){0,3}(,\d+)?[%‰‱°]?(-\w+)?) <- option("minus") -> −\1 # Mínuszjel kiskötőjel helyett. + +-(\d+([ ]\d\d\d){0,3})[.](\d+[%‰‱°]?(-\w+)?) <- option("minus") -> −\1,\2 # Mínuszjel és tizedesvessző. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#291. + +(−\d+([ ]\d\d\d){0,3})[.](\d+[%‰‱°]?(-\w+)?) -> \1,\2 # Tizedesvessző pont helyett. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#291. + +######################## fok ######################### + +[word] + +# 12°-kal + +([-−]?\d+(?:,\d+)?)[ ](°(-\w+)) -> \1\2 # Szóköz nélkül tapadó írásjel (AkH. 239.) + +# 12 °C-kal + +([-−]?\d+(?:,\d+)?)((°C|°F|℃|℉)(-\w+)?) -> \1 \2 # Nem törő szóközzel elválasztott mértékegység. + +######################## dátumok ##################### + +[word] + +year [12]\d\d\d +monthnum 0?[1-9]|1[012] +month január|február|március|április|május|június|július|augusztus|szeptember|október|november|december|jan[.]|febr[.]|márc[.]|ápr[.]|máj[.]|jún[.]|júl[.]|aug[.]|szept[.]|okt[.]|nov[.]|dec[.] +Month Január|Február|Március|Április|Május|Június|Július|Augusztus|Szeptember|Október|November|December +day [12]\d|3[01]|0?[1-9] + +notmonthposs (|[^-–jaáeé][a-zöüóűőúéáí]*) + +# 2010 június-július +notmonthcomp [-–]{month}{notmonthposs} + +# XXX: sentence boundary modification +\b{year}[.] {Month}\b -> = {year} + ". " + {Month}.lower() # A hónap nevét kisbetűvel írjuk. (AkH. 144.) + +year2 \d\d + +{year} {month}{notmonthposs} -> {year}. {month}{notmonthposs} # Az évszám után itt pontot írunk. \n \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294. +{year} {month}{notmonthcomp} -> {year}. {month}{notmonthcomp} # Az évszám után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294. +{year} évi -> {year}. évi # Az évszám után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294. +{year}[-–]{year2} évi -> {year}–{year2}. évi # Az évszám után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294. +# 2005 január -> 2005. január +# 1999 augusztusban -> 1999. augusztusban +# 2009-10 évi -> 2009–10. évi + +nu folyamán|előtti?|utáni?|közötti?|nyara|nyará\w+|tele|telé\w+|tavasza|tavaszá\w+|ősze|őszé\w+ +\b{year}[.] {nu}\b -> {year} \g<nu> # Az évszám után itt nem írunk pontot. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#295. +# 1974. előtti -> 1974 előtti + +monthposs ([jaáe]|é\w)\w* + +\b{year}[.] {month}{monthposs}\b -> {year} {month}{monthposs} # Az évszám után itt nem írunk pontot. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#295. +# 1999. augusztusában -> 1999 augusztusában + +[char] + +optdot ([.]|) +text [^\s][^\s]* +w \w* +djel [ ,;:?!] + +(?i)\b{month} {day}[.]-{w} -> {month} {day}-{w} # A nap után itt nem írunk pontot. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#296. +(?i)\b{month} {day}{djel} -> {month} {day}.{djel} # Ha dátum, hiányzik a pont. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#296. +# március 15.-én -> március 15-én +# március 15 volt. -> március 15. volt. + + +nu óta|előtti?|utáni?|közötti? +(?i)\b{month} {day} {nu} -> {month} {day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297. +# március 15 óta -> március 15. óta +(?i)\b{month} {day}[.] és {day} {nu} -> {month} {day}. és {day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297. +(?i)\b{month} {day} és {day}[.]? {nu} -> {month} {day}. és {day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297. +# március 15. és 27 között -> március 15. és 27. között +# március 15 és 27. között -> március 15. és 27. között +# március 15 és 27 között -> március 15. és 27. között +(?i)\b{month} {day}[-–]{day} {nu} -> {month} {day}–{day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297. +(?i)\b{month} {day}-{day}. {nu} -> {month} {day}–{day}. {nu} # A napok közé nagykötőjelet írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297. +# március 15-22. között -> március 15–22. között +# március 15-22 között -> március 15–22. között + +\b{year}[.]{monthnum}[.]{day}{optdot}{text} -> {year}. {monthnum}. {day}{optdot}{text} # Szóköz a dátumban. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#293. +# 2009.05.12. -> 2009. 05. 12. + +# 1. = elseje +e e|i|ei\w*|é\w+ +(?i){month} 1[.]?-{e}\b -> {month} 1-j{e} # Elseje számjegyes írása. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#296. +# május 1-i -> május 1-ji +# május 1-ei -> május 1-jei +# május 1-én -> május 1-jén +# április 1-étől május 1-ig -> április 1-jétől május 1-ig + + +########################## stb. ###################### + +#W \w+ # word +# tagmondatok és mondatrészek megkülönböztetéséhez mondatelemzés kell +#([(]|\w+: )(({W}, )+{W};( {W}[,;])* {W})[,]? stb. -> \1\2; stb. # Stb. előtt itt pontosvessző van. (AkH. 247/b) \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#247. +#([(]|\w+: )(({W}, )*{W}), stb. -> \1\2 stb. # Stb. előtt itt nincs vessző. (AkH. 247/d) \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#247. +\bstb[.], stb[.] -> stb. stb.\nstb.; stb. # Két stb. közé nem teszünk vesszőt. +## Madarak: rigó, cinke, veréb, stb. -> Madarak: rigó, cinke, veréb stb. +## Állatok (rigó, cinke; nyúl, pocok stb.) -> Állatok (rigó, cinke; nyúl, pocok; stb.) +# stb., stb. -> stb. stb.\nstb.; stb. + +#################### rövidítések ##################### + +[word] + +(db|Ft)[.](?= {abc}) -> \1 # Nem ponttal írjuk ezt a rövidítést. +(db|Ft)[.](?=[,;:]) -> \1 # Nem ponttal írjuk ezt a rövidítést. +# 25 db. vmi -> 25 db vmi + +##################### nagykötőjel #################### + +[char] + +country albán|amerikai|angol|belga|bolgár|bosnyák|brit|ciprusi|cseh|dán|észt|finn|francia|görög|holland|horvát|ír|japán|kínai|lengyel|lett|litván|macedón|magyar|máltai|német|norvég|olasz|orosz|osztrák|portugál|román|spanyol|svájci|svéd|szerb|szlovák|szlovén|török|ukrán +(?i)\b{country}-{country}\b -> {country}–{country} # Népnevek közé nagykötőjelet teszünk. +# magyar-német -> magyar–német + +# year2: Az 1000-1500 vagylagos összetételek kizárására +year2 (1\d\d[1-9]|1\d[1-9]\d|20\d[1-9]|20[1-9]\d) +"\b{year2}-{year}\b " -> "{year}–{year} " # Évszámok közé nagykötőjelet teszünk. +"\b{year}-{year2}\b " -> "{year}–{year} " # Évszámok közé nagykötőjelet teszünk. +"\b{year}-(\d\d)\b " -> "{year}–\2 " # Évszámok közé nagykötőjelet teszünk. +# 1998-2000 -> 1998–2000 +# 1998-99 -> 1998–99 + +([A-ZÖÜÓŰŐÚÉÁÍ]\w*)-(\d+(-\w+)?) -> \1–\2 # Típusnév és -szám közé nagykötőjelet teszünk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#263. +# UTF-8 -> UTF–8 +# Apolló-13-nak -> Apolló–13-nak + +pp[.] (\d+)-(\d+)[.] -> pp. \1–\2. # Oldalszámok közé nagykötőjelet teszünk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#263. +(\d+)-(\d+)[.] (o[.]|oldal\w*) -> \1–\2. \3 # Oldalszám +# 10-12. oldalon -> 10–12. oldalon + +" (u[.]|utca|út|tér) (\d\d*)-(\d\d*)[.]" -> " \1 \2–\3." # Nagykötőjel a házszámban. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#298. +# Széna tér 123-125. -> Széna tér 123–125. + + +###################### helyesírás #################### + +[Word] + +ne játs(zunk|zatok|zanak) -> ne játss\1 # Helyesírási hiba. + +###################### kifejezések ################### + +[Word] + +[aá] la carte -> à la carte # Helyesen à la carte. +(állta(ss\w*|t\w*)) <- not morph(\1, "pa:") -> álta\2 # Áltat, hiteget értelemben egy l-lel írjuk. +önáll(tat[óá]\w*) -> önál\1 # Helyesen egy l-lel. +belsőséges -> bensőséges\nbelsőségből készült # Szótévesztés vagy szójáték? +dehogy is -> dehogyis # Egybeírás „egyáltalán nem” jelentésben. +dehogy nem -> dehogynem # Egybeírás „de igen” jelentésben. +dehogyis nem -> dehogyisnem # Egybeírás „de igen” jelentésben. +eképpen -> ekképpen # Helyesen két k-val. +egyel (több\w*|kevesebb\w*) -> eggyel \1 # 1-gyel értelemben hosszú gy-vel írjuk. +egyenlőre -> egyelőre\negyformára\ndöntetlenre\negyenlő számúra\nazonos méretűre # Helyesírási (egyelőre) vagy stílushiba (egyformára). +egyi(vású\w*) -> egyí\1 # Hosszú í-vel helyes. +egytől-egyig -> egytől egyig # Kötőjel nélkül írjuk. +előre hátra -> előre-hátra # Kötőjellel írjuk. +előre láthatólag -> előreláthatólag # Egybeírás. +email: -> e-mail: # e-mail (elektronikus levél) +email-lel -> e-maillel # e-mail (elektronikus levél) +e(mail[ -]|-mail-|-mail)(cím\w*) -> e-mail \2 # Helyesen e-mail cím. +ex[- ](\w+) <- spell("ex" + \1) -> ex\1 # Egybeírás. +figyelemre(méltó\w*) <- word(-1) != "igen" -> figyelemre \1 # Különírás (kivéve: „igen figyelemreméltó”). +igen figyelemre (méltó\w*) -> igen figyelemre\1 # Egybeírás. +(állat|csepp|csillag|ék|ellipszis|ember|félgömb|félkör|gáz|gömb|gúla|harang|háromszög|hasáb|hatszög|henger|kagyló|kereszt|kocka|korong|kör|körte|kúp|négyszög|négyzet|nyereg|patkó|piramis|piskóta|szivar|tojás|tölcsér|trapéz|vese)(formájú|alakú) -> \1 \2 # Különírás. +fő(irány\w*|közlekedés\w*|szabály\w*|szervező\w*) -> fő \1 # A „fő mű”-höz hasonlóan különírjuk. +hátba (támadás\w*) -> hátba\1 # Egybeírás. +időről-időre -> időről időre # Különírás. +jing és jang -> jin és jang # Helyesen jin és jang. +kőr((öz|út|ut)\w*) <- morph(\0, ur"st:kőr\b") -> kör\1 # Rövid ö-vel a kör összetételeiben. +légyszíves -> légy szíves\nlegyél szíves # Legyél szíves értelemben különírjuk. +legalább is -> legalábbis # Egybeírás. +Lichten(stein\w*) -> Liechten\1 # Helyesen Liechtenstein. +mellékhely(ség\w*) -> mellékhelyi\1 # Helyiség, mint szoba. +mú(landó\w*) -> mu\1 # Helyesen rövid u-val. +nembiztos -> nem biztos # Különírás. +originált -> originál\neredeti\nbontatlan # Ha nem tárgyesetben van, „t” nélkül írjuk. +(szén|kén|mangán|nitrogén|ón|titán|tórium)(dioxid\w*) -> \1-\2 # Kötőjeles alak. +(szén|kén|nitrogén)(monoxid\w*) -> \1-\2 # Kötőjeles alak. +továbbittunk -> továbbítunk\ntovább ittunk # Helyesírási hiba. + +[char] + +# Mivel az "un." rövidítésként szerepel az OpenOffice.org-ban, nagybetűs folytatás esetén nem húzzuk alá +\bun[.] <- word(1) and not re.match(u"[A-ZÖÜÓŰŐÚÉÁÍ]", word(1)) -> ún. # Úgy nevezett rövidítése ún. (AkH. 282.) +(?i)\bvíz(hang\w*)\b -> vissz\1 # Szótévesztés? + +#################### nyelvtani szabályok ################## + +# az "a" névelő (kivétel: a 4. a osztályban, a II. világháború, az A alaphang...) +a [aA] +aword [aáeéiíoóöőuúüűAÁEÉIÍOÓÖŐUÚÜŰ]\w* +^[aA] {aword} <- not re.match(r"(?i)i(ii?|[vx])$|Unicode$|Unix\w*$", {aword}) and spell({aword}) -> az {aword} # Hibás névelő? +(?<!(\d[.]|az) )\b{a} {aword} <- word(-1) and not re.match(r"(?i)i(ii?|[vx])$|Unicode$|Unix\w*$", {aword}) and + spell({aword}) -> {a}z {aword}\n{aword} # Hibás vagy felesleges névelő? +# A 4. a osztály a órán az A alaphangot -> A 4. a osztály az órán\nórán az A alaphangot + +# névelők és számok + +[Word] + +a <- word(1) and re.match(r"(1|5\d*|[15]\d\d\d)[.]?$", word(1)) -> az # Hibás névelő. + +az <- not option("grammar") and word(2) and + re.match(ur"(alfejezet|alszakasz|ábr|bekezdés|diagram|fejezet|kép|lap|oldal|paragrafus|szakasz|táblázat)\w*", word(2)) and + re.match(r"([02-46-9]|[1-46-9]\d|[1-46-9]\d\d|[2346-9]\d\d\d)[.]", word(1)) -> a # Hibás névelő? + +az <- option("grammar") and word(1) and + re.match(r"([02-46-9]|[1-46-9]\d|[1-46-9]\d\d|[2346-9]\d\d\d)[.]", word(1)) -> a # Hibás névelő? + +# g = gramm + +num \d+|\d+,\d+ +{num} gr[.]?-mal -> {num} g-mal # grammal rövidítése g-mal (AkH. 286.) +# 25 gr-mal -> 25 g-mal +# 25,2 gr.-mal -> 25,2 g-mal + +[char] + +hw [a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ][a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ]* + +" A vitamin{w}" -> " A-vitamin{w}" # Kötőjeles név. + +[word] + +([B-Z]) vitamin{w} -> \1-vitamin{w} # Kötőjeles név. +([A-Z])-(vitamin)(\w+) <- morph(\2+\3, "pa:") -> \1-vitamin-\2 # Két kötőjellel írt alak. +# vitaminhiány külön szerepel a szótárban, ezért szóköz nélkül is javítani kell +([A-Z])-(vitamin) *(hiány) -> \1-\2-\3 # Két kötőjellel írt alak. + + +[char] + +(?i)\bnyílt szívű{w} -> nyíltszívű{w} # Egybeírás. +(?i)\bjó szándékú{w} -> jószándékú{w} # Egybeírás. +(?i)közös lónak túrós -> közös lónak túros # Helyes kifejezés. +(?i)\bnejlon harisnya\b -> nejlonharisnya # Egybeírás. +(?i)\boda-vissza{hw} -> oda-vissza {hw} # Különírás. +(?i)\bpro és kontra\b -> pró és kontra # Helyes latin kifejezés. +(?i)\brákövetkez{hw} -> rá következ{hw} # Különírás. +(?i)\btáj jellegű{w} -> tájjellegű{w} # Egybeírás. +(?i)([stluv])-alakú{w} -> \1 alakú{w} # Különírás. +# B vitamin -> B-vitamin +# Pro és kontra -> Pró és kontra +# oda-visszamentek -> oda-vissza mentek +# S-alakúakat -> S alakúakat + +(\d\d*)-szobás{w} -> \1 szobás{w} # Különírás. +(\d\d*)-részes{w} -> \1 részes{w} # Különírás. +# 5-szobásat -> 5 szobásat + +[word] + +event (Advent|Húsvét|Karácsony|Mindenszentek|Pünkösd|(Anyák|Apák|Halottak|Nők) [Nn]apj){abc}* +{event} <- word(-1) and word(1) == word(1).lower() -> = {event}.lower() # Kisbetűs kifejezés, ha nem cím. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_kis_és_a_nagy_kezdőbetűk#145. +# Nemsokára Anyák napja. -> Nemsokára anyák napja. + +[char] + +kw ([-][a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ][a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ]*)? + +foci ([Ev])[bB]{kw} -> foci-\1b{kw} # Kötőjeles kifejezés. +# foci EB -> foci-Eb +# foci vb-ről -> foci-vb-ről + +^Kétség kívül -> Kétségkívül # Egybeírás. +# Kétség kívül -> Kétségkívül + +[Word] + +alig alig -> alig-alig # Kötőjeles szókettőzés. (AkH. 97.) +ki ki -> ki-ki # Kötőjeles szókettőzés. (AkH. 97.) +is is -> is-is # Kötőjeles szókettőzés. (AkH. 97.) +kinek kinek -> kinek-kinek # Kötőjeles szókettőzés. (AkH. 97.) +körbe körbe -> körbe-körbe # Kötőjeles szókettőzés. (AkH. 97.) +közbe közbe -> közbe-közbe # Kötőjeles szókettőzés. (AkH. 97.) +külön külön -> külön-külön # Kötőjeles szókettőzés. (AkH. 97.) +már már -> már-már # Kötőjeles szókettőzés. (AkH. 97.) +más más -> más-más # Kötőjeles szókettőzés. (AkH. 97.) +messze messze -> messze-messze # Kötőjeles szókettőzés. (AkH. 97.) +nagyon nagyon -> nagyon-nagyon # Kötőjeles szókettőzés. (AkH. 97.) +néha néha -> néha-néha # Kötőjeles szókettőzés. (AkH. 97.) +olykor olykor -> olykor-olykor # Kötőjeles szókettőzés. (AkH. 97.) +túl túl -> túl-túl # Kötőjeles szókettőzés. (AkH. 97.) +sok sok -> sok-sok # Kötőjeles szókettőzés. (AkH. 97.) +úgy úgy -> úgy-úgy # Kötőjeles szókettőzés. (AkH. 97.) + +csip csup -> csip-csup # Kötőjeles ikerszó. (AkH. 103.) +éhen szomjan -> éhen-szomjan # Mellérendelő szókapcsolat. (AkH. 100.) +ingó bingó -> ingó-bingó # Kötőjeles ikerszó. (AkH. 103.) +sebbel lobbal -> sebbel-lobbal # Mellérendelő szókapcsolat. (AkH. 100.) +szegről végről -> szegről-végről # Mellérendelő szókapcsolat. (AkH. 100.) +széltében hosszában -> széltében-hosszában # Mellérendelő szókapcsolat. (AkH. 100.) +szőröstül bőröstül -> szőröstül-bőröstül # Mellérendelő szókapcsolat. (AkH. 100.) +szőrén szálán -> szőrén-szálán # Mellérendelő szókapcsolat. (AkH. 100.) +télen nyáron -> télen-nyáron # Mellérendelő szókapcsolat. (AkH. 100.) +testestől lelkestől -> testestől-lelkestől # Mellérendelő szókapcsolat. (AkH. 100.) +testestül lelkestül -> testestül-lelkestül # Mellérendelő szókapcsolat. (AkH. 100.) +többé kevésbé -> többé-kevésbé # Mellérendelő szókapcsolat. (AkH. 100.) +törik szakad -> törik-szakad # Mellérendelő szókapcsolat. (AkH. 100.) +tűzön vízen -> tűzön-vízen # Mellérendelő szókapcsolat. (AkH. 100.) +tűzzel vassal -> tűzzel-vassal # Mellérendelő szókapcsolat. (AkH. 100.) +véges végig -> véges-végig # Mellérendelő szókapcsolat. (AkH. 100.) +tüskén bokron -> tüskén-bokron # Mellérendelő szókapcsolat. (AkH. 100.) +végre valahára -> végre-valahára # Mellérendelő szókapcsolat. (AkH. 100.) +imígy amúgy -> imígy-amúgy # Mellérendelő szókapcsolat. (AkH. 100.) +innen onnan -> innen-onnan # Mellérendelő szókapcsolat. (AkH. 100.) +itt ott -> itt-ott # Mellérendelő szókapcsolat. (AkH. 100.) +ízig vérig -> ízig-vérig # Mellérendelő szókapcsolat. (AkH. 100.) +ízzé porrá -> ízzé-porrá # Mellérendelő szókapcsolat. (AkH. 100.) +jajjal bajjal -> jajjal-bajjal # Mellérendelő szókapcsolat. (AkH. 100.) +jóban rosszban -> jóban-rosszban # Mellérendelő szókapcsolat. (AkH. 100.) +jobbra balra -> jobbra-balra # Mellérendelő szókapcsolat. (AkH. 100.) +jól rosszul -> jól-rosszul # Mellérendelő szókapcsolat. (AkH. 100.) +kékre zöldre -> kékre-zöldre # Mellérendelő szókapcsolat. (AkH. 100.) +kénytelen kelletlen -> kénytelen-kelletlen # Mellérendelő szókapcsolat. (AkH. 100.) +kézen közön -> kézen-közön # Mellérendelő szókapcsolat. (AkH. 100.) +körös körül -> körös-körül # Mellérendelő szókapcsolat. (AkH. 100.) +kézzel lábbal -> kézzel-lábbal # Mellérendelő szókapcsolat. (AkH. 100.) +kurtán furcsán -> kurtán-furcsán # Mellérendelő szókapcsolat. (AkH. 100.) +lépten nyomon -> lépten-nyomon # Mellérendelő szókapcsolat. (AkH. 100.) +menet jövet -> menet-jövet # Mellérendelő szókapcsolat. (AkH. 100.) +nyakra főre -> nyakra-főre # Mellérendelő szókapcsolat. (AkH. 100.) +örökkön örökké -> örökkön-örökké # Mellérendelő szókapcsolat. (AkH. 100.) +sülve főve -> sülve-főve # Mellérendelő szókapcsolat. (AkH. 100.) +úton útfélen -> úton-útfélen # Mellérendelő szókapcsolat. (AkH. 100.) +üggyel bajjal -> üggyel-bajjal # Mellérendelő szókapcsolat. (AkH. 100.) +# alig alig -> alig-alig +# Úgy úgy -> Úgy-úgy + +# ágat-bogat + +(ág\w*) (bog\w*) <- stem(\1) == [u"ág"] and stem(\2) == ["bog"] -> \1-\2 # Kötőjeles ikerszó. (AkH. 103.) + +###################### Földrajzi nevek ###################### + +[word] + +(Északi|Déli)(?:-S| [Ss])ark{w} -> \1-sark{w} # Földrajzi név. +# Az Északi sarkon -> Az Északi-sarkon # Földrajzi név. +# Az Északi-Sarkon -> Az Északi-sarkon # Földrajzi név. + +dir észak|dél|kelet|nyugat|északkelet|északnyugat|délkelet|délnyugat +Dir Észak|Dél|Kelet|Nyugat|Északkelet|Északnyugat|Délkelet|Délnyugat +cap {ABC}{abc}+ +sc {abc}+ +w {Abc}+ + +# Észak-Amerikai Észak-amerikai helyett + +{Dir}-{cap} <- morph({cap}, r"po:noun_prs.*is:i_PLACE", False) -> = {Dir} + "-" + {cap}.lower() # Kisbetűvel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179. + +# észak-Amerika Észak-Amerika helyett + +{dir}-{cap} <- morph({cap}, r"po:noun_prs", False) and not morph({cap},"is:i_PLACE", False) -> + = {dir}.capitalize() + "-" + {cap} # Nagybetűvel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179. + +# Észak-amerikai csak akkor nagybetűs, ha mondatkezdő és nem nagybetűs az utána jövő szó + +{Dir}-{sc} <- word(-1) and word(1) and not word(1) == word(1).capitalize() and + morph({sc}, r"po:noun_prs.*is:i_PLACE", False) -> = {Dir}.lower() + "-" + {sc} # Kisbetűvel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179. + +# hiányzó kötőjel + +{Dir} {w} <- morph({w}, r"po:noun_prs") -> {Dir}-{w} # Kötőjellel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179. + +# köznevek + +prop Tenger|Óceán|Sziget|Félsziget|Középhegység + +{cap}-{prop} -> = {cap} + "-" + {prop}.lower() # Kisbetűs írt köznévi tag. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#176. + +# AkH. 182. + +(Árpád|Erzsébet|Hajógyári|Margit|Megyeri|Petőfi|Rákóczi|Szabadság)-(híd\w*) -> \1 \2 # Különírás. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#182. +(Szabadság)(híd\w*) -> \1 \2 # Különírás. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#182. +(Szabadság ?)(szobo?r\w*) -> \1-\2 # Kötőjeles összetétel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A különírás és az egybeírás#140. + +# AkH. 183. + +(Fertő)-(([tT]ó|[tT]av)\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183. +(Góbi|Kalahári|Szahara)-([sS]ivatag\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183. +(Börzsöny|Bükk|Mátra|Mecsek|Pilis|Zemplén|Vértes)-([Hh]egység\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183. +(Duna)-(folyam\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183. +(Bodrog|Duna|Dráva|Ipoly|Körös|Maros|Rába|Sajó|Tisza|Zala)-(([Ff]olyó|[Ff]olyam)\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183. + +Budapest (Liszt Ferenc )([Nn]emzetközi [Rr]epülőt[eé])(r\w*) -> = + \1 + \2.lower() + \3 + + "\nferihegyi " + \1 + \2.lower() + \3 + "\n" + + \3.replace("r", "Ferihegy", 1).replace("gyrel", "ggyel").replace(u"gyré", u"ggyé") + + "\nBudapest, " + \1 + \2.lower() + \3 + # A köznévi tag kisbetűs, a címet vesszővel tagoljuk. (AkH. 190., 247.; FNB 74.) \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#247. + +########################## vesszők ########################## + +(olya\w+) (aki\w*|ami\w*) <- morph(\2, r"st:(aki|ami|amilyen)\b") -> \1, \2 # Hiányzó vessző a tagmondatok határán? + +##################### nyelvtani szabályok ################### + +W \w+ # word +W2 \w+ # word + +############### egybeírt segédigék és igekötők ############# +# megszabad csinálni -> meg szabad csinálni +# megtudta volna tenni -> meg tudta volna tenni +# megfogja majd tudni -> meg fogja majd tudni +# megszeretném még enni -> meg szeretném még enni +# -> Megpróbálom megcsinálni. + +igekoto abba|agyon|alá|által|át|be|bele|benn|egybe|együtt|el|ellen|elő|előre|fel|föl|félbe|félre|felül|fölül|fenn|fönn|hátra|haza|helyre|hozzá|ide|jóvá|keresztül|ketté|ki|kölcsön|körbe|körül|közbe|közre|külön|le|meg|mellé|neki|oda|össze|rá|rajta|széjjel|szembe|szerte|szét|tele|tova|tovább|túl|újjá|újra|utána|végbe|végig|vissza +segedige (akar|bír|fog|legy|lehet|lenn|lesz|lett|szabad|szeret|talál|tud|van|vol)\w* +szavak ( \w+){0,} +igenev (\w+ni) + +[Word] + +{igekoto}{segedige}{szavak} {igenev} + <- morph({igenev}, "INFINITIVE") and + morph({igekoto}+{segedige}, r"is:[/\w]*DEF|ds:tt") + -> {igekoto} {segedige}{szavak} {igenev} # Az igekötőt nem írjuk egybe a segédigével. + +# elvan ez már rég felejtve +letige (legy|lehet|lenn|lesz|lett|van|vol)\w* +igenev (\w+v[ea]) + +{igekoto}{letige}{szavak} {igenev} + <- morph({igenev}, "_PART") and + morph({igekoto}+{letige}, r"is:[/\w]*DEF|ds:tt") + -> {igekoto} {letige}{szavak} {igenev} # Az igekötő a lenni + -va/-ve szerkezetben nem a létigéhez kapcsolódik. + +############### had -> hadd ################ +# Eltusolták az ügyet. -> Eltussolták az ügyet. +# Had legyen meglepetés! -> Hadd legyen meglepetés! + +(had|hagy)( (ne )?){W} <- morph({W}, r"(IMPER[_\w]*SG_1|is:[_/\w]*DEF_PL)") or + (not word(-1) and morph({W}, r"is:[_/\w]*DEF_SG_[23]")) + -> \1d\2{W} # Hadd helyesen. + +############### *Áld meg! stb. ################### +(\w+[lnrz]d) {igekoto} <- (not word(-1) or word(-1).lower() == "ne") and + morph(\1, "st:" + \1.lower() + r"\b") and morph(\1+"d", r"IMPER") -> \1d \2 # Felszólító mód. + +############### kér, kérd ######################## + +kérdd el -> kérd el # „kér” felszólító módja. + +############### megfedd, eltussol ########## +# Aztán jól megfedte. -> Aztán jól megfeddte. +# Eltusolták az ügyet. -> Eltussolták az ügyet. + +(megfe)(d\w*) <- morph(\1+\2, r"st:fed\b") -> \1d\2 # Megfedd helyesen. +(eltus)(ol\w*) <- morph(\1+\2, r"st:tusol\b") -> \1s\2 # Eltussol helyesen (kivéve, ha zuhanyzásról van szó). + +############## főkép -> főképp ############# +főké(p|pen) <- word(-1) != "a" and word(-1) != "A" + -> főkép\1 # Ha határozószó, akkor főképp. + +############# számok ###################### + +[char] + +\b0-á(\w+) -> 0-\1 # Hibás toldalék? +(\d*[14])-el\b -> \1-gyel # Hibás toldalék? +(\d*2)-ő(\w+) -> \1-\2 # Hibás toldalék? +(\d*3)-á\b -> \1-má # Hibás toldalék? +(\d*3)-al\b -> \1-mal # Hibás toldalék? +(\d*[57])-el\b -> \1-tel # Hibás toldalék? +(\d*6)-á\b -> \1-tá # Hibás toldalék? +(\d*8)-á\b -> \1-cá # Hibás toldalék? +(\d*9)-el\b -> \1-cel # Hibás toldalék? +(\d*10)-el\b -> \1-zel # Hibás toldalék? +(\d*20)-á\b -> \1-szá # Hibás toldalék? +(\d*30)-á\b -> \1-cá # Hibás toldalék? +(\d*[4579]0)-el\b -> \1-nel # Hibás toldalék? +(\d*[68]0)-á\b -> \1-ná # Hibás toldalék? +\b(\d)00-á\b <- \1 != "0" -> \100-zá # Hibás toldalék? +\b(\d)000-el\b <- \1 != "0" -> \1000-rel # Hibás toldalék? +#(\d*\d)0000-el\b <- \1 != "0" -> \1\2000-rel # Hibás toldalék? +#(\d*)(\d)00000-el\b <- \1 != "0" -> \1\2000-rel # Hibás toldalék? + +############## több mint ####################### +# több, mint testőr -> több mint testőr XXX tavaly, délután stb. miatt nincs kezelve +# -> több, mint tavaly +# több, mint unalmas -> több mint unalmas +# több, mint kiváló -> több mint kiváló +# több, mint 70%-uk -> több mint 70%-uk +# több, mint négyen -> több mint négyen +# -> öt több, mint négy +# több, mint 25 ezren -> több mint 25 ezren +# több, mint két embert -> több mint két embert +# több, mint 9 embert -> több mint 9 embert +# több, mint 9 ezer fát -> több mint 9 ezer fát + +[Word] + +több, mint <- + # (több mint jó), több mint nyolcan, több mint 12-en + morph(word(1), r"(po:noun.*ds:s_\w*|po:adj|PRESPART_adj|po:adj_num.*(is:|An_MODE_adv))\b") or + # több mint 25 ezren, több mint 25 ezerről, több mint száz birkát + # (fix: "ezer" adj-ként is szerepel, ezért külön kezelve XXX) + (morph(word(1), r"(po:adj_num|^\d+$)") and morph(word(2), r"(po:noun\b.*is:|(po:adj_num|st:ezer\b).*(is:|An_MODE_adv))")) or + # több mint 25 ezer birkát + (re.match(r"\d+$", word(1)) and morph(word(2), r"po:adj_num|st:ezer\b") and morph(word(3), r"po:noun\b.*is:")) or + # több mint 75%-a + re.match(r"\d+%-", word(1)) -> több mint # Ha nem összehasonlítás, + hanem a mondanivaló erősítése, itt nem használunk vesszőt. \n + http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#243. + +############ avagy, illetve, ill., valamint ########## + +(\w+)( avagy) -> \1,\2 # Az avagy kötőszó elé vesszőt teszünk. +(\w+)( illetve) -> \1,\2 # Az illetve kötőszó elé vesszőt teszünk. +(\w+)( ill[.]) -> \1,\2\n\1, illetve # Az illetve kötőszó elé vesszőt teszünk. +(\w+)( valamint) -> \1,\2 # A valamint kötőszó elé vesszőt teszünk. + +############ mellet -> mellett ################## +# a fa mellet -> a fa mellett +# -> De! feszes mellet +mellet <- morph(word(-1), r"po:noun.*:NOM(?!.*[di]s:)|_noun\s+ts:NOM$") -> mellett # Nem inkább mellett (vagy hibás különírás)? + +############ kellet -> kellett ################## +# nem kellet volna -> nem kellett volna +kellet <- morph(word(-1), r"INF_|_inf") or morph(word(-2), r"INF_|_inf") -> kellett # Helyesírási hiba. +kellet <- morph(word(1), r"INF_|_inf") or morph(word(2), r"INF_|_inf") or word(1) == "volna" -> kellett # Helyesírási hiba. + +############### helyett kapott ####################### +# is helyett kapott -> is helyet kapott +# a csomagban helyett kapott -> a csomagban helyet kapott +(\w+) helyett (kap\w*) <- morph(\1, r"st:(is|ismét|mellett|még)\b|is:INE") and morph(\2, r"st:kap\b") -> \1 helyet \2 # Helyesen: helyet kap. + +############## halott -> hallott ################## + +(?<=[Nn]em )halott(am|unk) -> hallott\1 # Helyesírási hiba? + +(hal)(ott\w*)(?= róla\w*) -> \1l\2 # Helyesírási hiba? + +############### összetett szavak ################################# + +[Word] + +# rövid összetett szó + +W \w{4,5} +{W} <- option("compound") and morph({W}, "pa:") -> =suggest({W}) # Biztos, hogy helyes összetett szó? + +# rövid (kétbetűs) tagot tartalmazó összetett szó + +W \w{4,} +{W} <- option("compound") and morph({W}, ur"(?u)pa:\w\w\b") -> =suggest({W}) # Biztos, hogy helyes összetett szó? + +# minden képzett összetett szó + +{W} <- option("allcompound") and morph({W}, "pa:") -> =suggest({W}) # Biztos, hogy helyes összetett szó? + +############### vesszőhasználat ######################## + +############### Stílus ################################# + +[Word] +#asszem -> azt hiszem\nazt hiszem, hogy # Helyesírási hiba. +#h <- option("style") -> hogy # Hibás rövidítés? +#szar\w* <- option("style") and morph(\0, r"st:szar\b") -> rossz # Stílushiba. + +médiák <- option("style") -> médiák\nmédia\nhírek\nlapok\nhírcsatornák # Vitatott stílusértékű alak. +unszimpatikus <- option("style") -> unszimpatikus\nellenszenves\nantipatikus # Vitatott stílusértékű alak. + +# ezresek számjegyekkel + +#(\d{2,3})[ ]?000-(\w+) <- option("style") and (not word(-1) or not re.match("[0-9]+$", word(-1))) and spell("ezer" + \2) and not morph("ezer" + \2, "_adj") -> \1 ezer\2 # Ha szám, javasolt betűkkel írni. +#(\d{2,3})[ ]?000[ ]?000-(\w+) +# <- option("style") and (not word(-1) or not re.match("[0-9]+$", word(-1))) and spell(u"millió" + \2) -> \1 millió\2 # Ha szám, javasolt betűkkel írni. + +############### különírás ############################### + +[char] +" (-\w+)" <- option("wordpart") and morph(\0, "st:-e|po:(suffix|punct)") + -> \1 # A toldalékot szóköz nélkül írjuk. + +[Word] + +(a|az|egy) (\w+) (\w+) <- option("wordpart") and spell(\2 + \3) and + morph(word(1), "po:vrb") and + affix(\2, "ts:NOM$") and not morph(\2, "ts:PLUR") and + affix(\3, "[it]s:NOM$") -> \1 \2\3 # Hibás különírás? + +############### szóismétlés ############################### + +W [-\w]{3,} + +[word] + +{W} \1 <- option("dup0") and (not word(-1) or + not word(-1).lower() in ["a", "az", "minden"]) and word(1) != u"hátán" and word(1) != u"hátán." and + not morph(word(1), "po:post", False) -> {W}\n{W}-\1 # Szóismétlés vagy hiányzó kötőjel? + +{W}(?: [-–\w„”]+)* \1 <- option("dup") -> {W} # Túlzott szóismétlés? + +{W}[;,:]?(?: [-–\w„”]+[;,:]?)* \1 <- option("dup2") -> {W} # Túlzott szóismétlés? + +# toldalékolva is (de nem összetett szó) + +([-\w]{4})([-\w]+)(?: [-–\w„”]+)* \1(\w+) <- option("dup3") and + option("dup") and morph(\1+\2, r"(?u)st:\w+") == + morph(\1+\3, r"(?u)st:\w+") and not morph(\1+\3, "pa:") and not morph(\1+\2, "pa:") -> \1\2 # Túlzott szóismétlés? + +([-\w]{4})([-\w]+)[;,:]?(?: [-–\w„”]+[;,:]?)* \1(\w+) <- option("dup3") and + option("dup2") and morph(\1+\2, r"(?u)st:\w+") == + morph(\1+\3, r"(?u)st:\w+") and not morph(\1+\3, "pa:") and not morph(\1+\2, "pa:") -> \1\2 # Túlzott szóismétlés? + +################# ligatúrák ################################# + +[word] + +[-\w]*f[fil][-\w]* <- option("ligature") -> =\0.replace("ffi",u"ffi").replace("ffl",u"ffl").replace("ff",u"ff").replace("fi",u"fi").replace("fl",u"fl") + # A szó unicode-os f-ligatúrákkal: + +[-\w]*(ffi|ffl|ff|fi|fl)[-\w]* <- option("noligature") -> =\0.replace(u"ffi","ffi").replace(u"ffl","ffl").replace(u"ff","ff").replace(u"fi","fi").replace(u"fl","fl") + # A szó unicode-os f-ligatúrák nélkül: + + +################# indexek, törtek ############################## + +[word] + +1/2((-\w+)?) <- option("frac") -> ½\1 # Tipográfiai jel: +1/3((-\w+)?) <- option("frac") -> ⅓\1 # Tipográfiai jel: +1/4((-\w+)?) <- option("frac") -> ¼\1 # Tipográfiai jel: +3/4((-\w+)?) <- option("frac") -> ¾\1 # Tipográfiai jel: +2/3((-\w+)?) <- option("frac") -> ⅔\1 # Tipográfiai jel: +1/5((-\w+)?) <- option("frac") -> ⅕\1 # Tipográfiai jel: +1/6((-\w+)?) <- option("frac") -> ⅙\1 # Tipográfiai jel: +5/6((-\w+)?) <- option("frac") -> ⅚\1 # Tipográfiai jel: +1/8((-\w+)?) <- option("frac") -> ⅛\1 # Tipográfiai jel: +3/8((-\w+)?) <- option("frac") -> ⅜\1 # Tipográfiai jel: +5/8((-\w+)?) <- option("frac") -> ⅝\1 # Tipográfiai jel: +7/8((-\w+)?) <- option("frac") -> ⅞\1 # Tipográfiai jel: + +1/(\d{1,3})((-\w+)?) <- option("frac") -> = u"⅟" + \1.replace("0", u"₀").replace("1", u"₁").replace("2", + u"₂").replace("3", u"₃").replace("4", u"₄").replace("5", u"₅").replace("6", u"₆").replace("7", + u"₇").replace("8", u"₈").replace("9", u"₉") + \2 # Tört tipográfiai jelekkel: + +([2-9]|\d{2,3})/(\d{1,3})((-\w+)?) <- option("frac") -> = \1.replace("0", u"⁰").replace("1", u"¹").replace("2", u"²").replace("3", + u"³").replace("4", u"⁴").replace("5", u"⁵").replace("6", u"⁶").replace("7", u"⁷").replace("8", u"⁸").replace("9", u"⁹") + + u"⁄" + \2.replace("0", u"₀").replace("1", u"₁").replace("2", u"₂").replace("3", u"₃").replace("4", + u"₄").replace("5", u"₅").replace("6", u"₆").replace("7", u"₇").replace("8", u"₈").replace("9", u"₉") + \3 # Tört tipográfiai jelekkel: + +[µmck]?m[23](-\w+)? <- option("idx") -> =\0.replace("2", u"²").replace("3", u"³") # Index tipográfiai jellel: + +(Ca(CO3|SO4)|CO2|(H2|Na2)(CO3|O|SO4)|[HNO]2|HNO3|Fe2O3|KMnO4|NO2|SiO2|SO[23])(-\w+)? <- option("idx") -> =\0.replace("2", u"₂").replace("3", u"₃").replace("4", u"₄") # Index tipográfiai jellel. + +[word] + +kedvel <- word(-1).lower() == u"jó" or word(-1).lower() == "rossz" -> kedvvel # Szótévesztés? + +################### mértékegységek ########################## + +([-−]?\d+(?:,\d+)?) (°F(-\w+)?) <- option("SI") -> = measurement(\1, "F", "C", " " + \2.replace("F", "C")) # Váltás SI mértékegységre +([-−]?\d+(?:,\d+)?) (℉(-\w+)?) <- option("SI") -> = measurement(\1, "F", "C", " °C" + \2[1:]) # Váltás SI mértékegységre + +([-−]?\d(?:,\d+)?) (láb\w*) <- option("SI") and stem(\2) == [u"láb"] -> = + measurement(\1, "ft", "cm", " " + generate(u"centiméter", \2)[0]) + "\n" + + measurement(\1, "ft", "m", " " + generate(u"méter", \2)[0]) # Váltás SI mértékegységre + +([-−]?\d\d+(?:,\d+)?) (láb\w*) <- option("SI") and stem(\2) == [u"láb"] -> = measurement(\1, "ft", "m", + " " + generate(u"méter", \2)[0]) # Váltás SI mértékegységre + +([-−]?\d+(?:,\d+)?) (hüvelyk\w*) <- option("SI") -> = measurement(\1, "in", "cm", + " " + generate(u"centiméter", \2)[0]) # Váltás SI mértékegységre + +([-−]?\d+(?:,\d+)?) (mérföld\w*) <- option("SI") -> = measurement(\1, "mi", "km", + " " + generate(u"kilométer", \2)[0]) # Váltás SI mértékegységre + +([-−]?\d+(?:,\d+)?) (yard\w*) <- option("SI") -> = measurement(\1, "yd", "m", + " " + generate(u"méter", \2)[0]) # Váltás SI mértékegységre + +([-−]?\d+(?:,\d+)?) (font (súlyú\w*)) <- option("SI") -> = measurement(\1, "lbm", "kg", + " " + generate("kilogramm", u"szomor" + \3[4:])[0]) # Váltás SI mértékegységre + +([-−]?\d+(?:,\d+)?) (gallon\w*) <- option("SI") -> = measurement(\1, "gal", "l", + " " + generate("liter", \2)[0]) # Váltás SI mértékegységre + +([-−]?\d+(?:,\d+)?) (pint\w*) <- option("SI") -> = + measurement(\1, "uk_pt", "dl", " " + generate("deciliter", \2)[0]) + "\n" + + measurement(\1, "us_pt", "dl", " " + generate("deciliter", \2)[0]) # Váltás SI mértékegységre (angol és amerikai pint) + +# elválasztás + +adatút <- option("hyphen") -> adatút\nadatút # Elválasztás: +felett(em|ed|e|ünk|ük) <- option("hyphen") -> felett\1\nfelett\1 # Elválasztás: +felettetek <- option("hyphen") -> felettetek\nfelettetek # Elválasztás: +fölül <- option("hyphen") -> fölül\nfölül # Elválasztás: +gépelem <- option("hyphen") -> gépelem\ngépelem # Elválasztás: +karóra <- option("hyphen") -> karóra\nkaróra # Elválasztás: +megás <- option("hyphen") -> megás\nmegás # Elválasztás: +megint <- option("hyphen") -> megint\nmegint # Elválasztás: + +[code] + +def measurement(mnum, min, mout, mstr): + m = calc("CONVERT_ADD", (float(mnum.replace(",", ".").replace(u"−", "-")), min, mout)) + a = list(set([str(calc("ROUND", (m, 0)))[:-2], str(calc("ROUND", (m, 1))), str(calc("ROUND", (m, 2))), str(m)])) # remove duplicated rounded items + a.sort(lambda x, y: len(x) - len(y)) # sort by string length + return join(a, mstr + "\n").replace(".", ",").replace("-", u"−") + mstr diff --git a/src/hu_HU/hu_HU.dlg b/src/hu_HU/hu_HU.dlg new file mode 100644 index 0000000..6822f08 --- /dev/null +++ b/src/hu_HU/hu_HU.dlg @@ -0,0 +1,99 @@ +# Options and title texts for the Settings and conditional rules +# +# The Lightproof dialogs contain only grouped checkboxes. +# +# Format of the dialog definition: +# +# GroupID: OptionID, OptionID ... +# Group2ID: OptionID, OptionID ... +# ... +# [Language_code=title of the window] +# OptionID=title of the option +# Option2ID=title of the option +# +# The first language is the default language for other locales +# (use en_US or the common language of your country) +# +# The OptionIDs declared here are used in the rules, too. For example: +# +# foo <- option("style") -> bar # bar is far better +# +# this rule depends from the state of the "style" checkbox. + +# options (starred options are default checked ones) + +spelling: cap par, quot wordpart, *dash comma, numpart grammar +proofreading: style *dup0, compound dup, allcompound dup2, *money dup3, SI hyphen +typography: *apost *spaces frac ligature, elli spaces2 thin noligature, idx minus - - + +# titles + +[en_US=Hungarian sentence checking] + +spelling=Spelling +cap=Capitalization +par=Parentheses +wordpart=Word parts of compounds +comma=Comma usage +proofreading=Proofreading +style=Style checking +compound=Underline typo-like compound words +allcompound=Underline all generated compound words +grammar=Possible mistakes +money=Consistency of money amounts +duplication=Word duplication +dup0=Word duplication +dup=Duplication within clauses +dup2=Duplication within sentences +dup3=Allow previous checkings with affixes +numpart=Thousand separation of numbers +typography=Typography +quot=Quotation marks +apost=Apostrophe +dash=En dash +elli=Ellipsis +ligature=Ligature suggestion +noligature=Underline ligatures +frac=Fractions +thin=Thin space +spaces=Double spaces +spaces2=More spaces +idx=Indices +minus=Minus +SI=Measurements +hyphen=Hyphenation of ambiguous words + +[hu_HU=Magyar mondatellenőrzés] + +spelling=Helyesírás +cap=Nagy kezdőbetű\nMondatok nagy kezdőbetűjének ellenőrzése. +par=Zárójelek\nZárójelpárok ellenőrzése. +wordpart=Egybe- és különírási javaslatok +comma=Vesszőhasználatra vonatkozó javaslatok\nA valószínűleg hiányzó és felesleges vesszők jelzése. +numpart=Nagy számok tagolása szóközökkel\nEzrestagolás nem-törő szóközökkel (10000 → 10 000). +proofreading=Korrektúra +style=Stílusellenőrzés +compound=Egyszerű nem szótári összetett szavak\nRövid, vagy rövid tagot tartalmazó, szóösszetételi szabályok alapján gyakran hibásan elfogadott alakok aláhúzása. +allcompound=Minden nem szótári összetett szó\nMinden szóösszetételi szabály alapján elfogadott alak aláhúzása. +grammar=Javaslat kevésbé egyértelmű esetben is +dup0=Szóismétlés\nSzóismétlés egymást közvetlenül követő szavak esetében. +dup=Szóismétlés tagmondaton belül +dup2=Szóismétlés mondaton belül +dup3=Szóismétlés eltérő toldalékok esetén is +money=Számok és átírásuk\nA számmal és számnévvel is leírt mennyiség megegyezik-e? (Pl. 10, azaz tíz Ft.) +typography=Tipográfia +quot=Idézőjelek\nA magyar „külső” és »belső« idézőjelek ellenőrzése. +apost=Aposztróf\nAz írógépes aposztróf cseréje a tipográfiailag megfelelőre (' → ’). +dash=Nagykötőjel és gondolatjel\nA kiskötőjel cseréje a nagykötőjelre (- → –). +elli=Három pont\nHárom pont cseréje az egalizált három pont karakterre (...→…). +frac=Törtek\nPerjellel elválasztott törtek cseréje Unicode karakterre (1/2 → ½). +thin=Keskeny szóköz\nKeskeny szóköz (spácium) használata ezrestagoláshoz és más esetekben. +ligature=f-ligatúra javaslata\nCsere Unicode f-ligatúrára. +noligature=f-ligatúra tiltása\nUnicode f-ligatúra cseréje különálló betűkre. +spaces=Dupla szóköz\nKét vagy három ismétlődő szóköz cseréje egyre. +spaces2=Sok szóköz\nNégy vagy több ismétlődő szóköz cseréje egy tabulátorra. +idx=Indexek\nSzámok cseréje mértékegységekben és kémiai képletekben valódi indexekre (m2 → m²). +minus=Mínuszjel\nKötőjelek cseréje Unicode mínuszjelre a számok előtt. +SI=Mértékegységek\nNem SI mértékegységek átalakítása (°F, mérföld, yard, láb, hüvelyk, gallon, pint, font súlyú). +hyphen=Hiányzó elválasztás megadása\nNem egyértelműen elválasztható szóalakok elválasztásának megadása (pl. megint, fölül). + diff --git a/src/ru_RU/README_lightproof_ru_RU.txt b/src/ru_RU/README_lightproof_ru_RU.txt new file mode 100644 index 0000000..1744797 --- /dev/null +++ b/src/ru_RU/README_lightproof_ru_RU.txt @@ -0,0 +1,7 @@ +Russian grammar checker + +(developed by the Lightproof grammar checker extension generator, +see http://launchpad.net/lightproof) + +2009, 2011 (c) Yakov Reztsov <yr at myooo dot ru>, license: MPL 1.1 / GPL / LGPL + diff --git a/src/ru_RU/ru_RU.cfg b/src/ru_RU/ru_RU.cfg new file mode 100644 index 0000000..3ba09c7 --- /dev/null +++ b/src/ru_RU/ru_RU.cfg @@ -0,0 +1,13 @@ +[args] +lang = ru_RU +locales = ru_RU +name = Lightproof grammar checker (Russian) +version = 0.3.1 +author = Yakov Reztsov <yr at myooo dot ru> +provider = LibreOffice +implname = lightproof_ru_RU +link = http://www.libreoffice.org +description = Russian grammar checker for LibreOffice +extras = README_lightproof_ru_RU.txt +# logo = +# sourcefiles =
\ No newline at end of file diff --git a/src/ru_RU/ru_RU.dat b/src/ru_RU/ru_RU.dat new file mode 100644 index 0000000..512dc25 --- /dev/null +++ b/src/ru_RU/ru_RU.dat @@ -0,0 +1,248 @@ +# Sample proofreading rules for Russian (by Yakov Reztsov 2009, 2011) + + + +# test +\bfoo\b -> bar # test +# foo -> bar + + +# punctuation + +" ([.?!,:;)”]($| ))" <- option("space") -> \1 # Лишний пробел перед знаком пунктуации. +"([(“]) " <- option("space") -> \1 # Лишний пробел после знака пунктуации. +# ( item ) -> (item) + +# definitions +abc [a-zа-я]+ +ABC [A-ZА-Я]+ +Abc [a-zA-Zа-яА-Я]+ +punct [?!,:;%‰‱˚“”‘„] +abbr руб|коп|грн|тыс|ул|кв|пос|ст|пр|просп|ед|экз|тел|исп + +novvod авось|буквально|будто|вдобавок|вдруг|ведь|вот|даже|исключительно|именно|небось|приблизительно|примерно|притом|почти|поэтому|просто|решительно|словно|якобы|в довершение|в конечном счете|вряд ли|все-таки|как будто|как бы|как раз|к тому же|между тем|по предложению|по постановлению|по решению + +vvod итак|следовательно|во-первых|во-вторых|в-третьих|в-четвертых|в-пятых|пожалуйста|как нарочно|как исключение|как правило + +adv1 кто|что|где|зачем|кое + + +{Abc}{punct}{Abc} <- option("space") -> {Abc}{punct} {Abc} # Пропущен пробел? +{abc}[.]{ABC} <- option("space") -> {abc}. {ABC} # Пропущен пробел? +# missing,space -> missing, space +# missing.Space -> missing. Space + + +# typography +"[.]{3}" <- option("typographica") -> "…" # Символ троеточия. +(\d+)x(\d+) <- option("typographica") -> \1×\2 # Знак умножения. +"^[-—] " <- option("typographica") -> "– " # Заменить на тире (n-dash)? +" [-—]([ ,;])" <- option("typographica") -> " –\1" # Заменить на тире (n-dash)? + +# 800x600 -> 800×600 +# End... -> End… +# A small - but reliable - example. -> A small – but reliable – example. + +"[,]{2}" <- option("comma") -> "," # Две запятые подряд. +[ ]{abbr}[ ] <- option("abbreviation") -> " {abbr}. " # Точка после сокращений. +(^|\b|{punct}|[.]) {2,3}(\b|$) <- option("space") -> "\1 " # Лишний пробел. +# Extra space -> Extra space +# " мм " -> " мм. " + +# quotation + +\"(\w[^\"“”]*[\w.?!,])\" <- option("quotation") -> «\1»\n„\1”\n“\1” # Кавычки. +\B'(\w[^']*[\w.?!,])'\B <- option("quotation") -> ‘\1’ # Кавычки. +# "The 'old' boy" -> „The ‘old’ boy”\n«The ‘old’ boy»\n“The ‘old’ boy” + +# apostrophe + +w \w* +(?i){Abc}'{w} <- option("quotation") -> {Abc}’{w} # Апостроф. +# o'clock -> o’clock +# singers' voices -> singers’ voices + +# words + + +# punctuation + +{abc}[ ]а[ ] <- option("comma") -> "{abc}, а " # Пропущена запятая перед а. +{abc}[ ]но[ ] <- option("comma") -> "{abc}, но " # Пропущена запятая перед но. + + +# nopunctuation + +"{abc}, {novvod}," <- option("comma") -> "{abc} {novvod}" # Слова, не являющиеся вводными. +# думали, авось, -> думали авось + + + +# vvodpunctuation + +{abc} {vvod} <- option("comma") -> {abc}, {vvod}, # Слова, являющиеся вводными, выделяются запятыми. +# дому следовательно -> дому, следовательно, + + + +# frequent mistakes + +\bложить\b <- option("common") -> класть # Общие ошибки +\bляжь\b <- option("common") -> ляг # Общие ошибки +\bехай\b <- option("common") -> поезжай # Общие ошибки + +\bихн{abc}\b <- option("common") -> их # Притяжательное местоимение не склоняется + + + + +# common rules +жы <- option("common") -> жи # Через "и" +шы <- option("common") -> ши # Через "и" + +# жыр -> жир + + + +# multiword expressions + + +\bнорд ост\b <- option("hyphen") -> норд-ост\nнордост # Дефис? +# норд ост -> норд-ост\nнордост # Suggestions separated by new lines (\n) + +\bнорд вест\b <- option("hyphen") -> норд-вест\nнордвест # Дефис? +# норд вест -> норд-вест\nнордвест # Suggestions separated by new lines (\n) + +\bсеверо западн{abc}\b <- option("hyphen") -> северо-западн{abc}\nсеверозападн{abc} # Дефис? +# северо западный -> северо-западный\nсеверозападный # Suggestions separated by new lines (\n) + + +\bюго западн{abc}\b <- option("hyphen") -> юго-западн{abc}\nюгозападн{abc} # Дефис? +# юго западный -> юго-западный\nюгозападный # Suggestions separated by new lines (\n) + +\bсеверо восточн{abc}\b <- option("hyphen") -> северо-восточн{abc}\nсеверовосточн{abc} # Дефис? +# северо восточный -> северо-восточный\nсеверовосточный # Suggestions separated by new lines (\n) + +\bюго восточн{abc}\b <- option("hyphen") -> юго-восточн{abc}\nюговосточн{abc} # Дефис? +# юго восточный -> юго-восточный\nюговосточный # Suggestions separated by new lines (\n) + + +\b{adv1} нибудь\b <- option("hyphen") -> {adv1}-нибудь # Дефис? +# что нибудь -> что-нибудь # Suggestions separated by new lines (\n) + +\b{adv1} либо\b <- option("hyphen") -> {adv1}-либо # Дефис? +# что либо -> что-либо # Suggestions separated by new lines (\n) + +\b{adv1} то\b <- option("hyphen") -> {adv1}-то # Дефис? +# кто то -> кто-то # Suggestions separated by new lines (\n) + +\bточь в точь\b <- option("hyphen") -> точь-в-точь # Дефис? +# точь в точь -> точь-в-точь # Suggestions separated by new lines (\n) + +\bиз за\b <- option("hyphen") -> из-за # Дефис? +# из за -> из-за # Suggestions separated by new lines (\n) + +\bвсё таки\b <- option("hyphen") -> всё-таки # Дефис? +# всё таки -> всё-таки # Suggestions separated by new lines (\n) + +\bкое кто\b <- option("hyphen") -> кое-кто # Дефис? +# кое кто -> кое-кто # Suggestions separated by new lines (\n) + +\bкое что\b <- option("hyphen") -> кое-что # Дефис? +# кое что -> кое-что # Suggestions separated by new lines (\n) + +\bво что бы то нe стало\b <- option("multiword") -> во что бы то ни стало # Имелось ввиду: +\bво чтобы то нe стало\b <- option("multiword") -> во что бы то ни стало # Имелось ввиду: +\bво чтобы то ни стало\b <- option("multiword") -> во что бы то ни стало # Имелось ввиду: + + +\bтакже как и\b <- option("multiword") -> так же как и # Сложный союз. + +\bво избежании\b<- option("multiword") -> во избежание # Сложный предлог. + +\bравноправны друг другу\b<- option("multiword") -> равноправны друг c другом # Равноправны друг c другом. + +\bни кто иной как\b<- option("multiword") -> не кто иной, как # Оборот. +\bни что иное как\b<- option("multiword") -> не что иное, как # Оборот. +\bне кто иной как\b<- option("multiword") -> не кто иной, как # Оборот. +\bне что иное как\b<- option("multiword") -> не что иное, как # Оборот. + + + +\bникто иной, не\b<- option("multiword") -> никто иной не # Оборот. +\bничто иное, не\b<- option("multiword") -> ничто иное не # Оборот. + +\bнекто иной, не\b<- option("multiword") -> никто иной не # Оборот. +\bнечто иное, не\b<- option("multiword") -> ничто иное не # Оборот. + + +\bнекто иной не\b<- option("multiword") -> никто иной не # Оборот. +\bнечто иное не\b<- option("multiword") -> ничто иное не # Оборот. + + +\bне кто иной, не\b<- option("multiword") -> никто иной не # Оборот. +\bне что иное, не\b<- option("multiword") -> ничто иное не # Оборот. + + +\bне кто иной не\b<- option("multiword") -> никто иной не # Оборот. +\bне что иное не\b<- option("multiword") -> ничто иное не # Оборот. + + +\bникто иной, не\b<- option("multiword") -> никто иной не # Оборот. +\bничто иное, не\b<- option("multiword") -> ничто иное не # Оборот. + +\bни кто иной, не\b<- option("multiword") -> никто иной не # Оборот. +\bни что иное, не\b<- option("multiword") -> ничто иное не # Оборот. + + + +\bкакбудто<- option("together") -> как будто # Составная частица + +\bпо мимо\b <- option("together") -> помимо # Пишется слитно + + + +\bна кануне\b<- option("together") -> накануне # Слитно +\bна подобие\b<- option("together") -> наподобие # Слитно +\bна против\b<- option("together") -> напротив # Слитно +\bв низу\b<- option("together") -> внизу # Слитно +\bс низу\b<- option("together") -> снизу # Слитно +\bна верху\b<- option("together") -> наверху # Слитно +\bв верху\b<- option("together") -> вверху # Слитно +\bс верху\b<- option("together") -> сверху # Слитно +\bс верх\b<- option("together") -> сверх # Слитно +\bс выше\b<- option("together") -> свыше # Слитно +\bсо гласно\b<- option("together") -> согласно # Слитно +\bв глубь\b<- option("together") -> вглубь # Слитно +\bв доль\b<- option("together") -> вдоль # Слитно +\bв замен\b<- option("together") -> взамен # Слитно + +# formats + +# Thousand separators: 10000 -> 10,000 (common) or 10 000 (ISO standard) + +# definitions +d \d\d\d # name definition: 3 digits +d2 \d\d # 2 digits +D \d|\d\d|\d\d\d # 1, 2 or 3 digits + +# ISO thousand separatos: space, here: no-break space (U+00A0) +\b{d2}{d}\b <- option("numsep") -> {d2} {d} # Добавить разделитель разрядов (ISO)? +\b{D}{d}{d}\b <- option("numsep") -> {D} {d} {d} # Добавить разделитель разрядов (ISO)? +\b{D}{d}{d}{d}\b <- option("numsep") -> {D} {d} {d} {d} # Добавить разделитель разрядов (ISO)? +# 1234567890 -> 1 234 567 890 + + +# word duplication + +[Word] + +W [-\w]{3,} + +# within clauses + +{W}(?: [-–\w“”]+)* \1 <- option("dup") -> {W} # Повтор слова? + +# within sentences + +{W}[;,:]?(?: [-–\w“”]+[;,:]?)* \1 <- option("dup2") -> {W} # Повтор слова? diff --git a/src/ru_RU/ru_RU.dlg b/src/ru_RU/ru_RU.dlg new file mode 100644 index 0000000..b3b3c1b --- /dev/null +++ b/src/ru_RU/ru_RU.dlg @@ -0,0 +1,66 @@ +# Options and title texts for the Settings and conditional rules +# for Russian (translated by Yakov Reztsov 2011) +# The Lightproof dialogs contain only grouped checkboxes. +# +# Format of the dialog definition: +# +# GroupID: OptionID, OptionID ... +# Group2ID: OptionID, OptionID ... +# ... +# [Language_code=title of the window] +# OptionID=title of the option +# Option2ID=title of the option +# +# The first language is the default language for other locales +# (use en_US or the common language of your country) +# +# The OptionIDs declared here are used in the rules, too. For example: +# +# foo <- option("style") -> bar # bar is far better +# +# this rule depends from the state of the "style" checkbox. + +# options (starred options are checked) + +grammar: *hyphen *comma, *multiword *together +proofreading: *dup dup2, *common *space, *abbreviation +others: numsep, *typographica, *quotation + +# titles + +[en_US=Russian sentence checking] + +abbreviation=Abbreviation +grammar=Grammar +hyphen=Compound words with hyphen +comma=Comma usage +common=General error +multiword=Multiword expressions +together=Together/separately +proofreading=Proofreading +space=Space mistake +typographica=Typographica +dup=Word duplication within clauses +dup2=Word duplication within sentences +others=Others +numsep=Separation of large numbers (ISO) +quotation=Quotation + +[ru_RU=Проверка грамматики (Русский язык)] + +abbreviation=Аббревиатуры +grammar=Грамматика +hyphen=Дефис +comma=Пунктуация +common=Общие ошибки +multiword=Словосочетания +together=Слитно/раздельно +proofreading=Стилистика +space=Пробел +typographica=Типографика +dup=Повтор слов в словосочетаниях +dup2=Повтор слов в предложениях +others=Прочее +numsep=Разделители групп разрядов (ISO) для чисел +quotation=Кавычки + |