I wrote this to check a user’s input (for the number of copies they want on a print script) to make sure they didn’t enter a letter, or a zero, or a negative number.
It seem like the kind of thing that could have been done with less code. Just wondering if anyone has a more efficient way of doing what I did here:
repeat
set StartOver to false
set InputNum to text returned of (display dialog "How many copies?" default answer "")
try
set NumCopies to InputNum as integer
on error
display dialog "Expected a number?!? Try again" with icon 0 buttons "Error!" giving up after 2
set StartOver to true
end try
if StartOver is false then
if NumCopies is greater than 0 then
exit repeat
else
display dialog "Positive whole numbers only!" with icon 0 buttons "Error!" giving up after 2
end if
end if
end repeat
Browser: Safari 419.3
Operating System: Mac OS X (10.4)
set defaultAnswer to ""
repeat
try
display dialog "How many copies?" default answer defaultAnswer
set numCopies to (text returned of result) as integer
if numCopies is less than 1 then error
exit repeat
on error number errNum
if errNum is -128 then error number -128 -- User canceled dialog
set defaultAnswer to "Enter a positive whole number!"
end try
end repeat
repeat
set InputNum to text returned of (display dialog "How many copies?" default answer "1")
try
set NumCopies to InputNum as integer
if NumCopies < 0 then set NumCopies to -NumCopies
if NumCopies = 0 then error
exit repeat
on error
display dialog "Expected a number > 0 ?!? Try again" with icon 0 buttons "Error!" giving up after 2
end try
end repeat
btw: some suggestions for your print pdf script
-- This droplet processes both files or folders of files dropped onto the applet
property YourPrinterPanther : "NameOfYourPrinter on Address" --Name as it appears in the Printer List in Panther
property YourPrinterTiger : "NameOfYourPrinter" --Name as it appears in the Printer List in Tiger
property YourPrinter : ""
property NumCopies : 1
on open these_items
setup_printer()
tell application "Finder"
activate
set InputNum to the button returned of (display dialog "How many copies?" buttons {"1", "2", "3"} default button "1")
set NumCopies to InputNum as real
end tell
process_folder(these_items)
tell application "Finder"
activate
display dialog ("Finished!") buttons " " giving up after 1
end tell
end open
-- this sub-routine processes folders
on process_folder(these_items)
repeat with this_item in these_items
if (folder of (info for this_item as alias)) then
tell application "Finder" to set sub_items to (get files of this_item)
process_folder(sub_items)
else
my process_item(this_item)
end if
end repeat
end process_folder
-- this sub-routine prints the files
on process_item(this_item)
tell application "System Events"
tell (info for this_item as alias) to if its alias or (its kind does not contain "PDF") then return -- skip aliases and no pdf files
end tell
set thisPath to quoted form of POSIX path of (this_item as alias)
--On the next line, change "letter" to whatever paper size you need.
set theShell to ("lpr -P " & YourPrinter & " -#" & NumCopies & " " & thisPath & " -o media=letter")
try
do shell script theShell
end try
end process_item
on setup_printer()
tell application "Printer Setup Utility" --This checks which system you are in, thanks to Kai by the way.
if ((system attribute "sysv") ≥ 4160) then
set current printer to printer YourPrinterTiger
set YourPrinter to YourPrinterTiger
else
set current printer to printer YourPrinterPanther
set YourPrinter to YourPrinterPanther
end if
end tell
end setup_printer
repeat
try
tell (text returned of (display dialog "How many copies?" default answer "") as integer) to if it is greater than 0 then
set numCopies to it
exit repeat
else
error
end if
on error
display dialog "Expected a positive whole number?!? Try again" with icon 0 buttons "Error!" giving up after 2
end try
end repeat
James beat me to it, but my submission is very similar to his:
repeat
set Num to text returned of (display dialog "How many copies" default answer "1")
try
if Num ≠"0" and Num does not contain "-" then
set Num to Num as integer
exit repeat
else
error
end if
on error
display dialog "Not a Positive Integer"
end try
end repeat
repeat
try
set theResult to text returned of (display dialog "Enter a positive integer:" default answer "") as number
if not (isPositiveInt(theResult)) then error
exit repeat
on error
display dialog "HURRR NOT A POSITIVE INTEGER LOLS."
end try
end repeat
on isPositiveInt(input)
if not (class of input is integer) or not (input > 0) then return false
return true
end isPositiveInt
If you don’t enter something that can be coerced to a number, the error catch triggers. Don’t need to evaluate anything other than that.
The evaluation function is portable, in case you want to test other numbers–or other objects entirely–later.
What does this gain you over the more readable version? Imagine three or six months from now: which one is going to be easier to parse, understand, and alter if needed? Since you’re not really gaining anything significant, performance-wise, and you aren’t actually reducing clutter, I can’t say I’d recommend doing it that way over the first.
Remember, just because you can combine lots of things into a single line doesn’t mean you should.
I knew if I put that up I would get a number of new perpectives. Thanks to everyone.
For what it’s worth, I am going with Bruce’s first suggestion. I like the “defaultAnswer” approach over an error dialog that has to clear. And I don’t need to do another interger check in the script so a subroutine is not really needed in this case.
Thanks again.
-Matt
Browser: Safari 419.3
Operating System: Mac OS X (10.4)
But it’s not as straightforward to read though aloud. I deal with this kind of stuff in Carbon and Cocoa all the time, and it really does make a difference down the road. The apostrophe, honestly, doesn’t help either. (I’ve ALWAYS hated that about AppleScript. What a terrible idea it was to add it to the language.)
It’s not an issue of being only one more operator, it’s that it doesn’t read through as cleanly. I really don’t see the benefit of combining it into one line, other than to say it can be done.
Right now you don’t, but who knows what you might do later. Portable code is good code.
The subroutine is the only one that throws an error if you enter a decimal value like “3.4”. The others round up or down. I combined the “defaultAnswer” approach with the sub-routine approach:
set defaultAnswer to ""
repeat
try
set theResult to text returned of (display dialog "Enter a positive integer:" default answer defaultAnswer) as number
if not (isPositiveInt(theResult)) then error
exit repeat
on error number errNum
if errNum is -128 then error number -128 -- User canceled dialog
set defaultAnswer to "Enter a positive whole number!"
end try
end repeat
on isPositiveInt(input)
return (input's class is integer) and (input > 0)
end isPositiveInt
A dialog in a handler, for anyone who’s interested:
on askForPositiveInteger(someDialogText)
set defaultAnswer to ""
repeat
try
display dialog someDialogText default answer defaultAnswer
text returned of result as number
if (class of result is integer) and (result > 0) then return result
error
on error number errNum
if errNum is -128 then error number -128 -- User canceled dialog
set defaultAnswer to "Enter a positive whole number!"
end try
end repeat
end askForPositiveInteger
set test to askForPositiveInteger("Enter a positive integer:")
You can change the the greater than comparison to meet your needs. If you want to accept decimals, you can use this if statement instead:
if ((class of result is integer) or (class of result is real)) and (result > 0) then return result