Steve Mills wrote:
> I think I asked about this many years ago, but am not in a
place where I can look through my archived mail. Is there a way to
pass application declared property codes in a list or record and
then use them? Here's what I'm trying to do. I have a script for
InDesign CS6 that needs to do a bunch of different "change grep"s. I
wrote a function in the script to do the repeated work:
>
> [...]
>
> This doesn't work for all properties of change grep
preferences. When called like so:
>
> my changeStuff(findObj, "!!ALPH!!", {bullets and numbering list
type:numbered list, numbering start at:3, numbering format:"a, b, c,
d..."})
>
> The "numbering format" property does not get set in the "set
properties of change grep preferences to changeProps". InDesign bug.
I've tried changing the order of the properties, but that didn't
help. So I thought there might be some way to loop through a
list/record and set each property individually.
In AppleScript? No. An AppleScript record is a fixed collection of
properties, not an arbitrary collection of key-value pairs
(associative list, hash, dictionary, etc [1]). In other languages?
Sure, since those generally map AE records to dictionaries, it's
absolutely trivial; but then you need an Apple event bridge that
doesn't crap its pants at the sight of InDesign (so you can forget
about Scripting Bridge and _javascript_ for Automation in other
words[2]).
If InDesign can't handle your 'set properties of <whatever> to
<record>' command correctly, then as you say you'll need to
set each property individually. While you can't iterate over an
AppleScript record, you _can_ concatenate it with a second record,
allowing you to add any 'missing' properties:
set change grep preferences to nothing
set changeProps to changeProps & (properties of change grep
preferences)
While it's just marginally possible 'set properties of...' will
start to behave correctly when supplied with a 'complete' record,
I'm assuming that's not the case[3], so then it's just a case of
including individual 'set' commands for whichever properties ID
fails to set en-masse:
set properties of change grep preferences to changeProps -- sets
most, but not all, properties
-- individual workarounds:
set numbering format of change grep preferences to numbering
format of changeProps
...
Tedious if there's a lot of properties that need to be set
individually like this, but it should get the job done.
HTH
has
[1] AppleScript-ObjC bridges AS records to NSDictionary, but it has
issues bridging record keys and object specifiers correctly, so I
suspect that way madness lies.
[2] e.g. In theory [3], here's how you'd do the iteration-based
approach in Python using appscript (which eats even the most cranky
obnoxious old Carbon pro-apps for breakfast):
#!/usr/bin/python
from appscript import *
inDesign = app("Adobe InDesign CS6")
changeProps = {
k.bullets_and_numbering_list_type: k.numbered_list,
k.numbering_start_at: 3,
k.numbering_format: "a, b, c, d..."}
inDesign.change_grep_preferences.set(k.nothing)
for key, value in changeProps.items():
setattr(
inDesign.change_grep_preferences, key.name, value)
However, since I no longer have any interest in supporting appscript
except for my own use, it's not an approach I can recommend for
others, and while I have recently been developing a new Swift-AE
bridge, I won't be wasting my time supporting that either unless
Apple includes in OS X (once bitten, etc).
[3] In practice, ID does appear to be extremely sensitive to the
precise order in which certain properties are set, e.g. if the
script tries to set the numbering format before the numbering list
type, it throws a 'Cannot set bullets or numbering properties in
Find/Change if the list type is none or not set' error. My guess is
that when you do 'set properties of change grep preferences to
changeProps', ID is stupidly applying your new settings in the order
in which they appear in your AE record (which is totally arbitrary)
instead of the order ID _needs_ them to be set, with any failed
assignments being silently ignored instead of reported as errors.
Such implicit, invisible order-sensitivity should not exist -
clearly the interface design wasn't thought through with adequate
rigor, or they'd have grouped such dependent properties into
classes/records of their own - but the entire ID dictionary is a
giant sprawling mess like this, so I doubt much can be done about it
now.
With this in mind, a quick-n-dirty workaround could be to put your
'set properties...to changeProps' command in a 'repeat N times'
loop, so that it gets sent enough times for all the given values to
eventually stick. The exact value of N needed to guarantee all
properties are eventually set correctly will depend on just how deep
these "can't set property X until after property Y is set, and can't
set property Y until property Z is set" dependencies go. Worst case
would be N = number of properties in the 'change grep preferences'
class, but I'd expect it's _much_ lower than that. Confirming
whether or not this actually works in practice, and determining the
exact minimum number of 'set properties...' required is left as an
exercise (personally, I'd probably just have it repeat 3 or 4 times
on the assumption that this should provide a more than adequate
margin of error - assuming the ID devs aren't _completely_ nuts, of
course).
|