""" 2009-05-20: created by bousch_AT_gmail.com Do with it what you want, no warranty whatsoever. Changes: 2009-06-20: fixed error when exporting to directory with spaces in name. Description: Enables you to insert Groff fragment in your pages. Install: Save this file to your WikidPad/extensions folder Dependencies: Groff ImageMagick Arguments: groff: the "-e -p" arguments are passed to Groff by default. If you want extra arguments you can pass them with the 'args=' string ImageMagick: You can pass arguments to the convert command with the 'iargs=' string Example: [:groff:/// .EQ delim $$ .EN .PS arrow box color "darkgreen" outline "white" "$space 0 {H( omega )} over {1 - H( omega )}$" arrow .PE ///;'iargs=-trim -density 150'] """ import os, os.path from subprocess import list2cmdline import time import wx from pwiki.TempFileSet import createTempFile from pwiki.StringOps import mbcsEnc, mbcsDec, lineendToOs WIKIDPAD_PLUGIN = (("InsertionByKey", 1), ("Options", 1)) LOG = False def describeInsertionKeys(ver, app): """ API function for "InsertionByKey" plugins Returns a sequence of tuples describing the supported insertion keys. Each tuple has the form (insKey, exportTypes, handlerFactory) where insKey is the insertion key handled, exportTypes is a sequence of strings describing the supported export types and handlerFactory is a factory function (normally a class) taking the wxApp object as parameter and returning a handler object fulfilling the protocol for "insertion by key" (see EqnHandler as example). ver -- API version (can only be 1 currently) app -- wxApp object """ return ( (u"groff", ("html_single", "html_previewWX", "html_preview", "html_multi"), GroffHandler), ) class GroffHandler: """ Base class fulfilling the "insertion by key" protocol. """ def __init__(self, app): self.app = app self.extAppExe = None def taskStart(self, exporter, exportType): """ This is called before any call to createContent() during an export task. An export task can be a single HTML page for preview or a single page or a set of pages for export. exporter -- Exporter object calling the handler exportType -- string describing the export type Calls to createContent() will only happen after a call to taskStart() and before the call to taskEnd() """ # Find Gnuplot executable by configuration setting self.extAppExe = self.app.getGlobalConfig().get("main", "plugin_groff_exePath", "") self.imExtAppExe = self.app.getGlobalConfig().get("main", "plugin_imagemagick_dirPath", "") def taskEnd(self): """ Called after export task ended and after the last call to createContent(). """ pass def createContent(self, exporter, exportType, insToken): """ Handle an insertion and create the appropriate content. exporter -- Exporter object calling the handler exportType -- string describing the export type insToken -- insertion token to create content for (see also PageAst.Insertion) An insertion token has the following member variables: key: insertion key (unistring) value: value of an insertion (unistring) appendices: sequence of strings with the appendices Meaning and type of return value is solely defined by the type of the calling exporter. For HtmlXmlExporter a unistring is returned with the HTML code to insert instead of the insertion. """ if not insToken.value: # Nothing in, nothing out return u"" if self.extAppExe == "": # No path to groff executable -> show message return u"
" + _(u"[Please set path to groff executable]") +\
u""
if self.imExtAppExe == "":
return u"" + _(u"[Please set path to imageMagick executable]") +\
u""
# Get exporters temporary file set (manages creation and deletion of
# temporary files)
tfs = exporter.getTempFileSet()
pythonUrl = (exportType != "html_previewWX")
dstPSFullPath = tfs.createTempFile("", ".ps", relativeTo="")
dstPSFullPath = dstPSFullPath.replace ( '\\','/')
dstFullPath = tfs.createTempFile("", ".png", relativeTo="")
dstFullPath = dstFullPath.replace ( '\\','/')
url = tfs.getRelativeUrl(None, dstFullPath, pythonUrl=pythonUrl)
baseDir = os.path.dirname(exporter.getMainControl().getWikiConfigPath())
# find arguments in appendices
groffPattern = 'args='
imPattern = 'iargs='
groffArguments = ''
convertArguments = ''
for a in insToken.appendices:
if a.startswith(groffPattern):
groffArguments = str(a[len(groffPattern):])
if a.startswith(imPattern):
convertArguments = str(a[len(imPattern):])
# Retrieve quoted content of the insertion
#bstr = lineendToOs(mbcsEnc(insToken.value, "replace")[0])
# windows lineendings confuse pic2plot
bstr = mbcsEnc(insToken.value, "replace")[0]
# Store token content in a temporary file
srcfilepath = createTempFile(bstr, ".ms")
srcfilepath = srcfilepath.replace ( '\\','/')
try:
cmdline = '%s -t -e -p %s "%s" > "%s"' % (self.extAppExe, groffArguments, srcfilepath, dstPSFullPath)
# Run external application
from subprocess import Popen, PIPE
p = Popen(cmdline, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=False, cwd=os.path.dirname(self.extAppExe))
p.wait() # Will wait for process to end
childIn, childOut, childErr = (p.stdin, p.stdout, p.stderr)
# convert ps to png
convertcmd = '%s %s "%s" "%s"' % (os.path.join(self.imExtAppExe, 'convert'), convertArguments, dstPSFullPath, dstFullPath)
p2 = Popen(convertcmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=False)
p2.wait()
childIn2, childOut2, childErr2 =(p2.stdin, p2.stdout, p2.stderr)
if u"noerror" in [a.strip() for a in insToken.appendices]:
childErr.read()
errResponse = ""
else:
errResponse = childErr.read()
finally:
os.unlink(srcfilepath)
# Open logfile
if LOG:
f = open(baseDir + '\groff.log', 'a')
f.write(time.strftime('\n%d-%m-%Y %H:%M:%S\n'))
f.write("Current dir: %s\n" % os.getcwd())
f.write("Commandline: %s\n" % cmdline)
f.write(time.strftime('\n%d-%m-%Y %H:%M:%S') + ' : ' + errResponse)
f.write("Convert: %s\n" % convertcmd)
f.write("Appendices:\n")
for a in insToken.appendices:
appendices = a.strip().split("---")
for app in appendices:
f.write(app.strip() + "\n")
f.close()
if errResponse != "":
errResponse = mbcsDec(errResponse, "replace")[0]
return u"" + _(u"[Groff error: %s]") % errResponse +\
u""
# Return appropriate HTML code for the image
if exportType == "html_previewWX":
# Workaround for internal HTML renderer
return (u'