Script Object Implementation

“… and I heard a voice crying out from heaven saying, 'Behold the script object and blessed be its implementation.” :wink:

Ok, so I’m starting to grasp the Script Object (and Script Object within a Handler) syntax. There are some definite correlations going on in my brain about .h and .m files in Cocoa. While it may not be as extensive as Cocoa/ObjC, I really think that tis is a very overlooked and misunderstood area of scripting. There’s some real power in this stuff that I believe most people are missing. Can I prove it? Not yet! Incredibly, some of this is really starting to make sense! Thanks to Adam, Nigel, HHas, etc. who gave some extra clues to what’s happening here.

Anyways… I’m thinking about implementation… I can intuit times when SObj’s would be appropriate and others when SObj’s within Handlers may be more flexible. So here’s my first attempt at a script object written raw (no reference - just (hopefully) understanding the syntax and structures)…


property folderPath : (path to desktop)
property intLabelIndex : 1
property subFolders : {"IMG", "URLS", "PDFs", "Downloads", "Music"}
global myNewFolder

script myFolder
	on makeFolder(folderName, folderDestination, Foldercolor)
		tell application "Finder"
			set myNewFolder to make new folder at folderDestination with properties {name:folderName}
			set label index of myNewFolder to Foldercolor
		end tell
	end makeFolder
	return myNewFolder
end script

tell myFolder to makeFolder(((short date string of (current date)) & " Unfiled"), folderPath, intLabelIndex)
set {FilingFolder, intLabelIndex} to {myNewFolder, 3}
repeat with thisFolder in subFolders
	tell myFolder to makeFolder(thisFolder, FilingFolder, intLabelIndex)
end repeat

tell application "Finder"
	open FilingFolder
	set current view of window 1 to column view
end tell

Obviously, it’s a simple folder maker. It may seem like overkill but lessons are being learned here. I do thinnk there’s plenty of opportunity to make it smarter / more concise but it’s early in the ballgame. We’ll see what happens. :slight_smile: Thanks again.

Jim Neumann
BLUEFROG

P.S. I’m not real happy with the global for myNewFolder but I’m working on it!

Interesting that this doesn’t work:


tell application "Finder" to set F to make new folder at desktop with properties {name:"TestIt", label index:3}

and that it must be written this way:


tell application "Finder"
	set F to make new folder at desktop with properties {name:"TestIt"}
	set label index of F to 3
end tell

Apparently the folder has to exist before we can color it (or this is yet another Finder bug).

Strange isn’t it. And this “bug” has persisted for a long, long time.
-Jim

That’s because it may not be so much a “bug” as an unimplemented feature. (That is, it’s not that something’s broken, but that it doesn’t exist.) As an analogy, there was a time in the Unix world, many eons ago, when mkdir couldn’t create a directory with specified permission bits. You had to create the directory and then chmod the item if the directory was created successfully. Eventually, that was rolled into a convenience flag in mkdir (the -m flag). Just because you can get or set the property after the directory has been created doesn’t mean not being able to do it during creation is a bug, per se.

I don’t mean to say it isn’t a bug, but there’s really no way to know unless it worked previously, spits out an error, or one of us has the Finder source code. Of course, when speaking in terms of “hey, we want Apple to get this working”, it would be filed as a bug in Radar ('cause it’s either a bug or a request for enhancement).

So, uh, who’s gonna file it? :slight_smile:

It’s not just that theoretically settable (in the Dictionary) properties cannot be set, another point of confusion is that the properties listed by various means don’t all agree with each other:


set tFolder to alias ((path to desktop folder as text) & "untitled folder")

tell application "System Events" to set PSE to properties of tFolder
--> {class:alias, package folder:false, visible:true, volume:"ACB-G5_1", kind:"Folder", URL:"file://localhost/Users/bellac/Desktop/untitled%20folder/", size:missing value, modification date:date "Friday, April 6, 2007 2:39:00 PM", busy status:false, name:"untitled folder", path:"ACB-G5_1:Users:bellac:Desktop:untitled folder:", creator type:missing value, version:"", displayed name:"untitled folder", name extension:"", type identifier:"dyn.age8u", file type:missing value, product version:"", id:{-100, 5067516}, stationery:false, creation date:date "Friday, April 6, 2007 2:39:00 PM", physical size:missing value, POSIX path:"/Users/bellac/Desktop/untitled folder", container:folder "ACB-G5_1:Users:bellac:Desktop:" of application "System Events"}

tell application "Finder" to set PF to properties of tFolder
--> {class:folder, name:"untitled folder", index:10, displayed name:"untitled folder", name extension:"", extension hidden:false, container:folder "Desktop" of folder "bellac" of folder "Users" of startup disk of application "Finder", disk:startup disk of application "Finder", position:{-1, -1}, desktop position:{1074, 541}, bounds:{-33, -33, 31, 31}, kind:"Folder", label index:0, locked:false, description:missing value, comment:"", size:missing value, physical size:missing value, creation date:date "Friday, April 6, 2007 2:39:00 PM", modification date:date "Friday, April 6, 2007 2:39:00 PM", icon:missing value, URL:"file://localhost/Users/bellac/Desktop/untitled%20folder/", owner:"bellac", group:"staff", owner privileges:read write, group privileges:read only, everyones privileges:read only, container window:container window of folder "untitled folder" of folder "Desktop" of folder "bellac" of folder "Users" of startup disk of application "Finder"}

set PIF to (info for tFolder)
--> {name:"untitled folder", creation date:date "Friday, April 6, 2007 2:39:00 PM", modification date:date "Friday, April 6, 2007 2:39:00 PM", icon position:{0, 0}, size:0.0, folder:true, alias:false, package folder:false, visible:true, extension hidden:false, name extension:missing value, displayed name:"untitled folder", default application:alias "ACB-G5_1:System:Library:CoreServices:Finder.app:", kind:"Folder", folder window:{0, 0, 0, 0}, file type:"

It’s not just that theoretically settable (in the Dictionary) properties cannot be set, another point of confusion is that the properties listed by various means don’t all agree with each other:


set tFolder to alias ((path to desktop folder as text) & "untitled folder")

tell application "System Events" to set PSE to properties of tFolder
--> {class:alias, package folder:false, visible:true, volume:"ACB-G5_1", kind:"Folder", URL:"file://localhost/Users/bellac/Desktop/untitled%20folder/", size:missing value, modification date:date "Friday, April 6, 2007 2:39:00 PM", busy status:false, name:"untitled folder", path:"ACB-G5_1:Users:bellac:Desktop:untitled folder:", creator type:missing value, version:"", displayed name:"untitled folder", name extension:"", type identifier:"dyn.age8u", file type:missing value, product version:"", id:{-100, 5067516}, stationery:false, creation date:date "Friday, April 6, 2007 2:39:00 PM", physical size:missing value, POSIX path:"/Users/bellac/Desktop/untitled folder", container:folder "ACB-G5_1:Users:bellac:Desktop:" of application "System Events"}

tell application "Finder" to set PF to properties of tFolder
--> {class:folder, name:"untitled folder", index:10, displayed name:"untitled folder", name extension:"", extension hidden:false, container:folder "Desktop" of folder "bellac" of folder "Users" of startup disk of application "Finder", disk:startup disk of application "Finder", position:{-1, -1}, desktop position:{1074, 541}, bounds:{-33, -33, 31, 31}, kind:"Folder", label index:0, locked:false, description:missing value, comment:"", size:missing value, physical size:missing value, creation date:date "Friday, April 6, 2007 2:39:00 PM", modification date:date "Friday, April 6, 2007 2:39:00 PM", icon:missing value, URL:"file://localhost/Users/bellac/Desktop/untitled%20folder/", owner:"bellac", group:"staff", owner privileges:read write, group privileges:read only, everyones privileges:read only, container window:container window of folder "untitled folder" of folder "Desktop" of folder "bellac" of folder "Users" of startup disk of application "Finder"}

set PIF to (info for tFolder)
--> {name:"untitled folder", creation date:date "Friday, April 6, 2007 2:39:00 PM", modification date:date "Friday, April 6, 2007 2:39:00 PM", icon position:{0, 0}, size:0.0, folder:true, alias:false, package folder:false, visible:true, extension hidden:false, name extension:missing value, displayed name:"untitled folder", default application:alias "ACB-G5_1:System:Library:CoreServices:Finder.app:", kind:"Folder", folder window:{0, 0, 0, 0}, file type:"null char", file creator:"null char"} -- where I've replaced the nulls with null char.

There are some inconsistencies although, once the unique properties are discounted, along with those that are consistent, they aren’t quite as numerous as it might appear initially.

There are, of course, some known issues regarding size. The info for command seems to be generally more reliable here “ although Finder can be persuaded to return a more accurate value for a freshly created folder, by using its update command (possibly followed by a short delay). I believe that, for a future version of Finder, a new parameter may be introduced, similar to info for’s size parameter, which (depending on the specified boolean value) either forces a size recalculation or ignores size altogether.

Currently, the properties for which a missing value might be returned in place of a null character, empty string or zero real (0.0) include: size, name extension, file type and file creator/creator type. (The latter pair possibly not being an entirely fair comparison, because of the different labels.)

While Finder and System Events return different values for their respective container properties, I think we’d have to put that down to fundamental differences between their reference forms.

As for the difference between their object class properties, well… I’ll leave you to decide which approach is the more sensible/consistent:


tell application "Finder" -- assumes at least one folder on the desktop
	set f to folder 1 as alias
	set Finder_class to f's class
	set Finder_property to class of (get f's properties)
end tell

tell application "System Events"
	set SE_class to f's class
	set SE_property to class of (get f's properties)
	set SE_extracted to class of disk item (f as Unicode text)
end tell

{AppleScript_class:f's class, Finder_class:Finder_class, Finder_property:Finder_property, SE_class:SE_class, SE_property:SE_property, SE_extracted:SE_extracted}

--> {AppleScript_class:alias, Finder_class:alias, Finder_property:folder, SE_class:alias, SE_property:alias, SE_extracted:folder}


It can be avoided Jim, perhaps with something like:


property folderPath : (path to desktop)
property intLabelIndex : 1
property subFolders : {"IMG", "URLS", "PDFs", "Downloads", "Music"}

script myFolder
	on makeFolder(folderName, folderDestination, Foldercolor)
		tell application "Finder" to tell ¬
			(make new folder at folderDestination with properties {name:folderName})
			set label index to Foldercolor
			it
		end tell
	end makeFolder
end script

tell myFolder
	set FilingFolder to makeFolder((short date string of (current date) & " Unfiled"), folderPath, intLabelIndex)
	set intLabelIndex to 3
	repeat with thisFolder in subFolders
		makeFolder(thisFolder, FilingFolder, intLabelIndex)
	end repeat
end tell

tell application "Finder" to tell FilingFolder
	set its window's current view to column view
	open
end tell