Question

When a script is saved as a bundle, it can use the localized string command to find the appropriate string, e.g. in Contents/Resources/English.lproj/Localizable.strings. If this is a format string, what is the best way to fill in the placeholders? In other words, what is the AppleScript equivalent of +[NSString stringWithFormat:]?

One idea I had was to use do shell script with printf(1). Is there a better way?

Was it helpful?

Solution

Since OS X 10.10, it’s been possible for any AppleScript script to use Objective-C. There are a few ways to call Objective-C methods from within AppleScript, as detailed in this translation guide. An Objective-C developer like me would gravitate toward this syntax, which interpolates the method's parameters with their values:

use framework "Foundation"

tell the current application's NSWorkspace's sharedWorkspace to openFile:"/Users/me/Desktop/filter.png" withApplication:"Preview"

Result:

true

+[NSString stringWithFormat:] is a tricky case. It takes a vararg list as its first parameter, so you need some way to force both the format string and its arguments into the same method parameter. The following results in an error, because AppleScript ends up passing a single NSArray into the parameter that expects, conceptually, a C array of NSStrings:

use framework "Foundation"

the current application's NSString's stringWithFormat:{"%lu documents", 8}

Result:

error "-[__NSArrayM length]: unrecognized selector sent to instance 0x7fd8d59f3bf0" number -10000

Instead, you have to use an alternative syntax that looks more like an AppleScript handler call than an Objective-C message. You also need to coerce the return value (an NSString object) into a text:

use framework "Foundation"

the current application's NSString's stringWithFormat_("%lu documents", 8) as text

Result:

"2087 documents"

The “with parameters” syntax that @nlanza mentions points to the fact that AppleScript is using something akin to NSInvocation under the hood. In Objective-C, NSInvocation allows you to send a message to an object, along with an array of parameter values, without necessarily matching each value to a particular parameter. (See this article for some examples of using NSInvocation directly.)

OTHER TIPS

As ugly as it is, calling out to printf(1) is the common solution.

A cleaner, though somewhat more complex, solution is to use AppleScript Studio, which allows you to call into Objective-C objects/classes from your AppleScript code with the call method syntax documented here.

With that, you'd be able to use something like this:

call method "stringWithFormat:" of class "NSString" with parameters {formatString, arguments}

The downside of this, of course, is that you need to write an AppleScript Studio app instead of just writing a simple script. You do get a good bit more flexibility in general with Studio apps, though, so it's not all together a terrible route to go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top