// Proposed changes and additions to the JavaScript Library file
// embedded in the JavaScript OSA component.
// I have yet to create a non-trivial jsosa project where I
// didn't neeed .appSelf(), especially for general purpose
// access the scripting additions, as well as generic access
// to calling .sendAE(). I always end up creating a global
// holding the "current application" because I'm worried
// about how expensive it is to repeatedly call the .appSelf
// method. This is especially problematic because most of my
// libraries also need an instance of the script-app itself.
//
// My only concern is with (in the future) loading Script
// Debugger's entire aete even though it would not nessesarily
// be needed. Would their be any way to create an instance of
// .appSelf() that would not load SD's dictionary but would
// still allow access to scripting addition terminology?
//
Self = MacOS.appSelf();
//
// P.S. I found this in your library file:
//
// ... MacOS.appSelf( false, false ) ...
//
// What does the second boolean parameter do? I can't
// find documentation for it.
// Access to the global object is often needed for object/
// variable detection in the global namespace. In web
// browsers, one always has access to the "window" object,
// while in ActionScript, one always has access to "_root".
// JSOSA has no equivelant object, except via use of the
// contextual "this" keyword. Unfortunately, "this" is not
// always pointing at the global object, such as in a
// constructor function.
//
Global = this;
// The current MacOS.pathToMe() doesn't honor the Script
// Debugger preference setting for referring to the saved
// script file. This method does:
//
MacOS.pathToMe = function() {
var ae = new MacOS.AEDesc(); ae.build( "'null'()" );
// return MacOS.appSelf( false ).sendAE( 'ears', 'ffdr', ae );
return Self.sendAE( 'ears', 'ffdr', ae );
}
Core.me = MacOS.pathToMe().path;
// The current MacOS.findFolder() doesn't allow one to
// specify the "domain", as in "/Library" or
// "Users/USER/Library", etc. The .path_to event allows
// for this, along with the "folder creation" boolean.
//
MacOS.findFolder = function( fold, from, make ) {
var param = { 'ae_----' : fold };
if ( from ) param.ae_from = from;
if ( make ) param.ae_crfl = true;
// return MacOS.appSelf( false ).sendAE( 'ears', 'ffdr', param );
return Self.sendAE( 'ears', 'ffdr', param );
}
// I want to introduce the notion of "search paths" to OSA
// scripting. This would make dealing with libraries a
// thousand times easier. MacOS.search() tries to resolve
// and then locate a given posix|relative|special path
// string, returning a FileSpec instance.
//
// If the parameter starts with "/", then it is assumed to
// be a normal posix path:
//
// MacOS.search( "/foo.bar" ); //=> new MacOS.FileSpec( "/foo.bar" )
//
// In addition, "tilde expansion" is performed:
//
// MacOS.search( "~/foo.bar" ); //=> fspec "Users/USER/foo.bar"
//
// If the path starts with a "colon prefix", then a special
// "path to me" FileSpec is returned:
//
// MacOS.search( ":foo.bar" ); //=> (applet)/Contents/foo.bar
// MacOS.search( "::foo.bar" ); //=> (applet)/Contents/Resources/foo.bar
// MacOS.search( ":s:foo.bar" ); //=>
(applet)/Contents/Resources/Scripts/foo.bar
// MacOS.search( ":j:foo.bar" ); //=> (applet)/Contents/Resources/JavaScript
OSA/foo.bar
//
// Note: I'd like to introduce "JavaScript OSA" as a "standard"
// folder name for those who wish to keep their AppleScript
// and JSOSA files separated.
//
// If the path starts with one or more "../" prefixes, then it
// is assumed to be relative to the "path to me" applet, ie:
//
// MacOS.search( "../foo.bar" ); //=> (applet's parent folder)/foo.bar
//
// foo.bar is in the same directory as the script application.
//
// OTHERWISE:
//
// .search() will attempt to find the file along the following
// search paths, (in this order):
//
// (applet)/Contents/Resources/JavaScript OSA
// (applet)/Contents/Resources/Scripts
// (applet's parent folder)
// /Users/USER/Library/JavaScript OSA
// /Users/USER/Library/Scripts
// /Library/JavaScript OSA
// /Library/Scripts
// /Users/USER/Library/Application Support/Script Debugger 4/JavaScript OSA
// /Users/USER/Library/Application Support/Script Debugger 4/Script Libraries
//
// So for instance:
//
// var myFile = MacOS.search( "files/math.js" );
//
// math.js will be systematically looked for in a "files"
// folder in all of the above locations.
//
// NOTE: For paths that start with a "/", "~", or ":", the
// returned FileSpec may not exist, (allowing a scripter
// to use .search() for paths to files that have not
// yet been created). For a relative path that cannot
// be found along the search paths, null is returned:
//
// var myFile = MacOS.search( myPath );
// if ( ! myFile || ! myFile.valid )
// throw( "The file was not found!" );
//
// Whew...it took far longer for me to write the above comments
// than to write the code. ;-)
//
MacOS.search = function( path ) {
var c = path.charAt( 0 );
if ( c == "/" ) return new MacOS.FileSpec( path );
else if ( c == "~" ) return new MacOS.FileSpec( Core.home + path.slice( 1 ) );
var me = MacOS.pathToMe();
if ( c == ":" ) {
path = path.replace( ":j:", "/Contents/Resources/JavaScript OSA/" );
path = path.replace( ":s:", "/Contents/Resources/Scripts/" );
path = path.replace( "::", "/Contents/Resources/" );
path = path.replace( ":", "/Contents/" );
return new MacOS.FileSpec( me.path + path );
}
if ( c == "." ) {
while ( path.slice( 0, 2 ) == "../" ) {
me = me.container;
path = path.slice( 3 );
}
return me;
}
var fspec = new MacOS.FileSpec();
fspec.path = me.path + "/Contents/Resources/JavaScript OSA/" + path;
if ( fspec.valid ) return fspec;
fspec.path = me.path + "/Contents/Resources/Scripts/" + path;
if ( fspec.valid ) return fspec;
fspec.path = me.container.path + "/" + path;
if ( fspec.valid ) return fspec;
fspec.path = me.container.path + "/" + path;
if ( fspec.valid ) return fspec;
var currentDir = MacOS.findFolder( 'dlib', 'fldu' ); // /Users/USER/Library
fspec.path = currentDir.path + "/JavaScript OSA/" + path;
if ( fspec.valid ) return fspec;
fspec.path = currentDir.path + "/Scripts/" + path;
if ( fspec.valid ) return fspec;
currentDir = MacOS.findFolder( 'dlib', 'fldl' ); // /Library
fspec.path = currentDir.path + "/JavaScript OSA/" + path;
if ( fspec.valid ) return fspec;
fspec.path = currentDir.path + "/Scripts/" + path;
if ( fspec.valid ) return fspec;
currentDir = MacOS.findFolder( 'asup', 'fldu' ); // Application Support, user
domain
currentDir.path += "/Script Debugger 4";
fspec.path = currentDir.path + "/JavaScript OSA/" + path;
if ( fspec.valid ) return fspec;
fspec.path = currentDir.path + "/Script Libraries/" + path;
if ( fspec.valid ) return fspec;
return null;
}
// I wanted to name this .import(), but for no sane reason
// that appears to be a JavaScript reserved word.
//
// Script Debugger's Library feature does not work with
// JSOSA, and my problem with Core.load() is that it does
// not evaluate in the context of the global object; for
// example: I can't create a library that attaches methods
// to Array.prototype, because Core.load() seems to compile
// source code in it's own context.
//
// .include() passes it's parameter off to MacOS.search(),
// allowing for relative paths to be found in multiple
// locations.
//
Core.include = function( path ) {
var fspec = MacOS.search( path );
if ( ! fspec || ! fspec.valid )
throw( 'The path "' + path + '" cannot be located.' );
// this.eval( MacOS.appSelf( false ).read( fspec.alias ) );
Global.eval( Self.read( fspec.alias ) );
}
-- Arthur