# --------------------------------------------------------------------------- #
# $Id: tex.py,v 1.6 2004/01/10 10:43:22 weismann Exp $
# --------------------------------------------------------------------------- #
#
# Encapsulated Postscript, source code via a2ps, LaTeX, Metapost and TeX support
#
# This file contains a bunch of hacks that demonstrate how you can try
# to integrate support for your favorite tool into pointless. There is NOT 
# much error checking at the moment. The aim was merely to demonstrate how to
# integrate support for external tools.
#
# The integration of a given tool <foo> can be split into four sections, the
# register_foo section, the write_foo section, the run_foo section and
# the _foo section. The register_foo is used to registre the command
# into the PLL language. The _foo function is the one that will be
# called as part of the parsing of the pll-input whenever a =foo (or a
# =begin-foo ... =end-foo section is detected. Finally, the write_foo 
# and run_foo functions are auxilary functions for the _foo function. 
# The write_foo is used to modify the input with additinon commands
# required for the run and the run_foo is finally used to run the
# external foo application.
#

from pllshared import *
import os
import re
import pllmodules 
import eps 

pll = None

_minlatexscale = 0.00001
_maxlatexscale = 100000.0

def register():
	latex = pll.add_command("latex", _latex, transform=1, vars=1)
	latex.set_attrs({'scale':3.0})
	shell = pll.add_command("shell", _shell, transform=1, vars=1)
	shell.set_attrs({'scale':3.0})

# --------------------------------------------------------------------------- #

def write_latex_file(filename, content):
	f = open(filename, 'w')
	f.write("\\documentclass[fleqn]{article}\n")
	f.write("\\usepackage[latin1]{inputenc}\n")
	f.write("\\begin{document}\n")
	f.write("\\thispagestyle{empty}\n")
	f.write("\\mathindent0cm\n")
	f.write("\\parindent0cm\n")
	f.write(content)
	f.write("\\end{document}\n")
	f.close()

def run_latex(filename):
	olddir = os.getcwd()
	path = os.path.dirname(filename)
	file = os.path.basename(filename)
	os.chdir(path)
	latex = pllmodules.find_program("latex")
	errormsg = ""
	if latex:
		failed = os.system("%s -interaction=batchmode %s" % (latex, file))
	else:
		errormsg = "Unable to find the latex program";
		return 0, errormsg
	if failed:
		logfile = re.sub("\.tex$",".log",file)
		log = open(logfile).readlines()
		relevant = 0
		for l in log:
			if re.match("^!",l): relevant = 2
			if relevant:
				errormsg += l
				relevant -= 1
	os.chdir(olddir)
	return not failed, errormsg

def _latex(args, text, vars):

	scale = vars['scale']
	if not scale or scale < _minlatexscale or scale > _maxlatexscale:
		errmsg = "latexscale must be in the interval (%f,%f)" % (_minlatexscale, _maxlatexscale)
		raise PllCommandError(errmsg)

	filename = pll.get_tempfilename()
	texfile = filename+".tex"
	epsfile = filename+".eps"
	dvifile = filename+".dvi"
	pngfile = filename+".png"

	oldmd5 = pllmodules.md5_file(texfile)
	re_txt = re.compile('[A-Za-z0-9]')
	r = re_txt.search(text)
	if r:
		write_latex_file(texfile, text)
	else:
		raise PllCommandError("Missing relevant input to latex\n")
	newmd5 = pllmodules.md5_file(texfile)

	if oldmd5 != newmd5 or not os.path.isfile(pngfile):
		ok, error = run_latex(texfile)
		if not ok:
			os.unlink(texfile) # to purge cache
			errmsg = "Error running LaTeX on '%s'.\n" % text
			errmsg += error
			raise PllCommandError(errmsg)
		ok, error = run_dvips(dvifile, epsfile)
		if not ok:
			os.unlink(texfile) # to purge cache
			errmsg = "Error running dvips on '%s'.\n" % dvifile
			errmsg += error
			raise PllCommandError(errmsg)

	ok, error = eps.eps2png(epsfile, pngfile, scale*pll.scale)

	if not ok:
		os.unlink(texfile) # to purge cache
		errmsg = "Error converting eps '%s'.\n" % epsfile
		errmsg += error
		raise PllCommandError(errmsg)

	return '=gaimage("%s")' % pngfile

# --------------------------------------------------------------------------- #

def run_dvips(filename, outfile):
	dvips = pllmodules.find_program("dvips")
	errormsg = ""
	if dvips:
		failed = os.system("%s -q -E %s -o %s" % (dvips, filename, outfile))
	else:
		errormsg = "Unable to find the dvips program";
		failed = 1
	return not failed, errormsg

# --------------------------------------------------------------------------- #

def run_tex(filename):
	olddir = os.getcwd()
	path = os.path.dirname(filename)
	file = os.path.basename(filename)
	os.chdir(path)
	tex = pllmodules.find_program("tex")
	if tex:
		failed = os.system("%s %s" % (tex, filename))
	else:
		errormsg = "Unable to find the tex program"
		os.chdir(olddir)
		return 0, errormsg

	errormsg = ""
	if failed:
		logfile = re.sub("\.tex$",".log",file)
		log = open(logfile).readlines()
		relevant = 0
		for l in log:
			if re.match("^!",l): relevant = 2
			if relevant:
				errormsg += l
				relevant -= 1
	os.chdir(olddir)
	return not failed, errormsg

# --------------------------------------------------------------------------- #

def write_shell_latex(filename, content):
	print content
	f = open(filename, 'w')
	f.write("\\documentclass[fleqn]{article}\n")
	f.write("\\usepackage[latin1]{inputenc}\n")
	f.write("\\begin{document}\n")
	f.write("\\thispagestyle{empty}\n")
	f.write("\\mathindent0cm\n")
	f.write("\\parindent0cm\n")
	f.write("\\begin{verbatim}\n")
	f.close()
	run_shell(filename, content)
	f = open(filename, 'a')
	f.write("\\end{verbatim}\n")
	f.write("\\end{document}\n")
	f.close()

def run_shell(filename, content):
	for l in str(content).split("\n"):
		failed = os.system("%s >> %s" % (l, filename))
		if failed:
			errmsg = "Unable to run %s >> %s" % (content, filename)
			raise PllCommandError(errmsg)
	
def _shell(args, text, vars):

	scale = vars['scale']
	if not scale or scale < _minlatexscale or scale > _maxlatexscale:
		errmsg = "latexscale must be in the interval (%f,%f)" % (_minlatexscale, _maxlatexscale)
		raise PllCommandError(errmsg)

	filename = pll.get_tempfilename()
	shelltex = filename+".tex"
	epsfile = filename+".eps"
	dvifile = filename+".dvi"
	pngfile = filename+".png"

	oldmd5 = pllmodules.md5_file(shelltex)
	write_shell_latex(shelltex, text.strip())
	newmd5 = pllmodules.md5_file(shelltex)

	if oldmd5 != newmd5 or not os.path.isfile(pngfile):
		ok, error = run_latex(shelltex)
		if not ok:
			os.unlink(shelltex) # to purge cache
			errmsg = "Error running LaTeX on '%s'.\n" % text
			errmsg += error
			raise PllCommandError(errmsg)
		ok, error = run_dvips(dvifile, epsfile)
		if not ok:
			os.unlink(shelltex) # to purge cache
			errmsg = "Error running dvips on '%s'.\n" % dvifile
			errmsg += error
			raise PllCommandError(errmsg)

	ok, error = eps.eps2png(epsfile, pngfile, vars['scale']*pll.scale)

	if not ok:
		os.unlink(shelltex) # to purge cache
		errmsg = "Error converting eps '%s'.\n" % epsfile
		errmsg += error
		raise PllCommandError(errmsg)

	return '=gaimage("%s")' % pngfile

# --------------------------------------------------------------------------- #

