#!/usr/bin/env python # # tcl2py.py - try to Pythonize a vtk tcl script # # This code is based on tcl2py.py from VTK 3.2 which was written by # Randy Heiland. # # Changes: # # (21/12/2002) -- Prabhu Ramachandran # Made to work with re instead of regex. Superficial cleanup of the # code, fixed a few issues, using new VTK package structure, added # support for VTK_DATA_ROOT and set keyword, primitive support for # expr, made code easier to run with usage message etc. Seems to # generate decent output now. Simple Tcl scripts work out of the # box! Complex ones need work. For a truly general solution the # code has to be rewritten. # import sys import string import re def scanner(name,function): file = open(name,'r') while 1: line = file.readline() if not line: break function(line) file.close() def processLine(line, output, keepTcl=1): line = string.strip(line) + "\n" if line[0] == '#': output.write(line) elif line[:15] == 'package require': if keepTcl == 1: output.write('# ' + line) elif string.find(line, "deiconify") > -1: output.write('# ' + line) else: if keepTcl == 1: output.write('#' + line) if string.find(line, 'expr') > -1: match = re.search("\[\s*expr ([^\]]+)\]", line).groups()[0] match = re.sub('\s+', '', match) line = re.sub("\[\s*expr ([^\]]+)\]", match, line) line = re.sub('\[','',line) line = re.sub('\]','',line) line = re.sub('ren1','ren',line) line = re.sub(';','\n',line) line = re.sub('\$','',line) line = re.sub('{',' ',line) line = re.sub('}',' ',line) n = len(line) keys = string.split(line) # handle set keyword. inSet = 0 if len(keys) and keys[0] == 'set': output.write(keys[1] + ' = ') keys = keys[2:] inSet = 1 keysLength = len(keys) inaModule = 0 inaForLoop = 0 if keysLength == 0: output.write(line) # Catch some tcl-specific keywords and comment out elif keys[0] == 'proc': inaModule = 0 output.write( 'def ' + keys[1] + '(') if len(keys) > 2: output.write(keys[2]) for i in range(3,len(keys)): output.write(', ' + keys[i]) output.write('):\n') elif keys[0] == 'catch': output.write( '#' + line) elif keys[0] == 'source': output.write( '#' + line) if re.search("colors.tcl",line) > -1: output.write("from colors import *") elif keys[0] == 'wm': output.write( '#' + line) elif keysLength > 1 and keys[1] == 'SetUserMethod': if keepTcl == 1: output.write( '#' + line) elif keys[0] == 'for' and keys[1]=='set': inaForLoop = 1 #print '...Handling for loop' output.write( "for " + keys[2] + " in range(" + keys[3] +", ") upper = keys[6] if keys[5] == "<=": output.write( upper + "+1):\n" ) else: output.write( upper + "):\n" ) # Detect vtk class instance; Pythonize it. elif line[:3] == 'vtk': output.write( keys[1] + ' = vtk.' + keys[0] + '()\n' ) else: lparen = 0 finishedFlag = 0 # for i in range(len(keys)-1): for i in range(len(keys)): ls = len(keys[i]) if keys[i] == 'eval': continue # continuation mark elif keys[i] == '\\': output.write( " \\\n") elif keys[i][-8:] == 'FileName': if keys[i+1][0:1] == '"': f_name = re.sub('"VTK_DATA_ROOT/', \ 'VTK_DATA_ROOT + "/', keys[i+1]) output.write( keys[i] + "(" + f_name + ")") else: f_name = re.sub('VTK_DATA_ROOT/', \ 'VTK_DATA_ROOT + "/', keys[i+1]) if f_name[:13] == 'VTK_DATA_ROOT': output.write(keys[i] + "(" + f_name + "\")") else: output.write( keys[i] + "(\"" + keys[i+1] + "\")") finishedFlag = 1 break elif keys[i] == 'SetColor': #print '...doing SetColor' #print keys if not re.search('[-\d.]', keys[i+1][0:1]): #print '...got a named color' color = keys[i+1][0:] #print 'color = ' + color output.write( "SetColor(" + color+"[0]," + \ color+"[1]," + color+"[2])" ) else: output.write( "SetColor("+keys[i+1]+", "+keys[i+2]+", "+keys[i+3]+")") finishedFlag = 1 break elif keys[i][:3]=='Set' or keys[i][:3]=='Add' or keys[i][:6]=='Insert': output.write( keys[i] + '(' ) lparen = 1 elif i < len(keys)-1 and \ re.search('[-\d.]', keys[i+1][0:1]) and \ not re.search('[-\d.]', keys[i][ls-1:ls]): output.write( keys[i] + '(' ) lparen = 1 elif keys[i][:3] == 'Get': output.write( keys[i] + '()' ) if i < len(keys)-1: output.write( '.' ) else: if i < len(keys)-1: npos = re.search("[-\d.]", keys[i][0:1]) if npos > -1 or keys[i][0:3] == 'VTK': output.write( keys[i] + ', ' ) else: output.write( keys[i] + '.' ) else: if inaModule == 1: output.write( '\t' ) output.write( keys[i] ) if finishedFlag == 0: if keys[-1][:3] != 'Get' and \ (not re.search("[-+\d.]", keys[-1])): if lparen == 0: output.write( '(' ) lparen = 1 else: output.write( '\n' ) # Terminating right paren. #output.write( ')\n' ) if lparen == 1: output.write( ')\n' ) if inSet == 1: output.write( '\n' ) def usage(): msg = """Usage:\n tcl2py.py script.tcl [keep_tcl_code]\n This script attempts to convert a VTK-Tcl script to Python. The converted code is printed on the standard output. Options: keep_tcl_code -- If 1 it keeps the original tcl code in a commented line. If zero it does not print the translated Tcl line. Defaults to 1. Example: $ ./tcl2py.py example.tcl 0 > example.py """ print msg def main(): global keepTcl if len(sys.argv) < 2: usage() sys.exit(1) keepTcl = 1 if len(sys.argv) > 2: try: keepTcl = int(sys.argv[2]) except ValueError: usage() print "Second argument must be 0 or 1." sys.exit(1) name = sys.argv[1] output = sys.stdout if name[-4:] == '.tcl': input = open(name, 'r') #output = open(name[:-4] + '.py', 'w') else: input = open(name + '.tcl', 'r') #output = open(name + '.py', 'w') # Standard stuff; import useful things and handle VTK_DATA_ROOT. output.write('#!/usr/bin/env python\n') output.write('\nimport vtk\n') output.write('from vtk.util.misc import vtkGetDataRoot\n') output.write('VTK_DATA_ROOT = vtkGetDataRoot()\n\n') for line in input.readlines(): processLine(line, output, keepTcl) input.close() output.write('iren.Initialize()\nrenWin.Render()\niren.Start()\n') output.close() if __name__ == "__main__": main()