Monday, November 08, 2010 at 12:03 AM.

on newTool (f) {
		<<5/26/09; 9:30:48 AM by DW
			<<New tools don't have their threads turned on. Create an init script. Rewrite install code for statuscenter script, thread script.
		<<6/12/02; 12:26:44 AM by JES
			<<Add a table to new Tools. This table is for callback scripts which will be installed at, when the Tool is installed.
		<<12/4/01; 1:33:29 PM by JES
			<<New Tools now have a toolSuite.statusCenterMessage script, which returns the string, "I'm a cool Tool!".
		<<11/27/01; 3:13:21 AM by JES
			<<Added a description element to the toolInfo table for new tools.
		<<09/19/01; 7:05:20 PM by JES
			<<Added initialization of the toolInfo table, which contains information about the Tool and the tool's author.
		<<06/8/01; 12:12:16 PM by JES
			<<Bug fix: The condition for the responder checked string.lower (path) against the inner-case name, which would always fail. Now it checks string.lower (path) against string.lower (toolName).
		<<07/02/01; 2:57:22 AM by JES
			<<Create an empty windowTypes table.
		<<01/11/01; 12:18:44 PM by JES
			<<Don't enable the responder for new tools.
		<<09/30/00; 11:48:06 PM by PBS
			<<Take the path to the tool as parameter, not the name of the tool.
		<<09/25/00; 11:47:56 PM by JES
			<<Create a new, empty tool database.
	local (fname = file.fileFromPath (f));
	local (name = (fname));
	local (firstUpperName = string.upper (name[1]) + string.mid (name, 2, infinity));
	local (adrTool);
	bundle { // create the database (f, true);
		adrTool = @[f]};
	on newTable (t) { //create a subtable, return its address
		local (adrTable = @adrTool^.[name + t]);
		new (tableType, adrTable);
		return (adrTable)};
	on newScriptWithComment (adrScript, comment) {
		new (scriptType, adrScript);
		local (oldTarget = target.set (adrScript));
		op.setLineText (comment);
		script.makeComment ();
		try {target.set (oldTarget)}};
	newTable ("RpcHandlers");
	newTable ("SoapHandlers");
	newTable ("NodeTypes");
	newTable ("WindowTypes");
	bundle { //toolData and prefs subtable
		local (adrData = newTable ("Data"));
		new (tableType, @adrData^.prefs)};
	bundle { //toolResponder (with sample any method)
		local (adrResponder = newTable ("Responder"));
		adrResponder^.condition = "(string.lower (path) beginsWith \"/" + string.lower (name) + "/\")";
		adrResponder^.enabled = false; //01/11/01 JES: don't initially enable responder
		new (tableType, @adrResponder^.methods);
		local (s = "on any (pta) //boilerplate for your responder\r");
		s = s + "\tpta^.responseHeaders.[\"Content-Type\"] = \"text/html\"\r";
		s = s + "\tpta^.code = 200; //everything was OK\r";
		s = s + "\tpta^.responseBody = \"\" //build response\r";
		s = s + "\treturn (true)";
		script.newScriptObject (s, @adrResponder^.methods.any);
		local (oldTarget = target.set (@adrResponder^.methods.any));
		op.firstSummit ();
		op.fullExpand ();
		try {target.set (oldTarget)}};
	bundle { //toolSuite (background, callbacks, menu)
		local (adrSuite = newTable ("Suite"));
		bundle { //background
			new (tableType, @adrSuite^.background);
			newScriptWithComment (@adrSuite^.background.everyMinute, "This script runs every minute.");
			newScriptWithComment (@adrSuite^.background.everyHour, "This script runs every hour.");
			newScriptWithComment (@adrSuite^.background.everyNight, "This script runs every night.")};
		bundle { //callbacks
			new (tableType, @adrSuite^.callbacks);
			new (tableType, @adrSuite^.callbacks.fileMenu);
			new (tableType, @adrSuite^;
			new (tableType, @adrSuite^.callbacks.user)};
		bundle { //menu
			new (menubarType, @adrSuite^.menu);
			local (oldTarget = target.set (@adrSuite^.menu));
			op.setLineText (firstUpperName);
			try {target.set (oldTarget)};
			menu.addMenuCommand (@adrSuite^.menu, firstUpperName, "Hello World", "dialog.notify (\"Hello, World!\")")};
		bundle { //statusCenterMessage, 5/26/09 by DW -- rewrite
			<<local (adrscript = @adrSuite^.statusCenterMessage)
			<<newScriptWithComment (adrscript, "This script returns a string which appears in the Status Center on the Radio UserLand home page.")
			<<local (oldTarget = target.set (adrscript))
			<<op.insert ("return (\"I'm a cool Tool!\")", down)
			<<try {target.set (oldTarget)} (, @adrSuite^.statusCenterMessage, name)};
		bundle { //init //5/26/09 by DW (, @adrSuite^.init, name)}};
	bundle { //toolThread
		local (adrThread = newTable ("Thread"));
		adrThread^.ct = 0;
		adrThread^.enabled = false; //5/26/09 by DW (, @adrThread^.script, name);
		<<newScriptWithComment (@adrThread^.script, "This script runs in its own thread.")
		<<local (oldTarget = target.set (@adrThread^.script))
		<<op.insert ("loop //loop until the application quits", down)
		<<op.insert ("Add your code here.", right)
		<<script.makeComment ()
		<<op.insert ("thread.sleepFor (10) //sleep for ten seconds", down)
		<<try {target.set (oldTarget)}
	bundle { //toolWebsite
		local (adrSite = newTable ("Website"));
		adrSite^ =;
		local (adrFtpSite = @adrSite^.["#ftpSite"]);
		adrFtpSite^.url = "" + name + "/"};
	bundle { //toolInfo
		local (adrInfo = newTable ("Info"));
		adrInfo^.author =;
		adrInfo^.authorEmail = user.prefs.mailAddress;
		adrInfo^.description = "";
		adrInfo^.homePageUrl = "";
		adrInfo^.name = string.popSuffix (file.fileFromPath (f), '.');
		adrInfo^.releaseDate = ();
		adrInfo^.version = "0.1"};
	bundle { //clean up
		try {delete (@adrTool^.["item #1"])};
		local (oldTarget = target.set (adrTool));
		wp.setTextMode (false);
		op.firstSummit ();
		try {target.set (oldTarget)}; (f)};
	bundle { //install now if in Tools folder
		local (toolsFolder = ());
		local (lowerToolsFolder = string.lower (toolsFolder));
		local (folder = file.folderFromPath (f));
		local (lowerFolder = string.lower (folder));
		if lowerFolder == lowerToolsFolder { (f)}}; //install now
	return (adrTool)}

This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.