Escaping an apostrophe on when sending script to commandLine through AppleScript

I’m trying to send a AppleScript from $Text the osascript command line, e.g., property NSAttributedString : a reference to current application's NSAttributedString, via runCommand. It looks like the apostrophe is causing the process to break. The script is making it to the command line but it breaks at the first apostrophe. How can I escape the apostrophe in the script? Does anyone know?

Try escaping the apostrophe (\’)

Ya, I tried that, did not work.

Do you need to quote the argument? Do you need to pass the $Text as an argument, or pass it to stdin?

I am using this stampt:

$Text(log)="";
var:string theScript =$Text("Email3Script");
runCommand("/usr/bin/osascript"+" '"+theScript+"'");
$Text(log)=runCommand("/usr/bin/osascript"+" '"+theScript+"'");

Here is the script:

the log shows the script breaking right at the apostrophe, in fact it shows the apostrophe being removed.

I’m not sure what to do.

I’ve a try to pass the script to the runCommand via a path on the harddrive, I get a different error:

osascript[4621:225409] *** -[NSConcreteAttributedString initWithHTML:documentAttributes:]: value passed to argument of type ^@ must be either `missing value' or `reference'; assuming `missing value'.
/usr/bin/osascript: couldn't save changes to script /Users/username/Desktop/EmailScript3.scpt: error -1763.

I think you’re including documentation in the script.

I don’t think so…what makes you think that? Here is the whole script:

use framework "Foundation"
set ca to current application

-- Produce email copy

runStamp("EmailTextCreate")

to runStamp(stampName)
	activate application "Tinderbox 9"
	tell application "System Events" to click menu item stampName of menu "Stamps" of menu bar item "Stamps" of menu bar 1 of process "Tinderbox 9"
end runStamp

-- classes, constants, and enums used
property NSUTF8StringEncoding : a reference to 4
property NSSharingServiceNameComposeEmail : a reference to current application's NSSharingServiceNameComposeEmail
property NSAttributedString : a reference to current application's NSAttributedString
property NSString : a reference to current application's NSString
property NSSharingService : a reference to current application's NSSharingService


-- The inputs (to be retrieved from Tinderbox or wherever)
tell front document of application "Tinderbox 9"
	tell selection 1
		set theHTML to value of attribute "theText"
		set messageSubject to value of attribute "Subject"
		set recipientAddresses to value of attribute "Recipient"
	end tell
end tell


-- Convert the html to NSAttributedString
set theSource to ca's NSString's stringWithString:theHTML
set theData to theSource's dataUsingEncoding:(ca's NSUTF8StringEncoding)
set anAttributedString to ca's NSAttributedString's alloc()'s initWithHTML:theData documentAttributes:{}

-- Use NSSharingService to create email, preserving the formatting in contents
set aSharingService to ca's NSSharingService's sharingServiceNamed:(ca's NSSharingServiceNameComposeEmail)
if aSharingService's canPerformWithItems:{"someone@somewhere.com"} then
	set aSharingService's subject to messageSubject
	set aSharingService's recipients to recipientAddresses
	tell aSharingService to performSelectorOnMainThread:"performWithItems:" withObject:{anAttributedString} waitUntilDone:false
end if

runStamp2("EmailTextClear")

to runStamp2(stampName2)
	activate application "Tinderbox 9"
	tell application "System Events" to click menu item stampName2 of menu "Stamps" of menu bar item "Stamps" of menu bar 1 of process "Tinderbox 9"
end runStamp2

-- Remove email copy

Can you use the form " a reference to NSAttributedString of current application" to circumvent the apostrophe?

I tried that. The more the script process bu then I end up with an error “no such file exists.” It is not clear how I an pass the script from TBX or point to a specific file that has the script.

If I recall correctly, we don’t have as NSAttributedString of the current application. (See the Tinderbox applescript dictionary by using Open Dictionary… in script editor).

We do have a text, which is plain text.

Running a single straight quote (apostrophe) through runCommand may be possible but it’s asking for trouble!

That pretty much rules out AsObjC.

In the old days using osascript in runCommand in a stamp was the only way to pass Tinderbox attribute values out to a script. But now with TB’s external scripting support you don’t have to go through those contortions.

Why not activate the script externally in one of the normal ways? (A convenient way these days is to have a ‘Run AppleScript’ action in a shortcut in the Shortcuts app and pin that shortcut to the menu bar). That way you have just as convenient access as to a stamp and don’t have to worry about apostrophes.

2 Likes

And it’s not THAT hard. Piping through stdin is your friend.

Great idea…thanks for the promote. One issue is. However, it does to seem to be working. Are you aware of any security settings that I would need to set that would allow Shortcuts to open macMail? The shortcut appears to run the TBX stamps but fails to open the emails (the same script works fine in the script editor, so it may be a security issue, but I am not sure).

Note: I’ve turned on “Allow Running Scripts”

ISTM we need an “assume no prior expertise” step-by-step set of instructions for using AppleScript in this manner. IOW, for a saved AppleScript document (made in Script Editor, or Script Debugger, etc.) where to put it in the macOS and what permissions/menubar options/etc. need making so a user new to this process can ‘just’ run an AppleScript from Tinderbox.

I’m not offering the above as I’m not sure of all the settings/steps. But if someone comes up with one I’ll happily add it to aTbref so its easy for those in need (or updating to a fresh macOS install) can check all is set OK. Side nite, I’m sure macOS major iterations (Monterey, Ventura, etc.) will throw curveballs so some per-OS notes will be needed. But, I suspect the lack of such a set-up guide is likely one reason people not familiar with AppleScript don’t use it. And of course, poor AppleScript has clearly been unloved for ages and on Apple’s “We’d dump this feature it if only our user base would allow it” list. iOS-derived toy automations aren’t a like-for-like replacement.

No, definitely not hard at all, for almost everything. Great feature to have! When trying to pass a script through to osascript, escaping for the shell can get really tricky, though. Stymied by the humble apostrophe.

I see what you mean. The AsObjC in the AppleScript within Shortcuts doesn’t seem talk to Apple Mail.

The very same script within a Run AppleScript action in Automator does work on my machine. You could create Quick Action in Automator and run it from the Services Menu (attaching a keyboard shortcut if you want).

Thank you. I tried to figure this out but failed. Could you be prescriptive, and provide the steps on how to do this?

Well, I’ve failed now too! I blame it on Ventura security features I don’t quite understand. (I’ve hunted down and flipped all the security switches I could find in System Settings).

A script with AsObjC to send a rich text email from a selected Tinderbox note runs from Script Editor or Script Debugger or from Automator if it is open.

But it won’t run on my machine from Shortcuts or from a QuickAction created in Automator and placed in the Services menu.

Nor does it run properly any more from the Script Menu, whereas it did before.

So we might be grappling here not just with an apostrophe escaping problem for the shell if trying to use runCommand but also with security features in macOS, perhaps specifically related to sharing.

Test script here:

-- 1. get html and note Name from Tinderbox
tell front document of application "Tinderbox 9"
	repeat with aNote in selections
		tell aNote
			set noteHtml to evaluate it with "exportedString(this,\"^text^\")"
			set noteName to value of attribute "Name" -- we will use Name as subject of email
		end tell
	end repeat
end tell

-- 2. send to Apple Mail as formatted rich text
use framework "Foundation" -- for NSString, NSSharingService
set ca to current application -- for more compact AsObjC syntax
--   a. Convert the exported html to NSAttributedString
set theSource to ca's NSString's stringWithString:noteHtml
set theData to theSource's dataUsingEncoding:(ca's NSUTF8StringEncoding)
set anAttributedString to ca's NSAttributedString's alloc()'s initWithHTML:theData documentAttributes:{}
--   b. Use NSSharingService to create email, preserving the formatting in content
set aSharingService to ca's NSSharingService's sharingServiceNamed:(ca's NSSharingServiceNameComposeEmail)
set aSharingService's subject to noteName
tell aSharingService to performSelectorOnMainThread:"performWithItems:" withObject:{anAttributedString} waitUntilDone:false
2 Likes

FWIW, I’m working on some better documentation of runCommand() as those with most need will not be those with lots of Unix expertise.

Separately, if the community can come up with steps for setting up their Mac so their saved AppleScript scripts can easily be run, that too will be a boon. Again, the bar is highest for those new to such things even if they are simple in hindsight. :slight_smile:

To be honest, this is a relief. I thought all my newfound expertise was for not, as I just could not understand what I was doing wrong.

I tried on more thing and I got it working! :slight_smile: I had started getting echos of @TomD in my head “use Keyboard Maestro.” I listened. I created a Keyboard Maestro script that opened the script in Script Editor and ran it, as that is the only place I’ve been able to get the script to work. And it worked!

1 Like