This is probably an appleScript compiler issue, but I recall something similar with lists that seems to have been corrected, but I’ll just throw this out there.
I’d like to add line-breaks (option-return) to records so they’re easier to read in compiled scripts. Below is a visual example of what I mean.
Is there anything that can be done to correct the munging of line breaks in records when compiled?
--This is what it looks like
set progressRecord to {ProgressTotal:10, progressCompleted:0, progressDesc:"Filtering unwanted email from Calendar Mail", progressAddDesc:"Reading saved unwanted email addresses"}
--This is how I'd like it to look:
set progressRecord to {ProgressTotal:10, ¬
progressCompleted:0, ¬
progressDesc:"Filtering unwanted email from Calendar Mail", ¬
progressAddDesc:"Reading saved unwanted email addresses"}
--But this is how that compiles
set progressRecord to ¬
¬
{ProgressTotal:10, progressCompleted:0, progressDesc:"Filtering unwanted email from Calendar Mail", progressAddDesc:"Reading saved unwanted email addresses"} ¬
--This is the best I can do (but, no.)
set progressRecord to {ProgressTotal:¬
10, progressCompleted:¬
0, progressDesc:¬
"Filtering unwanted email from Calendar Mail", progressAddDesc:¬
"Reading saved unwanted email addresses"}
I feel your pain . This, as you guessed, an AppleScript issue. The problem lies with the AppleScript compiler which reformats scripts according to its own indentation rules when they are displayed (i.e. decompiled). This happens (a) when opening a script, and (b) after compiling a script.
One solution I’ve found is to use multiple assignments:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set r to {} -- using `r` to make the text shorter.
set r to r & {ProgressTotal:10}
set r to r & {progressCompleted:0}
set r to r & {progressDesc:"Filtering unwanted email from Calendar Mail"}
set r to r & {progressAddDesc:"Reading saved unwanted email addresses"}
set progressRecord to r
Its not optimal and fractionally slower, but it does let you break up a large record declaration into pieces.
Or if you are deriving any of the values at run-time, and want to zip them up with the keys and fold the whole lot into a record ‘just in time’, then perhaps something like:
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
on run
set ks to {"ProgressTotal", "progressCompleted", "progressDesc", "progressAddDesc"}
set vs to {10, 0, "Filtering unwanted email from Calendar Mail", "Reading saved unwanted email addresses"}
script field
on |λ|(acc, kv)
set {k, v} to kv
insertMap(acc, k, v)
end |λ|
end script
foldl(field, {} as record, zip(ks, vs))
end run
-- GENERIC ------------------------------------------------------
-- https://github.com/RobTrew/prelude-applescript
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- insertMap :: Dict -> String -> a -> Dict
on insertMap(rec, k, v)
tell (current application's NSMutableDictionary's ¬
dictionaryWithDictionary:rec)
its setValue:v forKey:(k as string)
return it as record
end tell
end insertMap
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- zip :: [a] -> [b] -> [(a, b)]
on zip(xs, ys)
set lng to min(length of xs, length of ys)
set lst to {}
repeat with i from 1 to lng
set end of lst to {item i of xs, item i of ys}
end repeat
return lst
end zip
Or take advantage or the more foldable nature of lists with:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on run
set kvs to {{ProgressTotal:10}, {progressCompleted:0}, ¬
{progressDesc:"Filtering unwanted email from Calendar Mail"}, ¬
{progressAddDesc:"Reading saved unwanted email addresses"}}
script
on |λ|(acc, rec)
acc & rec
end |λ|
end script
foldl(result, {} as record, kvs)
end run
-- GENERIC ------------------------------------------------------
-- https://github.com/RobTrew/prelude-applescript
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
How about using the continuation character (¬) to define line breaks? There’s no slowdown.
Stan C.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set r to {¬
{ProgressTotal:10}, ¬
{progressCompleted:0}, ¬
{progressDesc:"Filtering unwanted email from Calendar Mail"}, ¬
{progressAddDesc:"Reading saved unwanted email addresses"} ¬
}
set progressRecord to r
Whereas with lists, you can insert the continuation character after a comma, with records, you can insert them before the comma. Note that a continuation character can’t follow a string, but this can be circumvented by enclosing a string in parentheses.
set progressRecord to {ProgressTotal:10 ¬
, progressCompleted:0 ¬
, progressDesc:("Filtering unwanted email from Calendar Mail") ¬
, progressAddDesc:("Reading saved unwanted email addresses")}
Ah, of course! I was in a hurry and followed your code example a bit too closely. I should’ve omitted all the curly braces appearing inside the outermost pair.
As CJK points out, there are rules for using the continuation character, so those would need to have been moved to before the commas, in this case.