- Better commandline interface to BuildApplet, complete with options,
  verbose output to the console, etc.
- Allow Cocoa applets to be built with BuildApplet.

No full testing has been done yet to ensure OS9 operation hasn't suffered.
diff --git a/Mac/Lib/buildtools.py b/Mac/Lib/buildtools.py
index 0eef5ac..d831610 100644
--- a/Mac/Lib/buildtools.py
+++ b/Mac/Lib/buildtools.py
@@ -17,9 +17,6 @@
 
 BuildError = "BuildError"
 
-DEBUG=1
-
-
 # .pyc file (and 'PYC ' resource magic number)
 MAGIC = imp.get_magic()
 
@@ -70,13 +67,13 @@
 	return '/'.join(execpath[:i])
 
 
-def process(template, filename, output, copy_codefragment):
+def process(template, filename, destname, copy_codefragment, 
+		rsrcname=None, others=[], raw=0, progress="default"):
 	
-	if DEBUG:
+	if progress == "default":
 		progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120)
 		progress.label("Compiling...")
-	else:
-		progress = None
+		progress.inc(0)
 	
 	# Read the source and compile it
 	# (there's no point overwriting the destination if it has a syntax error)
@@ -89,34 +86,38 @@
 	except (SyntaxError, EOFError):
 		raise BuildError, "Syntax error in script %s" % `filename`
 	
-	# Set the destination file name
+	# Set the destination file name. Note that basename
+	# does contain the whole filepath, only a .py is stripped.
 	
 	if string.lower(filename[-3:]) == ".py":
-		destname = filename[:-3]
-		rsrcname = destname + '.rsrc'
+		basename = filename[:-3]
+		if MacOS.runtimemodel != 'macho' and not destname:
+			destname = basename
 	else:
+		basename = filename
+		
+	if not destname:
 		if MacOS.runtimemodel == 'macho':
-			destname = filename + '.app'
+			destname = basename + '.app'
 		else:
-			destname = filename + ".applet"
-		rsrcname = filename + '.rsrc'
-	
-	if output:
-		destname = output
-	
+			destname = basename + '.applet'
+	if not rsrcname:
+		rsrcname = basename + '.rsrc'
+		
 	# Try removing the output file. This fails in MachO, but it should
 	# do any harm.
 	try:
 		os.remove(destname)
 	except os.error:
 		pass
-	process_common(template, progress, code, rsrcname, destname, 0, copy_codefragment)
+	process_common(template, progress, code, rsrcname, destname, 0, 
+		copy_codefragment, raw, others)
 	
 
 def update(template, filename, output):
 	if MacOS.runtimemodel == 'macho':
 		raise BuildError, "No updating yet for MachO applets"
-	if DEBUG:
+	if progress:
 		progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
 	else:
 		progress = None
@@ -131,16 +132,20 @@
 	process_common(template, progress, None, filename, output, 1, 1)
 
 
-def process_common(template, progress, code, rsrcname, destname, is_update, copy_codefragment):
+def process_common(template, progress, code, rsrcname, destname, is_update, 
+		copy_codefragment, raw=0, others=[]):
 	if MacOS.runtimemodel == 'macho':
-		return process_common_macho(template, progress, code, rsrcname, destname, is_update)
+		return process_common_macho(template, progress, code, rsrcname, destname,
+			is_update, raw, others)
+	if others:
+		raise BuildError, "Extra files only allowed for MachoPython applets"
 	# Create FSSpecs for the various files
 	template_fss = macfs.FSSpec(template)
 	template_fss, d1, d2 = macfs.ResolveAliasFile(template_fss)
 	dest_fss = macfs.FSSpec(destname)
 	
 	# Copy data (not resources, yet) from the template
-	if DEBUG:
+	if progress:
 		progress.label("Copy data fork...")
 		progress.set(10)
 	
@@ -157,7 +162,7 @@
 	
 	# Open the output resource fork
 	
-	if DEBUG:
+	if progress:
 		progress.label("Copy resources...")
 		progress.set(20)
 	try:
@@ -172,7 +177,7 @@
 		input = Res.FSpOpenResFile(rsrcname, READ)
 	except (MacOS.Error, ValueError):
 		pass
-		if DEBUG:
+		if progress:
 			progress.inc(50)
 	else:
 		if is_update:
@@ -222,7 +227,7 @@
 			pass
 		
 		# Create the raw data for the resource from the code object
-		if DEBUG:
+		if progress:
 			progress.label("Write PYC resource...")
 			progress.set(120)
 		
@@ -256,10 +261,11 @@
 	dest_fss.SetFInfo(dest_finfo)
 	
 	macostools.touched(dest_fss)
-	if DEBUG:
+	if progress:
 		progress.label("Done.")
+		progress.inc(0)
 
-def process_common_macho(template, progress, code, rsrcname, destname, is_update):
+def process_common_macho(template, progress, code, rsrcname, destname, is_update, raw=0, others=[]):
 	# First make sure the name ends in ".app"
 	if destname[-4:] != '.app':
 		destname = destname + '.app'
@@ -286,14 +292,17 @@
 				"Contents/Resources/English.lproj/InfoPlist.strings", 
 				"Contents/Resources/python.rsrc",
 				]
-		copyapptree(template, destname, exceptlist)
+		copyapptree(template, destname, exceptlist, progress)
 	# Now either use the .plist file or the default
+	if progress:
+		progress.label('Create info.plist')
+		progress.inc(0)
 	if plistname:
-		shutil.copy2(plistname, os.path.join(destname, 'Contents/Info.plist'))
+		shutil.copy2(plistname, os.path.join(destname, 'Contents', 'Info.plist'))
 		if icnsname:
 			icnsdest = os.path.split(icnsname)[1]
 			icnsdest = os.path.join(destname, 
-				os.path.join('Contents/Resources', icnsdest))
+				os.path.join('Contents', 'Resources', icnsdest))
 			shutil.copy2(icnsname, icnsdest)
 		# XXXX Wrong. This should be parsed from plist file. Also a big hack:-)
 		if shortname == 'PythonIDE':
@@ -302,31 +311,44 @@
 			ownertype = 'PytA'
 		# XXXX Should copy .icns file
 	else:
-		plistname = os.path.join(template, 'Contents/Resources/Applet-Info.plist')
+		cocoainfo = ''
+		for o in others:
+			if o[-4:] == '.nib':
+				nibname = os.path.split(o)[1][:-4]
+				cocoainfo = """
+        <key>NSMainNibFile</key>
+        <string>%s</string>
+        <key>NSPrincipalClass</key>
+        <string>NSApplication</string>""" % nibname
+
+
+		plistname = os.path.join(template, 'Contents', 'Resources', 'Applet-Info.plist')
 		plistdata = open(plistname).read()
-		plistdata = plistdata % {'appletname':shortname}
-		ofp = open(os.path.join(destname, 'Contents/Info.plist'), 'w')
+		plistdata = plistdata % {'appletname':shortname, 'cocoainfo':cocoainfo}
+		ofp = open(os.path.join(destname, 'Contents', 'Info.plist'), 'w')
 		ofp.write(plistdata)
 		ofp.close()
 		ownertype = 'PytA'
 	# Create the PkgInfo file
-	ofp = open(os.path.join(destname, 'Contents/PkgInfo'), 'wb')
+	if progress:
+		progress.label('Create PkgInfo')
+		progress.inc(0)
+	ofp = open(os.path.join(destname, 'Contents', 'PkgInfo'), 'wb')
 	ofp.write('APPL' + ownertype)
 	ofp.close()
 		
 	
-	if DEBUG:
+	if progress:
 		progress.label("Copy resources...")
 		progress.set(20)
 	resfilename = '%s.rsrc' % shortname
-	respartialpathname = 'Contents/Resources/%s' % resfilename
 	try:
 		output = Res.FSOpenResourceFile(
-				os.path.join(destname, respartialpathname), 
+				os.path.join(destname, 'Contents', 'Resources', resfilename), 
 				u'', WRITE)
 	except MacOS.Error:
 		fsr, dummy = Res.FSCreateResourceFile(
-				os.path.join(destname, 'Contents/Resources'), 
+				os.path.join(destname, 'Contents', 'Resources'), 
 				unicode(resfilename), '')
 		output = Res.FSOpenResourceFile(fsr, u'', WRITE)
 	
@@ -336,7 +358,7 @@
 		input = macresource.open_pathname(rsrcname)
 	except (MacOS.Error, ValueError):
 		pass
-		if DEBUG:
+		if progress:
 			progress.inc(50)
 	else:
 		typesfound, ownertype = copyres(input, output, [], 0, progress)
@@ -355,8 +377,12 @@
 	# Copy the resources from the template
 	
 	input = Res.FSOpenResourceFile(
-			os.path.join(template, 'Contents/Resources/python.rsrc'), u'', READ)
-	dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
+			os.path.join(template, 'Contents', 'Resources', 'python.rsrc'), u'', READ)
+	if progress:
+		progress.label("Copy standard resources...")
+		progress.inc(0)
+##	dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
+	dummy, tmplowner = copyres(input, output, skiptypes, 1, None)
 		
 	Res.CloseResFile(input)
 ##	if ownertype == None:
@@ -366,8 +392,29 @@
 	Res.CloseResFile(output)
 
 	if code:
-		outputfilename = os.path.join(destname, 'Contents/Resources/__main__.pyc')
+		if raw:
+			pycname = '__rawmain__.pyc'
+		else:
+			pycname = '__main__.pyc'
+		outputfilename = os.path.join(destname, 'Contents', 'Resources', pycname)
+		if progress:
+			progress.label('Creating '+pycname)
+			progress.inc(0)
 		writepycfile(code, outputfilename)
+	# Copy other files the user asked for
+	for osrc in others:
+		oname = os.path.split(osrc)[1]
+		odst = os.path.join(destname, 'Contents', 'Resources', oname)
+		if progress: 
+			progress.label('Copy ' + oname)
+			progress.inc(0)
+		if os.path.isdir(osrc):
+			copyapptree(osrc, odst)
+		else:
+			shutil.copy2(osrc, odst)
+	if progress: 
+		progress.label('Done.')
+		progress.inc(0)
 	
 ##	macostools.touched(dest_fss)
 
@@ -400,7 +447,7 @@
 					ctor = type
 			size = res.size
 			attrs = res.GetResAttrs()
-			if DEBUG and progress:
+			if progress:
 				progress.label("Copy %s %d %s"%(type, id, name))
 				progress.inc(progress_cur_inc)
 			res.LoadResource()
@@ -411,8 +458,9 @@
 			except MacOS.Error:
 				res2 = None
 			if res2:
-				if DEBUG and progress:
+				if progress:
 					progress.label("Overwrite %s %d %s"%(type, id, name))
+					progress.inc(0)
 				res2.RemoveResource()
 			res.AddResource(type, id, name)
 			res.WriteResource()
@@ -421,7 +469,7 @@
 			Res.UseResFile(input)
 	return alltypes, ctor
 
-def copyapptree(srctree, dsttree, exceptlist=[]):
+def copyapptree(srctree, dsttree, exceptlist=[], progress=None):
 	names = []
 	if os.path.exists(dsttree):
 		shutil.rmtree(dsttree)
@@ -443,6 +491,9 @@
 		if os.path.isdir(srcpath):
 			os.mkdir(dstpath)
 		else:
+			if progress:
+				progress.label('Copy '+this)
+				progress.inc(0)
 			shutil.copy2(srcpath, dstpath)
 			
 def writepycfile(codeobject, cfile):
diff --git a/Mac/OSXResources/app/Resources/Applet-Info.plist b/Mac/OSXResources/app/Resources/Applet-Info.plist
index 8a61e6c..0440999 100644
--- a/Mac/OSXResources/app/Resources/Applet-Info.plist
+++ b/Mac/OSXResources/app/Resources/Applet-Info.plist
@@ -22,6 +22,8 @@
 
 	<key>CFBundleGetInfoString</key>
 	<string>%(appletname)s, a Python applet</string>
+	
+	%(cocoainfo)s
 
 	<key>CFBundleIconFile</key>
 	<string>PythonApplet.icns</string>
diff --git a/Mac/scripts/BuildApplet.py b/Mac/scripts/BuildApplet.py
index b57c425..0679825 100644
--- a/Mac/scripts/BuildApplet.py
+++ b/Mac/scripts/BuildApplet.py
@@ -15,7 +15,7 @@
 import MacOS
 import EasyDialogs
 import buildtools
-
+import getopt
 
 def main():
 	try:
@@ -54,14 +54,71 @@
 			buildtools.process(template, filename, dstfilename, 1)
 	else:
 		
+		SHORTOPTS = "o:r:ne:v?"
+		LONGOPTS=("output=", "resource=", "noargv", "extra=", "verbose", "help")
+		try:
+			options, args = getopt.getopt(sys.argv[1:], SHORTOPTS, LONGOPTS)
+		except getopt.error:
+			usage()
+		if options and len(args) > 1:
+			sys.stderr.write("Cannot use options when specifying multiple input files")
+			sys.exit(1)
+		dstfilename = None
+		rsrcfilename = None
+		raw = 0
+		extras = []
+		verbose = None
+		for opt, arg in options:
+			if opt in ('-o', '--output'):
+				dstfilename = arg
+			elif opt in ('-r', '--resource'):
+				rsrcfilename = arg
+			elif opt in ('-n', '--noargv'):
+				raw = 1
+			elif opt in ('-e', '--extra'):
+				extras.append(arg)
+			elif opt in ('-v', '--verbose'):
+				verbose = Verbose()
+			elif opt in ('-?', '--help'):
+				usage()
 		# Loop over all files to be processed
-		for filename in sys.argv[1:]:
+		for filename in args:
 			cr, tp = MacOS.GetCreatorAndType(filename)
 			if tp == 'APPL':
-				buildtools.update(template, filename, '')
+				buildtools.update(template, filename, dstfilename)
 			else:
-				buildtools.process(template, filename, '', 1)
+				buildtools.process(template, filename, dstfilename, 1,
+					rsrcname=rsrcfilename, others=extras, raw=raw, progress=verbose)
 
+def usage():
+	print "BuildApplet creates an application from a Python source file"
+	print "Usage:"
+	print "  BuildApplet     interactive, single file, no options"
+	print "  BuildApplet src1.py src2.py ...   non-interactive multiple file"
+	print "  BuildApplet [options] src.py    non-interactive single file"
+	print "Options:"
+	print "  --output o    Output file; default based on source filename, short -o"
+	print "  --resource r  Resource file; default based on source filename, short -r"
+	print "  --noargv      Build applet without drag-and-drop sys.argv emulation, short -n, OSX only"
+	print "  --extra f     Extra file to put in .app bundle, short -e, OSX only"
+	print "  --verbose     Verbose, short -v"
+	print "  --help        This message, short -?"
+	sys.exit(1)
+
+class Verbose:
+	"""This class mimics EasyDialogs.ProgressBar but prints to stderr"""
+	def __init__(self, *args):
+		if args and args[0]:
+			self.label(args[0])
+		
+	def set(self, *args):
+		pass
+		
+	def inc(self, *args):
+		pass
+		
+	def label(self, str):
+		sys.stderr.write(str+'\n')
 
 if __name__ == '__main__':
 	main()