How to Interpret an Applescript string variable as a command when sent to OmniGraffle?

Hi,
I am updating an Applescript that reads data from my calendar and writes into a year planner that gets drawn in Omnigraffle. My aim, in this update, is to set the colour of portions of the text in a rectangle. Looking at Applescript written by Omnigraffle shows that the text: value of a cell may be a list of text values, each with its own style commands. Note I have added line endings for clarity.

tell canvas of front window
		make new shape at end of graphics with properties {fill:no fill, draws stroke:false, draws shadow:false, autosizing:full, size:{512.32, 28.447998}, 
		text:{{size:16, alignment:center, color:{1.0, 0.13552, 0.16384}, font:"HelveticaNeue", text:"Here is "}, 
		{size:16, alignment:center, color:{0.137255, 0.368627, 0.0}, font:"HelveticaNeue", text:"Some"}, 
		{size:16, alignment:center, color:{1.0, 0.13552, 0.16384}, font:"HelveticaNeue", text:" Text : "}, 
		{size:16, alignment:center, color:{0.704176, 0.37007, 0.115055}, font:"HelveticaNeue", text:"The Quick Brown Fox"}, 
		{size:16, alignment:center, color:{1.0, 0.13552, 0.16384}, font:"HelveticaNeue", text:" Jumps OVER "}, 
		{size:16, alignment:center, color:{0.156863, 0.203922, 0.313726}, font:"HelveticaNeue", text:"the LAzy Dog"}, 
		{size:16, alignment:center, color:{1.0, 0.13552, 0.16384}, font:"HelveticaNeue", text:"."}}, origin:{90.708662, 58.110237}, thickness:2}
	end tell

My code generates the text portion of the command and stores it in a variable tText e.g.

{font:kfont, size:kCalEventTextSize, alignment:left, color:{0, 47802, 0},text:"Grn Bin"},{font:kfont, size:kCalEventTextSize, alignment:left, color:{33924, 16962, 12079},text:"Red/Brn Bin"}

Next, the string variable, tText, is wrapped in brackets and used in a command sent to OmniGraffle (inside a tell block) :

set tText to "{" & tText & "}"
make new shape at end of graphics of first canvas with properties {origin:{Col3LeftMargin, myVerticalCursor}, size:{myNotesColWidth, myNormalCellHt}, draws shadow:false, name:"Rectangle", user name:"MyEntry", fill color:tCellColour, text:tText, user data:{CellDate:userDataDate}}

This causes OmniGraffle to print out the full command as stored in variable tText into the rectangle rather than interpreting it as a command that includes variables.

I think that I should be using the RunScript command but am uncertain how ?

Any thoughts?

S

So I have a solution but I am sure it could be improved on.
The way I managed to get the code working is to use the Run Script command. As I understand it this command accepts a multi line string of text that has to be a valid Applescript in its own right.

So I modified my code to first write a long string :

set tCellColourString to "{" & item 1 of tCellColour & "," & item 2 of tCellColour & "," & item 3 of tCellColour & "}"							
set tCommand to "tell document 1 of application \"OmniGraffle\"" & return
set tCommand to tCommand & "set kfont to " & "\"" & kfont & "\"" & return
set tCommand to tCommand & "set kCalEventTextSize to " & "\"" & kCalEventTextSize & "\"" & return
set tCommand to tCommand & "make new shape at end of graphics of first canvas with properties {origin:{" & Col3LeftMargin & "," & myVerticalCursor & "}, size:{" & myNotesColWidth & "," & myNormalCellHt & "}, draws shadow:false, name:" & "\"Rectangle\", user name:\"MyEntry\", fill color:" & tCellColourString & ", text:{" & tText & "}, user data:{CellDate:" & userDataDate & "}}" & return
set tCommand to tCommand & "end tell"
							
run script tCommand

The code snip first converts a colour list present in the parent script to text. This is followed by the tell statement and the definition of two variables that are used in the contents of tText where tText is the Applescript code created in sub routines. The principle payload line is the one before the end tell.

The string that is created is of variable length depending on the number of ‘text’ items present in the ‘text’ list stored in tText. Here is an example of what the code above creates, note I have added some additional linefeeds for clarity:

tell document 1 of application "OmniGraffle"
	set kfont to "Gill Sans"
	set kCalEventTextSize to "9"
	make new shape at end of graphics of first canvas with properties {origin:{94, 171}, size:{216.666666666667, 28}, draws shadow:false, name:"Rectangle", user name:"MyEntry", fill color:{63000, 63000, 63000}, 
	text:{{font:"kfont", size:kCalEventTextSize, alignment:left, color:{0, 47802, 0}, text:"Grn Bin"}, 
	      {font:"kfont", size:kCalEventTextSize, alignment:left, color:{33924, 16962, 12079}, text:",Red/Brn Bin"}}, user data:{CellDate:1 / 6 / 2024}}
end tell

The code works but I’m sure it can be improved. For example I’m not sure if kfont needs to be in quotes when kCalEventTextSize is not. The down side of using this long string is difficulty debugging and set commands littered with & ""’ characters.

I can’t help thinking that there is probably a simpler method of merging a command with a string that contains a command but so far I have not discovered it.

best wishes
S

Hi.

I don’t have OmniGraffle, nor do I understand the first value you give for tText, which is two records separated by a comma. Presumably, since you then wrap it in text representations of braces, it’s actually the text “{font:kfont, size:kCalEventTextSize, alignment:left, color:{0, 47802, 0},text:\“Grn Bin\”},{font:kfont, size:kCalEventTextSize, alignment:left, color:{33924, 16962, 12079},text:\“Red/Brn Bin\”}”.

Since two of the records’ values appear to be variables from the script, it would be better if possible to build the list with the appropriate actual records. For example:

set tText to {}
tell application "OmniGraffle"
	set end of tText to {font:kfont, size:kCalEventTextSize, alignment:left, color:{0, 47802, 0}, text:"Grn Bin"}
	set end of tText to {font:kfont, size:kCalEventTextSize, alignment:left, color:{33924, 16962, 12079},text:"Red/Brn Bin"}
	make new shape at end of graphics of first canvas with properties {origin:{Col3LeftMargin, myVerticalCursor}, size:{myNotesColWidth, myNormalCellHt}, draws shadow:false, name:"Rectangle", user name:"MyEntry", fill color:tCellColour, text:tText, user data:{CellDate:userDataDate}}
end tell

Or of course:

tell application "OmniGraffle"
	set tText to {{font:kfont, size:kCalEventTextSize, alignment:left, color:{0, 47802, 0}, text:"Grn Bin"}, {font:kfont, size:kCalEventTextSize, alignment:left, color:{33924, 16962, 12079},text:"Red/Brn Bin"}}
	make new shape at end of graphics of first canvas with properties {origin:{Col3LeftMargin, myVerticalCursor}, size:{myNotesColWidth, myNormalCellHt}, draws shadow:false, name:"Rectangle", user name:"MyEntry", fill color:tCellColour, text:tText, user data:{CellDate:userDataDate}}
end tell

If tText really does start off as text and it really is necessary to do it that way, you may have some luck with run script as follows:

(*
Assuming that tText contains the string value
"{font:kfont, size:kCalEventTextSize, alignment:left, color:{0, 47802, 0},text:\"Grn Bin\"},{font:kfont, size:kCalEventTextSize, alignment:left, color:{33924, 16962, 12079},text:\"Red/Brn Bin\"}"
and that kfont and kCalEventTextSize are variables that have been set earlier in the script.
*)

set tText to (run script "on run {kfont, kCalEventTextSize}
tell application \"OmniGraffle\"
return {" & tText & "}
end tell
end run" with parameters {kfont, kCalEventTextSize})
tell appllication "OmniGraffle"
	make new shape at end of graphics of first canvas with properties {origin:{Col3LeftMargin, myVerticalCursor}, size:{myNotesColWidth, myNormalCellHt}, draws shadow:false, name:"Rectangle", user name:"MyEntry", fill color:tCellColour, text:tText, user data:{CellDate:userDataDate}}
end tell

Thanks Nigel for showing me the error of my ways. I have never really understood AS lists and I guess that the fact that the contents are described as items is a clue. I’m afraid I tend to think in terms of text strings but the code you suggest is far more elegant.

many thanks for responding,
Simon