How can i shorten my script

I have a script that’s gotten pretty long, and I want to know if there’s a way to shorten it. It has quite a few repeated sections, and I’ve been reading up on handlers, and if i’m right, handlers can take the repeated sections into 1 or a few lines apiece. Except the entire thing (almost) is contained within a tell command. Does that mean I can’t use handlers? Is there another option? Would it help if I took the entire tell command and broke it up into a bunch of tell/end tells? If you need specifics, my script (or an older version of it) is here: http://macscripter.net/viewtopic.php?id=36366. Thanks.

Handlers are definitely the way to go. If you use them within a “tell” block, you should precede their calls with the word “my” so the call will be passed back to your script rather than to the application which won’t recognize it.


set A to {}

tell application "Finder"
	repeat with k from 1 to 2
		set end of A to my getText(k)
	end repeat
end tell

tell application "System Events"
	set end of A to my getText(3)
end tell

to getText(n)
	return item n of {"Text_1", "Text_2", "Text_3"}
end getText

A --> {"Text_1", "Text_2", "Text_3"}

A couple of comments on what you’re doing first:
¢ Scripting Safari is much easier than other browsers thanks to its ability to “do javascript”. If you know a bit of javascript and DOM manipulation then you never have to do any “tell System Events to keystroke …” etc.
¢ Youtube videos almost always use AAC audio and personally I prefer to just download the whole video then extract the audio track with ffmpeg to a .m4a file. This means the audio does not get re-encoded so there’s zero loss of quality and no inflation in size. Of course it does mean a somewhat bigger download.

But as for simplifying your code, here are a few tips…

¢ Rather than using repeats like “repeat with numtimes from 1 to 15” where the loop counter variable doesn’t get used, you can just do “repeat 15 times”.

¢ Code like

if condition then
	statements
else
	if condition2 then
		statements
	end if
end if

Can be shortened to

if condition then
	statements
else if condition2 then
	statements
end if

¢ Code like

if condition then
	if condition2 then
		statements
	end if
end if

Can be shortened to

if condition and condition2 then
	statements
end if

¢ Code like


if condition then
	statement -- (one line)
end if

Can be shortened to

if condition then statement

¢ Text item delimiters! Saving and restoring these is a myth (I think from the days of OS 9). I do not understand why people insist on continuing to do so today. You’re writing your own script, you know when you’re relying on text item delimiters and when you’re not. One script’s text item delimiters does NOT affect another script’s text item delimiters.
Code like

set prevTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to "+"
set songs to text items of songs
set text item delimiters of AppleScript to " "
set songs to "" & songs
set text item delimiters of AppleScript to prevTIDs

Can be shortened to

set text item delimiters of AppleScript to "+"
set songs to text items of songs
set text item delimiters of AppleScript to " "
set songs to songs as text

Note also that “of AppleScript” is only necessary when you’re within a tell block.

¢ You have a couple of big sections that tab and return in a search results page. These could be shortened to something like

tell application "System Events"
	if doc contains "Translate results into my language" then keystroke tab
	if doc contains "did you mean" then keystroke tab
	repeat 13 times
		keystroke tab
	end repeat
	keystroke return
end tell

Hope this helps :slight_smile:

Wow guys you were sooooo helpful!!! I just learned a ton!! Thank you so much!!

Adam:
I think I understand what you’re saying. I’m a bit confused, but I might be able to figure it out with a bit of experimenting. If you care to help further, it would be nice to have an example from my script. Thanks so much though for your help! You may have given me the 1 clue needed to proceed, and I truly appreciate that! Thanks!!1

gannet:
I’m not sure that switching to Safari with this script would help because I know 0 javascript and nothing about DOM. This is the only language I know anything about besides the very basics of html. For my purpose, the quality isn’t that big of a deal, it’s mostly just getting masses of songs quickly, but thank you. I was trying to figure out how to repeat with a variable so thank you so much for that. For the “elses” and combining “ifs”, I just did that yesterday, actually, so that’s covered, but thanks again. I had seen the combining of “if” “then” to one line but hadn’t thought about it. As for the rest of it…You’re blowing my mind!!! I will put these in tomorrow on my day off! Thank you so much! You have been so helpful and I appreciate it so much! I can’t believe how kind you were to spell it all out for me so I could understand and so clearly too! THANK YOU!!

Because it’s always good practice to to restore any defaults that you change, especially in an environment where your code may incorporate code written by others or where others might incorporate your code into theirs. The principle ” as has already been quoted somewhere else ” is to “Script defensively but courteously.”

What you do in your own scripts is up to you. Beginners should always be taught the right way to do things. It sets them off on the right foot and saves the rest of us having to answer the same old “Why is this happening?” questions year after year.

I have to agree with Nigel because of this situation:

set aValue to "aKey:withvalue
anotherKey:withanotherValue"

return functionA(aValue)

on functionA(aValue)
	set text item delimiters of AppleScript to string id 10
	set theRow to functionB(text item 1 of aValue) -->will mess things up
	set theRow to functionB(text item 2 of aValue) --<for this call
	set text item delimiters of AppleScript to ""
	return theRow --it shoud be {"anotherKey", "withanotherValue"}
end functionA

on functionB(aValue) --will go wrong
	set text item delimiters of AppleScript to ":"
	set __textItems to text items of aValue
	set text item delimiters of AppleScript to ""
	return __textItems
end functionB

I have to admin that I always set delimiters to “” but that’s because it fits the way my programming works so text item delimiters aren’t set in a nested way but alway procedural.

Hm, I’m not sure I agree. If you are in an environment like Nigel says where you’re sharing code around, then yes it may be a good idea. But coding every script you write “courteously, just in case someone might want to copy code from it” seems a bit ridiculous and certainly gets tedious with TIDs. If someone does want to copy code from an arbitrary script, it’s their responsibility to make sure it works within their own script.
My own practice is to always (and only) set TIDs exactly when I need them, without restoring them to anything afterward. I only mentioned it in the interest of helping shorten the script, but I should let him choose his own style :slight_smile:

[edit] Just to clarify my comment about OS 9: Prior to 10.5, text item delimiters persisted across all scripts within Script Editor, so it was of some importance to preserve them. I had an idea the situation was worse back on OS 9 but I don’t know for sure.

Speaking of TIDs though, drummerof13 if you’re running on 10.6 or later you can actually do both your text substitutions at once:

set text item delimiters of AppleScript to {"+", tab}

Also, you appear to have a complex way of determining if a page has finished loading. Could you not just do something like this?

repeat while loading of active tab
	delay 1
end repeat

(I wish Safari could do this :()

haha thanks gannet for your loading idea. This is my first project using applescript, so I know very little. I had tried something like “if active tab is loading” (in the early stages of this script, but it never seemed to work, so I quickly went for something else. However, sometimes it says it’s done loading, but it’s really not, and it’s also important for me to know what’s on the page in order for the script to know what to do next, so I think i’ll morph both ideas together. Once again, thank you so much for your input. You have been SOOO helpful!!!

A page status 200 for example doesn’t say anything how it is represented on your page. You have to understand that a page status 200 is just the html content like you see in view source. The webkit (html renderer) hasn’t anything done yet, external files linked to this file hasn’t been loaded yet like javascript, images and css files and still the page status is 200. This is normal behaviour because the ‘main’ file is succesfully loaded and completed. Then there is another item named AJAX. AJAX get called when a page load is completed and then they load certain html code into your page.

To determine if a page is loaded you can do the following things with javascript

  1. check the http status of an image if it’s not loaded then the page load is not completed
  2. check if an element exists (I use it to check if an ajax request has took place or not)

Thanks DJ, but most of that was over my head, and I found out I can use cURL, so i don’t even need to wait for the pages to load. Thanks though!