Applies python syntax highlighting to all the TextShapes (i.e. text boxes) in an OpenOffice document with the "code" graphic style applied. Typical usage is for highlighting code snippets in an Impress presentation. I have the "HighlightPython" function assigned to a menu item in my Tools menu for easy access.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | import re
import keyword
###Following are some crude regexes which I use to tokenise a text object comprising python code
multiline_pat = "(\'\'\'|\"\"\")"+r"(.|\n)*?\1"
singleline_pat = "(\'|\")"+r".*?\1"
kw_pat = r"\b("+"|".join(keyword.kwlist)+r")\b"
number_pat = r"\b\d+\b"
def_pat = r"((?<=def )\w+)|((?<=class )\w+)"
comment_pat = r"#.*(\n|$)"
###Define some colors for each token type
kwcolor = RGB( 255, 0, 0 )
numberColor = RGB( 128, 50, 0)
defColor = RGB(0,0,255)
StrColor = RGB(125,125,0)
CommentColor = RGB(128,128,128)
MultiStrColor = RGB(0,255,0)
def RGB( nRed, nGreen, nBlue ):
"""Return an integer which repsents a color.
The color is specified in RGB notation.
Each of nRed, nGreen and nBlue must be a number from 0 to 255.
"""
return (int( nRed ) & 255) << 16 | (int( nGreen ) & 255) << 8 | (int( nBlue ) & 255)
def HighlightPython():
"""
Main function for highlighting python code in a document. Must be called 'in process'.
"""
ctx = XSCRIPTCONTEXT
doc = ctx.getDocument()
HighlightAll(doc)
def _highlight(pat, data, csr, color):
"""
Does the actual coloring of text
@param pat: a regex to find patterns to highlight
@param data: the source text to use, a string
@param csr: a OOo TextCursor instance
@param color: an integer representing a color. use the RGB() function above to calculate
"""
pos=0
csr.gotoStart(False)
print "pattern:", pat
for match in re.finditer(pat, data):
start, end = match.span()
print "match:", data[start:end]
diff = start-pos
csr.goRight(diff, False)
csr.goRight(end-start,True)
csr.CharColor = color
pos=end
def ColourTextBox(txt):
"""
Highlights a single TextShape item
"""
data = txt.String
csr = txt.createTextCursor()
_highlight(kw_pat, data, csr, kwcolor)
_highlight(number_pat, data, csr, numberColor)
_highlight(def_pat, data, csr, defColor )
_highlight(singleline_pat, data, csr, StrColor)
_highlight(comment_pat, data, csr, CommentColor )
_highlight(multiline_pat, data, csr, MultiStrColor )
def RemoteGetDoc():
"""
Retrieve the document instance when accessing OOo 'out of process', using uno over a socket.
"""
import uno
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext )
ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)
doc = desktop.getCurrentComponent()
return doc
def HighlightAll(doc):
"""
Apply syntax highlighting to all TextShapes in the document which have the "code"
graphic style applied to them
"""
styles = doc.StyleFamilies.getByName(u"graphics")
code = styles.getByName(u"code")
pages = doc.DrawPages
count = pages.getCount()
for idx in xrange(count):
page = pages.getByIndex(idx)
count = page.getCount()
for item_idx in xrange(count):
item = page.getByIndex(item_idx)
if 'com.sun.star.drawing.TextShape' in item.SupportedServiceNames:
style = item.Style
if style==code:
ColourTextBox(item)
g_exportedScripts = (HighlightPython,)
if __name__=="__main__":
#Script testing is easiest using remote uno over a socket
doc = RemoteGetDoc()
HighlightAll(doc)
|
To use this script, you need to define a graphic style named "code". I give this a monospaced font. You apply this to all text-frames containing python code. Then call the HighlightPython function from the OOo macros menu.
The script uses simple regexes to find each bit of text to color. A more robust method would be to exploit the Pygments library to tokenise the code instead (or learn more about regexes than I do).
The most useful aspect of the script is to demonstrate the OOo API used to find objects by their graphic-style, iterating over text with a Cursor object and coloring the text.
How do I get this script to work in OOo? I have it saved in ~/.openoffice.org/3/user/Scripts/python, but it comes up in the run macro dialog as a library with no macros. This shouldn't be--my understanding is that each function with no arguments should appear as a macro... Why might this be happening?
The g_exportedScripts variable defines which functions should be made available in the macros menu.
I've run into problems with python scripts in User folders not appearing in the macros menu. This is a OOo bug. Try putting the script in the system macros folder (e.g. /usr/lib/openoffice.org/basis3.1/share/Scripts/python/ , in Fedora11 although it may be somewhere else on other OSs/distros. Obviously you need root access to do this). Upgrading OOo may also fix this.