AppleScript for TextEdit - change color of highlighted text ?

My “simple” objective is to use a keyboard shortcut to change the color of a block of highlighted text in a TextEdit document to (for example) “blue”.

I have tried to create a simple Applescript to set the font of highlighted text (“the selection”) to “blue” but I kept getting type reference errors until I opened a new document, pasted the highlighted text into it, changed the color, then copied the text back into the original document. And now, if I try to automate this script with a keyboard shortcut it fails,
though when the Script Editor is open and I click on “Run” it works. How come? Any way [1] make it work with a keyboard shortcut and [2] avoid creating a new/temp document?
{see code snippet A}

I have also tried automating the color picker: can use System Events to control the keystrokes to bring up the color picker but then I am lost: I don’y know how to get System Events or keystrokes or even standard commands to set a specified color.
{see code snippet B}

Any help or hints would be vastly appreciated.

– code snippet A –

-- Code: Change Highlighted Text to Blue
-- Andrew White 3 Jan 2007
-- uses a 2nd document to make the change & copy back
--
set theText to "" as string
property paraColor : {0, 65000, 0}

-- copy the selected text to clipboard
tell application "TextEdit"
	activate
	tell application "System Events"
		tell process "TextEdit"
			keystroke "c" using {command down}
		end tell
	end tell
	
	--set theText to the clipboard as text
	set theText to (the clipboard)
	
	-- paste to new document
	set newDoc to (make new document at beginning of documents)
	set the text of document 1 to (the clipboard)
	
	-- color the text of the entire new document
	tell the text of document 1
		-- set the color of every word to {0, 65535, 0} -- green
		--set the color of every word to {65535, 0, 0} -- red
		set the color of every word to {0, 0, 65535} -- blue
	end tell
	
	-- copy the colored text to clipboard	
	--set the clipboard to the text of document 1
	
	--set text of document 1 to (the clipboard)
	tell application "System Events"
		tell process "TextEdit"
			keystroke "a" using {command down}
			--delay 1
			keystroke "c" using {command down}
		end tell
	end tell
	
	-- close the temp document
	close document 1 saving no
	
	-- temp: paste to new document
	-- set newDoc to (make new document at beginning of documents)
	
	
	-- paste to original document (hopefully still highlighted selection)
	tell application "System Events"
		tell process "TextEdit"
			keystroke "v" using {command down}
		end tell
	end tell
	
end tell

– code snippet B –

tell application "TextEdit" to activate
tell application "System Events"
	tell process "TextEdit"
              -- this just pops up the color picker
		keystroke "c" using {command down, shift down}
              -- but how to make a given color "selected" ?
              -- and if selected will it change the highlighted text color?
	end tell
end tell

Hi anwhite,

If you have Jon’s Commands osax, then you can do this to change color of selected text to blue:

tell application "TextEdit"
	activate
	ignoring application responses
		choose color starting color {0, 0, 65535}
	end ignoring
end tell

I don’t know if Jon’s Commands works in OS 10.4.x.

gl,

The choose color command was added to Standard Additions in AppleScript v1.9.2 (OS X v10.3).

-- This should work on OS X v10.3+. It returns a list of the RGB values.
choose color

Are you trying to do something like this, anwhite?


tell application "System Events" to tell text area 1 of scroll area 1 of window 1 of process "TextEdit" to if exists then
	set {x, y} to value of attribute "AXSelectedTextRange"
	if x ≤ y then tell application "TextEdit" to set color of document 1's characters x thru y to choose color
end if

Mind you, there’s not a great deal of difference between that and:


activate application "TextEdit"
tell application "System Events" to keystroke "c" using {command down, shift down}

Nevertheless, the original technique is quite handy for setting selected text to a preset color:


activate application "TextEdit"
tell application "System Events" to tell text area 1 of scroll area 1 of window 1 of process "TextEdit" to if exists then
	set {x, y} to value of attribute "AXSelectedTextRange"
	if x ≤ y then tell application "TextEdit" to set color of document 1's characters x thru y to {0, 0, 65535}
end if

Nice one, kai. :cool:

All these years I’ve had Jon˜s Commands and I didn’t realise it could do that! :slight_smile:

Jon’s works in OS 10.4, but doesn’t work on Intel machines. (I’m told.) Jon Pugh has indicated that he doesn’t consider it worth his while to port the OSAX for the new machines, so its days are apparently numbered. :frowning:

Does the new stard additions’ ‘choose color’ have a starting color parameter. Maybe they got it from Jon Pugh.

Oh no! No more ‘keys pressed’ whenever someone wants to know how to detect a key pressed. Maybe Apple will add that also considering they change systems every year.

hello,

there is a good discussion of using the header file of a text edit file to get the tags for different colors here:

http://bbs.applescript.net/viewtopic.php?id=17413

of course the methods discussed here may be more appealing. still, there’s more than one way…

cheers.

Yes it does. (http://www.apple.com/applescript/releasenotes/192OSX.html) (FWIW, AS Studio has this too. Not sure when that appeared.)

I am overwhelmed and indebted to all respondents
especially to “kai”
who provided the solution and a very fast one at that:

activate application “TextEdit”
tell application “System Events” to tell text area 1 of scroll area 1 of window 1 of process “TextEdit” to if exists then
set {x, y} to value of attribute “AXSelectedTextRange”
if x ≤ y then tell application “TextEdit” to set color of document 1’s characters x thru y to {0, 0, 65535}
end if

this worked perfectly on any selected text and very quickly replaced my (refined) kludge code (which required the temp document)
which is shown below (more for humor and contrast with kai’s parsimonious approach) - see below

However, to be just a bit more from kai or any others:
just HOW does kai’s fleet code work??

Recall: All I have started with is in any TextEdit document I have highlighted (not even copied) a selection of text (1 word, 1 paragraph, the whole document).
I have 3 stages of befuddlement here:
(1) tell text area 1 of scroll area 1 of window 1 of process “TextEdit” ← how does the selected text appear “identified” by that syntax-phrase?
(2) set {x, y} to value of attribute “AXSelectedTextRange” ← where did “AXSelectedTextRange” come from? and why assign it to {x,y} and not just x ?
ok, so i think it specifies a from-x to-y range and what I have is a short or long text ARRAY? identified by first and last character in the array - correct?
(3) if x ≤ y then tell application “TextEdit” to set color of document 1’s characters x thru y to {0, 0, 65535} ← why test for x <= y ?
so then as long as array element x is less than or equal to y (so whay even test for this??) set all characters in the array to a given color
Wow I started to comprehend but only barely …

Here’s the (refined) kludge code for comparison and historical archiving:

tell application “TextEdit”
activate
– add delay to allow time to activate before copying, else fails to copy!
delay 0.5
– copy highlighted text in orig document
tell application “System Events” to keystroke “c” using {command down}
– paste clipboard text to new document
set newDoc to (make new document at beginning of documents)
set the text of document 1 to (the clipboard)
– color the text of the entire new document
– green={0, 65535, 0},red={65535, 0, 0}, blue={0, 0, 65535}
tell the text of document 1 to set the color of every word to {0, 0, 65535}
– copy the colored text to clipboard
tell application “System Events” to keystroke “ac” using {command down}
– close the temp document
close document 1 saving no
delay 0.5
– paste to original document (hopefully still highlighted selection)
tell application “System Events” to keystroke “v” using {command down}
end tell

Model: iMac Core2Duo (Sep 2006)
AppleScript: for Mac OSX 10.4.8
Browser: Safari 419.3
Operating System: Mac OS X (10.4)

“AXSelectedTextRange” is an attribute of text area 1 of scroll area 1 of window 1 of the application process “TextEdit”, which currently running on the machine under the guidance of System Events. “AXSelectedTextRange”'s value is a list containing two integers. Setting {x, y} to this list sets x to the first integer and y to the second. The two integers represent the idices of the characters at either end of the selection in the text of the document. But see below.


Offhand, I’m not sure.
[/quote]

Are you sitting comfortably? :slight_smile: “AXSelectedTextRange” apparently doubles as an indicator of the current insertion point. So {x, y} doesn’t so much mean “the text from character x to character y” as “the text between the beginning of character x and the end of character y”. When no text is selected, the insertion-point cursor is still somewhere in the text and the “beginning of x” and the “end of y” are the same. This is indicated in {x, y} by having x set to 1 more than y. (ie. Character x begins where character y ends.) kai’s script tests for (x <= y) to ensure that there is some selected text.

(x < y): the text from the beginning of character x to the end of character y is selected.
(x = y): only one character is selected “ from its beginning to its end.
(x > y): characters x and y are adjacent and only the insertion point between them is “selected”. Since the script interprets the numbers as whole characters, and AppleScript treats ‘x thru y’ the same as ‘y thru x’, the script would colour both characters in this case instead of neither. So it has to check to ensure that x is not greater than y before continuing.

This is referring to the whole text area in TextEdit, not the selection.

I could use some assistance on that first part. :slight_smile:

A “Range” (in this case, based off the selection) is most likely a list of two values; the start of the range (which x takes) and the end of the range (which y takes).

Consider this:

set {test1, test2} to {10, 20}
display dialog test1 -- test1 is a number
display dialog test2 -- test2 is a number

-- If you did this, test1 would be a list
-- set test1 to {10, 20}

You do not have any text/characters, just two numbers.

Offhand, I’m not sure.

Don’t feel bad, this isn’t the most approachable script out there. :slight_smile:

Nice one, Nig. :cool:

Sorry I wasn’t around earlier to help out on this, guys. Didn’t think it would stir up something of a hornets’ nest. Thankfully, Mr. G., with his characteristic incisiveness and eloquence has ridden to the rescue (and let me off rather lightly). :wink:

Bruce is right, anwhite (although I could point you to some spookier stuff). :stuck_out_tongue: As with so many things, the trick is to break it down into more easily digestible chunks ” exactly as you’ve been doing.

Things might be easier if applications like TextEdit offered a little more in the way of scriptability, such as basic information about the selection, for example. The development of some features may be dependent on Cocoa, so we could have to wait a while longer for them to surface. In the meantime, we’ll just have to carry on jumping through a few hoops. (What fun! ;))

For comparison, you might also like to take a look at one two outstanding examples of scriptable text editors, such as Tex-Edit Plus or TextWrangler. (They’re not only eminently scriptable, but also recordable ” which can be handy when you’re looking for a vital clue about that elusive syntax…)

Or TextWrangler’s big brother if you want to get serious: BBEdit.

Quite ” although dipping a toe in the water is rarely a bad idea (unless, that is, one happens to be pursued by a mass of murderous, marauding invaders who can’t swim). :wink:

Agree :slight_smile: BBEdit is very scriptable, but often too powerful to get your head around. I ran a demo of Mellel for a while and found the same thing - if anything, I found it too powerful, too adjustable and hence confusing.