A friendly rant about ASOC

Now that I’ve been using ASOC for a while, I’m generally pleased with its power and with the ease in which it allows us to perform certain tasks that were a lot more complicated under AppleScript Studio. However, there are some commonly used procedures that were available under AppleScript Studio and {Apple}Script Editor which are missing in ASOC, and, IMHO, whose absence make the use of ASOC needlessly cumbersome.

It seems to me that the Apple engineers could easily have implemented helper handlers to make widely used constructs such as on idle and on open available to users who develop using ASOC. This way, if someone already has written such a handler in an AppleScript Studio or {Apple}Script Editor app, it would be much easier to port that app to the ASOC environment.

For example, if someone has an idle handler written for AppleScript Studio or {Apple}Script Editor that he or she wants to use within an ASOC app, something like the following has to be done:

script SampleAppDelegate

	property parent : class "NSObject"
	
	on applicationWillFinishLaunching_(aNotification)
		my performSelector_withObject_afterDelay_("idleWrapper", missing value, 0.01)
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		return true
	end applicationShouldTerminate_

	on idleWrapper()
		try
			-- The following calls the "on idle" handler and triggers
			-- an error if that handler fails, or if it returns a
			-- non-numeric value:
			set idleTime to (0.0 + (idle))
		on error
			set idleTime to missing value
		end try
		if (idleTime is missing value) or (idleTime <= 0.0) then
			set idleTime to 30.0 -- AppleScript default for idle handler delay
		end if
		my performSelector_withObject_afterDelay_("idleWrapper", missing value, idleTime)
	end idleWrapper
	
	on idle
		-- This is the idle handler from the former AppleScript Studio
		-- or {Apple}Script Editor application. It can return a number
		-- that specifies how long to wait before the next invocation.
	end idle
	
end script

It seems to me that it would be very easy for an Apple software engineer to enhance ASOC to cause something like “idleWrapper” to be automatically called behind the scenes if on idle appears within the app delegate script of an ASOC app.

Likewise, something similar could be done if on open appears.

I’ve never seen the ASOC source code, of course, but I’m sure that I could write something into that framework which implements usable helpers for on idle, on open, etc. in less than a day, if I had access to that source code.

The presence of these helpers would not take any functionality away from ASOC. If people didn’t want to use those capabilities, they wouldn’t have to. But all the developers who have been writing AppleScript code in AppleScript Studio and {Apple}Script Editor over the years would have a much easier time porting that code to ASOC. Furthermore, since constructs like on open and on idle have been part of the AppleScript language for ages, it makes sense that they should still be usable under ASOC.

Thoughts?

Honestly, I think the goal (Apple’s) is to wean us off of Applescript and onto Cocoa. For that reason, constructs like on idle and on open don’t work. They would rather we use whatever Cocoa has that tests for idle and awake from Nib, respectively.

I posted a rant (short one) in the OS X forum just tonight. Three years ago, Apple broke the ability to create new signatures in Apple Mail. As of now, that functionality is STILL broken in Snow Leopard. With the rise of Automator, I think Apple would like to phase out Applescript. So many app developers don’t implement Applescript dictionaries anymore, and the ones that do, seem to do so in a half-assed way that doesn’t help. I’ve become very dis-enchanted with the whole Applescript scene because Apple doesn’t seem to care about it anymore (the 2.0 version in Leopard not withstanding).

Sorry. Rant finished. :slight_smile:

Well, if Apple is truly trying to wean us, then this puts them into the role of a condescending parent.

I come from the free software and open source world, and I don’t need nor want a paternalistic entity trying to tell me what’s “best” for me. Apple certainly has a right to decide what’s best for Apple, but not for me nor for anyone else.

That’s why I’m trying to write code that emulates as close as possible the functions of on idle, on open, etc. The availability of code like this will save thousands of person hours among the host of users who have already written thousands of lines of AppleScript that they will be trying to port to ASOC. Why should each and every one of them have to re-invent the wheel to create workarounds for their commonly used constructs? … especially those constructs which are still officially part of the AppleScript language specification, ane which are not listed as being deprecated … and which therefore have been used in good faith when all these users originally wrote – and still write – their code.

In summary, I totally agree that Apple has the right to not help the user community port their existing apps to ASOC by writing these kinds of helper functions. And if they continue to exercise that right, I and others are going to step in and take on that role for free.

End of (current) rant. :slight_smile:

Hi,

I doubt this.
In Objective-C there is no alternative to Apple Events for interapplication communication.
Even the ScriptingBridge.framework uses Apple Events.
And most of the Automator actions are actually a GUI for Apple Events.

As long as this is the status quo, AppleScript will live .

Well, Apple Events will live. But we may see the day when Automator becomes the “preferred” way of issuing those events. That’s all I’m saying. Apple doesn’t have to kill Applescript, just keep ignoring it and eventually it will go away.

Introducing ASObjC is anything but “ignoring” it…

You’re right, but it still doesn’t explain why they “broke” AS Studio so they could ram Cocoa down our throats. Or why they don’t fully support AS in their own programs and leave things like the Mail signatures thing broken for 3 years.

If that’s them “supporting” AS, I’d hate to see them help us write scripts…:wink:

They didn’t “break” ASStudio, except in the sense that it’s always been limited. My guess is they decided the new method would take a lot less maintenance, give users access to lots more, and in the end be no harder to master. In fact, for simple interface stuff I reckon it’s actually considerably easier than ASStudio.

These sorts of transitions happen all the time with Apple – no more PPC chips, Rosetta on the way out, Carbon on the way out. Remember floppy drives, ADB keyboards?

As for Mail, it’s symptomatic of a lot of Apple app support of AS, unfortunately. But don’t confuse the “they” responsible for Mail with the “they” who came up with ASObjC – it may be one company, but various sections have lots of autonomy, and like in any other big company, they don’t all march to the same tune.

I asked Sal Soghoian on the Applescript List if their plan was to deprecate AS, he said NO in large letters. I hope he’s right, and able to make sure the answer stays that way.
I also feel like AS is being somewhat deprecated, but I hope I’m wrong. My scripts are all multiple-outlet workflow things in publishing. The Finder watches for files, InDesign exports, Interarchy sends FTP and then talks to Filemaker about the results, etc. The things I do can’t be done with Automator (nor have I had the inclination to try, honestly).

Hippo, if you make an IDLE framework let us know! I have many apps that watch hot folders for files and use an On Idle loop to do its main work. It would be a big help, when I finally get to 10.6

Chris

Well, I wrote an idle helper function and put it in the first message of this thread. Once you get to 10.6, just copy and paste the on idleWrapper() handler into your code, and put the performSelector_withObject_afterDelay_ line in your applicationWillFinishLaunching_ handler. Then, your normal on idle handler should work.

I’m still new to all this, and I haven’t yet figured out how to make all of this into a framework for ASOC. But once I do, I’ll definitely make it available.

As much as I love Applescript (and have made a living from it for many years now), I think this is a brilliant move on Apple’s part. With Applescript they got a huge group of people “programming”. Now they’re pushing them into the next phase by getting them used to ObjC and more OO type thinking. They are breeding more programmers to help continue Mac development, only now it’s with the language and concepts that “real” programmers use (no offense to anyone). And all for FREE! You can’t overstate the genius of this.

Jim Neumann
BLUEFROG

PS: I still don’t totally “get it” since I would just as soon learn ObjC. :stuck_out_tongue:

Honestly, I would like to also. But I found that the bar is a bit high. And I have both C and C++ experience. I think the truth is that some of us are better scripters than programmers, and there IS a difference between the two. Just ask any BASH scripter and he’ll say the same thing.

Scripters are used to being able to “invent” variables on the fly as we need them, find “hacks” that work around “features” (read “bugs”) in our chosen scripting language, and view scripts as an environment separate and apart from programming. While I still use some good coding practices (documenting my scripts, laying them out in pseudocode before I start, quality testing, etc.) I still enjoy scripting more than I do application programming.

With Applescript, especially, the ability to control applications is sheer magic. I’ve seen its power first-hand, dealing with automating workflows in QuarkXpress and PhotoShop. That being said, I’ve spent some time building AS Studio apps and they were more like Applescript than ASObjC is. I guess I liked AS Studio and am hacked that I have to go back to “square one” and start over. But I suppose it’s no different than when Hypercard died and Apple ported Hypertalk to create Applescript. That also required re-learning.

(sigh) Maybe this old dog is running out of new tricks. :wink:

I wouldn’t say you have to go back to “square one”, but I guess it depends on what it is your wanting to accomplish. Creating an interface for a small project is much simpler than with AppleScript Studio, and depending on what your needs are, it may contain little to no Objective-C code at all.

More complex projects will require more knowledge, but the same can be said for AppleScript Studio. I did not use it that much but there were many times when only a call method would do the job.

Think about this. You have a text field buried deep in a stack of views; a split view, scroll view, box, another split view, etc. How awful is the line of code it takes to reach that element? I don’t remember exactly how to reach it, but it goes something like this.


set contents of text field "textField" of split view 1 of view 1 of scroll view 1 of view 1 of box 1 of split view "something" of view "something" and on and on and on... to "My new value"

In an ASOC app, you can bind the text field to a property or a simple expression will do. If you go back to IB and move that element to some other nested set of views, your code does not have to change. It still knows how to reach that element.


textField's setStringValue_("My new value")

And if you were using bindings you would use this at the specific point in your code where you wanted to change its value.


-- In this example textField is a property and not
-- an instance of an NSTextField

set my textField to "My new value"

-- or using KVC style
setTextField_("My new value")

Seriously, you have to see the beauty in this. I think there will be a lot of very cool things you can do with ASOC with just a small amount of Objective-C knowledge.

What would really help me in the long run is not so much a framework for old ASS handlers (though that would be useful at times for sure) but a library of OBJ-C foundation classes that you could use to implement OBJ-C things that are too complex for the ASOC script but could be called from there. People could just add these to their projects and still enjoy the applescripting component to the fullest.

The only things that aren’t Applescript are the interactions with the UI and I am finding the tie-in to OBJ-C much more direct.

I now am diving in to bindings and have been able to bind two tables together with 24 user preferences without much code at all (thanks to Scott Stevens bindings tutorial). It works seamlessly whereas my old ASS app was patched to death. I have a long way to go but am quite enjoying ASOC so far.

Bindings are fantastic!

And there are things to be worked out for sure.

Cheers,

Rob

Rob:

Could you edit your previous post to include a link to the bindings tutorial you mentioned? Readers would certainly want to check those out.

Here is the link Scott Stevenson’s excellent tutorial on bindings and table View, including archiving with NSCoder. You could easily modify his example and import the class files into a project. I did and it works great, so far that is…

http://www.cocoadevcentral.com/articles/000080.php

and Cocoa Dev website with many tutorials. One on Drag and Drop, I just noticed.

http://cocoadevcentral.com/archives.php

Rob

I started this thread with an example of how an idle handler could be implemented in ASOC. I now have come up with something a little better. It uses a class called Enhancer which provides the necessary functionality.

I’m still learning how to write a framework. Once I figure that out, I’ll create a framework which encapsulates all of this. In the mean time, just put this Enhancer class into your ASOC project.

Enhancer.h

Enhancer.m

Then, the app delegate looks like this:

script ExampleAppDelegate

	-- Note that this is safe to do, because Enhancer is
	-- a subclass of NSObject:
	property parent : class "Enhancer" of current application

	-- Just rename your existing "on idle" handler with
	-- vertical bars around the name and follow that with
	-- an open and close parenthesis.
	--
	-- Any valid idle handler code will work. It doesn't
	-- have to be the two lines that I used.
	--
	-- This functions like a normal AppleScript idle
	-- handler: if a positive numeric value is returned,
	-- that represents the number of seconds to wait
	-- before invoking this handler again. Otherwise,
	-- it waits 30 seconds, which is the AppleScript
	-- default.
	on |idle|()
		log ("idle")
		return 1.0
	end |idle|

	on applicationWillFinishLaunching_(aNotification)
		-- Insert this line to enable the use of
		-- your |idle|() handler:
		my enableIdle()
	end applicationWillFinishLaunching_

	on applicationShouldTerminate_(sender)
		return true
	end applicationShouldTerminate_

end script

The Objective C code might need some better error handling. But it does work without any problems in my own tests.

Here’s a new-and-improved version of my Enhancer class. It now has two methods for managing an idle handler: the enableIdle method that I mentioned above, and also a new enableIdleWithHandler: method that lets you specify your own idle handler instead of |idle|().

Enhancer.h

Enhancer.m

And here’s the app delegate which shows how to use the new enableIdleWithHandler: method (the enableIdle method still works the same as described in my previous message).

script EnhancerAppDelegate
	
	property parent : class "Enhancer" of current application
	property idleTime : 10.0
	
	on applicationWillFinishLaunching_(aNotification)
		my enableIdleWithHandler_("idler")
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		return true
	end applicationShouldTerminate_
	
	on idler()
		log ("idler")
		if idleTime > 1.0 then
			set idleTime to (idleTime - 1.0)
		end if
		return idleTime
	end idler
	
end script