why does this repeat leave ome data out?

I have this little script. it will start a text session with a buddy. It will then read the conversation. It checks for new text every 3 seconds. It will then read the new text/conversation. Sometimes it will get the new text and not read it. I do not know if it is just timing and the new text is falling under the old text, so it skips it, or what. Also, the script is to end when the chat window closes. This works. but if it is t accessing the text field it will error. If you open it, it should run as it is in your computer. Here are my questions:

  1. Is there a way to make it quit skipping parts?

  2. is there a way to shut the script down as soon as the chat window closes, rather than throwing an error when it closes?

tell application "iChat"
	set myBuddy to name of first account
	set myMessage to "Who do you want to chat with?"
	repeat
		display dialog myMessage default answer myBuddy
		set myBuddy to text returned of result
		if account myBuddy exists then
			if status of account myBuddy is not offline then
				exit repeat
			else
				set myMessage to """ & myBuddy & "" is currently offline."
			end if
		else
			set myMessage to """ & myBuddy & "" is not a buddy name."
		end if
	end repeat
	set myAnswer1 to button returned of (display dialog "What is " & myBuddy & "?" buttons {"Boy", "Girl"} default button 2)
	if myAnswer1 is "Boy" then
		set voiceType to "Fred"
	else
		set voiceType to "victoria"
	end if
	send "Hey" to account myBuddy
end tell
--------------------------HERE IS THE REPEAT
tell application "System Events" to tell process "iChat"
	set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
	set x to number of paragraphs of talking1
	set OldCount to 3
	repeat while window ("chat with " & myBuddy) exists		delay 3
		repeat with i from OldCount to x
			say paragraph i of talking1 using voiceType
		end repeat
		set OldCount to x
		set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
		set x to number of paragraphs of talking1
	end repeat
end tell

Hi bonedoc,

You can look through this scirpt which uses TextEdit (plain text document) and maybe get clues as to what’s wrong in yours if you want. It uses the linefeed character to signal the end of a paragraph and hence the beginning of saying something. The paragraph index i only increments when new paragraphs are added, so like a chat it is assumed that paragraphs may not be deleted. I don’t know how much of the chat is stored also,

set lf to (ASCII character 10)
tell application “TextEdit”
launch
activate
make new document at front with properties ¬
{text:“type some paragraphs after this one” & lf}
end tell
set i to 0
set f to true
repeat while f
tell front document of application “TextEdit”
set para_list to paragraphs whose last character is lf
end tell
set c to count para_list
if i < c then
set i to i + 1
set this_para to item i of para_list
say (this_para as string)
end if
do shell script “sleep 1”
tell application “System Events”
if not (exists process “TextEdit”) then
set f to false
end if
end tell
end repeat

gl,

I modified the script a little.

set lf to (ASCII character 10)
tell application “TextEdit”
launch
activate
make new document at front with properties ¬
{text:“type some paragraphs after this one” & lf}
end tell
set i to 0
set f to true
repeat while f
tell front document of application “TextEdit”
try
set para_list to paragraphs whose last character is lf
on error
set f to false
end try
end tell
set c to count para_list
if i < c then
set i to i + 1
set this_para to item i of para_list
say (this_para as string)
end if
do shell script “sleep 1”
tell application “System Events”
set f to (exists process “TextEdit”)
end tell
end repeat

gl,

Kel, this works until the number of said paragraphs is equal to the initial number there. But, it does not see that other paragraphs have been added. So, it just does the delay/exist over and over. Can you tell which part of th script is not doing its job? It seems like the value x does not grow each time I add another paragraph.

tell application "iChat"
	set myBuddy to name of first account
	set myMessage to "Who do you want to chat with?"
	repeat
		display dialog myMessage default answer myBuddy
		set myBuddy to text returned of result
		if account myBuddy exists then
			if status of account myBuddy is not offline then
				exit repeat
			else
				set myMessage to """ & myBuddy & "" is currently offline."
			end if
		else
			set myMessage to """ & myBuddy & "" is not a buddy name."
		end if
	end repeat
	set myAnswer1 to button returned of (display dialog "What is " & myBuddy & "?" buttons {"Boy", "Girl"} default button 2)
	if myAnswer1 is "Boy" then
		set voiceType to "Fred"
	else
		set voiceType to "victoria"
	end if
	send "Hey" to account myBuddy
end tell
-----------------------------------
tell application "System Events" to tell process "iChat"
	set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
	set x to number of paragraphs of talking1
	set OldCount to 0
	set f to true
	repeat while f
		set x to number of paragraphs of talking1
		if x > OldCount then
			set OldCount to OldCount + 1
			say paragraph OldCount of talking1 using voiceType
		end if
		do shell script "sleep 1"
		if not (exists window ("chat with " & myBuddy)) then
			set f to false
		end if
	end repeat
end tell

A quick look, this statement needs to be in the repeat loop, to update the text:

set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)

otherwise the text talking1 is always the same. If you’re interested in my updated script I can post it. I caught more errors. Mainly, I placed the error handler around more statements because I think the script was trying to get the text from TextEdit while it was still in the act of quitting.

Editted: also, it’s not good to place the tell block around the whole script like that or you will probably get errors like I wrote above in my script.

Here’s my updated script:

set lf to (ASCII character 10)
tell application “TextEdit”
launch
activate
make new document at front with properties ¬
{text:“type some paragraphs after this one” & lf}
end tell
set i to 0
set f to true
repeat while f
try
tell front document of application “TextEdit”
set para_list to paragraphs whose last character is lf
end tell
set c to count para_list
if i < c then
set i to i + 1
set this_para to item i of para_list
say (this_para as string)
end if
do shell script “sleep 1”
tell application “System Events” to set f to (exists process “TextEdit”)
on error
set f to false
end try
end repeat

Can you see how the tell block doesn’t surround the main part of the script. The tell blocks are used when needed to querry the app or whatever.

gl,

Kel, is this what you mean? I added the try/end try. There are no troubles quitting it upon closure of the window. Here is what I do not understand:

  1. I inserted that into the repeats. it works fine as long as I keep typing paragraphs fast. If nothing new is typed for a few seconds, and then you start typing, it does not work properly. i cant figure this out. It is almost exactly the same as the script you posted.
  2. How to I remove the Tell/end tell stuff you suggest? I tried to do this, but it does not understand the “value of text area 1” when the system events is not doing it.
tell application "iChat"
	set myBuddy to name of first account
	set myMessage to "Who do you want to chat with?"
	repeat
		display dialog myMessage default answer myBuddy
		set myBuddy to text returned of result
		if account myBuddy exists then
			if status of account myBuddy is not offline then
				exit repeat
			else
				set myMessage to """ & myBuddy & "" is currently offline."
			end if
		else
			set myMessage to """ & myBuddy & "" is not a buddy name."
		end if
	end repeat
	set myAnswer1 to button returned of (display dialog "What is " & myBuddy & "?" buttons {"Boy", "Girl"} default button 2)
	if myAnswer1 is "Boy" then
		set voiceType to "Fred"
	else
		set voiceType to "victoria"
	end if
	send "Hey" to account myBuddy
end tell
-----------------------------------
tell application "System Events" to tell process "iChat"
	set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
	set x to number of paragraphs of talking1
	set OldCount to 2
	set f to true
	repeat while f
		try
			if x > OldCount then
				set OldCount to OldCount + 1
				say paragraph OldCount of talking1 using voiceType
			end if
			set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
			set x to number of paragraphs of talking1
			do shell script "sleep 1"
			if not (exists window ("chat with " & myBuddy)) then
				set f to false
			end if
on error
set f to false
		end try
	end repeat
end tell

I had to do this in the text editor and hope it’s at least close to working:

set OldCount to 2
set f to true
repeat while f
try
tell process “iChat” of application “System Events”
set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
end tell
set x to number of paragraphs of talking1
if x > OldCount then
set OldCount to OldCount + 1
– check if typer is finished with this paragraph, by checking for linefeed
set this_paragraph to paragraph OldCount of talking1
if last character of this_paragraph is (ascii character 10) then
say paragraph OldCount of talking1 using voiceType
else – reset the index
set OldCount to OldCount - 1
end if
do shell script “sleep 1”
tell process “iChat” of application “System Events”
set f to (exists window ("chat with " & myBuddy))
end tell
on error
set f to false
end try
end repeat

Instead of getting only paragraphs with linefeed, the script checks if the last character of the paragraph with updated index ends with linefeed. Cross your fingers and pray to God.

Editted: I think there should be another ‘end if’ right after the other one.

gl,

kel,
I had to change a couple thing that were just errors, but here it is below. The code runs, but it does not say the text. That makes no sense to me, it looks like it would.

tell application "iChat"
	set myBuddy to name of first account
	set myMessage to "Who do you want to chat with?"
	repeat
		display dialog myMessage default answer myBuddy
		set myBuddy to text returned of result
		if account myBuddy exists then
			if status of account myBuddy is not offline then
				exit repeat
			else
				set myMessage to """ & myBuddy & "" is currently offline."
			end if
		else
			set myMessage to """ & myBuddy & "" is not a buddy name."
		end if
	end repeat
	set myAnswer1 to button returned of (display dialog "What is " & myBuddy & "?" buttons {"Boy", "Girl"} default button 2)
	if myAnswer1 is "Boy" then
		set voiceType to "Fred"
	else
		set voiceType to "victoria"
	end if
	send "Hey" to account myBuddy
end tell
-----------------------------------
set OldCount to 2
set f to true
repeat while f
	try
		tell application "System Events" to tell process "iChat"
			set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
		end tell
		set X to number of paragraphs of talking1
		if X > OldCount then
			set OldCount to OldCount + 1
			-- check if typer is finished with this paragraph, by checking for linefeed
			set this_paragraph to paragraph OldCount of talking1
		end if
		if last character of this_paragraph is (ASCII character 10) then
			say paragraph OldCount of talking1 using voiceType
		else -- reset the index
			set OldCount to OldCount - 1
		end if
		do shell script "sleep 1"
		tell application "System Events" to tell process "iChat"
			set f to (exists window ("chat with " & myBuddy))
		end tell
	on error
		set f to false
	end try
end repeat

Hi bonedoc,

You have to coerce to string the unicode text that you get from the text field so ‘say’ can use it. Try this:

say ((paragraph OldCount of talking1) as strubg) using voiceType

I think that’s it.

Editted: ‘as string’

gl,

Hi Jacques,

How can you get paragraphs if there is no linefeed (or carriage return) in the text?

gl,

Thanks Kel and Jacques!
Jacques, I plugged your idea into it all. You ought to try it. There is one weird characteristic about it. It will keep on reading everything to you if you keep typing from the start. But, if you pause, it will stop recognizing the text. it will start reading again if you enter in bunch of lines real fast, but it skips the first couple. I do not know if it has to do with the delay time of the shell script or what. If I increase that delay, it seems to be more accurate, but it is so slow between sentences. I will have to play around and see if I can make it more accurate. Here is the full script if you want to open it and try it. It is sort of fun. Ian

tell application "iChat"
	set myBuddy to name of first account
	set myMessage to "Who do you want to chat with?"
	repeat
		display dialog myMessage default answer myBuddy
		set myBuddy to text returned of result
		if account myBuddy exists then
			if status of account myBuddy is not offline then
				exit repeat
			else
				set myMessage to """ & myBuddy & "" is currently offline."
			end if
		else
			set myMessage to """ & myBuddy & "" is not a buddy name."
		end if
	end repeat
	set myAnswer1 to button returned of (display dialog "What is " & myBuddy & "?" buttons {"Boy", "Girl"} default button 2)
	if myAnswer1 is "Boy" then
		set voiceType to "Fred"
	else
		set voiceType to "victoria"
	end if
	send "Hey" to account myBuddy
end tell
-----------------------------------
set OldCount to 2
set f to true
repeat while f
	try
		tell application "System Events" to tell process "iChat"
			set talking1 to value of text area 1 of scroll area 1 of window ("chat with " & myBuddy)
		end tell
		set X to number of paragraphs of talking1
		if X > OldCount then
			set OldCount to OldCount + 1
			set this_paragraph to paragraph OldCount of talking1
			if this_paragraph is not "" then say this_paragraph using voiceType
		end if
		do shell script "sleep 1"
		tell application "System Events" to tell process "iChat"
			set f to (exists window ("chat with " & myBuddy))
		end tell
	on error
		set f to false
	end try
end repeat

Hi bonedoc,

When I run the script for TextEdit, I set the delay for .5 seconds and it does quite well.

do shell script “sleep .5”

About the linefeed, it must be carriage return instead (dos linefeed + cr) or maybe they send a linefeed before it sends a paragraph. I wasn’t thinking that one whole paragraph is sent at a time.

gl,