I'm extracting a list of data from a database on a website,
How can I go set the results of items in my list to the clipboard, excluding the first result with is just a wrong link
How can I use this script in Chrome instead of Safari?
set dataINeedList to my getInputByClass2("sortable dataPersonId", 1)
-- to get the tenth value, use this --> item 10 of allData
to getInputByClass2(theClass) -- this return a list of values
tell application "Safari"
set r to do JavaScript "var outPut=[]; var arr=document.getElementsByClassName('" & theClass & "');for (var i in arr) {outPut.push(arr[i].innerHTML)};outPut;" in document 1
end tell
return strings of r --- this remove all 'Missing Value' from a list of strings
end getInputByClass2
set listSize to count of dataINeedList ## number of dataINeed founds
set theResult to item 2 of dataINeedList
##repeat with theItem in dataINeedList ## not working
## set the clipboard to theItem ##
##end repeat ##
basically, it's like this:
set x to {"a", "b", "c"}
set the clipboard to items 2 thru -1 of x
Related
I'm currently trying to create a list into an expect script and to fill it later
I can declare and initialize the list as follow
#!/usr/bin/expect
set matchList [list test1 test2]
foreach elem $matchList {
puts $elem
}
Which gives the following result
$ ./tmp.expect
test1
test2
However I can't find a way to correctly append a new string to the list
I have tried several syntax without being able to find the proper way
set matchList [list $matchList test3]
Considers that 'test1 test2' is the first element and 'test3' the second
$ ./tmp.expect
test1 test2
test3
set matchList [list [foreach elem $matchList { puts $elem } ] test3]
Set the third element as an empty string and 'test3' is the fourth element
$ ./tmp.expect
test1
test2
test3
set matchList [list [foreach elem $matchList { puts $elem } ]test3]
By removing the space after the foreach block The list is correctly filled. However it seems a bit overkill to do such a simple task.
$ ./tmp.expect
test1
test2
test3
Does anybody knows how to correctly fill a list element by element into an expect script ?
The proper way to add an element to the end of a list in Tcl is to use lappend; the first argument is the name of a variable containing a list, and the second and subsequent arguments are values to append:
lappend matchList test3
That works even when values have metacharacters embedded within them.
How can I only keep words / numbers from list?
I use the follow script and I want to count unique payment methods, but I have unwanted values on my list
I also tried to use "word of item" but this is not working
I try different version of the script but always having an issue
set PaymentMethods to {}
set UniquePaymentMethods to {}
set walletPayement to {}
set mobilePayemnt to {}
tell application "Safari"
set PaymentMethods to do JavaScript "var outPut=[]; var arr=document.getElementsByClassName('sortable Summary');for (var i in arr) {outPut.push(arr[i].innerHTML)};outPut;" in current tab of window 1
end tell
repeat with x from 1 to count of items of PaymentMethods
set n to item x of PaymentMethods
if n is in PaymentMethods and n is not in UniquePaymentMethods and n does not contain "<a href=\"/finance/Support.ok" and n does not contain "Safari" and n does not contain "None" then set end of UniquePaymentMethods to n
end repeat
e.g of the result :
{"
PayPal
", "
MasterCard (999)
", "
MasterCard (888)
", application "Safari"}
It's good that you're generally mindful about supplying a sample of the input, as you've done here with the list that I presume relates to PaymentMethods. But don't forget to also provide the output you want to get back at the end. It took me a while to realise "keep words / numbers from list" was actually referring to items of class text (or string), which was about my fifth interpretation of what was being asked.
Your solution appears to do what you want, but it doesn't really because you've had to use that very case-specific set of conditionals, i.e.:
if n is in PaymentMethods ¬
and n is not in UniquePaymentMethods ¬
and n does not contain ("<a href=\"/finance/Support.ok") ¬
and n does not contain ("Safari") ¬
and n does not contain "None" then ¬
set end of UniquePaymentMethods to n
Without that, the item application "Safari", for instance, would simply be coerced into class text, which would return "Safari" in your resulting list.
So, while your request was to filter a list's data types to contain only text class items, your proposed fix, i.e.:
set n to item x of PaymentMethods as text
doesn't isolate text items; it coerces items of any class into text.
The way to filter a list by class type is to use this syntax:
get every [class] in [list]
where [class] is the AppleScript class you want to keep (discarding any items not of this class), and [list] is the list (or variable that references a list), e.g.:
every text in {1, "Hello", true, missing value, "2", text, number, pi}
--> {"Hello", "2"}
every number in {1, "Hello", true, missing value, "2", text, number, pi}
--> {1, 3.14159265359}
every application in {"PayPal", "MasterCard (999)", "MasterCard (888)", application "Safari"}
--> {application "Safari"}
every text in {"PayPal", "MasterCard (999)", "MasterCard (888)", application "Safari"}
--> {"PayPal", "MasterCard (999)", "MasterCard (888)"}
But, there's a lot you can do to simplify your script by having the initial JavaScript code do the heavy lifting so it returns a cleaner list of items that will be simpler for AppleScript to process, or eliminate any need for additional processing.
Your list items have a lot of whitespace in them. In JS, use trim().
Your AppleScript conditionals reference "innerHTML property without ever wanting to use any actual HTML. You've been consistently interested only in the text that gets printed on your webpage. Therefore, in JS, experiment with innerText applied to the right HTML element and you'll probably be able to isolate the payment methods text straight away.
You appear to want your list to contain unique items. In JS, use sets, which are basically arrays with unique items.
Implementing these three recommendations, together with the above method of filtering by text class, would look something like:
tell application "Safari" to tell document 1 to tell (do JavaScript "
[...new Set( document.getElementsByClassName('sortable Summary') )]
.map( x => x.innerText.trim() );") ¬
to set PaymentMethods to every text
As I don't know what your webpage source looks like, you may need to make slight adjustments to how you want to transform innerText besides trim(), and/or consider whether getElementsByClassName('sortable Summary') is the best way to get access to the parts of the HTML DOM tree you require. querySelectorAll() is a much more powerful method to use, which I have mentioned before.
Found it, need to add the kind for each item
set n to item x of PaymentMethods as text
I'm making a script to create a food menu by randomly picking dishes off of a list 7 times. However, I would like to make it so that it doesn't pick any similar dishes. For instance, if 'Lamb Chops' was chosen as dish1, then dish2 would be a random item from the same list with all the options including 'lamb' and 'chops' removed. Then if dish2 was 'Spaghetti Bolognese', then dish3 would be chosen from the same list excluding 'lamb', 'chops', 'spaghetti', and 'bolognese', and so on and so on. Can anyone help?
-Thanks.
I'm somewhat rusty with AppleScript, so excuse me if I make mistakes.
To break down what you must do,
1) Choose a random item
-- The initial menuItems we start off with
set menuItems to {"Lamb Chops", "Lamb", "Chops", "Spaghetti Bolognese", "Spaghetti", "Bolognese"}
set randomItemNum to random number from 1 to count of menuItems
set randomItem to item randomItemNum of menuItems as string
2) Repeat through menuItems so we can exclude items that contain a word from randomItemWe'll use this subroutine to split strings:
on splitString(theString, theDelimiter)
-- save delimiters to restore old settings
set oldDelimiters to AppleScript's text item delimiters
-- set delimiters to delimiter to be used
set AppleScript's text item delimiters to theDelimiter
-- create the array
set theArray to every text item of theString
-- restore the old setting
set AppleScript's text item delimiters to oldDelimiters
-- return the result
return theArray
end splitString
and now we can easily split strings, lets continue with the reconstruction of the menu:
-- This loops through menuItems, and we can use menuItem to access the current looped item
-- We'll use this to reconstruct menuItems, but excluding what we need
set newMenuItems to {}
repeat with menuItem in menuItems
-- Get words from randomItem
-- For example, if randomItem is "Lamb Chops", it will return {"Lamb","Chops"}
set menuItemWords to splitString(randomItem, " ")
-- This is the conditional that will determine to include menuItem or not
-- Feel free to change this to get the outcome you want
if menuItemWords does not contain menuItem as string and menuItem does not contain menuItemWords then
-- And this conditional to not re-add the randomItem
-- However, it does it to one word items in the previous if statement
-- Note: Without using "as string" to menuItem it doesn't work correctly, not sure why
if menuItem as string is not equal to randomItem then
set the end of newMenuItems to menuItem
end
end
end repeat
-- Now we've finished creating a new menu with the changes we want, set it to the main one
set menuItems to newMenuItems
And, now it should work.
You might also want to examine the results easily, in which case, you can use this subroutine to concatenate the arrays into a string:
on arrayToString(theArray, theSeperator)
set arrayString to ""
repeat with theItem in theArray
if arrayString is equal to "" then
set arrayString to theItem
else
set arrayString to arrayString & theSeperator & theItem
end if
end repeat
end arrayToString
and just display the results before you set the menu to the new one.
........
display alert "I've picked " & randomItem & " for you." message "Old menu:
" & arrayToString(menuItems, ", ") & "
New menu:
" & arrayToString(newMenuItems, ", ")
-- Now we've finished creating a new menu with the changes we want and displayed the results, set it to the main one
set menuItems to newMenuItems
You can also loop through the menu items 7 times by warping the code in a repeat 7 times after specifying the initial menuItem, and a check to exit the repeat if menuItems is empty, like this:
on splitString(theString, theDelimiter)
...
end splitString
-- The initial menuItems we start off with
set menuItems to {"Lamb Chops", "Lamb", "Chops", "Spaghetti Bolognese", "Spaghetti", "Bolognese"}
-- Repeat statement to loop 7 times
repeat 7 times
-- If menuItems is empty, exit the repeat
if count of menuItems is 0 then
exit repeat
end if
set randomItemNum to random number from 1 to count of menuItems
set randomItem to item randomItemNum of menuItems as string
set newMenuItems to {}
repeat with menuItem in menuItems
...
end repeat
-- Now we've finished creating a new menu with the changes we want, set it to the main one
set menuItems to newMenuItems
-- This is the end of loop for 7 times
end repeat
I hope this helps.
If you need any other help, or there's an error, please comment below and l'll try my best.
Edit:
Here is the complete code that should do what you need, it repeats 7 times and shows the user a list of the selected dishes when completed:
on splitString(theString, theDelimiter)
-- save delimiters to restore old settings
set oldDelimiters to AppleScript's text item delimiters
-- set delimiters to delimiter to be used
set AppleScript's text item delimiters to theDelimiter
-- create the array
set theArray to every text item of theString
-- restore the old setting
set AppleScript's text item delimiters to oldDelimiters
-- return the result
return theArray
end splitString
on arrayToString(theArray, theSeperator)
set arrayString to ""
repeat with theItem in theArray
if arrayString is equal to "" then
set arrayString to theItem
else
set arrayString to arrayString & theSeperator & theItem
end if
end repeat
end arrayToString
-- The menu after you finish looping to show the user
set yourMenu to {}
-- The initial menuItems we start off with
set menuItems to {"Lamb Chops", "Lamb", "Chops", "Spaghetti Bolognese", "Spaghetti", "Bolognese"}
-- Repeat statement to loop 7 times
repeat 7 times
-- If menuItems is empty, exit the repeat
if (count of menuItems) is 0 then
exit repeat
end if
set randomItemNum to random number from 1 to count of menuItems
set randomItem to item randomItemNum of menuItems as string
-- This loops through menuItems, and we can use menuItem to access the current looped item
-- We'll use this to reconstruct menuItems, but excluding what we need
set newMenuItems to {}
repeat with menuItem in menuItems
-- Get words from randomItem
-- For example, if randomItem is "Lamb Chops", it will return {"Lamb","Chops"}
set menuItemWords to splitString(randomItem, " ")
-- This is the conditional that will determine to include menuItem or not
-- Feel free to change this to get the outcome you want
if menuItemWords does not contain menuItem as string and menuItem does not contain menuItemWords then
-- And this conditional to not re-add the randomItem
-- However, it does it to one word items in the previous if statement
-- Note: Without using "as string" to menuItem it doesn't work correctly, not sure why
if menuItem as string is not equal to randomItem then
set the end of newMenuItems to menuItem
end if
end if
end repeat
-- Now we've finished creating a new menu with the changes we want, set it to the main one
set menuItems to newMenuItems
set the end of yourMenu to randomItem
-- This is the end of loop for 7 times
end repeat
set itemSelected to (choose from list yourMenu with prompt "Here's your menu.")
display alert "You selected " & itemSelected & "."
Trying to learn how to use AppleScript records and lists to their upmost potential I've been trying to create a report of a BBEdit project but I'm finding very limited documentation. I asked a question yesterday trying to figure out why my find pattern wasn't working but after finding out that the issue was from me lacking returning results:true I was able to get the result record and I verified it was a record after reading Class and running:
class of findFunction
Since it says it's a record I reviewed here and ran length of findFunction and count of findFunction and they both returned 2. I was curious to know what the two items were in the record so I used return findFunction and was told there was:
found: true
found matches: list of X items
Wanting to know where and what files the matches were located in the list, I did some more searching and read Lists and records and ran:
set theMatches to get found matches of findFunction
it returned the list items and checking the new variable with get count of theMatches I am able get the quantity of items in the targeted list inside the record. When I review what's in the list (learned from: How to get a value from a list with a string in AppleScript? and Searching for items in list) I am able to conclude that when using the find in BBEdit every item in the list contains:
end_offset :
match_string :
message :
result_file :
result_kind :
result_line :
start_offset :
Experimenting with an item I set a variable with:
set itemOne to get item 1 of theMatches
and checked to see if it worked with:
display dialog (result_file of itemOne) as text
and a dialog with the full file path was displayed. Trying to utilize DRY I created:
set filesResult to get (result_file of (get item 1 of theMatches)) as text
Wanting to add any of the mentioned above to a file with something like:
set filesResult to get (result_file of (get item 1 of theMatches)) as text
set theMessage to get (message of (get item 1 of theMatches)) as text
set combined to filesResult & ":" & theMessage
I recalled being able to use the clipboard and found Set clipboard to Applescript variable? so I added:
set filesResult to the clipboard
make new text document
paste
but my issue I'm running into is how can I take every item in the list found_matches and add it to the clipboard an item on each line? I thought about using a repeat but I get an error when I try:
repeat with x from 1 to (length of matchesItems)
set filesResult to get (result_file of (get item x of theMatches)) as text
set theMessage to get (message of (get item x of theMatches)) as text
set combined to filesResult & ":" & theMessage
end repeat
With a message of:
The variable matchesItems is not defined.
So how can I get every item from the list into the clipboard with every item on it's own line so I can paste all items from the clipboard into a new file?
To clarify wording
theList = {A,B,C} -- this is a list with 3 variables
theRecord = {A:something, B:somethingElse, C:somethingElseTwo} -- this is a record.
A list can be addressed by its index.
theList's item 1 -- A
A record can be addressed by its keys
A of theRecord -- something
To get all items of a list into a string repeat it by its index (saying every item is of type text)
set finalString to ""
repeat with thisItem in TheList
set finalString to finalString & thisItem & return -- the return creates a new line
end repeat
Then you have finalString to do with whatever you like.
To get every item of a record you have to know it's keys (if it's not a ASOC NSDictionary)
set finalString to ""
set finalString to finalString & A of theRecord & return;
-- repeat last line with every key
The list is in the form of:-
0:
https://url
1:
https://url
..... And so on.
How could I loop on this list. So I could fetch the number first without ":" and type it somewhere then fetch the url that comes after that number and type it elsewhere. Then end repeat if the list is over.
Or should I use records instead?
I am still a beginner using AppleScript. I tried many commands I mixed up but the computer keeps running the script nonestop and the activity monitor shows the applescript using 100% of the processor and huge amount of ram.
Appreciate any help.
Thank you
You didn't define what your list really looks like very well so I made an assumption on my answer below. If I was wrong, hopefully my answer will at least point you in the right direction. (or if I've gotten it wrong, but you can choose to reformat it to the way I suggested, that could still help)
on run
set theList to {"0:http://apple.com", "1:http://google.com"} -- my guess at what your list looks like.
repeat with anItem in theList
set anItem to anItem as string
set itemParts to myParseItem(anItem)
set tID to the_integer of itemParts as integer
set tURL to the_url of itemParts as string
end repeat
end run
on myParseItem(theItem)
set AppleScript's text item delimiters to ":"
set delimitedList to every text item of theItem
set newString to (items 2 thru -1 of delimitedList as string)
set AppleScript's text item delimiters to {""}
set theInt to item 1 of delimitedList
set theURL to newString as string
return {the_integer:theInt, the_url:theURL}
end myParseItem