Bailing out of a double repeat loop

I’ve been scratching my head for a few days about how to use a “cancel” button to exit a double nested repeat loop without actually executing anything. I’m sure there’s a solution to this but it has me baffled.

Here’s a slightly simplified version of what I have so far:


on alert ended theObject with reply theReply

repeat
	set contents of text field "process info" to "Please insert a blank CD"
	set visible of button "cancel burn" to true
	-- Poll the optical drive to see if there's media in it. If there's not, wait a second and check again.
	repeat
		set mediaStatus to do shell script ("check for media")
		if mediaStatus is not "No Media Inserted" then
			set visible of button "cancel burn" to false
			exit repeat
		end if
		delay 1
	end repeat
	-- See if the media inserted is a recordable CD. If not, eject whatever is in there and start over.
	set mediaStatus to do shell script ("check for media type")
	if mediaStatus is "blank" or "overwritable" then exit repeat
	set contents of text field "process info" to "CD is not recordable!"
	do shell script ("drutil eject")
	delay 2
end repeat

--script continues on from here

end alert ended

I have a cancel button at the bottom of the window that, if pressed, should just immediately kill this process of checking for a blank CD. Any ideas on how to do this? Thanks!

Is this code being run after you press another button in your interface?

It’s part of an alert ended handler. I should probably add that to the example.

The only thing I can think to do is to have the cancel button set some variable when pressed, like “set cancelButton to true”, and then create a series of “if cancelButton is true then…” statements to exit the repeat loops. This isn’t the most elegant solution though, given that it’d probably be a few seconds before the loop made it back to the point of being able to recognize the button press. The button’s responsiveness would seem erratic to the user.

Personally, I’d try to do this another way. It doesn’t seem right where you have to jump out of a nested repeat loop.

You can set a flag when the user clicks the button.

property user_canceled: false

on clicked theObject
if name of theObject is “cancel” then
set user_canceled to true
else

end if
end clicked

Then in the repeat loop, check user_canceled. If true, then exit inner repeat loop. In out repeat loop, check user_canceled. If true, then set user_canceled to false and exit repeat.

Another way. You could wrap the nested repeat loops in an error handler.

try
repeat …
repeat …
if user_canceled then error number -128
end repeat
end repeat
on error
set user_canceled to false
end try

Try running this in the Script editor to see what this does.

try
error number -128
on error _err
display dialog _err
end try

gl,

Ah yeah, that’ll probably work. That’s similar to what I was thinking, but using an error handler is a great idea. My only concern is still the length of time it takes to make it through a single loop, but I suppose there’s no way to avoid that since the delays are caused by shell script execution. Thanks!