This stand alone library is dependent of the Script Cache Storage Library
(*
Version two: multiple selections allowed, one command and one item, to speed up things.
Copyright 2015 © McUsr
*)
use AppleScript version "2.3"
use scripting additions
use cacheStorage : script "Script Cache Storage"
property insertCommandChoice : "--- New/Insert"
property copyCommandChoice : "--- Copy/Duplicate"
property editCommandChoice : "--- Edit/Replace"
property deleteCommandChoice : "--- Delete/Remove"
property menuChoices : {insertCommandChoice, copyCommandChoice, editCommandChoice, deleteCommandChoice}
-- DON'T CHANGE THE PROPERTIES BELOW, THEY CONTROL THE INTERAL LOGIC!
-- property driverList : {"Ananas", "Grapes", "Strawberries", "BlueBerries"}
on __indexOfItem(theItem, theList) -- credit to Emmanuel Levy but I modified it with the considering case statements
set text item delimiters to return
set theList to return & theList & return
set text item delimiters to {""}
try
-1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
on error
0
end try
end __indexOfItem
(*
set res to listHandler("TestCache.scpt", "driver", "Fruit", "Snack", true)
log res
*)
on listHandler(theCacheName, fsysName, itemDescription, taskDescription, multiple)
-- Initialization: We set up the menu name, and read in data from the stored scriptcache, if any!
set scriptTitle to fsysName & ": " & taskDescription
set theCache to loadScript of cacheStorage from theCacheName
set PORTIFOLIO to theCache's itemslist
-- * set PORTIFOLIO to my driverList
-- Initialization
-- need to make the cachename first!
-- Do not forget that you must grab search expression from find window too.
set currentState to "anything"
set listHasChanged to false -- Determines whether we should save the list or not
if multiple then
set startOfListDialogPrompt to "Choose " & itemDescription & "(s) to maintain, or use for a "
else
set startOfListDialogPrompt to "Choose a " & itemDescription & " to maintain, or use for a "
end if
repeat
-- preparation of the Menu
if currentState is "anything" then
set menuList to menuChoices & PORTIFOLIO
set menuLevel to ": Main "
set listDialogPrompt to startOfListDialogPrompt & taskDescription & "."
else if currentState is in {"pickItemToEdit", "pickItemToDelete", "pickItemToDuplicate"} then -- TODO
if PORTIFOLIO is not {} then
set menuList to PORTIFOLIO -- List items
if currentState is "pickItemToEdit" then
set menuLevel to ": Edit "
set listDialogPrompt to "Choose a " & itemDescription & " for a " & taskDescription & " that you want to Edit."
else if currentState is "pickItemToDelete" then
set menuLevel to ": Delete "
set listDialogPrompt to "Choose a " & itemDescription & " for a " & taskDescription & " that you want to Delete."
else if currentState is "pickItemToDuplicate" then
set menuLevel to ": Duplicate "
set listDialogPrompt to "Choose a " & itemDescription & " for a " & taskDescription & " that you want to Duplicate."
end if
else
tell application (path to frontmost application as text)
display dialog "There are no Search Criteria that can be Edited/Deleted/Duplicated, please Insert one." with title scriptTitle buttons {"Stop"} default button 1 with icon stop
end tell
set menuList to menuChoices & PORTIFOLIO -- unnecessary
set currentState to "anything"
end if
end if
-- Display of the "Menu"
if currentState is not "shallInsert" then
tell application (path to frontmost application as text)
set chosenItems to choose from list menuList default items (item 1 of menuList) with prompt listDialogPrompt with title (scriptTitle & menuLevel) with multiple selections allowed
end tell
if chosenItems is not false then
if currentState is "pickItemToEdit" then
set currentState to "shallEdit"
else if currentState is "pickItemToDelete" then
set currentState to "shallDelete"
else if currentState is "pickItemToDuplicate" then
set currentState to "shallDuplicate"
end if
end if
end if
-- processing of menu choices, including shallInsert.
if currentState is "anything" then -- Main Level
if chosenItems is false then
exit repeat
else
set itemCount to count chosenItems
end if
if itemCount = 0 then
tell application (path to frontmost application as text)
display alert fsysName & ":
You have chosen no elements. I quit"
end tell
set chosenItems to false
exit repeat
else if itemCount = 1 then
-- We'll actually do something
set singleChoice to item 1 of chosenItems
if singleChoice is in menuChoices then
-- log "entered single command choice"
-- log "Administrative task"
if singleChoice is my editCommandChoice then
set currentState to "pickItemToEdit"
else if singleChoice is my insertCommandChoice then
set currentState to "shallInsert"
else if singleChoice is my deleteCommandChoice then
set currentState to "pickItemToDelete"
else if singleChoice is my copyCommandChoice then
set currentState to "pickItemToDuplicate"
end if
else
if currentState = "anything" then
set currentState to "elementSelected"
-- We are returning an element to the handler/script that invoked us
exit repeat
else if currentState = "pickItemToEdit" then
set currentState to "shallEdit"
else if currentState = "pickItemToDelete" then
set currentState to "shallDelete"
else if currentState = "pickItemToDuplicate" then
set currentState to "shallDuplicate"
end if
end if
else if itemCount = 2 then
(*
Business rules:
insert can not be one of the actions.
Not both items can be actions.
*)
if item 1 of chosenItems is my insertCommandChoice then
tell application (path to frontmost application as text)
display alert fsysName & ":
You can't both choose an item, and choose to insert."
end tell
set currentState to "anything"
else if (item 1 of chosenItems is in menuChoices) and (item 2 of chosenItems is not in menuChoices) then
set commandChoice to item 1 of chosenItems
set chosenItems to rest of chosenItems
if commandChoice is my editCommandChoice then
set currentState to "shallEdit"
else if commandChoice is my deleteCommandChoice then
set currentState to "shallDelete"
else if commandChoice is my copyCommandChoice then
set currentState to "shallDuplicate"
end if
else if item 1 of chosenItems is not in menuChoices then
-- 2 items selected
if multiple then
set currentState to "elementSelected"
-- We are returning elements to the handler/script that invoked us
exit repeat
else
tell application (path to frontmost application as text)
display alert fsysName & ":
Selecting multiple items is not allowed "
end tell
set currentState to "anything"
end if
else -- 2 commands!
tell application (path to frontmost application as text)
display alert fsysName & ":
You can't choose two commands at once."
end tell
set currentState to "anything"
end if
else -- temCount > 2
(*
Business rules:
No item can be an action
*)
if item 1 of chosenItems is not in menuChoices then
if multiple then
set currentState to "elementSelected"
-- We are returning elements to the handler/script that invoked us
exit repeat
else
tell application (path to frontmost application as text)
display alert fsysName & ":
Selecting multiple items is not allowed "
end tell
set currentState to "anything"
end if
else
tell application (path to frontmost application as text)
display alert fsysName & ":
You can't choose to do a command on more than one item at a time."
end tell
set currentState to "anything"
end if
end if
end if
-- out of the loop
if currentState is in {"shallEdit", "shallDelete", "shallDuplicate"} then
if PORTIFOLIO is not {} and chosenItems is not false then -- Sub Level, (Picking Item.)
set pickedItemNo to __indexOfItem(item 1 of chosenItems, PORTIFOLIO)
if currentState is "shallEdit" then
try
tell application (path to frontmost application as text)
set newText to text returned of (display dialog "Edit the " & itemDescription & ":" default answer item pickedItemNo of PORTIFOLIO with title scriptTitle & " : Edit " with icon caution)
end tell
on error
set currentState to "anything"
end try
if currentState is "shallEdit" then
set item pickedItemNo of PORTIFOLIO to newText
set currentState to "anything"
set listHasChanged to true
end if
else if currentState is "shallDelete" then
try
tell application (path to frontmost application as text)
display dialog "Do you really want to delete the " & itemDescription & ":
" & item pickedItemNo of PORTIFOLIO & "?" with title scriptTitle & " : Delete" with icon caution
end tell
on error
set currentState to "anything"
end try
if currentState is "shallDelete" then
if pickedItemNo = 1 then
set PORTIFOLIO to rest of PORTIFOLIO
else if pickedItemNo = (count PORTIFOLIO) then
set PORTIFOLIO to items 1 thru -2 of PORTIFOLIO
else
set PORTIFOLIO to (items 1 thru (pickedItemNo - 1) of PORTIFOLIO) & (items (pickedItemNo + 1) thru -1 of PORTIFOLIO)
end if
set listHasChanged to true
set currentState to "anything"
end if
else if currentState is "shallDuplicate" then
set theDuplicate to item pickedItemNo of PORTIFOLIO
if pickedItemNo = 1 then
set PORTIFOLIO to {item 1 of PORTIFOLIO} & {theDuplicate} & rest of PORTIFOLIO
else if pickedItemNo = (count PORTIFOLIO) then
set PORTIFOLIO to PORTIFOLIO & theDuplicate
else
set PORTIFOLIO to items 1 thru pickedItemNo of PORTIFOLIO & theDuplicate & items (pickedItemNo + 1) thru -1 of PORTIFOLIO
end if
set listHasChanged to true
set currentState to "anything"
end if
else
set currentState to "anything"
end if
else if currentState is "shallInsert" then
-- No preprocessing/Listchanging here so we don't have think of empty PORTIFOLIO or if
-- chosenItems is false!
try
tell application (path to frontmost application as text)
set newText to text returned of (display dialog "Enter the " & itemDescription & " you wish to insert :" default answer "" with title scriptTitle & " : Insert " with icon caution)
end tell
on error
set currentState to "anything"
end try
if currentState is "shallInsert" then
if newText is not "" then
set end of PORTIFOLIO to newText
set listHasChanged to true
end if
set currentState to "anything"
end if
end if
-- PostProcessing, we have to save the list as it is changed.
if listHasChanged then
set theCache's itemslist to PORTIFOLIO
set success to storeScript of cacheStorage from theCacheName against theCache
if not success then
tell application (path to frontmost application as text)
display alert fsysName & ":
I couldn't store the current script object, aborts"
end tell
return null
end if
set listHasChanged to false
end if
end repeat
return chosenItems
end listHandler
A little driver script:
use AppleScript version "2.3"
use scripting additions
use lm : script "ListMaintainer"
set theCacheName to "Metatags.scpt"
log theCacheName
set returnedKeywords to lm's listHandler(theCacheName, "Metatags", "Keyword", "Keyword Meta Tag", true)
if returnedKeywords is null then
tell application (path to frontmost application as text)
display alert "Problems during saving cache to disk. I quit."
end tell
return
else if returnedKeywords is false then
tell application (path to frontmost application as text)
display alert "No tags selected, Be sure to update the Meta tags later."
end tell
set returnedKeywords to ""
else
-- returns a list of comma separated values
-- this handler is really intended for single values
set astid to my text item delimiters
set my text item delimiters to ", "
set returnedKeywords to items of returnedKeywords as text
set my text item delimiters to astid
log "" & class of returnedKeywords & " : " & returnedKeywords
end if
log returnedKeywords
I hope you like it, and that you report any bugs, that I may not have come across, it has been working flawlessly for me however for some time.
Edit:
- I made an error message for the driver script less confusing.
- Some formatting errors in the doc are corrected.
- Removed an outdated paragraph in the doc.