On Mar 6, 2015, at 12:06 AM, Shane Stanley < email@hidden> wrote:
On 6 Mar 2015, at 3:37 pm, Alex Hall < email@hidden> wrote:
First, the length() property always gives me an error. I've tried it with and without the parentheses, but it fails either way.
My bad. That should be |count|(). Too much AppleScript muscle memory...
Interesting. At first I thought you were using the pipes as emphasis, so I left them out, and it didn't work. Just for fun, I put the pipes in, and it suddenly worked. I've never seen these before in AS. They're used in terminal commands, and as "or" in many languages, but what do they do here? I know they can't be used to access all properties, because I don't need them around "title" or "startDate" below.
You have to get used to the fact that, apart from some numbers, Cocoa methods return Cocoa objects, and to do AppleScript things to them, you need to coerce them to their AppleScript equivalents.
So you need "set theEvents to (...) as list" before you can iterate through it like an AS list.
Yes, that did work as expected. As you say, it's something I'll have to get used to. Working with an amalgamation of two languages is very different.
Using "repeat with e in theEvents" works fine, but you're better off using "repeat with i from 1 to count of...". The problem with using "repeat with" is that there's a bug that is triggered by trying to convert an object reference to a Cocoa object to a source string. You don't do that in scripts, but editors can and do when you're writing them, so it's best to avoid the problem.
Then when you get to the display dialog bit, you have to coerce again. You also don't need to use valueForKey: -- that's just a quick way of calling a method on all the items in an array, and you no longer have an array. And Cocoa dates don't coerce, so you the simplest thing is to get the description property, which returns a string. So something like:
display dialog ((e's title()) as text) & ". Starts on " & (e's startDate()'s |description|()) as text
Or perhaps better:
display dialog (current application's NSString's stringWithFormat_("%@. Starts on %@", e's title(), e's startDate())) as text
This is great--I forgot we can now use NSString stringWithFormat: and it will make things much easier. It feels weird to say "current application's NSString…", but it works.
The description property doesn't seem to make a difference; I see "yyyy-mm-dd hh:mm +hhhh" whether it's in there or not. Hopefully I can cast this to a regular date object and format it how I want, check for how far away it is, and so on. I suspect it doesn't like me iterating, meaning the NSArray isn't being given to AS in a way it understands. I'm guessing, though, and my hypothesis makes little sense. If AS and Cocoa can work together, data types would be transparent between them, right?
You might think so, but it's not that simple. If a method requires, say, an NSString for an argument, you can pass an AS string and it will be converted automagically. But if a method returns an NSString, you have to coerce it to use it as an AS string. This is a Good Thing. If that didn't happen, you wouldn't be able to call NSString instance methods on it (and unnecessary conversions would waste time and memory).
The other odd thing is that this suddenly started working today, once I re-checked my calendar titles (yeah, my mistake there--it helps to use calendars that, um, have upcoming events). I was never prompted to allow access to Calendars, though, or given any security warnings of any kind. I'd rather avoid distributing this as an app or applet if I could, but since I'm not being shown any security warnings, I can't say how using a script will go over on others' machines. I just can't figure out why I was never asked to grant access to Calendars.
I have a feeling Script Editor gets access by default. But I'm really unsure of that side of things.
--
Have a great day, Alex Hall
|