Can you please tell me what is wrong with the script below?
The grumpy compiler says:“TextEdit got an error: Can’t make selection of window 1 into type reference.”
tell application "TextEdit"
copy selection of window 1 to selStore
repeat with n from 1 to (get count of windows)
if name of window n is "Clippings.rtf" then exit repeat
end repeat
select window n
set insertion point after last character of window 1 to return & return
--insert date
set insertion point after last character of window 1 to return
set insertion point after last character of window 1 to selStore
save window 1
end tell
Mac mini PPC, OS X 10.4.8 Firefox 2.0.0.4 Applescript 1.10.7 Script Editor Version 2.1.1 (81)
This script is meant to copy selected text from the Web into a file named “Clippings.rtf”
The script compiles fine (when you press the compile button in Script Editor), but TextEdit is throwing an error (when you actually run the script).
I believe the reason that TextEdit is throwing that error is because is it doesn’t seem to have a selection property (or an insertion point property); However, those words compile because they are in Script Editor’s dictionary. (Which may be where you picked up those words…)
Side note: copy creates an actual copy of the data in memory, which makes it less efficient than the set command. You should only use AppleScript’s copy command when you want to explicitly avoid data sharing.
It’s possible to get TextEdit’s selection using GUI Scripting (if you have that enabled). Thereafter, you can either get the text of your “Clippings.rtf” document, concatenate the selected text to the end of it, and set the document’s text to the result; or you can make a new text element (a paragraph, say) at the end of the document with the selected text as data. In either case, if you want the new text to be separate from any existing text in the document, you need to add your own returns:
tell application "System Events"
tell application process "TextEdit"
set selStore to value of attribute "AXSelectedText" of text area 1 of scroll area 1 of front window
end tell
end tell
tell application "TextEdit"
tell document "Clippings.rtf"
set its text to its text & selStore & return & return
save
end tell
end tell
Or:
tell application "System Events"
tell application process "TextEdit"
set selStore to value of attribute "AXSelectedText" of text area 1 of scroll area 1 of front window
end tell
end tell
tell application "TextEdit"
tell document "Clippings.rtf"
make new paragraph at end with data (selStore & return & return)
save
end tell
end tell
You shouldn’t have any problem compiling either script with your set-up. I can only reproduce your particular errors if the document “Clippings.rtf” isn’t already open in TextEdit when the scripts are run. Is that possible?
Both versions are intended to do what your original was apparently trying to do: namely, to copy the selection from the front document in TextEdit and to append the text to the end of another open TextEdit document called “Clippings.rtf”. If you want to use the selection from, say, Firefox instead, you have to specify that that’s where the selection’s coming from. Unfortunately, Firefox itself isn’t very scriptable, but it’s possible to fake a few keystrokes to get the selected text. The script below uses the document “Clippings.rtf” if it’s already open; otherwise it gives the choice of opening it or creating a new one. Although, strictly speaking, it uses the GUI to get the selection from Firefox, it doesn’t use any commands that require GUI Scripting to be enabled.
set maxWait to 1.0 -- The maximum time the script will wait for the clipboard contents to change, in seconds.
tell application "System Events"
tell application process "firefox-bin" -- Firefox's process is called "firefox-bin".
set frontmost to true
-- Store the current clipboard contents and clear the clipboard.
set oldClipboard to (the clipboard)
set the clipboard to ""
-- Simulate the Command-C keystroke to copy from the frontmost process ("firefox-bin").
keystroke "c" using command down
-- Wait until the result appears on the clipboard or 1 second has elapsed.
set wait to 0.0
repeat while ((the clipboard) is "") and (wait < maxWait)
delay 0.2
set wait to wait + 0.2
end repeat
-- Get that result into the script and restore the previous clipboard contents.
set selStore to (the clipboard)
set the clipboard to oldClipboard
end tell
end tell
-- If the clipboard wait timed out, there's nothing selected in Firefox. Quit.
if (wait is greater than or equal to maxWait) then error number -128
tell application "TextEdit"
if (document "Clippings.rtf" exists) then
-- If "Clippings.rtf" is already open, use it.
set clippingsDoc to document "Clippings.rtf"
set newDocument to false
else
-- Otherwise, bring TextEdit to the front and ask the appropriate questions.
activate
display dialog "Do you want to create a new "Clippings.rtf" document or use an existing one?" buttons {"Cancel", "New", "Existing"} cancel button "Cancel" with icon note
-- Create a new document or open an existing one, as requested.
if (button returned of result is "New") then
set clippingsDoc to (make new document)
set newDocument to true
else
(open (choose file with prompt "Select the clippings file to use."))
set clippingsDoc to front document
set newDocument to false
end if
end if
tell clippingsDoc
-- Append the text to the clippings document and save the document.
set its text to its text & selStore & return & return
if (newDocument) then
-- Using 'choose file name' allows a more explanatory prompt than 'save' by itself.
save in (choose file name with prompt "Save the clippings file as.?" default name "Clippings.rtf")
else
save
end if
end tell
end tell
The theory is that if a script uses the clipboard, anything that the user him/herself may have put there will be lost. This is easily got round, as above, by getting the script to make a note of the existing contents first and then to restore them afterwards.
[i]Edit: Added a maximum wait time to the script, so it doesn’t wait indefinitely for the clipboard to change if there’s no selection in Firefox.
Since the script doesn’t use GUI Scripting, there’s no need to address the “firefox-bin” process in System events. We could instead address application “Firefox” directly. Nearly all visible applications understand ‘activate’ and the other commands are all vanilla or StandardAdditions. (In fact, it may not be necessary to address the other commands to Firefox at all, but I feel more secure explicitly using the frontmost application to access the clipboard.) Here’s the first half of the script again in that form:[/i]
set maxWait to 1.0 -- The maximum time the script will wait for the clipboard contents to change, in seconds.
tell application "Firefox"
activate
-- Store the current clipboard contents and clear the clipboard.
set oldClipboard to (the clipboard)
set the clipboard to ""
end tell
-- Simulate the Command-C keystroke to copy from the frontmost application ("Firefox").
tell application "System Events" to keystroke "c" using command down
-- Wait until the result appears on the clipboard or the maximum waiting time is reached.
set wait to 0.0
tell application "Firefox"
repeat while ((the clipboard) is "") and (wait < maxWait)
delay 0.2
set wait to wait + 0.2
end repeat
-- Get that result into the script and restore the previous clipboard contents.
set selStore to (the clipboard)
set the clipboard to oldClipboard
end tell
-- If the clipboard wait timed out, there's nothing selected in Firefox. Quit.
if (wait is greater than or equal to maxWait) then error number -128
I am very grateful for all the time you take to help me, and for answering my question about copy/paste.
I tried both your scripts, but for some obscure reason nothing happened.
I selected some text from a Firefox page and hit the RUN button of your second script
Nothing happened, even with Clippings.rtf opened. No error message either.
Looking at the Clipboard showed that it had neither changed nor been erased.
I then tried your first script with the same setup. Same result,
and again, the Clipboard was unchanged
I must have overlooked something, since it worked on your Mac.
After copying a few words to the Clipboard,
I tried this portion of your script on a new script window:
tell application “Firefox”
activate
set oldClipboard to (the clipboard)
set the clipboard to “”
end tell
The Clipboard remained unchanged. Does it mean that Firefox can’t give orders to the Clipboard?
I’m not clear what you mean by my “second script”. The second script in my second post above (message #5 in this thread) is an alternative to the first half of the first script in that message. By itself, it simply brings Firefox to the front, copies the selected Firefox text to the clipboard, sets the variable ‘selStore’ to that text, and restores the clipboard contents to what they were before. (The clipboard’s meant to appear unchanged afterwards.) It needs the second half of the first script in that post (everything from ‘tell application “TextEdit”’ to the last ‘end tell’) to take care of the TextEdit stuff.
If that’s the first script in message #5, it certainly does work on my Mac, both with GUI Scripting enabled and without. I can’t think why it’s not working on yours. I’m using a G5 with the same version of AppleScript as you, but with Firefox 2.0.0.3 and Mac OS 10.4.10.
No. That should place an empty string on the clipboard. The commands ‘the clipboard’ and ‘set the clipboard to’ are supplied by the StandardAdditions OSAX in your /System/Library/ScriptingAdditions/ folder. If your system’s healthy, they should work. You won’t see any difference in the Finder’s “Clipboard” window (if you’ve got that open) unless you close it first and reopen it “ but there shouldn’t be anything in the clipboard itself that can be pasted into a document.
If it really isn’t working for you, I’m afraid I don’t know what else to suggest.
I found that it was only the last part of your scripts that were rejected, so, for expediency’s sake I did a Frankenstein on that bit and it seemed to remove the blockage. The result is not as elegant but since it works there is no point to go any further on it.
Many thanks again for patiently following this up.