How can I get list item(s) that contains something specific?
For example:
set listItems to {"abc","a bc","a(b)c","(bc"}
get every item which contains "a" of listItems
desired result: "abc", "a bc", "a(b)c"
or
get every item which contains "(" and ")" of listItems
desired result: "a(b)c"
I've read the basic tutorial: http://www.macosxautomation.com/applescript/sbrt/sbrt-07.html so I'm interested in any kind of workarounds.
You can simply iterate through the list and test for matches:
set listItems to {"abc", "a bc", "a(b)c", "(bc"}
set finalItems to {}
repeat with thisItem in listItems
if (thisItem contains "(") and (thisItem contains ")") then set finalItems to finalItems & thisItem
end repeat
return finalItems
I don't think there is an oneliner for this in pure applescript. You have to loop the items. Something like this:
set listItems to {"abc", "a bc", "a(b)c", "(bc"}
my searchForPatterns(listItems, {"a"})
--result: {"abc", "a bc", "a(b)c"}
my searchForPatterns(listItems, {"(", ")"})
--result: {"a(b)c"}
on searchForPatterns(listItems, searchPatterns)
set resultList to {}
repeat with listItem in listItems
set match to true
repeat with searchPattern in searchPatterns
if listItem does not contain searchPattern then ¬
set match to false
end repeat
if match is true then ¬
copy listItem as text to end of resultList
end repeat
return resultList
end searchForPatterns
Related
I'm making a Automator to jump from citation in Word to the reference software(Zotero). But I can't find a AppleScript to extract text of selected field code (the first step).
The field code in Word is
ADDIN ZOTERO_ITEM CSL_CITATION {"citationID":"AFUiwuqi","properties":{"formattedCitation":"[1]","plainCitation":"[1]","noteIndex":0},"citationItems":[{"id":9752,"uris":["http://zotero.org/users/6410528/items/YYTRWPHH"],"itemData":{"id":9752,"type":"article-journal","container-title":"Nature","DOI":"10.1038/s41586-019-1737-7","ISSN":"0028-0836, 1476-4687","issue":"7782","page":"324-329","title":"Controlled flight of a microrobot powered by soft artificial muscles","volume":"575","author":[{"family":"Chen","given":"Yufeng"},{"family":"Zhao","given":"Huichan"},{"family":"Mao","given":"Jie"},{"family":"Chirarattananon","given":"Pakpong"},{"family":"Helbling","given":"E. Farrell"},{"family":"Hyun","given":"Nak-seung Patrick"},{"family":"Clarke","given":"David R."},{"family":"Wood","given":"Robert J."}],"issued":{"date-parts":[["2019",11,14]]}}}],"schema":"https://github.com/citation-style-language/schema/raw/master/csl-citation.json"}
Here is the script process:
Extract text from selected field code in Word (This is the question)
Get the uris text(http://zotero.org/users/6410528/items/YYTRWPHH)
Get the item-codes (YYTRWPHH).
Open url (zotero://select/library/items?itemKey=YYTRWPHH)
Now I use VBA to extract field code text, see below. But in this way, the file will be changed. So I want to do this via AppleScript.
Sub GetFiledsCodes()
Dim myRange As Range, myCodes As String
Set myRange = Selection.Range
With myRange
If .Fields.Count = 0 Then
MsgBox "No Code!", vbInformation
Exit Sub
Else
.Fields.Update
.TextRetrievalMode.IncludeFieldCodes = True
.TextRetrievalMode.IncludeHiddenText = True
myCodes = .Text
myCodes = VBA.Replace(myCodes, Chr(19), "{")
myCodes = VBA.Replace(myCodes, Chr(21), "}")
.SetRange .End, .End
.InsertAfter myCodes
.Font.Name = "Times New Roman"
.Font.Size = 12
.Cut
End If
End With
End Sub
PS:
Here is my process in Automator(it can work but using VBA):
Run AppleScript
on run {input, parameters}
tell application "Microsoft Word" to activate
tell application "Microsoft Word"
run VB macro macro name "GetFiledsCodes"
delay 0.5
end tell
return input
end run
Get contents from clipboard
Extract URLs from Text
Filter Paragraphs begin with http://zotero.org/users/
Copy to Clipboard
Run AppleScript
set myStr to do shell script "pbpaste"
tell application "Zotero" to activate
set AppleScript's text item delimiters to "
"
set myList to every text item of myStr
set zoterocode to ""
set codes to ""
repeat with j from 1 to the length of myList
set itemValue to item j of myList
set zoterocode to (do shell script "sed -E 's#http://zotero.org/users/[0-9]+/items/##g' <<< " & itemValue)
if j = 1 then
set codes to zoterocode
else
set codes to codes & "," & zoterocode
end if
end repeat
tell application "System Events"
key code 18 using {command down, control down, option down}
delay 0.5
set collectionKey to do shell script "pbpaste"
if collectionKey = myStr then
set theurl to "zotero://select/library/items?itemKey=" & codes
else
set theurl to collectionKey & "/items?itemKey=" & codes
end if
open location theurl
end tell
That helps a lot. Okay, so this isn't a turnkey solution for your question but I don't think you really need that as you'd probably end up having to tell me more about how this app works than is really necessary. So this script focuses on your initial question about getting the field codes/result ranges from a merge document.
I put together a simple mail merge consisting of labels and a data file with 8 records, each of which have 5 fields: {"«LastName»", "«JobTitle»", "«Company»", "«City»", "«Web»"}. The latter is the key field.
Basically, the script runs through the data merge document and cycles first through its fields, then the web field, and finally the web addresses.
Based on your script, I can't really determine what you are doing with each address so it finishes by collecting just the final part of each address in a list. The obscure parts for me are the pbpastes, the codes and the whole System Events block. This area would need tweaking.
Incidentally, it's quite likely that you can avoid some of the shell scripts but I can't say how yet. Obviously the script has some redundancies and could be further refined but I think it demonstrates how to extract the information you need. Take a look at it and let me know what issues there are that need addressing.
tell application "Microsoft Word"
set d1 to document "cardo_labels.docx"
set fContents to {} -- list of mergefield
set fResRange to {} -- list of result range, i.e. field merge data
repeat with x from 1 to (count of fields of d1)
set fcs to content of field code of field x of d1 --> " MERGEFIELD LastName "
set frr to content of result range of field x of d1 --> "Smith"
if fcs is not " NEXT " then -- ignore «Next Record»
set end of fContents to fcs
set end of fResRange to frr
end if
end repeat
--> single record example
fContents --> {" MERGEFIELD LastName ", " MERGEFIELD JobTitle ", " MERGEFIELD Company ", " MERGEFIELD City ", " MERGEFIELD Web "}
fResRange --> {"Smith", "President", "Acme Screw & Gear", "Metz", "http://zotero.org/users/1234/items/smith-metz"}
-- NB when not displaying 'merged data', fResRange will appear thusly: {"«LastName»", "«JobTitle»", "«Company»", "«City»", "«Web»"}
set webList to {}
repeat with y from 1 to (count of fResRange)
if item y of fResRange begins with "http://zotero.org/users/" then
set end of webList to (item y of fResRange)
end if
end repeat
--> {"http://zotero.org/users/1234/items/smith-metz"}
--> {"http://zotero.org/users/1234/items/smith-metz", "http://zotero.org/users/4222/items/branson-metz", "http://zotero.org/users/3236/items/house-metz", "http://zotero.org/users/3342/items/kurtz-london", "http://zotero.org/users/12345/items/jones-london"}
set urlPiece to {}
set AppleScript's text item delimiters to "/"
repeat with z in webList
set end of urlPiece to last text item of z
end repeat
-- contents of z
--> "http://zotero.org/users/1234/items/smith-metz"
set AppleScript's text item delimiters to ""
urlPiece
--> {"smith-metz"}
--> {"smith-metz", "jones-saopaolo", "branson-metz", "house-metz", "kurtz-london", "jones-london"}
end tell
Thanks to ideas from #Mockman.
Combining with the selection, here is the way to extract text from selected field code via AppleScript:
tell application "Microsoft Word"
tell selection
set fcs to content of field code of field of text object
end tell
end tell
fcs
This script is for use in Capture One where I am assigning people's names to the EXIF data.
I am trying to return the results of a list that could be one or more choices made by the user. I can get it to work with using item 1 in the list but I can't figure out how to deal with someone choosing 2 or more names from anywhere in the list?
Thanks for any help you can offer.
tell application "Capture One 11"
set peopleChoices to {"Abbie", "Charlie", "De-Arne", "Dean", "Jason", "Marlene", "Peta ", "Phoenix", "Rod", "Vanessa", "Yvonne"}
set peopleList to choose from list peopleChoices with prompt "Select your keyword/s:" with multiple selections allowed
if the result is not false then
set exif_keywords to item 1 of the result
end if
set selectedVariants to get selected variants
repeat with i from 1 to number of items in selectedVariants
set this_item to item i of selectedVariants
set theID to id of (parent image of this_item)
do shell script "/usr/local/bin/exiftool -Subject='" & exif_keywords & "' -m -overwrite_original_in_place " & quoted form of theID
reload metadata this_item
end repeat
display dialog "EXIF data has been updated"
end tell
You are constraining the list to one item in this line
set exif_keywords to item 1 of the result
Just change it to
set exif_keywords to result
I don't know how the keywords are supposed to be passed in the exiftool line, you might flatten the list with text item delimiters, this example joins the list comma separated. Replace "," with space if the parameters have to be space separated.
set {ASTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ","}
set exif_keywords to exif_keywords as text
set AppleScript's text item delimiters to ASTID
I have included the whole working script below in case anyone else is looking for something similar. The "-sep" is part of exiftool and splits the string depending on what you put after it. I had to escape it for the shell script line but it nromally does not have the back slashes.
tell application "Capture One 11"
set peopleChoices to {"Abbie", "Charlie", "De-Arne", "Dean", "Jason", "Marlene", "Peta", "Phoenix", "Rod", "Vanessa", "Yvonne"}
set peopleList to choose from list peopleChoices with prompt "Select your keyword:" with multiple selections allowed
if the result is not false then
set exif_keywords to result
set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ","}
set exif_keywords to exif_keywords as text
set AppleScript's text item delimiters to TID
end if
set selectedVariants to get selected variants
repeat with i from 1 to number of items in selectedVariants
set this_item to item i of selectedVariants
set theID to id of (parent image of this_item)
do shell script "/usr/local/bin/exiftool -sep \",\" -Keywords='" & exif_keywords & "' -m -overwrite_original_in_place " & quoted form of theID
reload metadata this_item
end repeat
display dialog "EXIF data has been updated"
end tell
I'm using this AppleScript to get the content of a selection of eMails:
using terms from application "Mail"
on run {input, parameters}
set mailContents to {}
repeat with aMessage in input
set end of mailContents to content of aMessage
end repeat
return mailContents
end run
end using terms from
The result looks like this:
{"

Here's some text followed by a longer URL, which is cut by a line break!
http://www.XYZ.net/diario/actualidad/economia/20140714/-ciudad-bar
ata-para-el-turismo_353_34541.html
"}
I want to use all links in those specific mails for fort her processing but it's not possible to use the divided URLs as seen in the example before.
So how to tell the AppleScript to keep the URL together?
Try this. I started with your mailContents example. You end up with a list of the links in the httpLinks variable. This works assuming every link starts with "http" and ends with "html". Good luck.
set mailContents to {"

Here's some text followed by a longer URL, which is cut by a line break!
http://www.XYZ.net/diario/actualidad/economia/20140714/-ciudad-bar
ata-para-el-turismo_353_34541.html
"}
set httpLinks to {}
repeat with i from 1 to count of mailContents
set thisContent to item i of mailContents
-- remove all return characters (mac, unix, and windows characters)
set AppleScript's text item delimiters to {character id 10, character id 13, character id 13 & character id 10}
set textItems to text items of thisContent
set AppleScript's text item delimiters to ""
set newText to textItems as text
-- find links
set AppleScript's text item delimiters to "http"
set textItems to text items of newText
if (count of textItems) is greater than 1 then
set AppleScript's text item delimiters to "html"
repeat with j from 2 to count of textItems
set linkItems to text items of (item j of textItems)
set thisLink to "http" & item 1 of linkItems & "html"
set end of httpLinks to thisLink
end repeat
end if
set AppleScript's text item delimiters to ""
end repeat
return httpLinks
This does not break lines, hope you can use it somehow:
tell application "Mail"
set mailSelection to selection
set mailContents to {}
repeat with mail in mailSelection
set end of mailContents to content of mail
end repeat
get mailContents
end tell
Thank you very much! I had to customize your script a bit because not every URL ends with html. Furthermore I used the source of the messages instead of content, because the deleted line breaks had the result, that it was very difficult to separate the URLs from other text. There was no space between them. This is my actual code:
`using terms from application "Mail"
on run {input, parameters}
set mailContents to {}
repeat with aMessage in input
set end of mailContents to source of aMessage
end repeat
set httpLinks to {}
repeat with i from 1 to count of mailContents
set thisContent to item i of mailContents
-- remove all return characters (mac, unix, and windows characters)
set AppleScript's text item delimiters to {"=09", "=" & character id 10, "=" & character id 13, "3D", character id 92}
set textItems to text items of thisContent
set AppleScript's text item delimiters to ""
set newText to textItems as rich text
-- find links
set AppleScript's text item delimiters to "http"
set textItems to text items of newText
if (count of textItems) is greater than 1 then
set AppleScript's text item delimiters to "target"
repeat with j from 2 to count of textItems
set linkItems to text items of (item j of textItems)
set thisLink to "http" & item 1 of linkItems & "target"
set end of httpLinks to thisLink
end repeat
end if
set AppleScript's text item delimiters to ""
end repeat
set list1 to httpLinks
set list2 to {}
repeat with x from 1 to count of items of list1
set n to item x of list1
if n is not in list2 then set end of list2 to n
end repeat
return list2
end run
end using terms from`
I am trying to make an Applescript that condenses multiple lines down to one line.
For example
"a
b
c
d"
to
('a','b','c','d')
The string is in TextWrangler, and my script is
set AppleScript's text item delimiters to {return & linefeed, return, linefeed, character id 8233, character id 8232}
tell application "TextWrangler"
tell text window 1
set i to 2
set selection to "('
"
repeat while i < 6
select (insertion point before line i)
select line the (startLine of the selection)
copy (contents of the selection) as text to myText
set newText to text items of myText
set AppleScript's text item delimiters to {""}
set newText to newText as text
select insertion point after line 1
if i = 2 then
set selection to newText
else
set selection to "','" & newText
end if
set i to i + 1
end repeat
set selection to "')"
end tell
end tell
The issue is that result of the script is ('a','b','b'), so I am unable to remove 'new line' character. If someone help me to improve it to work with dynamic number of lines, I will be grateful.
To get the text from TextWrangler, you would use:
tell application "TextWrangler"
set myString to text of window 1
end tell
To update the text in TextWrangler, you use:
tell application "TextWrangler"
set text of window 1 to myString
end tell
So, you can wrap those two pieces of code around adayzdone's code.
tell application "TextWrangler"
set myString to text of window 1
end tell
set myList to paragraphs of myString
set listCount to count myList
repeat with i from 1 to my listCount
set item i of myList to quoted form of item i of myList
end repeat
set {TID, text item delimiters} to {text item delimiters, ", "}
set newString to ("(" & myList as text) & ")"
set text item delimiters to TID
tell application "TextWrangler"
set text of window 1 to myString
end tell
You can try something like this:
set myString to "a
b
c
d"
set myList to paragraphs of myString
set listCount to count myList
repeat with i from 1 to my listCount
set item i of myList to quoted form of item i of myList
end repeat
set {TID, text item delimiters} to {text item delimiters, ", "}
set newString to ("(" & myList as text) & ")"
set text item delimiters to TID
return newString
Ive been playing with applescript for about 2 weeks now, but I have hit a problem
Im trying to create an applescript that reads all the names of the folders on our server.
Then displays them in a drop down menu so that I can select the client.
The problem I have is that it is displaying the result as one selection option as a big sentence and is not separating each client, so they can be selected individually.
so far I have:
set theFolder to alias "server:"
tell application "Finder"
set theText to name of theFolder & return
set k to 0
repeat with thisSubfolder in (get folders of theFolder)
set k to k + 1
set theText to theText & name of thisSubfolder & return
end repeat
end tell
set l to {theText}
set l2 to ""
repeat with i in l
set l2 to l2 & quoted form of i & " "
end repeat
do shell script "/Applications/CocoaDialog.app/Contents/MacOS/CocoaDialog \\
standard-dropdown --title Title --text Text --items " & l2
set {button, answer} to paragraphs of result
if button is 1 then
return item {answer + 1} of l
end if
Many thanks
D
When you do this:
set l to {theText}
You're just creating a list of one item (your string), which means you end up with this:
{"theFolder
folder1
folder2
folder3
"}
You're then repeating in that "list," trying to add spaces between the items. But, you don't have a list really. You have a one item list, with return-delimited strings.
The best way to get a list of folder names would be to get them from System Events. Notice that in this case, you have to create a list with the name of the first folder as the only item. Otherwise, the & operation will join everything together as a string, instead of creating a list.
tell application "System Events"
set l to (name of theFolder as list) & name of folders of theFolder
end tell
There are also some syntactical issues that will hurt you later:
1 != "1"
CocoaDialog returns a string, with the button number: "1". You are using if button is 1. For equality, it should be if button is "1".
Parentheses are used for grouping, not brackets
If button is "1", you are returning item {answer + 1} of l. I blame Applescript for letting this work when it shouldn't. You're actually creating a list with a number, which then gets coerced by Applescript for the list index. Here are all the steps, assuming answer is 0:
item {answer + 1} of l gets turned into
item {1} of {folder1, folder2, folder3}
Applescript coerces to item 1 of {folder1, folder2, folder3}
Value returned: folder1
Here is a fully updated version of your script:
set theFolder to alias "server:"
tell application "System Events"
set l to {name of theFolder} & name of folders of theFolder
end tell
set args to ""
repeat with i from 1 to (count l)
set args to args & quoted form of item i of l
if i < (count l) then
set args to args & " "
end if
end repeat
do shell script "/Applications/CocoaDialog.app/Contents/MacOS/CocoaDialog \\
standard-dropdown --title Title --text Text --items " & args
set {button, answer} to paragraphs of result
if button is "1" then
return item (answer + 1) of l
end if
Change the line:
set l to {theText}
to:
set l to paragraphs of theText
and you should be good to go.