use framework "Foundation"
script BaseObject -- the parent script object, required for AppleScriptObjC inheritance
end script
on smartSetWith:aList -- call this to make a new smartList
script SmartSet
property parent : BaseObject -- for inheritance
property setStore : missing value -- where the array is stored
on countOfSet() -- get count of items
return setStore's |count|() as integer
end countOfSet
-- get objects and indexes
on objectAtIndex:anInteger
set anInteger to my correctIndex:anInteger
set theResult to setStore's objectAtIndex:anInteger
return my coerceToASClass:theResult
end objectAtIndex:
on objectsFrom:anInteger toIndex:endInteger -- get range of objects
set anInteger to my correctIndex:anInteger
set endInteger to my correctIndex:endInteger
set theIndexSet to current application's NSMutableIndexSet's alloc()'s init()
theIndexSet's addIndexesInRange:(current application's NSMakeRange(anInteger, endInteger - anInteger + 1))
return (setStore's objectsAtIndexes:theIndexSet) as list
end objectsFrom:toIndex:
on indexOfObject:anObject
try -- will error if not found because NSNotFound is too big to coerce to an integer
set theResult to ((setStore's indexOfObject:anObject) as integer) + 1
on error
return 0
end try
return theResult
end indexOfObject:
-- add objects
on addObject:anObject -- adds to end
setStore's addObject:anObject
end addObject:
on addObjectsFromArray:anObject -- adds to end
setStore's addObjectsFromArray:anObject
end addObjectsFromArray:
on insertObject:anObject atIndex:anInteger -- insert object
set anInteger to my correctIndex:anInteger
setStore's insertObject:anObject atIndex:anInteger
end insertObject:atIndex:
-- remove objects
on removeObject:anObject
setStore's removeObject:anObject
end removeObject:
on removeObjects:newList
setStore's removeObjectsInArray:newList
end removeObjects:
on removeObjectAtIndex:anInteger
set anInteger to my correctIndex:anInteger
setStore's removeObjectAtIndex:anInteger
end removeObjectAtIndex:
on removeObjectsFrom:anInteger toIndex:endInteger
set anInteger to my correctIndex:anInteger
set endInteger to my correctIndex:endInteger
setStore's removeObjectsInRange:(current application's NSMakeRange(anInteger, endInteger - anInteger + 1))
end removeObjectsFrom:toIndex:
-- replace objects
on replaceObjectAtIndex:anInteger withObject:anObject
set anInteger to my correctIndex:anInteger
setStore's replaceObjectAtIndex:anInteger withObject:anObject
end replaceObjectAtIndex:withObject:
on setObject:anObject atIndex:anInteger -- replace or add, depending on index
set anInteger to my correctIndex:anInteger
setStore's setObject:anObject atIndex:anInteger
end setObject:atIndex:
-- swap objects
on swapObjectAtIndex:anInteger withObjectAtIndex:endInteger
set anInteger to my correctIndex:anInteger
set endInteger to my correctIndex:endInteger
setStore's exchangeObjectAtIndex:anInteger withObjectAtIndex:endInteger
end swapObjectAtIndex:withObjectAtIndex:
-- sort objects
on sortIgnoringCase()
my sortUsingSelector:"localizedCaseInsensitiveCompare:"
end sortIgnoringCase
on sortConsideringCase()
my sortUsingSelector:"localizedCompare:"
end sortConsideringCase
on sortLikeFinder()
my sortUsingSelector:"localizedStandardCompare:"
end sortLikeFinder
on standardSort() -- use for other than strings
my sortUsingSelector:"compare:"
end standardSort
-- query the set
on containsObject:anObject -- whether set contains an object
return ((setStore's containsObject:anObject) as integer = 1)
end containsObject:
on containsObjects:listOrArray -- whether set contains all objects in the list
set newSet to current application's NSSet's setWithArray:listOrArray
return ((newSet's isSubsetOfSet:(setStore's |set|())) as integer = 1)
end containsObjects:
on intersects:listOrArray -- whether list items and set intersect
set theSet to current application's NSSet's setWithArray:listOrArray
return ((setStore's intersectsSet:theSet) as integer = 1)
end intersects:
on intersectsInOrder:listOrArray -- whether list in order and set intersect
set theSet to current application's NSOrderedSet's orderedSetWithArray:listOrArray
return ((setStore's intersectsOrderedSet:theSet) as integer = 1)
end intersectsInOrder:
on isSubsetOf:listOrArray -- whether set is a subset of the list
set theSet to current application's NSSet's setWithArray:listOrArray
return ((setStore's isSubsetOfSet:theSet) as integer = 1)
end isSubsetOf:
on isSubsetInOrderOf:listOrArray -- whether set is a subset of the list in matching order
set theSet to current application's NSOrderedSet's orderedSetWithArray:listOrArray
return ((setStore's isSubsetOfOrderedSet:theSet) as integer = 1)
end isSubsetInOrderOf:
on minusSet:listOrArray -- subtract objects in list from set
set theSet to current application's NSSet's setWithArray:listOrArray
setStore's minusSet:theSet
end minusSet:
on unionSet:listOrArray -- add objects in list to set if they are not in it already
set theSet to current application's NSOrderedSet's orderedSetWithArray:listOrArray
setStore's unionOrderedSet:theSet
end unionSet:
on intersectSet:listOrArray -- remove objects not in list from set
set theSet to current application's NSSet's setWithArray:listOrArray
setStore's intersectSet:theSet
end intersectSet:
-- return as list/array
on asArray() -- return as array for further use
return setStore's array()
end asArray
on asList() -- return as list
return setStore's array() as list
end asList
-- handlers for script's use
on correctIndex:anInteger -- for script's use; convert AS index to Cocoa index
if anInteger < 0 then
return anInteger + (my countOfSet())
else
return anInteger - 1
end if
end correctIndex:
on coerceToASClass:anObject -- for script's use; coerce to AS class for return
if ((anObject's isKindOfClass:(current application's NSArray)) as integer = 1) then
return anObject as list
else -- coerce to list and return item 1; workaround to coerce item of unknown class
set anObject to anObject as list
return item 1 of anObject
end if
end coerceToASClass:
on sortUsingSelector:theSel -- for script's use
set theDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"self" ascending:true selector:theSel
setStore's sortUsingDescriptors:{theDesc}
end sortUsingSelector:
end script
set setStore of SmartSet to current application's NSMutableOrderedSet's orderedSetWithArray:aList -- set initial value
return SmartSet
end smartSetWith: