Пример #1
0
	def __init__(self, plugin, attachment_folder=None):
		ImageGeneratorClass.__init__(self, plugin)
		file = data_file('templates/plugins/gnuploteditor.gnu')
		assert file, 'BUG: could not find templates/plugins/gnuploteditor.gnu'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.attachment_folder = attachment_folder
		self.plotscriptfile = TmpFile(self.scriptname)
Пример #2
0
 def __init__(self, plugin):
     ImageGeneratorClass.__init__(self, plugin)
     file = data_file('templates/plugins/scoreeditor.ly')
     assert file, 'BUG: could not find templates/plugins/scoreeditor.ly'
     self.template = GenericTemplate(file.readlines(), name=file)
     self.scorefile = TmpFile(self.scriptname)
     self.cur_lilypond_version = _get_lilypond_version()
     self.include_header = plugin.preferences['include_header']
     self.include_footer = plugin.preferences['include_footer']
Пример #3
0
	def testSyntax(self):
		'''Test Template processing simple statements without page'''
		input = '''
[%- SET test  = "foo"  -%]
[%- SET true  = "true" -%]
[%- SET false = ""     -%]
---
<b>[% test %]</b>
<i>[% some_none_existing_parameter %]</i>
<u>[% upper('foo') %]</u>
---
[% IF true %]OK[% ELSE %]NOK[% END %]
[% IF false -%]
OK
[%- ELSE -%]
NOK
[%- END %]
---
[% FOREACH name = [ 'foo', 'bar', 'baz' ] -%]
	NAME = [% GET name %]
[% END -%]
---
[% numbers = ['1', '2', '3'] -%]
[% FOREACH n IN numbers %][% n %]...[% END %]
---
'''

		wantedresult = u'''\
---
<b>foo</b>
<i></i>
<u>FOO</u>
---
OK
NOK
---
	NAME = foo
	NAME = bar
	NAME = baz
---
1...2...3...
---
'''
		tmpl = GenericTemplate(input)
		#~ import pprint
		#~ pprint.pprint( tmpl.tokens )
		dict = { 'upper': TemplateFunction(lambda d, *a: a[0].upper()) }
		result = tmpl.process(dict)
		#~ print test.getvalue()
		self.assertEqualDiff(result, wantedresult.splitlines(True))
Пример #4
0
	def testSyntax(self):
		'''Test Template processing simple statements without page'''
		input = '''
[%- SET test  = "foo"  -%]
[%- SET true  = "true" -%]
[%- SET false = ""     -%]
---
<b>[% test %]</b>
<i>[% some_none_existing_parameter %]</i>
<u>[% upper('foo') %]</u>
---
[% IF true %]OK[% ELSE %]NOK[% END %]
[% IF false -%]
OK
[%- ELSE -%]
NOK
[%- END %]
---
[% FOREACH name = [ 'foo', 'bar', 'baz' ] -%]
	NAME = [% GET name %]
[% END -%]
---
[% numbers = ['1', '2', '3'] -%]
[% FOREACH n IN numbers %][% n %]...[% END %]
---
'''

		wantedresult = u'''\
---
<b>foo</b>
<i></i>
<u>FOO</u>
---
OK
NOK
---
	NAME = foo
	NAME = bar
	NAME = baz
---
1...2...3...
---
'''
		tmpl = GenericTemplate(input)
		#~ import pprint
		#~ pprint.pprint( tmpl.tokens )
		dict = { 'upper': TemplateFunction(lambda d, *a: a[0].upper()) }
		result = tmpl.process(dict)
		#~ print test.getvalue()
		self.assertEqual(result, wantedresult.splitlines(True))
Пример #5
0
	def __init__(self, plugin):
		ImageGeneratorClass.__init__(self, plugin)
		file = data_file('templates/plugins/scoreeditor.ly')
		assert file, 'BUG: could not find templates/plugins/scoreeditor.ly'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.scorefile = TmpFile(self.scriptname)
		self.cur_lilypond_version = _get_lilypond_version()
		self.include_header = plugin.preferences['include_header']
		self.include_footer = plugin.preferences['include_footer']
Пример #6
0
	def __init__(self, preferences={}):
		file = data_file('templates/plugins/scoreeditor.ly')
		assert file, 'BUG: could not find templates/plugins/scoreeditor.ly'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.scorefile = TmpFile(self.scriptname)
		self.cur_lilypond_version = _get_lilypond_version()
		if preferences.has_key('include_header'):
			self.include_header = preferences['include_header']
		if preferences.has_key('include_footer'):
			self.include_footer = preferences['include_footer']
Пример #7
0
class GnuplotGenerator(ImageGeneratorClass):

	uses_log_file = False

	object_type = 'gnuplot'
	scriptname = 'gnuplot.gnu'
	imagename = 'gnuplot.png'

	def __init__(self, plugin, attachment_folder=None):
		ImageGeneratorClass.__init__(self, plugin)
		file = data_file('templates/plugins/gnuploteditor.gnu')
		assert file, 'BUG: could not find templates/plugins/gnuploteditor.gnu'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.attachment_folder = attachment_folder
		self.plotscriptfile = TmpFile(self.scriptname)

	def generate_image(self, text):
		if isinstance(text, basestring):
			text = text.splitlines(True)

		plotscriptfile = self.plotscriptfile
		pngfile = File(plotscriptfile.path[:-4] + '.png')

		plot_script = "".join(text)

		template_vars = { # they go in the template
			'gnuplot_script': plot_script,
			'png_fname': pngfile.path,
		}
		if self.attachment_folder and self.attachment_folder.exists():
			template_vars['attachment_folder'] = self.attachment_folder.path

		# Write to tmp file using the template for the header / footer
		plotscriptfile.writelines(
			self.template.process(template_vars)
		)
		#~ print '>>>\n%s<<<' % plotscriptfile.read()

		# Call Gnuplot
		try:
			gnu_gp = Application(gnuplot_cmd)
			gnu_gp.run(args=( plotscriptfile.basename, ), cwd=plotscriptfile.dir)
							# you call it as % gnuplot output.plt

		except ApplicationError:
			return None, None # Sorry - no log
		else:
			return pngfile, None

	def cleanup(self):
		path = self.plotscriptfile.path
		for path in glob.glob(path[:-4]+'.*'):
			File(path).remove()
Пример #8
0
class EquationGenerator(object):

	# TODO: generic base class for image generators

	type = 'equation'
	basename = 'equation.tex'

	def __init__(self):
		file = data_file('templates/_Equation.tex')
		assert file, 'BUG: could not find templates/_Equation.tex'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.texfile = TmpFile('latex-equation.tex')

	def generate_image(self, text):
		if isinstance(text, basestring):
			text = text.splitlines(True)

		# Filter out empty lines, not allowed in latex equation blocks
		text = (line for line in text if line and not line.isspace())
		text = ''.join(text)
		#~ print '>>>%s<<<' % text

		# Write to tmp file usign the template for the header / footer
		texfile = self.texfile
		texfile.writelines(
			self.template.process({'equation': text}) )
		#~ print '>>>%s<<<' % texfile.read()

		# Call latex
		logfile = File(texfile.path[:-4] + '.log') # len('.tex') == 4
		try:
			latex = Application(latexcmd)
			latex.run((texfile.basename,), cwd=texfile.dir)
		except:
			# log should have details of failure
			return None, logfile

		# Call dvipng
		dvifile = File(texfile.path[:-4] + '.dvi') # len('.tex') == 4
		pngfile = File(texfile.path[:-4] + '.png') # len('.tex') == 4
		dvipng = Application(dvipngcmd)
		dvipng.run((pngfile, dvifile)) # output, input
			# No try .. except here - should never fail
		# TODO dvipng can start processing before latex finished - can we win speed there ?

		return pngfile, logfile

	def cleanup(self):
		path = self.texfile.path
		for path in glob.glob(path[:-4]+'.*'):
			File(path).remove()
Пример #9
0
class GNURPlotGenerator(ImageGeneratorClass):

	uses_log_file = False

	object_type = 'gnu_r_plot'
	scriptname = 'gnu_r_plot.r'
	imagename = 'gnu_r_plot.png'

	def __init__(self, plugin):
		ImageGeneratorClass.__init__(self, plugin)
		file = data_file('templates/plugins/gnu_r_editor.r')
		assert file, 'BUG: could not find templates/plugins/gnu_r_editor.r'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.plotscriptfile = TmpFile(self.scriptname)

	def generate_image(self, text):
		if isinstance(text, basestring):
			text = text.splitlines(True)

		plotscriptfile = self.plotscriptfile
		pngfile = File(plotscriptfile.path[:-2] + '.png')

		plot_script = "".join(text)

		template_vars = {
			'gnu_r_plot_script': plot_script,
			'png_fname': pngfile.path.replace('\\', '/'),
				# Even on windows, GNU R expects unix path seperator
		}

		# Write to tmp file usign the template for the header / footer
		plotscriptfile.writelines(
			self.template.process(template_vars)
		)
		#print '>>>%s<<<' % plotscriptfile.read()

		# Call GNU R
		try:
			gnu_r = Application(gnu_r_cmd)
			#~ gnu_r.run(args=('-f', plotscriptfile.basename, ), cwd=plotscriptfile.dir)
			gnu_r.run(args=('-f', plotscriptfile.basename, '--vanilla'), cwd=plotscriptfile.dir)
		except:
			return None, None # Sorry, no log
		else:
			return pngfile, None

	def cleanup(self):
		path = self.plotscriptfile.path
		for path in glob.glob(path[:-2]+'.*'):
			File(path).remove()
Пример #10
0
class EquationGenerator(ImageGeneratorClass):

    object_type = 'equation'
    scriptname = 'equation.tex'
    imagename = 'equation.png'

    def __init__(self, plugin):
        ImageGeneratorClass.__init__(self, plugin)
        file = data_file('templates/plugins/equationeditor.tex')
        assert file, 'BUG: could not find templates/plugins/equationeditor.tex'
        self.template = GenericTemplate(file.readlines(), name=file)
        self.texfile = TmpFile(self.scriptname)

    def generate_image(self, text):
        if isinstance(text, basestring):
            text = text.splitlines(True)

        # Filter out empty lines, not allowed in latex equation blocks
        text = (line for line in text if line and not line.isspace())
        text = ''.join(text)
        #~ print '>>>%s<<<' % text

        # Write to tmp file using the template for the header / footer
        texfile = self.texfile
        texfile.writelines(self.template.process({'equation': text}))
        #~ print '>>>%s<<<' % texfile.read()

        # Call latex
        logfile = File(texfile.path[:-4] + '.log')  # len('.tex') == 4
        try:
            latex = Application(latexcmd)
            latex.run((texfile.basename, ), cwd=texfile.dir)
        except ApplicationError:
            # log should have details of failure
            return None, logfile

        # Call dvipng
        dvifile = File(texfile.path[:-4] + '.dvi')  # len('.tex') == 4
        pngfile = File(texfile.path[:-4] + '.png')  # len('.tex') == 4
        dvipng = Application(dvipngcmd)
        dvipng.run((pngfile, dvifile))  # output, input
        # No try .. except here - should never fail
        # TODO dvipng can start processing before latex finished - can we win speed there ?

        return pngfile, logfile

    def cleanup(self):
        path = self.texfile.path
        for path in glob.glob(path[:-4] + '.*'):
            File(path).remove()
Пример #11
0
	def testRaise(self):
		'''Test Template invalid syntax raises TemplateError'''
		input = 'foo[% ELSE %]bar'
		self.assertRaises(TemplateSyntaxError, GenericTemplate, input)

		input = 'foo[% FOREACH foo = ("1", "2", "3") %]bar'
		self.assertRaises(TemplateSyntaxError, GenericTemplate, input)

		input = 'foo[% `echo /etc/passwd` %]bar'
		self.assertRaises(TemplateSyntaxError, GenericTemplate, input)

		input = 'foo[% duss("ja") %]bar'
		templ = GenericTemplate(input)
		self.assertRaises(TemplateProcessError, templ.process, {})
Пример #12
0
	def runTest(self):
		'''Load all shipped templates for syntax check'''
		for dir, dirs, files in os.walk('./data/templates'):
			format = os.path.basename(dir)
			if format == 'templates':
				continue # skip top level dir
			files = [f for f in files if not f.startswith('.') and not '~' in f]
			files.sort()
			self.assertTrue(len(files) > 0)
			templates = list_templates(format)
			for file in files:
				self.assertIn(file, [t[1] for t in templates])

				file = os.path.join(dir, file)
				input = open(file).readlines()
				if format == 'plugins':
					tmpl = GenericTemplate(input)
				else:
					tmpl = Template(input, format)
Пример #13
0
class ScoreGenerator(ImageGeneratorClass):

	object_type = 'score'
	scriptname = 'score.ly'
	imagename = 'score.png'
	cur_lilypond_version = None

	def __init__(self, plugin):
		ImageGeneratorClass.__init__(self, plugin)
		file = data_file('templates/plugins/scoreeditor.ly')
		assert file, 'BUG: could not find templates/plugins/scoreeditor.ly'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.scorefile = TmpFile(self.scriptname)
		self.cur_lilypond_version = _get_lilypond_version()
		self.include_header = plugin.preferences['include_header']
		self.include_footer = plugin.preferences['include_footer']

	def process_input(self, text):
		'''Prepend version string to user input. It is also stored in
		the script file.
		'''
		version_present = False
		for l in text.splitlines(True):
			if l.strip().startswith('\\version'):
				version_present = True
		if not version_present:
			text = '\\version "{0}"\n\n'.format(self.cur_lilypond_version) + text
		return text

	def extract_version(self, text):
		outtext = []
		version = None
		for l in text:
			if l.strip().startswith('\\version'):
				version = l.strip()
			else:
				outtext.append(l)
		return (version, outtext)

	def generate_image(self, text):
		if isinstance(text, basestring):
			text = text.splitlines(True)

		(version, text) = self.extract_version(text)
		text = ''.join(text)
		#~ print '>>>%s<<<' % text

		# Write to tmp file using the template for the header / footer
		scorefile = self.scorefile
		scorefile.writelines(
			self.template.process({'score': text,
				'version': version,
				'include_header': self.include_header,
				'include_footer': self.include_footer}) )
		#~ print '>>>%s<<<' % scorefile.read()

		# Call convert-ly to convert document of current version of
		# Lilypond.
		clogfile = File(scorefile.path[:-3] + '-convertly.log') # len('.ly) == 3
		try:
			convertly = Application(convertly_cmd)
			convertly.run((scorefile.basename,), cwd=scorefile.dir)
		except ApplicationError:
			clogfile.write('convert-ly failed.\n')
			return None, clogfile


		# Call lilypond to generate image.
		logfile = File(scorefile.path[:-3] + '.log') # len('.ly') == 3
		try:
			lilypond = Application(lilypond_cmd)
			lilypond.run(('-dlog-file=' + logfile.basename[:-4], scorefile.basename,), cwd=scorefile.dir)
		except ApplicationError:
			# log should have details of failure
			return None, logfile
		pngfile = File(scorefile.path[:-3] + '.png') # len('.ly') == 3

		return pngfile, logfile

	def cleanup(self):
		path = self.scorefile.path
		for path in glob.glob(path[:-3]+'*'):
			File(path).remove()
Пример #14
0
	def _init_inputs(self, namespace, basename, append, text, template_options, custom=None):
		if template_options is None:
			template_options = {}
		else:
			template_options = template_options.copy()

		if namespace is not None and basename is not None:
			page = namespace + ':' + basename
		else:
			page = namespace or basename

		self.form.add_inputs( (
				('page', 'page', _('Page')),
				('namespace', 'namespace', _('Namespace')), # T: text entry field
				('new_page', 'bool', _('Create a new page for each note')), # T: checkbox in Quick Note dialog
				('basename', 'string', _('Title')) # T: text entry field
			) )
		self.form.update({
				'page': page,
				'namespace': namespace,
				'new_page': True,
				'basename': basename,
			} )

		self.uistate.setdefault('open_page', True)
		self.uistate.setdefault('new_page', True)

		if basename:
			self.uistate['new_page'] = True # Be consistent with input

		# Set up the inputs and set page/ namespace to switch on
		# toggling the checkbox
		self.form.widgets['page'].set_no_show_all(True)
		self.form.widgets['namespace'].set_no_show_all(True)
		if append is None:
			self.form['new_page'] = bool(self.uistate['new_page'])
		else:
			self.form['new_page'] = not append

		def switch_input(*a):
			if self.form['new_page']:
				self.form.widgets['page'].hide()
				self.form.widgets['namespace'].show()
				self.form.widgets['basename'].set_sensitive(True)
			else:
				self.form.widgets['page'].show()
				self.form.widgets['namespace'].hide()
				self.form.widgets['basename'].set_sensitive(False)

		switch_input()
		self.form.widgets['new_page'].connect('toggled', switch_input)

		self.open_page = gtk.CheckButton(_('Open _Page')) # T: Option in quicknote dialog
			# Don't use "O" as accelerator here to avoid conflict with "Ok"
		self.open_page.set_active(self.uistate['open_page'])
		self.action_area.pack_start(self.open_page, False)
		self.action_area.set_child_secondary(self.open_page, True)

		# Add the main textview and hook up the basename field to
		# sync with first line of the textview
		window, textview = ScrolledTextView()
		self.textview = textview
		self.textview.set_editable(True)
		self.vbox.add(window)

		self.form.widgets['basename'].connect('changed', self.on_title_changed)
		self.textview.get_buffer().connect('changed', self.on_text_changed)

		# Initialize text from template
		file = data_file('templates/plugins/quicknote.txt')
		template = GenericTemplate(file.readlines(), name=file)
		template_options.update({
			'text': text or '',
			'strftime': StrftimeFunction(),
		} )
		output = template.process(template_options)
		buffer = self.textview.get_buffer()
		buffer.set_text(''.join(output))
		begin, end = buffer.get_bounds()
		buffer.place_cursor(begin)

		buffer.set_modified(False)

		self.connect('delete-event', self.do_delete_event)
Пример #15
0
    def _init_inputs(self,
                     namespace,
                     basename,
                     append,
                     text,
                     template_options,
                     custom=None):
        if template_options is None:
            template_options = {}
        else:
            template_options = template_options.copy()

        if namespace is not None and basename is not None:
            page = namespace + ':' + basename
        else:
            page = namespace or basename

        self.form.add_inputs((
            ('page', 'page', _('Page')),
            ('namespace', 'namespace', _('Namespace')),  # T: text entry field
            ('new_page', 'bool', _('Create a new page for each note')
             ),  # T: checkbox in Quick Note dialog
            ('basename', 'string', _('Title'))  # T: text entry field
        ))
        self.form.update({
            'page': page,
            'namespace': namespace,
            'new_page': True,
            'basename': basename,
        })

        self.uistate.setdefault('open_page', True)
        self.uistate.setdefault('new_page', True)

        if basename:
            self.uistate['new_page'] = True  # Be consistent with input

        # Set up the inputs and set page/ namespace to switch on
        # toggling the checkbox
        self.form.widgets['page'].set_no_show_all(True)
        self.form.widgets['namespace'].set_no_show_all(True)
        if append is None:
            self.form['new_page'] = bool(self.uistate['new_page'])
        else:
            self.form['new_page'] = not append

        def switch_input(*a):
            if self.form['new_page']:
                self.form.widgets['page'].hide()
                self.form.widgets['namespace'].show()
                self.form.widgets['basename'].set_sensitive(True)
            else:
                self.form.widgets['page'].show()
                self.form.widgets['namespace'].hide()
                self.form.widgets['basename'].set_sensitive(False)

        switch_input()
        self.form.widgets['new_page'].connect('toggled', switch_input)

        self.open_page = gtk.CheckButton(
            _('Open _Page'))  # T: Option in quicknote dialog
        # Don't use "O" as accelerator here to avoid conflict with "Ok"
        self.open_page.set_active(self.uistate['open_page'])
        self.action_area.pack_start(self.open_page, False)
        self.action_area.set_child_secondary(self.open_page, True)

        # Add the main textview and hook up the basename field to
        # sync with first line of the textview
        window, textview = ScrolledTextView()
        self.textview = textview
        self.textview.set_editable(True)
        self.vbox.add(window)

        self.form.widgets['basename'].connect('changed', self.on_title_changed)
        self.textview.get_buffer().connect('changed', self.on_text_changed)

        # Initialize text from template
        file = data_file('templates/plugins/quicknote.txt')
        template = GenericTemplate(file.readlines(), name=file)
        template_options.update({
            'text': text or '',
            'strftime': StrftimeFunction(),
        })
        output = template.process(template_options)
        buffer = self.textview.get_buffer()
        buffer.set_text(''.join(output))
        begin, end = buffer.get_bounds()
        buffer.place_cursor(begin)

        buffer.set_modified(False)

        self.connect('delete-event', self.do_delete_event)
Пример #16
0
class ScoreGenerator(ImageGeneratorClass):

    object_type = 'score'
    scriptname = 'score.ly'
    imagename = 'score.png'
    cur_lilypond_version = None

    def __init__(self, plugin):
        ImageGeneratorClass.__init__(self, plugin)
        file = data_file('templates/plugins/scoreeditor.ly')
        assert file, 'BUG: could not find templates/plugins/scoreeditor.ly'
        self.template = GenericTemplate(file.readlines(), name=file)
        self.scorefile = TmpFile(self.scriptname)
        self.cur_lilypond_version = _get_lilypond_version()
        self.include_header = plugin.preferences['include_header']
        self.include_footer = plugin.preferences['include_footer']

    def process_input(self, text):
        '''Prepend version string to user input. It is also stored in
		the script file.
		'''
        version_present = False
        for l in text.splitlines(True):
            if l.strip().startswith('\\version'):
                version_present = True
        if not version_present:
            text = '\\version "{0}"\n\n'.format(
                self.cur_lilypond_version) + text
        return text

    def extract_version(self, text):
        outtext = []
        version = None
        for l in text:
            if l.strip().startswith('\\version'):
                version = l.strip()
            else:
                outtext.append(l)
        return (version, outtext)

    def generate_image(self, text):
        if isinstance(text, basestring):
            text = text.splitlines(True)

        (version, text) = self.extract_version(text)
        text = ''.join(text)
        #~ print '>>>%s<<<' % text

        # Write to tmp file using the template for the header / footer
        scorefile = self.scorefile
        scorefile.writelines(
            self.template.process({
                'score': text,
                'version': version,
                'include_header': self.include_header,
                'include_footer': self.include_footer
            }))
        #~ print '>>>%s<<<' % scorefile.read()

        # Call convert-ly to convert document of current version of
        # Lilypond.
        clogfile = File(scorefile.path[:-3] +
                        '-convertly.log')  # len('.ly) == 3
        try:
            convertly = Application(convertly_cmd)
            convertly.run((scorefile.basename, ), cwd=scorefile.dir)
        except ApplicationError:
            clogfile.write('convert-ly failed.\n')
            return None, clogfile

        # Call lilypond to generate image.
        logfile = File(scorefile.path[:-3] + '.log')  # len('.ly') == 3
        try:
            lilypond = Application(lilypond_cmd)
            lilypond.run((
                '-dlog-file=' + logfile.basename[:-4],
                scorefile.basename,
            ),
                         cwd=scorefile.dir)
        except ApplicationError:
            # log should have details of failure
            return None, logfile
        pngfile = File(scorefile.path[:-3] + '.png')  # len('.ly') == 3

        return pngfile, logfile

    def cleanup(self):
        path = self.scorefile.path
        for path in glob.glob(path[:-3] + '*'):
            File(path).remove()
Пример #17
0
 def __init__(self, plugin):
     ImageGeneratorClass.__init__(self, plugin)
     file = data_file('templates/plugins/equationeditor.tex')
     assert file, 'BUG: could not find templates/plugins/equationeditor.tex'
     self.template = GenericTemplate(file.readlines(), name=file)
     self.texfile = TmpFile(self.scriptname)
Пример #18
0
	def __init__(self):
		file = data_file('templates/_Equation.tex')
		assert file, 'BUG: could not find templates/_Equation.tex'
		self.template = GenericTemplate(file.readlines(), name=file)
		self.texfile = TmpFile('latex-equation.tex')
Пример #19
0
 def __init__(self):
     file = data_file('templates/plugins/gnu_r_editor.r')
     assert file, 'BUG: could not find templates/plugins/gnu_r_editor.r'
     self.template = GenericTemplate(file.readlines(), name=file)
     self.plotscriptfile = TmpFile(self.scriptname)
Пример #20
0
 def __init__(self):
     file = data_file('templates/plugins/equationeditor.tex')
     assert file, 'BUG: could not find templates/plugins/equationeditor.tex'
     self.template = GenericTemplate(file.readlines(), name=file)
     self.texfile = TmpFile(self.scriptname)