I often copy and paste from iBook for personal note taking. How do I create a script that will automatically remove the words "Excerpt From" and all the words following that text whenever I paste in any application?
You'd have to run the script before you paste, and it might look something like this:
try
set c to the clipboard as text
considering case --to match exactly
set o to offset of "Excerpt From" in c
end considering
set the clipboard to (text beginning thru (o - 1) of c)
on error e
display dialog e
end try
--given text on clipboard like "1234------Excerpt From 0987654" you'd end up with "1234------"
Related
PreNote: I am open and hungry for any information, advice, tip etc.
Hello Everyone!
I am trying to create automation with applescript. This is my first personal applescript task but I have some valuable questions. Basically I am trying to catch live notifications from a website and display them in mac os notification.
I am trying to build process for a few days but I don't want to give a mess to you :) so I have roughly explained my process below.
(* Variables used in whole process
set $webToCheck > This is Safari webpage which I want to run my script on it. It won't be front window, script should be run with its name or other property.
set $theClass > This is class name of DOM element to check if it is exist or not. This class is not always exist on DOM of $webpage. It comes with notifications so when use it in "do Javascript" I got error "variable is not defined"
set $num > number of class to use in "do Javascript"
set $input > variable to assign HTML text
set $modifiedInput > Text of input seperated from HTML tags
*)
-- Step 1
tell application "Safari"
work on $webToCheck
-- Step 2
repeat until $input is not empty
set input do Javascript
document.getElementsByClassName > $theClass, $num of $webToCheck
end repeat
-- Step 3
modify text of $input to seperate from RAW HTML -- For example: <a class="" value=""> TEXT to be seperated </a>
Display notification $modifiedInput
-- Step 4
Go back to step 1 or 2 to check and display notification again
First of all, here are some general tips though:
Applescript won't accept $ at the start of variable names.
The variable assignment you are looking for is set {variable} to {value}. You can optionally at the end of it clarify the variable's class using as {class} at the end of the assignment.
Focusing a certain website does not happen with work on {URL} but as with most object oriented things in Applescript with the tell-statement. It will be shown in the full solution.
Text concatenation in Applescript happens with &. So something like "Hello " & "World" is the standard way to do it.
Modification of most things in Applescript happens with set.
It is easier to use innerText instead of innerHTML as splitting text in Applescript is a bit of a pain.
There is no goto but you could wrap the first few steps into a function, which are declared with on or to in Applescript.
Here is the full code with some documentation sprinkled in there:
global webToCheck, theClass, num, input --This says that all variables can be used even in functions.
set webToCheck to "youtube.com" --Strings can only use double quotes.
set theClass to "style-scope yt-alert-with-actions-renderer" --I will use an actual demo to prove that it is working
set num to 0 as integer -- This is the type declaration I was talking about. For numbers we have integer, real(float) and number.
set input to "" -- You don't have define everything at the top, but I will do so for this.
on displayNotification()
tell application "Safari"
tell window 1 -- This will target only the first window. For multiple windows you would have to write a repeat with-loop(for-loop), which I'm not going to do, for the sake of simplicity.
tell (first tab whose URL contains webToCheck) -- This targets just the first tab which contains the webToCheck variable.
set input to do JavaScript "document.getElementsByClassName('" & theClass & "')[" & num & "].innerText" -- This is the way I would go about writing the Javascript. I think you had something different in mind, but this works for my example.
display notification (paragraph 1 of input) with title webToCheck -- This displays the first line of my input since that is the relevant part. I also set a title so I doesn't just say "Script Editor"
end tell
end tell
end tell
end displayNotification
repeat 4 times -- I think this is quite obvious. Adjust this to your needs.
displayNotification()
delay 4
end repeat
Running this while having not used youtube on Safari in a while it displays this:
Note that this isn't the most elegant solution, but I think it is readable and it (hopefully) works for your needs.
I am trying to create an AppleScript that can find text on a webpage and tell me the amount of matches I received(Command + F).
I already know how to do the "Find" part:
tell application "System Events"
delay 0.5
keystroke "f" using {command down}
end tell
However, I do not know how to interpret these results, such as tell me whether there is a match, or how many matches I have.
Is there any way to do this?(If it seems a bit vague, I can be more specific)
Thanks!
I agree with #user3439894 and his sentiments about using UI scripting (that is—in this case—getting System Events to issue mouse clicks and keypresses on your behalf). Although it has its uses in other areas, it's by far and away my personal least favourite method to achieve a goal, and one of last resort.
Two very quick reasons why it can be a fragile implementation is: 1) the CmdF shortcut used to initiate the Find... menu command could change, either by your own doing, or if it were to be overridden by a systemwide shortcut that supersedes Safari's claim to it (in fact, for this reason, I would personally trigger the Find... command via the menu bar, which System Events can click on your behalf. Menu items tend not to change like shortcuts, unless regional language settings do); and 2) if Safari loses focus during the time the keypresses are issued and the search is initiated, it messes up the whole command flow in your script, and will at best give you no results, but more likely, throw an error in a later part of the script.
I'm going to demonstrate two alternative methods of searching a Safari webpage for a piece of text, and obtaining the number of times it matches throughout the whole document.
1. Safari's do JavaScript AppleScript command
Most modern web browsers have the ability to run JavaScript code inside their tabs, and Safari can too. AppleScript can take command of this very useful function, provided you give it permission to do so by going into the Develop menu of Safari and ticking Allow JavaScript from Apple Events and Allow Remote Automation (the latter of which will already be on, I'm guessing). There's another menu item called Allow JavaScript from Smart Search Field—I would advise you keep this one off, otherwise it could potentially allow naughty websites to issue commands to your computer and cause mischief.
use A : application "Safari"
set D to the front document of A
set s to "AppleScript" -- the search string
try
set n to (do JavaScript ¬
"document" & ¬
".body" & ¬
".innerText" & ¬
".match(/" & s & "/ig)" & ¬
".length;" in D) as integer -- the number of matches
on error
set n to 0
end try
To break this down: s is the search string that you would otherwise be typing into the search box. It is fed into a JavaScript command, that has the following components:
document: a reference to the Safari webpage document;
body: the body of the document, as opposed to, say, the header or the footer. It's the main bulk of the webpage that users see in front of them;
innerText: the text contained within the body of the document, free of any HTML formatting, but preserving whitespace;
match(): a method or function in JavaScript where the search string s is used to perform a search within the innerText and return an array listing all of the matches;
length: a property of the array returned by match() that reports how many elements is contains, and this equates to the number of matches found during the search.
It's all one command, which, written in full on a single line, looks like this (using the search string "AppleScript"):
document.body.innerText.match(/AppleScript/ig).length;
It returns a number, which is stored in the variable n, and that's it.
This is my favourite method that I would elect to use myself, as it's unlikely to break, and it's nice and fast.
I should point out that match() actually searches and matches using a Regular Expression. I won't go into them right now, but it means that the search string s will need to be a little careful if using any special characters:
\ [ ] { } ^ $ . | ? * + ( )
All you need to be aware of is that, if your search string uses any of these characters, you should precede it with a double-backslash \\. So, for example, if I wanted to search for "matches I received(Command + F)" (which uses (, ) and +), then I would declare my variable s as:
set s to "matches I received\\(Command \\+ F\\)"
2. Chop & Measure
This method is useful if you don't wish to enable Remote JavaScript in your browser, or simply want something that's straightforward to remember and implement off the top of your head next time.
It's simple text manipulation, using AppleScript's text item delimiters and a bit of counting:
use A : application "Safari"
set D to the front document of A
set s to "AppleScript" -- the search string
set T to text of D -- the webpage text content
set l to {initialValue:length of T, finalValue:missing value}
set the text item delimiters to s
set T to text items of T
set the text item delimiters to ""
set T to T as text
set l's finalValue to length of T
set |𝚫l| to (l's initialValue) - (l's finalValue)
set n to |𝚫l| / (length of s)
Safari has a useful AppleScript property called text, which refers to the text content of the specified document or tab (it also has another property called source that contains the HTML source of the document or tab).
Here's the breakdown:
The value of Safari's text property—which is the text content of the webpage—is stored in a variable, T;
The length of T is read and stored. This equates to the number of characters on the whole webpage;
The text item delimiters are set to the search string, s, (which does not need to worry about special characters, so don't insert unnecessary backslashes in this one). The text item delimiters basically erase all occurrences of s from within T;
Then the length of T is read again. If s found any matches in T, it means that the length of T—the number of characters—will have reduced;
It will have reduced by the number of characters in s for each match that occurred. Therefore, turning the equation round a bit, the number of matches, n, is equal to the change in length of T divided by the length of s.
There are other ways to search a webpage with AppleScript, JavaScript, bash, etc., but I think these two serve as reasonable examples of how to achieve the same goal using very different methods. I refer to them as examples, because you might need to make small adjustments to the script to cater for your own needs, such as inserting backslashes where necessary in the first example, or considering in the second how you'd handle the situation if you set s to be an empty string "" (it will throw an error, but this is easily managed).
They also both return real values for n, i.e. 11.0. It's easy to see why in the second example, but I assume it's just a type conversion between JavaScript and AppleScript in the first example (I don't know). Therefore, purely for neatness, I would then coerce the returned value into an integer as I did in the first one, so it reads 11 instead of 11.0:
set n to (...) as integer
but you don't have to.
First of all I must say that UI Scripting can be messy and unreliable. I'd suggest you find a different way to accomplish whatever the real goal is.
That said, using Safari in macOS High Sierra 10.13.3 set to this web page, the following example AppleScript code will set the variable theSearchResult to the result of the search for the word "vague":
tell application "Safari" to activate
delay 0.5
tell application "System Events"
keystroke "f" using command down
delay 0.2
keystroke "vague"
delay 0.2
set theSearchResult to (value of static text 1 of group 2 of tab group 1 of splitter group 1 of window 1 of application process "Safari")
delay 0.2
key code 53 -- # Esc
end tell
return theSearchResult
Result:
"1 match"
Note that the value of the delay commands may need to be adjusted for your system, and or additional delay commands may or may not be needed. Adjust values of and or add/remove the delay commands as appropriate.
The search result can be one of the following, Not found or an integer followed by the word match, e.g. 1 match, and possibly something else, not sure as I've not done extensive testing.
How you want to interpret the result is up to you. You could use a if statement on the theSearchResult, e.g.:
if theSearchResult contains "Not found" then
-- # Do something.
-- # Your code goes here.
else
-- # Do something else.
-- # Your code goes here
end if
Another factor to consider is how is it being searched, i.e. Starts With or Contains. I believe the default in for Safari in macOS High Sierra 10.13.3 is Starts With.
Note: The example AppleScript code is just that and does not employ any error handling and is meant only to show one of many ways to accomplish a task. The onus is always upon the User to add/use appropriate error handling as needed/wanted.
I currently have an AppleScript that reads a hardcoded plain text file, which contains a long list, into a variable, which is then read into another variable as paragraphs. The script works very well for my purposes. This is basically what I am using:
set fileHandler to (read POSIX file "/path/to/my/file.txt")
set newList to paragraphs of fileHandler
repeat with i in newList
# do stuff
end repeat
The omitted script opens a Safari location, invokes JavaScript using i as a variable on that page, writes the result to a new plain text file, closes the Safari window, then repeats. It continues until it reaches the end of the list, then outside the repeat runs a do shell script that cleans up the new text file a bit.
The trouble is that every time I want to run the script using a different list, I have to open the hardcoded file and paste in the list. I'd rather just drop any .txt file on to an Automator application that wraps around my current script.
I've tried to use "Combine Text Files" and I feel like I get pretty close but I can't quite pass in the contents of the .txt file the way I'd like. I can't pass it in the same, unless I am doing something wrong with it. And "Get Value of Variable"/"Set Value of Variable" add on an extra "Text" item to my list, which I don't understand.
Ideally, I'd like to do something like this:
set fileHandler to (read POSIX file arg) -- the dropped text file
set newList to paragraphs of fileHandler
repeat with i in newList
# do stuff
end repeat
...but it doesn't work that way, unfortunately.
I'd really rather not reinvent a whole new script if I can help it. Any suggestions would be great. Thanks.
Automator is actually not needed. Save this code in Script Editor as application (bundle) and drop files onto it.
on open theFiles
repeat with aFile in theFiles
set newList to paragraphs of (read aFile)
repeat with i in newList
# do stuff
end repeat
end repeat
end open
thanks in advance for your help.
New to Applescript.
Trying to open in Preview all files in folder and save them.
The problem is that saving pops up a dialog half the time, which requires me to sit there hitting enter.
Code:
tell application "Finder"
set fl to files of folder POSIX file "/Users/myname/Desktop/myfolder/" as alias list
end tell
repeat with f in fl
tell application "Preview"
activate
open f
# Trying to save before the window has appeared will fail.
# Note: - This assumes that NO window was initially open.
# - The code should be made more robust to eventually time out.
repeat until (count of windows) > 0
delay 0.3
end repeat
save front document
close front document
end tell
end repeat
Thank you for the help
I made several PDF files and download from different sites and I get sample of version 1.3, 1.4, 1.5, 1.7, ..but no 1.6 ! For all of them no issue.
Anyway, because I have not been able to reproduce what you have, I took different approach.
1) I have added at top of the script, a list of encoding/version list which may required special treatment (like hit return key). You can of course amend these 2 lists to manage other cases you may have.
2) I changed your script to allow the script to get encoding and version values of the pdf. This is done by using spotlight data base via shell command 'mdls'. I use it 2 times to get version and encoding characteristics. The shell command returns characters before and after the value we want to get, so I use text x thru Y to extract the encoding and the version itself.
3) if PDF version/encoding are in the list predefined which requires special treatment, then I set OKReturn to true.
4) Just after the save instruction, the script now test if OKReturn is true. then I ask the script to hit return key for you. you may have to adjust this part, for instance, it could be not only 1 return, but 2 or something else. this is something I have not been able to test, because all my pdf are working. please keep in mind that because I simulate return key, you should not use the keyboard during the script run.
based on my test, I don't think the encoding is the blocking criteria. I think the version 1.6 is.Here is the script. It includes comment to make you able to adjust it:
set CodingReturn to {"Mac OS X 10.7.3 Quartz PDFContext"}
set VersionReturn to {"1.6"}
set myFolder to choose folder
tell application "Finder"
set fl to files of myFolder as alias list
end tell
repeat with f in fl
set FVersion to do shell script "mdls -name kMDItemVersion " & quoted form of POSIX path of f
set FEncoding to do shell script "mdls -name kMDItemEncodingApplications " & quoted form of POSIX path of f
if (length of FVersion) > 21 then set FVersion to text 19 thru -2 of FVersion -- extract only version number
if (length of FEncoding) > 42 then set FEncoding to text 38 thru -4 of FEncoding -- extract only the coding
set OKReturn to ((FVersion is in VersionReturn) and (FEncoding is in CodingReturn)) -- special treatment true/false
tell application "Preview"
activate
open f
repeat until (count of windows) > 0
delay 0.3
end repeat
save front document
if OKReturn then -- we need special key to be pressed
tell application "System Events" to keystroke return
end if
close front document
end tell
end repeat
I would be very interested to get your feedback about this version.
To save without the "save as" dialog popping up, add "in f". Here "f" was the filename. You could also put in a different path.
save front document in f
I am new to applescript.
I am trying to create an Automator script app that opens a batch existing files in InDesign, finds and changes text within the file. ( I thought this would be the complicated bit but it's not it was easy)
What I'm struggling with is then saving these files in another location but using the original filenames as I need to keep the original files.
I have a script to specify a path and a filename but I need to specify the path only and use the existing filename. Is this possible?
The code I tried was this:
tell application "Adobe InDesign CS5.5"
save document 1 to "users:xxx:Desktop:"
close document 1
end tell
It doesn't seem to work for the reason that I'm not specifying a filename BUT I DON'T WANT TO! Is there a way of calling up the original filename?
I'm assuming there must be a way of doing this, as I can't see the point of a script that is specific to one particular file.
My next step is to then rename the files by replacing the last bit of the filename eg:
xxx_xxx_M6.indd to xxx_xxx_M7.indd
I know how to do this in another script but if it can be done in the above section that would be great.
If you want to use the original file name when saving, you can just pull it from the file's properties and combine it with the path you want to save to, like so:
set origName to the name of document 1 as string
save document 1 to ("your:path:here:" & origName)
EDIT: If you already have your own routine for replacing the suffix, you can just perform those operations on origName before you pass it to the save command. I'll leave my look at suffix replacement below just in case it's helpful to anyone.
As for the second part of your question, about replacing a suffix, it depends on what exactly you want to do. From your example I’m guessing you want to increment a number, which you could do with the following code:
set thePoint to the offset of "." in origName
set firstPart to (characters 1 through (thePoint - 1) of origName) as string
set fpLength to the length of firstPart
set newSuffix to ((the last character of firstPart) as number) + 1
set newName to (characters 1 through (fpLength - 1) of firstPart) & newSuffix ¬
& ".indd" as string
This takes separates the file’s name from its extension, creates a new suffix by incrementing the last character (coerced to a number) of that name by 1, and then combines the lot to form a full file name that you can then use in the save command.
The key is breaking apart the original file name, then performing operations on the parts.
Now, this currently has a few limitations: any suffix other than a single digit makes things more complicated (though not impossible), and assumes that anyone running the script has “Show all filename extensions” enabled in the Finder’s preferences (this can be worked around, though).
Wrapping everything up gives us this:
tell application "Adobe InDesign CS5.5"
set origName to the name of document 1 as string
set thePoint to the offset of "." in origName
set firstPart to (characters 1 through (thePoint - 1) of origName) as string
set fpLength to the length of firstPart
set newSuffix to ((the last character of firstPart) as number) + 1
set newName to (characters 1 through (fpLength - 1) of firstPart) ¬
& newSuffix & ".indd" as string
save document 1 to ("your:path:here:" & newName)
end tell
If you could provide some more information about the suffixes you’d intend to use I’d be happy to update my answer.
InDesign documents have 3 properties that could interests you:
name : "xxx_xxx_M6.indd"
file path : file "Macintosh HD:sourceFolder:"
full name : file "Macintosh HD:sourceFolder:xxx_xxx_M6.indd"
So, to save (& close) the open file on the desktop, with same name, you could do this :
tell application "Adobe InDesign CS5.5"
save document 1 to "users:xxx:Desktop:" & name of document 1
close document 1
end tell