Sluggish Clipboard Behaviour

I am trying to create a script to take the clipboard, strip out certain characters, paste the stripped down string and finally restore the clipboard to its original state:

I have the following script:

--delay 2
set chars_to_strip to {" ", ASCII character 10, ASCII character 13, "(", ")", "-"}
set message_text to the clipboard -- get clipboard
set temp_store to message_text

repeat with cnt from 1 to count (chars_to_strip)
	set the message_text to replace_chars(message_text, item cnt of chars_to_strip, "")
end repeat
--display dialog message_text
set the clipboard to message_text
--with timeout of 1 second
tell application "System Events" to tell (name of application processes whose frontmost is true) to keystroke "v" using command down -- paste stripped down text
--end timeout

delay 0.5
set the clipboard to temp_store --restore clipboard

on replace_chars(this_text, search_string, replacement_string)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to astid
	return this_text
end replace_chars

Two issues encountered:
(1) I lose formatting after I restore the clipboard (minor issue)
(2) The clipboard does not restore until after a number of seconds have passed after running the script. The peculiar thing is that I had to introduce a delay 0.5 to get the script to work at all because without the delay, by the time System Events pasted the parsed text, the script had already restored the original clipboard.

Any ideas? And as an aside, is it possible to issue a paste command without having to use the “V” hot key, which would have to work across all applications?

Thanks

It seems to work for me, except that if I run it from the script editor, that’s where the text gets pasted, so I inserted a line to tell Text Edit to activate:

--delay 2
set chars_to_strip to {" ", ASCII character 10, ASCII character 13, "(", ")", "-"}
--set message_text to the clipboard -- get clipboard
set message_text to the clipboard font
set temp_store to message_text

repeat with cnt from 1 to count (chars_to_strip)
	set the message_text to replace_chars(message_text, item cnt of chars_to_strip, "")
end repeat
set the clipboard to message_text
--with timeout of 1 second

--Insert this line:
tell application "TextEdit" to activate

tell application "System Events" to tell (name of application processes whose frontmost is true) to keystroke "v" using command down -- paste stripped down text
--end timeout

delay 0.5
set the clipboard to temp_store --restore clipboard

on replace_chars(this_text, search_string, replacement_string)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to astid
	return this_text
end replace_chars

I have the script attached to a Hotkey with Quicksilver as it needs to work in all apps.

It seems that when the script is invoked with Quicksilver, the funny behaviour I am experiencing occurs. But if run direct from Script Editor, the script works as you would expect. You can hit command V just after running the script and the original clipboard is back in place. Not so when invoked from Quicksilver.

Not sure what to make of this…

Here is what is happening:

I add a “delay 2” to the beginning of the script so that I can run it and switch to the relevant app before it starts processing pasting. If I run from Script Editor and as soon as it pastes the parsed clipboard (into Word or Textedit) I start hitting command V manually, I get this:

Just as you would expect.

If I run the script from Quicksilver, do exactly the same thing, I get this:

As you can see, it takes some time before the clipboard is restored and the computer feels unresponsive as I hit the command Vs this time.

Curious…

… part of the problem (but not all) is that the scripted “command v” interferes with the hotkey used by Quicksilver. If I could directly command the frontmost application to paste without needing to resort to simulating keyboard presses, that would help…

I’m not sure, but I think that Quicksilver is showing up in your list “of application processes whose frontmost is true” and that is causing the delay.

Any time you use UI scripting, you’ll need to experiment with adding delays. I have the following values in my UI scripts these days:

short_delay = 0.2
medium_delay = 1
long_delay = 3

These three values seem to cover most circumstances in Tiger and Leopard using anything as fast or faster than a “mirror front” Mac. Your values may vary depending on the speed of the machine the script is running on.

I’ve yet to meet a UI script that didn’t need at least a few stretegically place delays to make it run smoother and more repeatably.

EDIT:
To be clear, I forgot to add a syntax example:

delay medium_delay

I use variables so I can globally control certain delay intervals. Comes in handy when my scripts move to a faster machine or a new OS version (like Tiger-to-Leopard), I can re-tweak the delays easier. I used to use 0.4 for short_delay and 2 for long_delay under Tiger, but Leopard changed the dynamics…things needing little delays got quicker, but the apps needing long delays (like Lotus Notes) needed longer ones. Maybe it’s a Rosetta side-effect?

Thanks for the suggestions

For those who may find it useful, final script follows below. I still use Quicksilver but the hotkey is now set in Quicksilver to run the script after it has been released. All seems to work pretty well. Have added Growl notification for visual feedback that it is working as it is not instantaneous with GUI scripting being necessary.

set frontApp to my getFrontApp() -- determine frontmost app
my notify(1, frontApp) -- Growl notify that special pasting

delay 0.3
set chars_to_strip to {" ", ASCII character 10, ASCII character 13, ASCII character 9, "(", ")", "-"}
set message_text to the clipboard -- get clipboard
set temp_store to message_text

repeat with cnt from 1 to count (chars_to_strip)
	set the message_text to replace_chars(message_text, item cnt of chars_to_strip, "")
end repeat
set the clipboard to message_text

tell application "System Events" to tell (name of application processes whose frontmost is true) to keystroke "v" using command down -- paste stripped down text

delay 0.3
set the clipboard to temp_store --restore clipboard

-- various subroutines follow
on replace_chars(this_text, search_string, replacement_string)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to astid
	return this_text
end replace_chars

on notify(messNum, appname)
	tell application "GrowlHelperApp"
		set the allNotificationsList to ¬
			{"StripPaste"}
		set the enabledNotificationsList to {"StripPaste"}
		register as application ¬
			"StripPaste" all notifications allNotificationsList ¬
			default notifications enabledNotificationsList ¬
			icon of application appname
		if messNum is 1 then
			notify with name ¬
				"StripPaste" title ¬
				appname description ¬
				"Pasted stripped text" application name "StripPaste"
		end if
	end tell
end notify

on getFrontApp()
	set colon to ":" as Unicode text
	set dot to "." as Unicode text
	set appPath to (path to frontmost application as Unicode text)
	considering case
		if (appPath ends with colon) then
			set n to -2
		else
			set n to -1
		end if
		set astid to AppleScript's text item delimiters
		set AppleScript's text item delimiters to colon
		set appname to text item n of appPath
		if (appname contains dot) then
			set AppleScript's text item delimiters to dot
			set appname to text 1 thru text item -2 of appname
		end if
		set AppleScript's text item delimiters to astid
	end considering
	return appname
end getFrontApp

Whoops. Replace the tell “System Events” line above with:

tell application "System Events" to tell application frontApp to keystroke "v" using command down -- paste stripped down text

Seems to help with speed as well.