Re: Trying to move away from Finder...
Re: Trying to move away from Finder...
- Subject: Re: Trying to move away from Finder...
- From: Shane Stanley <email@hidden>
- Date: Thu, 2 Nov 2017 16:29:10 +1100
On 2 Nov 2017, at 3:50 pm, Jean-Christophe Helary
<email@hidden> wrote:
>
>> set default_location_url to current application's |NSURL|'s
>> fileURLWithPath:default_location
>
> It looks like you are calling a handler (fileURLWithPath) that belongs to
> whatever |NSURL| is (are the || required ?) and that "|NSURL|" belongs to
> "current application", with the parameter default_location.
>
> Checking the Foundation documentation, I find that fileURLWithPath is a "Type
> Method" for the "NSURL" class. Is it the same "|NSURL|" as above?
The pipes around NSURL are used because there's a terminology clash with a
fairly common scripting addition that unfortunately uses the Cocoa class name.
Preceding it by "current application's " is just the way to refer to a Cocoa
class. The term "type method" is a relatively new Swiftian thing -- these were
traditionally called "class methods", because the target of them is the class
itself (as opposed to "instance methods", which are targeted at instances of
the class).
> So I guess I can use other "Type Methods" instead of fileURLWithPath to
> produce different results, right? As long as the parameter type corresponds
> to what the method requests (here, fileURLWithPath requests a "path" and I'm
> guessing the only valid path for a NSURL parameter is a POSIX path).
Right. So if you were creating a NSURL for a web page, you'd use URLWithString:
(the colon is considered part of the name).
>
> Why call "current application" here ? What is its role here ?
It's basically telling AppleScript that the following variable's parent isn't
AppleScript -- that it's not simply an AppleScript variable you've made up.
>
>> set originals_folder_url to default_location_url's
>> URLByAppendingPathComponent:"originaux"
>> set new_folder_url to default_location_url's
>> URLByAppendingPathComponent:"whatever"
>
> Once you've set default_location_url to the above thing that I'm not sure I
> understand
It's just the file type used in Cocoa -- like AppleScript uses aliases of file
references. You can do a lot of this with POSIX paths instead, but having a
file object is more efficient. (And as of 10.11, they can be coerced to aliases
or files).
> , it looks like it has the ability to be called through handlers, like
> "URLByAppendingPathComponent", which is an "Instance Method" in the
> Foundation documentation.
Right. Take an instance, call the method, and it's returning a new NSURL
instance.
>
> Does that mean that the "set default_location_url to" command created an
> instance of NSURL and that I can use relevant instance methods on it?
Yes.
> The Foundation documentation also mentions
> "URLByAppendingPathComponent:isDirectory:
> <apple-reference-documentation://hc_bnxUkO4>" but even though we're creating
> a directory, why don't you use it?
Simplicity. If I were writing Objective-C I might, but the time gain here is
just noise.
>
> I know I should not have thrown away my Objective-C book. I can't find a page
> that explains the difference between Instance Method, Type Method (and there
> is seemingly also a Class Method thing)...
See above (and no you shouldn't have ;-)).
>
>> -- make new folder
>> set fileManager to current application's NSFileManager's defaultManager()
>
> Ok, now I guessed that "NSFileManager" was a class, and I was right... Good
> :-) But why not use the "|NSFileManager|" syntax that you used above?
Because there's no terminology clash.
> Now, "defaultManager()" looks like it won't take a parameter, but the
> Foundation documentation says that defaultManager is a "Type Property", so
> I'm not sure what to do with that information and how to interpret what the
> code does.
It returns an instance of NSFileManager (one that is shared throughout the host
application). You need an instance before you can call any instance methods.
When a Cocoa method takes no arguments (that is, has no colon), you use
parentheses in AppleScript.
>
> But in the end, we get an instance of the class NSFileManager's in
> fileManager, correct?
Right.
> So we can use the instance method "createDirectoryAtURL" on it. The
> Foundation documentation shows something like:
>
> createDirectoryAtURL:withIntermediateDirectories:attributes:error:
>
> And the way you write it shows how to make sense of that notation:
>
>> set {theResult, theError} to fileManager's
>> createDirectoryAtURL:new_folder_url withIntermediateDirectories:true
>> attributes:(missing value) |error|:(reference)
>> if theResult as boolean is false then error theError's
>> localizedDescription() as text
>
> Here again, you use a " | ... | " notation, for "|error|" this time. Why?
Because "error" is a reserved AppleScript word, so we have to avoid a clash. It
looks painful, but Script Debugger's code-completion inserts the full method
including any pipes required for you, as well as hints about the types required
for the various arguments.
>
> Checking localizedDescription, I see that it is an Instance Property, so I
> guess it means it the property of an instance of the class NSError,
Right.
> that is automatically returned by createDirectoryAtURL and set to theError.
Objective-C is a superset of C, and like AppleScript handlers, methods can only
return a single item as a result. In AppleScript we tend to deal with the issue
by returning a single item that is a list or record, but for various reasons
that's not a good idea in C. Instead, where multiple values are required, the
caller normally passes the address of a new object as an argument (often called
an "out" argument); the method can then populate that address, which means the
calling code has the result. You can't do that in AppleScript, but what you can
do is pass the term "reference" for an argument, in which case AppleScriptObjC
does all the work and returns the results as a list.
>
> I'm not sure what to do with (missing value) and (reference) though. Is
> (missing value) just a way to say that you don't set that parameter?
"missing value" is essentially nil or NULL. Many out arguments (and some
others) are optional.
> The documentation for (reference) as a value for |error| is much less clear.
> I mean, not clear at all.
See above. If you don't care about an error, you pass missing value, the out
argument is ignored, and you get just theResult. If the error might be useful,
you pass reference and the result will now be a list of {theResult, theError}.
>
> createDirectoryAtURL returns YES or NO depending on whether the directory was
> created or not, so I guess YES and NO are automatically considered as boolean?
Yes and no :-) Yes, they are, but for various reasons it doesn't hurt to add
"as boolean".
>
> I was not aware of the Applescript error statement (except in "on error"), so
> here theError's localizedDescription() returns something that needs to be
> changed to text so that error can display it.
It returns an NSString, which you need to convert to an AppleScript string.
>
>> -- get contents of originaux
>> set contents_urls to fileManager's
>> contentsOfDirectoryAtURL:originals_folder_url includingPropertiesForKeys:{}
>> options:(current application's NSDirectoryEnumerationSkipsHiddenFiles)
>> |error|:(missing value)
>
> contentsOfDirectoryAtURL requires a number of parameters and now we use "{}"
> to say something equivalent, I guess to "(missing value)"?
An empty list. it wants a list/array, so we pass one.
> Also, the documentation for the options is not super clear. Not sure what a
> "shallow enumeration" is...
Shallow means non-recursive -- just the top level of the folder.
> And I guess we are not interested in the error message here...
>
>> -- move the files
>> repeat with one_url in contents_urls
>> set destination_url to (new_folder_url's
>> URLByAppendingPathComponent:(one_url's lastPathComponent()))
>> (fileManager's moveItemAtURL:one_url toURL:destination_url
>> |error|:(missing value))
>> end repeat
>
> It's slowly beginning to make sense... Plus we have a super sunny afternoon
> here, so I guess I'm blessed...
You're having more luck than hereā¦
>
> Ok, here we use URLByAppendingPathComponent again, this time by adding not an
> arbitrary string like we did when we created new_folder_url's but by adding
> the lastPathComponent() of the URL of one of the contents of the "originaux"
> folder.
> lastPathComponent is an Instance Property. It looks like the syntax for all
> the properties we've had so far was property() and not property.
Think of properties as methods (which is sort of what they're hiding), so you
use parentheses.
>
> Now we have a (fileManager's moveItemAtURL:one_url...), why is it between
> parens and not on it's own like a normal statement?
A quirk of the AppleScript compiler. For some reason it inserts them around
many statements used in repeat loops.
>
> Also, I do have your book on ASOC, so if answers are to be found there (sorry
> I was focusing on the Foundation doc here), don't hesitate to give a pointer
> instead.
Well, yes, it does :-)
--
Shane Stanley <email@hidden>
<www.macosxautomation.com/applescript/apps/>, <latenightsw.com>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden