1

My current code:

property cityList : {"City A","City B","City C","New City"}
choose from list cityList with prompt "Choose your city:"
set choice to result
if choice is not false then set city to choice
if choice is false then error number -128

if (city as string) is "City A" then
    set lat to 1
    set lon to 1
else if (city as string) is "City B" then
    set lat to 1
    set lon to 1
else if (city as string) is "City C" then
    set lat to 1
    set lon to 1
else if (city as string) is "New City" then
    set lat to my customLat()
    set lon to my customLon()
    set city to my customCity()
    set x to the length of cityList
    set the end of cityList to "New City"
    copy city as string to item x of cityList
end if

--script that does things based on values of lat and lon

where customLat() is a subroutine that prompts the user for a latitude, tries to coerce it to a number and outputs an error if it can't, and outputs another error if said number is not between -90 and 90, and customLon() is a similar one, but it tests for between -180 and 180 instead. In either case, if an error is returned, it prompts the user for the relevant number once more. customCity() merely prompts the user for the city's name.

My problem is what to type in after the copy city line. Is there a way to add an if block in my code - that is, have the code write on top of itself - based on the result of the "New City" if block? That is, once the code has established the variables city, lat, and lon, it will then insert before the end if line a similar block to the previous cities:

else if (city as string) is "Newly Inputted City" then
    set lat to 1
    set lon to 1

I am looking for a way that the user can input a custom city and coordinates, and the code will overwrite itself to allow that as a valid option, so that the next time the script is run the custom city will be available as an option, and selecting it will automatically set its lat and lon, just like the other cities.

  • 2
    Having a hard time understanding what your code is supposed to be doing… Specifically, where would “Newly Inputted City” come from, and why do you append “New City” to the end of cityList, then also replace the previous element of cityList with “New City”? – user11633 Jul 31 '17 at 19:04
  • 1
    This doesn't answer your question, but are you aware that copy city to item x of cityList creates city as a list into the existing cityList list? It should be copy city as string to item x of cityList so it will be {"City A", "City B", "City C", "New City", "New City"} vs {"City A", "City B", "City C", {"New City"}, "New City"} the way it's presently coded. – user3439894 Jul 31 '17 at 19:08
  • @Phong Newly inputted city is the city identified in the subroutines. Afterwards, I add that city to the list, but keep the option to add a new city ("New City") as the last item on the list. – DonielF Jul 31 '17 at 21:07
  • @user3439894 Huh. It's not showing that when I log it, so I had no idea. Thanks for pointing that out. – DonielF Jul 31 '17 at 21:07
  • You said, "Huh. It's not showing that when I log it, so I had no idea." ... When a list object is logged, e.g. log cityList, it's as a string, e.g. (*City A, City B, City C, New City, New City, New City*) not a list object, and why you don't see it, but if you look in the Events pane or the Event Log History, it will show it as choose from list {"City A", "City B", "City C", {"New City"}, "New City"} with prompt "Choose your city:". Understand? – user3439894 Jul 31 '17 at 22:27
1

Your code doesn’t need to rewrite itself. else already takes care of all cases that are unaccounted for:

property cityList : {"City A", "City B", "City C", "New City"}
set choice to choose from list cityList with prompt "Choose your city:"
if choice is false then
    error number -128
end if

set city to choice as string
if city is "New City" then
    set lat to my customLat()
    set lon to my customLon()
    set city to my customCity()
    set x to the length of cityList
    set the end of cityList to "New City"
    copy city to item x of cityList
else
    set lat to 1
    set lon to 1
end if
  • Not at all what I'm trying to do. I'm not trying to allow the user to input custom coordinates - I already know how to do that. I'm trying to allow the user to input custom coordinates, update the default list of choices, and edit the code itself to reflect those changes. So that way next time I can boot up the program, my custom choice will be on the list, and I can just click that choice and it will automatically set the latitude and longitude accordingly. I don't want to have to anticipate any entry that could be used - I want the code to edit itself to reflect the user's inputs. – DonielF Jul 31 '17 at 21:39
1

Adding lines to a script is possible, but it is very complicated and unnecessary.

You only need two lists, cities and coordinates.

Simply use a loop to get the city index in the list, and use that index to get the coordinates in the other list.

Here's the script:

property myRecord : {cityList:{"City A", "City B", "City C", "New City"}, coordinates:{{1, 1}, {1, 1}, {1, 1}}}

set choice to choose from list (cityList of myRecord) with prompt "Choose your city:"
if choice is false then error number -128
set city to item 1 of choice -- the class of choice is a list, this list contains one item

if city is "New City" then
    set lat to my customLat()
    set lon to my customLon()
    set city to my customCity()

    tell (cityList of myRecord)
        set last item to city -- replace the last item in the cityList
        set end to "New City" -- append "New City" to cityList
    end tell
    set end of (coordinates of myRecord) to {lat, lon} -- append a list in the 'coordinates' list

else -- the city is not "New City"
    tell myRecord
        set len to (length of its cityList) - 1 -- ***    -1 to skip the last item ("New City")   ****
        repeat with i from 1 to len
            if (item i of its cityList) = city then -- the index of the city in the 'cityList' is i
                set {lat, lon} to item i of its coordinates -- I use the index to get the latitude and the longitude in the 'coordinates' list
                exit repeat
            end if
        end repeat
    end tell
end if
log {lat, lon}
--script that does things based on values of lat and lon

Note : I use a record in the script, but you can use two properties if you prefer:

property cityList : {"City A", "City B", "City C", "New City"}
property coordinates : {{1, 1}, {1, 1}, {1, 1}}
  • Much better alternative. Let me try it out and see if it does what I want it to do, and if it does I'll give you your well-earned green check. :) – DonielF Aug 2 '17 at 17:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .