Choose from list cancel button

Hello everyone,

This is my first post as well as my first AppleScript. Please forgive my lack of knowledge! I am trying to write a script that uses a CSV file to provide a list of network devices a user would use telnet or ssh to access and administer. The CSV file has the following contents:

Core1,ssh,1.1.1.1
Core2,telnet,2.2.2.2
Edge1,telnet,3.3.3.3
Edge2,ssh,4.4.4.4

The script seems to work “OK” for a first attempt, but when I run it and hit cancel on the first “choose from list” windows I don’t know how to handle that exception. I have searched this forum and found some threads that will fix my problem but don’t have the knowledge implement them correctly.

Any help that the gurus of this forum can provide would be greatly appreciated. I am sure the script as a whole is pretty poorly written and I would be most grateful for all your inputs and knowledge sharing. If anyone has any books or references that are extremely newbie friendly please pass them on. I have some and they have been helpful but I fear they are not what a newbie like me should start with.

Thanks in advance for any and all help!!!

v/r
Eric

Below is my script:

global gUnixPath, gDeviceName, gClientType, gIPAddress, gAnswer, gbooleanConnect, gCancelByUser
set gbooleanConnect to false --Determines if User confirmed selection of device
set gCancelByUser to false --Determines if User cancelled the Select Device List Box

–BEGIN: FOR DEVELOPMENT ONLY------------------------------------------------------
set gUnixPath to “/Users/emidd/Documents/AppleScriptTextFile.csv”
–END: FOR DEVELOPMENT ONLY------------------------------------------------------

–CHOOSE ONE OR THE OTHER:
–set gUnixPath to (choose file with prompt “Select a Device file to read:” of type {“TEXT”}) - browse for device file
–set gUnixPath to (choose file with prompt “Select a Device file to read:”) - browse for device file

set AppleScript’s text item delimiters to {“”} – set AppleScript’s text delimiter to the DEFAULT

–BEGIN: Select/Confirmation of Selected Device–
repeat while not gbooleanConnect

selectdevice(gUnixPath) -- Select the device you want to connect too

if gCancelByUser then
	exit repeat
end if

confirmSelection(gDeviceName, gClientType, gIPAddress) -- Confirm the device to connect too

end repeat
–END: Select/Confirmation of Selected Device–

tell application “System Events” to set terminalOn to (exists process “Terminal”)

if gAnswer = “Connect” then

if (terminalOn) then -- If terminal process exists, open a new window
	
	tell application "Terminal"
		set number of rows of window 1 to 50
		set number of columns of window 1 to 100
		set background color of window 1 to "black"
		set normal text color of window 1 to "green"
		set custom title of window 1 to gDeviceName
		
		if gClientType = "telnet" then
			do script gClientType & " " & gIPAddress
		else if gClientType = "ssh" then
			do script gClientType & " -l eric " & gIPAddress
		else
			display dialog "Not able to determine client type (ssh/telnet)" with title "!!!ERROR!!!" with icon 2
		end if
		
	end tell
	
else
	
	tell application "Terminal" -- If terminal process DOES NOT exist, open in FRONT window
		set number of rows of window 1 to 50
		set number of columns of window 1 to 100
		set background color of window 1 to "black"
		set normal text color of window 1 to "green"
		set custom title of window 1 to gDeviceName
		
		if gClientType = "telnet" then
			do script gClientType & " " & gIPAddress in front window
		else if gClientType = "ssh" then
			do script gClientType & " -l eric " & gIPAddress in front window
		else
			display dialog "Not able to determine client type (ssh/telnet)" with title "!!!ERROR!!!" with icon 2
		end if
		
		activate
		
	end tell
	
end if

else if gAnswer = “Reselect” then

selectdevice(gUnixPath)

end if

–#################
–Functions below this point–
–#################

on confirmSelection(device, client, ipAddr)

set question to display dialog "Do you want to use " & gClientType & " to connect to device " & gDeviceName & " at IP Address " & gIPAddress & "." with icon 2 buttons {"Reselect", "Connect"} default button 2

set gAnswer to button returned of question

if gAnswer = "Connect" then
	set gbooleanConnect to true
end if

end confirmSelection

on selectdevice(filepath)

set devices to (do shell script "/bin/cat " & POSIX path of filepath) -- get list of devices
set theDeviceList to (paragraphs of devices) as list -- create a list of devices by line (paragraph)
set theDevice to (choose from list theDeviceList with title "Device Selection" OK button name "OK" cancel button name "Cancel" with prompt "Choose a device:")

if the result is not false then
	
	set theText to theDevice as text -- create a text variable of "," delimited values
	set AppleScript's text item delimiters to {","} -- set AppleScript's text delimiter to the ","
	set {gDeviceName, gClientType, gIPAddress} to text items of theText -- set the attributes of the selected device
	
	--display dialog gDeviceName with title "Device Name is:" with icon 2
	--display dialog gIPAddress with title "IP Address is:" with icon 2
	--display dialog gClientType with title "Client Type is:" with icon 2
	
	return gDeviceName
	return gClientType
	return gIPAddress
	return
	
else
	
	set gCancelByUser to true
	
end if

end selectdevice

Hi,

the buttons OK and Cancel are the default setting for choose from list
there is no need to specify them explicitly.

choose from list returns boolean false in case of the user presses “Cancel”
otherwise always a list of the selected item(s), even there is only one selected.
To process a single item you have to flatten the list

for example


set theDeviceList to {"A", "B", "C"}
set theDevice to (choose from list theDeviceList with title "Device Selection" with prompt "Choose a device:")

if theDevice is false then
	display dialog "User pressed Cancel"
else
	display dialog "User selected " & item 1 of theDevice
end if

Stefan,

Thanks for your reply! I have a follow-up question as well. What do I do after this step (display dialog “User pressed Cancel”) to exit the script without closing the AppleScript editor and the script itself?

Also, is it possible to run an AppleScript without opening the editor, can the script be made to run in some sort of standalone mode?

Thanks,
Eric

Hi,
return will exit the current handler (here on run).

set aList to every character of "ABCDEFGHIJKLMNOPQURSTUVWXYZ"
set chosenLetter to choose from list aList

if chosenLetter is false then return -- stops the script

display dialog "You have chosen the letter \"" & (chosenLetter as string) & "\"."

Hope it helps,
ief2

Save the script as application bundle or run the plain compiled script from the script menu.
You can enable the script menu in the Script Editor (10.6) or /Applications/AppleScript/AppleScript Utility.app/ (pre 10.6)

ief2,

I am not sure I understand how that will stop my script. When I put the return in the script it just continues on from where the “selectdevice” function was called.

If I had to guess I would say that my script is poorly written in a way that doesn’t take advantage of your wisdon. I don’t know what you mean by (on run).

Thanks!
Eric

the choose from list part is within a handler, in this case return exits the handler, not the script.
If there is no try block round the choose from list part, use error number -128 (user cancelled) instead

If you use “return” in a handler it just exits the handler (with or without a result) and it doesn’t stop the whole script.

You could rewrite your handler so it returns “false”. When the on run-handler (more of that below) then receives the “false” it should return and exit the on run handler.

if selectdevice(fileName) is false then
	-- exit on run handler
	return
end if

-- will be executed only if selectdevice() does not return false
display dialog "Not Canceled by user"

on selectdevice(filepath)
	
	set devices to (do shell script "/bin/cat " & POSIX path of filepath) -- get list of devices
	set theDeviceList to (paragraphs of devices) as list -- create a list of devices by line (paragraph)
	set theDevice to (choose from list theDeviceList with title "Device Selection" OK button name "OK" cancel button name "Cancel" with prompt "Choose a device:")
	
	if the result is not false then
		
		set theText to theDevice as text -- create a text variable of "," delimited values
		set AppleScript's text item delimiters to {","} -- set AppleScript's text delimiter to the ","
		set {gDeviceName, gClientType, gIPAddress} to text items of theText -- set the attributes of the selected device
		
		--display dialog gDeviceName with title "Device Name is:" with icon 2
		--display dialog gIPAddress with title "IP Address is:" with icon 2
		--display dialog gClientType with title "Client Type is:" with icon 2
		
		return gDeviceName
		return gClientType
		return gIPAddress
		return
		
	else
		
		set gCancelByUser to true
		return false
		
	end if
end selectdevice

Now some more about on run. The on run is actually the handler that gets called when the user runs the script. You don’t have to use this handler because AppleScript automatically sets the code outside all other handlers to be run when the user wants to execute the script. So the two below scripts do the same.

display dialog "Hello World"
on run
	display dialog "Hello World"
end run

When you combine these two scripts into one, AppleScript will throw an error because there are actually two on run handlers:

on run
	display dialog "Hello World"
end run

display dialog "Hello World"

Beside the on run-handler there are a couple of other pre-defined handlers by AppleScript like on quit, on idle and on open aVar (used for droplets).

-- save this as an application stay-open bundle
global idleCount

-- when the application gets double clicked or un via scripteditor
on run
	display dialog "The application was double clicked"
	set idleCount to 1
end run

-- when you drop files on the application
on open theObjects
	display dialog "There were/is " & (count theObjects) & " file(s) dropped"
	set idleCount to 1
end open

-- when the application stays open and is idle
on idle
	display dialog "The application has executed the idle handler " & idleCount & " times"
	return 1 -- waits 1 second 
end idle


-- when the application will quit
on quit
	display dialog "The application will quit"
end quit


Save the above script as a stay-open application bundle.

When you double click the save application the on run-handler will be called. Afterwards the on idle-handler. If you quit the application (for example via the dock) the on quit-handler will be called.

If you drop finder items on the saved application the on open-handler will be called. The variable theObjects then contains the aliases to the dropped items.

Hope you can understand it a little bit,
ief2

ief2,

Wow! What can I say, that was an excellent explanation. I really appreciate you taking the time to put that together. It cleared up a few different items for me.

Now that the script is working in its most basic form I have a few enhancements to make it more friendly.

Next on the list is how to pull only the first item of each line from the CSV file and put it into the “choose from list” box instead of all the attributes on each line while still keeping all the attributes from the selected item and passing them on in the script. I would like to be able to put the script on the menu bar independently of the “Scripts” menu, like an application that I can click and select a host in that fashion as well.

If you have any ideas feel free to pass them on. I have many more hours just for this one script I am afraid. However, it has been a great experience thus far.

Thanks again!!!

Eric

Stefan,

Thanks for the pointer regarding the Scripts Menu and how to save the script so it can be run independently. I have googled until my eyes were cross on how to run it separate from the editor. I guess I was just asking Google the wrong question. :wink:

Thanks!
Eric

You’re welcome :slight_smile:

By putting numbers in front of them, you can easily get the full paragraph by index:

set myData to "hallo,qsd,f
hallo3,sqd,f
f,e,z"

set chosenParagraph to chooseFromFirstItem(d)
if chosenParagraph is missing value then return

on chooseFromFirstItem(csvData)
	set allParagraphs to every paragraph of csvData
	set chooseList to {}
	repeat with i from 1 to (count allParagraphs)
		set AppleScript's text item delimiters to ","
		set firstItem to text item 1 of (item i of allParagraphs)
		set AppleScript's text item delimiters to ""
		set end of chooseList to (i & ". " & firstItem) as string
	end repeat
	
	set chosenItem to choose from list chooseList
	if chosenItem is false then return missing value
	
	set chosenItem to chosenItem as string
	set AppleScript's text item delimiters to "."
	set nr to text item 1 of chosenItem
	set AppleScript's text item delimiters to ""
	set nr to nr as integer
	set chosenParagraph to paragraph nr of csvData
	
	return chosenParagraph
end chooseFromFirstItem

I personally love Butler! (http://www.petermaurer.de/butler/)

Hope it helps,
ief2

ief2,

Thanks again. I got the list box just the way I want it with your help. However… :wink: another question comes to mind. Is it possible to keep the script open after I connect to my selection so that I may continue to connect to other devices? Also, instead of opening a new terminal window for each connection can I just have terminal open a new tab?

Neither of these may be possible but I thought I would ask?

Thanks in advance,
Eric