Slow Keystroke causing errors

Hi,

I have a handy perl and applescript combo that creates events from highlighted text. It’s a little buggy, but I’m working on it. Today, I found an issue that I could reproduce reliably with some text I’d highlighted. I found that the input text I was entering using keystroke was going too slow and that if I increased the delay, it worked. However, I don’t like this solution, as I could imagine scenarios where even that 2 second delay might cause it to fail.

Keystroke goes ridiculously slow. I watch it enter the text and it appears to get hung up at different points. I suppose I could paste the text, but I’m avoiding mucking with the clipboard, which I’d prefer remain untouched by the script. Here’s the snippet of code where I do the keystroke (with my delay that fixed it):

on quickevent(inputText, locationVal, urlVal, notesVal)
	tell application "Calendar" to activate
	tell application "System Events"
		keystroke "n" using {command down}
		keystroke inputText
		keystroke return
		delay 2
		key code 53
	end tell
...

And here’s the text that reliably took more than 1 second to enter:

Is there some way to make keystroke go faster or is there a better method of putting the text in? Or - is there a way for me to loop and test whether keystroke is done so I can wait a variable amount of time depending on how long the input text is? OR: Perhaps there’s a way to enter all the keystrokes and key codes together so that they are guaranteed to happen sequentially?

Thanks in advance,
Rob

This draft may help :

set inputText to "Michael Levine, University of California, Berkeley, The Regulatory Genome in Animal Development and Evolution Apr 23, 2014, 4:00 p.m."

set AddEvent_loc to localized string "Add event" in bundle path to application "Calendar"
# In French it's "Ajouter un événement"

activate application "Calendar"

tell application "System Events" to tell process "Calendar"
	
	tell window 1 to tell toolbar 1 to tell (first button whose description is AddEvent_loc)
		keystroke "n" using {command down}
		repeat
			delay 0.1
			if exists first pop over then
				tell first pop over
					set value of its first text field to inputText
				end tell
				exit repeat
			end if
		end repeat
	end tell
	--key code 53 # What need for Escape ???
end telll

Alternate version :

set inputText to "Michael Levine, University of California, Berkeley, The Regulatory Genome in Animal Development and Evolution Apr 23, 2014, 4:00 p.m."

set AddEvent_loc to localized string "Add event" in bundle path to application "Calendar"
# In French it's "Ajouter un événement"

activate application "Calendar"

tell application "System Events" to tell process "Calendar"
	
	tell window 1 to tell toolbar 1 to tell (first button whose description is AddEvent_loc)
		keystroke "n" using {command down}
		repeat
			delay 0.1
			if exists first pop over then exit repeat
		end repeat
		tell first pop over
			set value of its first text field to inputText
		end tell
	end tell
	--key code 53 # What need for Escape ???
end tell

Yvan KOENIG (VALLAURIS, France) lundi 21 avril 2014 18:02:59

The escape was needed in the old version of iCal so that the next step (getting the selected event) would work - otherwise there was a window in the way and the focus was wrong and getting the selected event wouldn’t work. It appears as though it may be unnecessary in this current version of iCal, but it’s not hurting anything, so I’ll leave it in there for backward compatibility.

If I understand your code correctly, you’re testing for the existence of the input text field before entering the “inputText”, is that correct? If that’s the case, then I don’t think this would solve my problem, which is the amount of time it takes to enter the text before performing the next step. The next step appears to be executing before the entry of the text is finished. I suppose I should have at least included the line following the code I pasted:

on quickevent(inputText, locationVal, urlVal, notesVal)
	tell application "Calendar" to activate
	tell application "System Events"
		keystroke "n" using {command down}
		keystroke inputText
		keystroke return
		delay 2
		key code 53
	end tell
	set thisEvent to get_selected_event()
	...

The call to get_selected_event returns an undefined value unless I add the extra second delay. I can reproduce the error by changing the delay to 1 second. Despite the delay, I can sit there and watch the text being entered, so I know that waiting for the entry field is not the problem. Text entry pauses in places, indirectly causing the error, because I think get_selected_event is being called before the event has finished being created (i.e. before the text has been fully entered).

But perhaps I can alter your code to test for the disappearance of the “pop over” to know when the event creation is complete? What do you think?

Thanks,
Rob

Try the script.
When I ran it, the field was filled quite instantly.
Setting the value is more efficient than keystroking the text.
I issued a return to validate the entry and it worked flawlessly.

If I issue the Escape, the entry is just cancelled so the previous work was just wasted time.

In the loop testing the availability of the text field, I am accustomed to put the short delay on entry but you may move it between end if and end repeat. If your machine is fast enough, it will never be applied.

With :
repeat
if exists first pop over then exit repeat
delay 0.1
end repeat

The Event log is :

keystroke “n” using {command down}
exists pop over 1 of button 1 of toolbar 1 of window 1 of process “Calendar” whose description = “Ajouter un événement”
→ true
set value of text field 1

which means that on my iMac mid 2011, the field is available with no delay.
I’m quite sure that you may use :

set inputText to "Michael Levine, University of California, Berkeley, The Regulatory Genome in Animal Development and Evolution Apr 23, 2014, 4:00 p.m."

set AddEvent_loc to localized string "Add event" in bundle path to application "Calendar"
# In French it's "Ajouter un événement"

activate application "Calendar"

tell application "System Events" to tell process "Calendar"
	
	tell window 1 to tell toolbar 1 to tell (first button whose description is AddEvent_loc)
		keystroke "n" using {command down}
		repeat
			if exists first pop over then exit repeat
			# delay 0.1
		end repeat
		tell first pop over
			set value of its first text field to inputText
		end tell
	end tell
	keystroke return
end tell

Yvan KOENIG (VALLAURIS, France) lundi 21 avril 2014 18:40:29

Try the script.
When I ran it, the field was filled quite instantly.
Setting the value is more efficient than keystroking the text.
I issued a return to validate the entry and it worked flawlessly.

If I issue the Escape, the entry is just cancelled so the previous work was just wasted time.

In the loop testing the availability of the text field, I am accustomed to put the short delay on entry but you may move it between end if and end repeat. If your machine is fast enough, it will never be applied.

With :
repeat
if exists first pop over then exit repeat
delay 0.1
end repeat

The Event log is :

keystroke “n” using {command down}
exists pop over 1 of button 1 of toolbar 1 of window 1 of process “Calendar” whose description = “Ajouter un événement”
→ true
set value of text field 1

which means that on my iMac mid 2011, the field is available with no delay.
I’m quite sure that you may use :

set inputText to "Michael Levine, University of California, Berkeley, The Regulatory Genome in Animal Development and Evolution Apr 23, 2014, 4:00 p.m."

set AddEvent_loc to localized string "Add event" in bundle path to application "Calendar"
# In French it's "Ajouter un événement"

activate application "Calendar"

tell application "System Events" to tell process "Calendar"
	
	tell window 1 to tell toolbar 1 to tell (first button whose description is AddEvent_loc)
		keystroke "n" using {command down}
		repeat
			if exists first pop over then exit repeat
			# delay 0.1
		end repeat
		tell first pop over
			set value of its first text field to inputText
		end tell
	end tell
	keystroke return
end tell

My understanding is that when we use set value, the next instruction ” here keystroke return ” is issued only when the setting is achieved.

Yvan KOENIG (VALLAURIS, France) lundi 21 avril 2014 18:40:29

Thanks!

I had to allow FastScripts access to accessibility features (see image) and then the first time it ran, I had to click to allow access, but after that, it works well.

I hadn’t looked closely enough to see you weren’t using keystroke. Cool.

I wonder about compatibility. Do you know if an older OS would be able to run this? I believe I’ll run the old method on error.

Thanks again,
Rob

I’m not really using Calendar so I don’t know how it behaved in older systems.
I would not be surprised if it behaved differently.
This afternoon I revised an old script because I just discovered that the same feature had three different GUI structure :

one applying for 10.4.x and older systems - I knew it
one applying from 10.5 thru 10.8.x - I knew it
one applying in 10.9.x - I was unaware of it

If Calendar (which was iCal) doesn’t behave in old system as it does in 10.9, Accessibility Inspector.app to learn the structure of its GUI.
Under 10.9 we have :
Application
AXWindow
Toolbar (one)
Button (two)
Pop Over (one)
Text Field (one)
At this time I don’t have a disk under 10.8.x

Yvan KOENIG (VALLAURIS, France) lundi 21 avril 2014 22:11:57

Hi robleach72,

Don’t know if you know this and haven’t been following this thread, but fyi, if an app is not allowed access with assistive devices then you can go to Preferences > Security & Privacy > Privacy > Accessability and allow access to for that app. Of I’m way off then disregard this.

gl,
kel

Thanks kel1. I got it.