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
25 # cache for morphogical analyses
30 # assign Calc functions
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.)
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()
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
):
51 if word
not in analyses
:
52 x
= spellchecker
.spell(u
"<?xml?><query type='analyze'><word>" + word
+ "</word></query>", rLoc
, ())
55 t
= x
.getAlternatives()
59 a
= analyses
[word
].split("</a>")[:-1]
61 p
= re
.compile(pattern
)
67 result
= result
.group(0)
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
):
83 return spellchecker
.isValid(word
, rLoc
, ())
85 # get the tuple of the stem of the word or an empty array
91 x
= spellchecker
.spell(u
"<?xml?><query type='stem'><word>" + word
+ "</word></query>", rLoc
, ())
94 t
= x
.getAlternatives()
100 # get the tuple of the morphological generation of a word or an empty array
101 def generate(rLoc
, word
, example
):
104 x
= spellchecker
.spell(u
"<?xml?><query type='generate'><word>" + word
+ "</word><word>" + example
+ "</word></query>", rLoc
, ())
107 t
= x
.getAlternatives()
113 def suggest(rLoc
, word
):
117 if word
not in suggestions
:
118 x
= spellchecker
.spell("_" + word
, rLoc
, ())
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
127 a
= re
.match("(?u)( [-.\w%]+){" + str(n
-1) + "}( [-.\w%]+)", s
)
130 return a
.group(2)[1:]
132 # get the (-)nth word of the input string or None
134 a
= re
.search("(?u)([-.\w%]+ )([-.\w%]+ ){" + str(n
-1) + "}$", s
)
137 return a
.group(1)[:-1]
139 def calc(funcname
, par
):
143 calcfunc
= SMGR
.createInstance( "com.sun.star.sheet.FunctionAccess")
146 return calcfunc
.callFunction(funcname
, par
)
148 def proofread( nDocId
, TEXT
, LOCALE
, nStartOfSentencePos
, nSuggestedSentenceEndPos
, rProperties
):
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())
163 aErr
.aSuggestions
= tuple(cap(eval(i
[1][1:]).split("\n"), iscap
, LOCALE
))
165 aErr
.aSuggestions
= tuple(cap(m
.expand(i
[1]).split("\n"), iscap
, LOCALE
))
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
]
175 def cap(a
, iscap
, rLoc
):
177 for i
in range(0, len(a
)):
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:]
184 a
[i
] = "I" + a
[i
][1:]
186 a
[i
] = a
[i
].capitalize()
189 def get_rule(rLocale
):
190 module
= rLocale
.Language
191 if rLocale
.Country
!= "":
192 module
= module
+ "_" + rLocale
.Country
194 return langrule
[module
]
197 module
= rLocale
.Language
198 return langrule
[module
]
201 d
= __import__("lightproof_" + pkg
)
203 print "Error: missing language data: " + module
205 # compile regular expressions
208 if re
.compile("[(][?]iu[)]").match(i
[0]):
210 i
[0] = re
.sub("[(][?]iu[)]", "(?u)", i
[0])
213 i
[0] = re
.compile(i
[0])
215 print "Lightproof: bad rule -- ", i
[0]
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
):
226 self
.ServiceName
= "com.sun.star.linguistic2.Proofreader"
227 self
.ImplementationName
= "org.openoffice.comp.pyuno.Lightproof." + pkg
228 self
.SupportedServiceNames
= (self
.ServiceName
, )
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
254 def hasLocale(self
, aLocale
):
255 if aLocale
in self
.locales
:
257 for i
in self
.locales
:
258 if (i
.Country
== aLocale
.Country
or i
.Country
== "") and aLocale
.Language
== i
.Language
:
262 def getLocales(self
):
266 def isSpellChecker(self
):
269 def doProofreading(self
, nDocId
, rText
, rLocale
, nStartOfSentencePos
, \
270 nSuggestedSentenceEndPos
, rProperties
):
271 aRes
= uno
.createUnoStruct( "com.sun.star.linguistic2.ProofreadingResult" )
272 aRes
.aDocumentIdentifier
= nDocId
274 aRes
.aLocale
= rLocale
275 aRes
.nStartOfSentencePosition
= nStartOfSentencePos
276 aRes
.nStartOfNextSentencePosition
= nSuggestedSentenceEndPos
277 l
= rText
[nSuggestedSentenceEndPos
:nSuggestedSentenceEndPos
+1]
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
286 aRes
.aErrors
= proofread( nDocId
, rText
, rLocale
, \
287 nStartOfSentencePos
, aRes
.nBehindEndOfSentencePosition
, rProperties
)
289 traceback
.print_exc(file=sys
.stdout
)
291 aRes
.aProperties
= ()
292 aRes
.xProofreader
= self
295 def ignoreRule(self
, rid
, aLocale
):
299 def resetIgnoreRules(self
):
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",),)