updated on Sun Jan 22 12:09:12 UTC 2012
[aur-mirror.git] / libreoffice-extension-lightproof-ru / Lightproof_.py
blob320d778b3751ca122e9f33236a87c0cc26002a51
1 # -*- encoding: UTF-8 -*-
2 # Lightproof grammar checker for LibreOffice and OpenOffice.org
3 # http://launchpad.net/lightproof
4 # version 1.4.3 (2011-12-05)
6 # 2009-2011 (c) László Németh (nemeth at numbertext org), license: MPL 1.1 / GPLv3+ / LGPLv3+
8 import uno, unohelper, sys, traceback, re
9 from lightproof_impl_ru_RU import locales
10 from lightproof_impl_ru_RU import pkg
11 import lightproof_handler_ru_RU
12 from string import join
14 from com.sun.star.linguistic2 import XProofreader, XSupportedLocales
15 from com.sun.star.linguistic2 import ProofreadingResult, SingleProofreadingError
16 from com.sun.star.lang import XServiceInfo, XServiceName, XServiceDisplayName
17 from com.sun.star.lang import Locale
18 from com.sun.star.text.TextMarkupType import PROOFREADING
20 # loaded rules
21 langrule = {}
22 # ignored rules
23 ignore = {}
25 # cache for morphogical analyses
26 analyses = {}
27 stems = {}
28 suggestions = {}
30 # assign Calc functions
31 calcfunc = None
33 # check settings
34 def option(lang, opt):
35 return lightproof_handler_ru_RU.get_option(lang.Language + "_" + lang.Country, opt)
37 # filtering affix fields (ds, is, ts etc.)
38 def onlymorph(st):
39 if st != None:
40 st = re.sub(r"^.*(st:|po:)", r"\1", st) # keep last word part
41 st = re.sub(r"\b(?=[dit][sp]:)","@", st) # and its affixes
42 st = re.sub(r"(?<!@)\b\w\w:\w+","", st).replace('@','').strip()
43 return st
45 # if the pattern matches all analyses of the input word,
46 # return the last matched substring
47 def _morph(rLoc, word, pattern, all, onlyaffix):
48 global analyses
49 if word == None:
50 return None
51 if word not in analyses:
52 x = spellchecker.spell(u"<?xml?><query type='analyze'><word>" + word + "</word></query>", rLoc, ())
53 if not x:
54 return None
55 t = x.getAlternatives()
56 if not t:
57 t = [""]
58 analyses[word] = t[0]
59 a = analyses[word].split("</a>")[:-1]
60 result = None
61 p = re.compile(pattern)
62 for i in a:
63 if onlyaffix:
64 i = onlymorph(i)
65 result = p.search(i)
66 if result:
67 result = result.group(0)
68 if not all:
69 return result
70 elif all:
71 return None
72 return result
74 def morph(rLoc, word, pattern, all=True):
75 return _morph(rLoc, word, pattern, all, False)
77 def affix(rLoc, word, pattern, all=True):
78 return _morph(rLoc, word, pattern, all, True)
80 def spell(rLoc, word):
81 if word == None:
82 return None
83 return spellchecker.isValid(word, rLoc, ())
85 # get the tuple of the stem of the word or an empty array
86 def stem(rLoc, word):
87 global stems
88 if word == None:
89 return []
90 if not word in stems:
91 x = spellchecker.spell(u"<?xml?><query type='stem'><word>" + word + "</word></query>", rLoc, ())
92 if not x:
93 return []
94 t = x.getAlternatives()
95 if not t:
96 t = []
97 stems[word] = list(t)
98 return stems[word]
100 # get the tuple of the morphological generation of a word or an empty array
101 def generate(rLoc, word, example):
102 if word == None:
103 return []
104 x = spellchecker.spell(u"<?xml?><query type='generate'><word>" + word + "</word><word>" + example + "</word></query>", rLoc, ())
105 if not x:
106 return []
107 t = x.getAlternatives()
108 if not t:
109 t = []
110 return list(t)
112 # get suggestions
113 def suggest(rLoc, word):
114 global suggestions
115 if word == None:
116 return word
117 if word not in suggestions:
118 x = spellchecker.spell("_" + word, rLoc, ())
119 if not x:
120 return word
121 t = x.getAlternatives()
122 suggestions[word] = join(t, "\n")
123 return suggestions[word]
125 # get the nth word of the input string or None
126 def word(s, n):
127 a = re.match("(?u)( [-.\w%]+){" + str(n-1) + "}( [-.\w%]+)", s)
128 if not a:
129 return None
130 return a.group(2)[1:]
132 # get the (-)nth word of the input string or None
133 def wordmin(s, n):
134 a = re.search("(?u)([-.\w%]+ )([-.\w%]+ ){" + str(n-1) + "}$", s)
135 if not a:
136 return None
137 return a.group(1)[:-1]
139 def calc(funcname, par):
140 global calcfunc
141 global SMGR
142 if calcfunc == None:
143 calcfunc = SMGR.createInstance( "com.sun.star.sheet.FunctionAccess")
144 if calcfunc == None:
145 return None
146 return calcfunc.callFunction(funcname, par)
148 def proofread( nDocId, TEXT, LOCALE, nStartOfSentencePos, nSuggestedSentenceEndPos, rProperties ):
149 global ignore
150 aErrs = []
151 s = TEXT[nStartOfSentencePos:nSuggestedSentenceEndPos]
152 for i in get_rule(LOCALE):
153 if i[0] and not str(i[0]) in ignore:
154 for m in i[0].finditer(s):
155 if not i[3] or eval(i[3]):
156 aErr = uno.createUnoStruct( "com.sun.star.linguistic2.SingleProofreadingError" )
157 aErr.nErrorStart = nStartOfSentencePos + m.start(0) # nStartOfSentencePos
158 aErr.nErrorLength = m.end(0) - m.start(0)
159 aErr.nErrorType = PROOFREADING
160 aErr.aRuleIdentifier = str(i[0])
161 iscap = (i[4] and m.group(0)[0:1].isupper())
162 if i[1][0:1] == "=":
163 aErr.aSuggestions = tuple(cap(eval(i[1][1:]).split("\n"), iscap, LOCALE))
164 else:
165 aErr.aSuggestions = tuple(cap(m.expand(i[1]).split("\n"), iscap, LOCALE))
166 comment = i[2]
167 if comment[0:1] == "=":
168 comment = eval(comment[1:])
169 aErr.aShortComment = comment.split("\n")[0]
170 aErr.aFullComment = comment.split("\n")[-1]
171 aErr.aProperties = ()
172 aErrs = aErrs + [aErr]
173 return tuple(aErrs)
175 def cap(a, iscap, rLoc):
176 if iscap:
177 for i in range(0, len(a)):
178 if a[i][0:1] == "i":
179 if rLoc.Language == "tr" or rLoc.Language == "az":
180 a[i] = u"\u0130" + a[i][1:]
181 elif a[i][1:2] == "j" and rLoc.Language == "nl":
182 a[i] = "IJ" + a[i][2:]
183 else:
184 a[i] = "I" + a[i][1:]
185 else:
186 a[i] = a[i].capitalize()
187 return a
189 def get_rule(rLocale):
190 module = rLocale.Language
191 if rLocale.Country != "":
192 module = module + "_" + rLocale.Country
193 try:
194 return langrule[module]
195 except:
196 try:
197 module = rLocale.Language
198 return langrule[module]
199 except:
200 try:
201 d = __import__("lightproof_" + pkg)
202 except:
203 print "Error: missing language data: " + module
204 return None
205 # compile regular expressions
206 for i in d.dic:
207 try:
208 if re.compile("[(][?]iu[)]").match(i[0]):
209 i += [True]
210 i[0] = re.sub("[(][?]iu[)]", "(?u)", i[0])
211 else:
212 i += [False]
213 i[0] = re.compile(i[0])
214 except:
215 print "Lightproof: bad rule -- ", i[0]
216 i[0] = None
217 langrule[module] = d.dic
218 return langrule[module]
220 class Lightproof( unohelper.Base, XProofreader, XServiceInfo, XServiceName, XServiceDisplayName, XSupportedLocales):
222 def __init__( self, ctx, *args ):
223 global spellchecker
224 global SMGR
225 self.ctx = ctx
226 self.ServiceName = "com.sun.star.linguistic2.Proofreader"
227 self.ImplementationName = "org.openoffice.comp.pyuno.Lightproof." + pkg
228 self.SupportedServiceNames = (self.ServiceName, )
229 self.locales = []
230 for i in locales:
231 l = locales[i]
232 self.locales += [Locale(l[0], l[1], l[2])]
233 self.locales = tuple(self.locales)
234 currentContext = uno.getComponentContext()
235 SMGR = currentContext.ServiceManager
236 spellchecker = SMGR.createInstanceWithContext("com.sun.star.linguistic2.SpellChecker", currentContext)
237 lightproof_handler_ru_RU.load(currentContext)
239 # XServiceName method implementations
240 def getServiceName(self):
241 return self.ImplementationName
243 # XServiceInfo method implementations
244 def getImplementationName (self):
245 return self.ImplementationName
247 def supportsService(self, ServiceName):
248 return (ServiceName in self.SupportedServiceNames)
250 def getSupportedServiceNames (self):
251 return self.SupportedServiceNames
253 # XSupportedLocales
254 def hasLocale(self, aLocale):
255 if aLocale in self.locales:
256 return True
257 for i in self.locales:
258 if (i.Country == aLocale.Country or i.Country == "") and aLocale.Language == i.Language:
259 return True
260 return False
262 def getLocales(self):
263 return self.locales
265 # XProofreader
266 def isSpellChecker(self):
267 return False
269 def doProofreading(self, nDocId, rText, rLocale, nStartOfSentencePos, \
270 nSuggestedSentenceEndPos, rProperties):
271 aRes = uno.createUnoStruct( "com.sun.star.linguistic2.ProofreadingResult" )
272 aRes.aDocumentIdentifier = nDocId
273 aRes.aText = rText
274 aRes.aLocale = rLocale
275 aRes.nStartOfSentencePosition = nStartOfSentencePos
276 aRes.nStartOfNextSentencePosition = nSuggestedSentenceEndPos
277 l = rText[nSuggestedSentenceEndPos:nSuggestedSentenceEndPos+1]
278 while l == " ":
279 aRes.nStartOfNextSentencePosition = aRes.nStartOfNextSentencePosition + 1
280 l = rText[aRes.nStartOfNextSentencePosition:aRes.nStartOfNextSentencePosition+1]
281 if aRes.nStartOfNextSentencePosition == nSuggestedSentenceEndPos and l!="":
282 aRes.nStartOfNextSentencePosition = nSuggestedSentenceEndPos + 1
283 aRes.nBehindEndOfSentencePosition = aRes.nStartOfNextSentencePosition
285 try:
286 aRes.aErrors = proofread( nDocId, rText, rLocale, \
287 nStartOfSentencePos, aRes.nBehindEndOfSentencePosition, rProperties)
288 except:
289 traceback.print_exc(file=sys.stdout)
290 aRes.aErrors = ()
291 aRes.aProperties = ()
292 aRes.xProofreader = self
293 return aRes
295 def ignoreRule(self, rid, aLocale):
296 global ignore
297 ignore[rid] = 1
299 def resetIgnoreRules(self):
300 global ignore
301 ignore = {}
303 # XServiceDisplayName
304 def getServiceDisplayName(self, aLocale):
305 return "Lightproof Grammar Checker (" + pkg + ")"
307 g_ImplementationHelper = unohelper.ImplementationHelper()
308 g_ImplementationHelper.addImplementation( Lightproof, \
309 "org.openoffice.comp.pyuno.Lightproof." + pkg,
310 ("com.sun.star.linguistic2.Proofreader",),)
312 g_ImplementationHelper.addImplementation( lightproof_handler_ru_RU.LightproofOptionsEventHandler, \
313 "org.openoffice.comp.pyuno.LightproofOptionsEventHandler." + pkg,
314 ("com.sun.star.awt.XContainerWindowEventHandler",),)