AppleScript: encoding arbitrary query-string values in URLs passed to Firefox - macos

I use firefox for a long time as my only browser on Pc or Mac.
In a few words my problem: I want to create a service on mac with automator and
Applescript for quite instant translation using translate.google.com.
What works great with Safari or Chrome (below the 4 or 5 lines of script)
On run {input, parameters}
Tell application "Safari"
activate
try
Open location "https://translate.google.com/#auto/en/" & (the clipboard)
end try
end tell
end run
The same thing (script) does not work at all with Firefox, I try by different ways
To circumvent the impossible problem
On run {input, parameters}
Set theProcess to "Firefox"
Set info to {}
Set y to 0
Set x to 0
Set n to 0
Tell application "Applications / Firefox.app"
activate
Open location "http://translate.google.com/#auto/en/"
end tell
Tell application "System events"
Repeat with theProcess in (process "Firefox")
try
Set info to info & (value of (first attribute whose name is "AXWindows") of theProcess)
end try
end repeats
Set n to count of info
info
end tell
Tell application "System Events" to tell process "Firefox"
Set x to "1"
Set frontmost to true
try
Click menu item "Paste" of menu "Edit" of menu bar 1
end try
Repeat while x is "1" -
If x is "1" then
Keystroke "V" using command down
Set x to "0"
end if
end repeat
end tell
end run
By copying and pasting, the actions take place before the complete loading of the page, even by slowing down the Copy and Paste procedure.
After many observations there is a problem of formatting the text contained in the clipboard with the association of the URL, I improved this but it is not perfect yet.
tell application "Applications/Firefox.app" to activate
tell application "System Events" to tell process "Firefox"
set frontmost to true
set sentence to text of (the clipboard)
set thesentences to paragraphs of sentence
set thenewsentences to thesentences as string
set the clipboard to thenewsentences
keystroke "t" using command down
keystroke "https://translate.google.com/#auto/fr/" & (the clipboard) & return
end tell
Anyway if it works with Safari without modifying anything, the problem is at the Firefox entry, so if you can look at this problem, that would be very useful to us all.
Thank you for your attention.
Thank you for your answers.

Safari and Chrome perform the necessary encoding of reserved characters in the URL for you, but Firefox doesn't.
Therefore, you need to perform the encoding of the query-string value (the text to embed in the URL) explicitly.
The easiest (though not obvious) approach is to use perl, via a shell command, gratefully adapted from here:
# Example input that contains chars. that have special meaning in a URL ('&' and '?')
set the clipboard to "Non, Je ne regrette rien & rien ne va plus?"
# Get text from the clipboard and URL-encode it.
set encodedText to do shell script ¬
"perl -MURI::Escape -lne 'print uri_escape($_)' <<<" & quoted form of (the clipboard)
# Now it's safe to append the encoded text to the URL template.
tell application "Firefox"
activate
open location "https://translate.google.com/#auto/en/" & encodedText
end tell
The above approach works with all three browsers mentioned: Firefox, Safari, and Google Chrome.
Note:
As of (at least) Firefox v50, Firefox opens the URL in in a new tab in the current front window by default.
You can make Firefox open the URL in a new window instead, by unchecking Open new windows in a new tab instead on the General tab of Firefox's preferences.
Note, however, that this is a persistent setting that affects all URLs opened from outside of Firefox.
For an ad-hoc solution for opening in a new window that doesn't rely on changing the setting, see this answer of mine.

Hello below the service Automator with some version it is possible to encounter problems, I modified the script so that it works almost everywhere.
A frequent system error is the permission to applications to control your computer that is handled by the system preferences tab Security and Privacy, the system asks if you allow Firefox, TexEdit and others using this service for its keyboard shortcuts.
Also in Automator create service (to be General (and appear in all applications) no entry (up to Yosemite since El Capitan I saw that with Firefox for example all the services are usable), choose Execute a script Applescript paste the script below divided into 2 script or 1 script only.
on run
set Sn to ""
tell application "System Events"
set Sn to the short name of first process whose frontmost is true --here we look for and find which application to launch the service
tell process Sn
set frontmost to true
try
click menu item "Copy" of menu "Edit" of menu bar 1 -- there is used the Copier of the menu Editing of the application
end try
end tell
end tell
return the clipboard
end run
In the script following the entry is done with the contents of the Clipboard
On run {input}
on run {input}
set input to (the clipboard) -- Here we paste the contents of the Clipboard into a variable
try
set input to do shell script "Perl -MURI :: Escape -lne 'print uri_escape ($ _)' <<< " & quoted form of input --To format the text to make it usable with Firefox and the url of translate.google.com
tell application id "org.mozilla.firefox"
activate
open location "https://translate.google.com/#auto/en/" & input --here since version 50 of Firefox you must open a tab and not a new url window of translate.google.com, with option #auto automatic detection by google of the language, and fr to translate into French (these options are modifiable at will)
end tell
end try
end run -- end of the operation you have a tab open on translate, a text to translate and a translated text

Related

How can I copy result from Calculator.app to the clipboard using AppleScript

How do I copy the result of the Calculator.app including decimals.
By defaults is selected, so if you just do a CMD+C it copies it into your clipboard. I got this code from #jweaks
set the clipboard to {?????}
I tried entering many different options but I don't know what I should put.
How do I copy the result of the Calculator.app including decimals.
set the clipboard to {?????}
As you already know ⌘C can do it, however, if you want to use a set clipboard to method, then here is one way to go about it:
Example AppleScript code:
if not running of application "Calculator" then return
tell application "System Events" to ¬
set the clipboard to ¬
(get the value of ¬
static text 1 of ¬
group 1 of ¬
window 1 of ¬
process "Calculator")
Notes:
Does not require Calculator to be frontmost.
Does not require the use of keystroke or key code to accomplish the task.
Can set the value to a variable instead of the clipboard, if wanting to process it in a different manner.
The example AppleScript code, shown below, was tested in Script Editor under macOS Catalina and macOS Monterey with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.
1 Assumes necessary and appropriate settings in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.
In testing, the Replies pane in Script Editor returned, e.g.,:
tell application "System Events"
get value of static text 1 of group 1 of window 1 of process "Calculator"
--> "6200.549407114624506"
set the clipboard to "6200.549407114624506"
end tell
Then when pasting into a document it pasted as: 6200.549407114624506
Update to address comments
To address the ensuing comments by sebseb under my answer and specifically…
Is it possible to run the script every time I hit enter on Calculator? then copy the result.
Basic vanilla AppleScript is not that intelligent and does not have the ability in of and by itself to understand what one is doing in Calculator and know when one has pressed the enter key to then place the result on the clipboard.
One would have to use an intermediary, an application like Hammerspoon, where it can wait for the Calculator application being activated/deactivated or its window being focused/unfocused to then enabled/disable trapping the enter key being pressed on the keyboard to then run the script to perform an action to calculate the result by pressing the = key then copy the result to the clipboard.
This works because pressing the = key in Calculator is equivalent to pressing the enter key, thus enabling trapping the enter key to perform the necessary actions using AppleScript. It quite possibly can be done without using AppleScript and just Lua, the language used by Hammerspoon and its API. However, since I already use various AppleScript scripts in conjunction with Hammerspoon and can easily recycle some existing code I'll present an addendum to the original answer using both methods in Hammerspoon.
The following example Lua code and API of Hammerspoon is placed in the ~/.hammerspoon/init.lua file.:
-- Create a hotkey used to trap the enter key and disable it.
-- It will then be enabled/disabled as Calculator is focused/unfocused
-- When enabled and the enter key is pressed it runs the AppleScript script.
local applicationCalculatorEnterHotkey = hs.hotkey.bind({}, "return", function()
local asFile = "/.hammerspoon/Scripts/CalculatorResultToClipboard.applescript"
local ok, status = hs.osascript.applescriptFromFile(os.getenv("HOME") .. asFile)
if not ok then
msg = "An error occurred running the CalculatorResultToClipboard script."
hs.notify.new({title="Hammerspoon", informativeText=msg}):send()
end
end)
applicationCalculatorEnterHotkey:disable()
-- One of two methods of watching Calculator.
--
-- The other is below this one and commented out.
-- Initialize a Calculator window filter.
local CalculatorWindowFilter = hs.window.filter.new("Calculator")
-- Subscribe to when the Calculator window is focused/unfocused.
CalculatorWindowFilter:subscribe(hs.window.filter.windowFocused, function()
-- Enable hotkey when Calculator is focused.
applicationCalculatorEnterHotkey:enable()
end)
CalculatorWindowFilter:subscribe(hs.window.filter.windowUnfocused, function()
-- Disable hotkey when Calculator is unfocused.
applicationCalculatorEnterHotkey:disable()
end)
-- Alternate method to wait for Calculator and enable/disable the hotkey.
--
-- Uncomment below method and comment the above method to test between them. Adding the
-- multiple line opening '--[[' and closing '--]]' to above method and removed from below,
-- leaving 'local CalculatorWindowFilter = hs.window.filter.new("Calculator")' uncommented.
--[[
function applicationCalculatorWatcher(appName, eventType, appObject)
if (eventType == hs.application.watcher.activated) then
if (appName == "Calculator") then
-- Enable hotkey when Calculator is activated.
applicationCalculatorEnterHotkey:enable()
end
end
if (eventType == hs.application.watcher.deactivated) then
if (appName == "Calculator") then
-- Disable hotkey when Calculator is deactivated.
applicationCalculatorEnterHotkey:disable()
end
end
end
appCalculatorWatcher = hs.application.watcher.new(applicationCalculatorWatcher)
appCalculatorWatcher:start()
-- appCalculatorwWatcher:stop()
--]]
The following example AppleScript code is used in conjunction with Hammerspoon and is saved as CalculatorResultToClipboard.applescript in ~/.hammerspoon/Scripts/, and you'll need to create the hierarchical folder structure.
Example AppleScript code:
One can use either:
tell application "Calculator" to activate
tell application "System Events"
key code 24
delay 0.5
set the theResult to the value of static text 1 of group 1 of window 1 of process "Calculator"
end tell
set the clipboard to theResult
Or:
tell application "Calculator" to activate
tell application "System Events"
key code 24
delay 0.5
key code 8 using command down
end tell
To accomplish the task.
An alternate option, as previously mentioned, is to forgo the use of AppleScript and use the following example Lua code:
local applicationCalculatorEnterHotkey = hs.hotkey.bind({}, "return", function()
-- Press the '=' key to finish the calculation.
hs.eventtap.keyStroke({}, "=")
-- Copy the result to the clipboard.
hs.eventtap.keyStroke({"cmd"}, "C")
end)
applicationCalculatorEnterHotkey:disable()
This function would be used instead of the same function further above. It replaces the execution of the AppleScript script with keystrokes generated by Hammerspoon to accomplish the same tasks, while using the remaining example Lua code and the API of Hammerspoon already presented.
Notes:
With the example Lua code, as coded, the behavior of pressing the enter key is only trapped and modified to trigger the example AppleScript code, or if using the alternate option send Hammerspoon keystrokes, while Calculator has focus. The enter key should work normally in all other applications.
See my other Hammerspoon related answers for instructions to install it and utilize the information contained herein.
One in particle is:
A: How can I make preview stop wrapping around when paging?
If using Script Editor, the example AppleScript code is saved as Text in the File Format: pop-up menu in the Save dialog box.
The example Lua code and API of Hammerspoon and AppleScript code, shown directly above, were tested respectively with Hammerspoon and Script Editor under macOS Mojave and macOS Catalina with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.
1 Assumes necessary and appropriate settings in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.
Calculator.app doesn't have an AppleScript dictionary.
You have to script the UI with System Events
tell application "System Events"
tell process "Calculator"
set frontmost to true
keystroke "c" using command down
end tell
end tell

Applescript alter text on clipboard

I have written an AppleScript to automate my work setup and just need the final touch. I copy something to clipboard in my script; I need to edit the text I copied to leave only the last line (preferably without opening an actual text editor application, as this would clutter my workspace) and just paste that line in the Google Chrome browser.
In the last step of my script so far I do something causing message text to be output to Terminal. Then I get the text visible in Terminal to be copied to the clipboard as follows:
tell application "Terminal"
tell front window
set the clipboard to contents of selected tab as text
end tell
end tell
Now I can for example paste it, and it's something like
...
[I 15:03:31.259 LabApp] Serving notebooks from local directory: /workspace
[I 15:03:31.259 LabApp] The Jupyter Notebook is running at:
[I 15:03:31.259 LabApp] http://1fw5c518af9:1932/?token=5e6d97b348fsy734gd
[I 15:03:31.259 LabApp] or http://88.0.0.1:1932/?token=5e6d97b348fsy734gd
[I 23:56:47.798 LabApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 23:56:47.803 LabApp]
To access the notebook, open this file in a browser:
file:///root/.local/share/jupyter/runtime-open.html
Or copy and paste one of these URLs:
http://1fw5c518af9:1932/?token=5e6d97b348fsy734gd
or http://88.0.0.1:1932/?token=5e6d97b348fsy734gd
This always ends with text of the format or *URL*, e.g. in the above example it would be or http://88.0.0.1:1932/?token=5e6d97b348fsy734gd. This is separated from the line above by a line delimiter plus some trailing white-space before "or".
What I need to do is grab that URL, start a Google Chrome browser and paste it in there.
For opening Google Chrome, it should be simple enough, the following code (from this tut) takes you to Instagram:
tell application "Google Chrome" to activate
tell application "System Events"
key code 37 using command down
delay 0.5
keystroke "https://www.instagram.com/instagram"
delay 1
key code 36
delay 1
end tell
and literally all I need is something which edits what's on the clipboard to just the *URL* (in the case of the above example, just http://88.0.0.1:1932/?token=5e6d97b348fsy734gd). After that I can paste it from the clipboard (where Instagram is typed in, in the tutorial).
After trying the lovely answer by #user3439894 below I found the situation is a bit more complicated:
there are an unpredictable number of blank lines "" after the final
link.
I'm also wondering whether there may be white-space at the end
as well
I already know the form of http://88.0.0.1 (it's always consistently this) so is there a way of maybe searching for that and then just grabbing it with the rest of the link that follows? (it would be great to be able to delimit the end by either " " or new-line)
Edit 2:
In case http://88.0.0.1... occurs multiple times, we would like to select just one of these URLs - they are probably generally the same, but selecting the last would be safest.
What I need to do is grab that URL, start a Google Chrome browser and paste it in there.
&
This always ends with text of the format or *URL*, e.g. in the above
example it would be or http://88.0.0.1:1932/?token=5e6d97b348fsy734gd. This is separated
from the line above by a line delimiter plus some trailing white-space
before "or".
&
In case http://88.0.0.1... occurs multiple times, we would like to
select just one of these URLs - they are probably generally the
same, but selecting the last would be safest.
If what you are trying to do is get the last URL that starts with http://88 from the contents of the selected tab of the front window in Terminal, then here is a way to do it without using the clipboard, and open it in Google Chrome, and also do it without having to use UI Scripting.
In other words, no need to alter the text on the clipboard or keystroke the URL as you can just tell Google Chrome what to use for the URL.
Example AppleScript code:
tell application "Terminal" to ¬
set theTextFromTerminal to ¬
the contents of ¬
the selected tab of ¬
the front window ¬
as text
set theURL to ¬
the last paragraph of ¬
(do shell script ¬
"grep -o 'http://88.*$' <<< " & ¬
theTextFromTerminal's quoted form & ¬
"; exit 0")
if theURL is "" then return
if theURL does not start with ¬
"http://88." then return
tell application "Google Chrome"
activate
delay 1
if exists front window then
make new tab at ¬
end of front window ¬
with properties {URL:theURL}
else
set URL of ¬
the active tab of ¬
(make new window) to theURL
end if
end tell
Note: The example AppleScript code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.

How to select file using AppleScript in Finder prompt?

I am working with Selenium on macOS to automate sending images using WhatsApp web in Google Chrome. The task involves uploading the image, and for that a system(Finder) prompt comes up to select the file. It's done in Windows using AutoIt.
I tried looking up how to automate this task in macOS, and I believe AppleScript can be used for it. Since I have no experience in GUI scripting, any help would be appreciated.
Thanks.
I was able to find the answer on another post on Stack Overflow. I have added the answer for anyone who comes across the same problem.
tell application "System Events"
keystroke "G" using {command down, shift down}
delay 1
keystroke "/path/to/file"
delay 1
keystroke return
delay 1
keystroke return
delay 1
end tell
I don't advocate GUI scripting any more than the burning down of the Amazon, but it seems to be necessary for this task, and I wanted to provide you with an example of a GUI script that tries its best to minimise the unpleasantness of the user experience, and aim for fewer weak points in the code where GUI scripts are most likely to falter.
If you know the path to your file—which I assume you do in these sorts of situations, as your script keystrokes the filepath—then you might find the following technique saves a few steps, and feels a bit more graceful in how it gets executed:
set filepath to "/path/to/image.jpg"
-- Copy file object to clipboard
set the clipboard to filepath as «class furl»
-- Make sure Chrome is in focus and the
-- active tab is a WhatsApp tab
tell application id "com.google.Chrome"
activate
if the URL of the active tab in the front window ¬
does not contain "web.whatsapp.com" then return
end tell
-- Paste the clipboard contents
-- and hit return (send)
tell application id "com.apple.SystemEvents"
tell (process 1 where it is frontmost) to tell ¬
menu bar 1 to tell menu bar item "Edit" to tell ¬
menu 1 to tell menu item "Paste" to set Paste to it
if (click Paste) = Paste then keystroke return
end tell
The if (click Paste) = Paste check should negate the need for a delay, as it explicitly forces AppleScript to evaluate the click command before going on to issue a keystroke. However, I can't test this under all possible conditions, and if there are other factors, like CPU usage, or process freezes, that are likely to give the script a chance to jump ahead, then just insert a small delay after then and move keystroke return down onto its own line.
If you wish to remove the file object from the clipboard afterwards, then simply add as the final line set the clipboard to (and just leave it blank after the word "to", which will clear the clipboard's contents). Of course, this won't affect any clipboard history data you might have if you use a clipboard managing app, only the system clipboard's current item.

using applescript in textwrangler to send code to julia

I am trying to setup a TextWrangler script that automatically sends selected code to Julia. Copying a bit from a similar script that does the job for sending code to R I tried the script
tell application "TextWrangler"
set the_selection to (selection of front window as string)
if (the_selection) is "" then
set the_selection to line (get startLine of selection) of front window as string
end if
end tell
tell application "Julia-0.2.1"
activate
cmd the_selection
end tell
It does not work. Probably because of the line containing "cmd the_selection". Anyone a suggestion on how to fix this?
Well if Julia isn't scriptable as #khagler says, then you can usually use gui scripting. This will work as long as Julia has an edit menu and the keyboard shortcut for paste is cmd-v (like in most applications) and your cursor is placed in the proper location for the paste to work. Good luck.
tell application "TextWrangler"
set the_selection to (selection of front window as string)
if (the_selection) is "" then
set the_selection to line (get startLine of selection) of front window as string
end if
end tell
set the clipboard to the_selection
tell application "Julia-0.2.1" to activate
delay 0.2
tell application "System Events" to keystroke "v" using command down
EDIT: I see in your comments that a new Julia window opens every time the script is run. That might be happening because of the line... tell application "Julia" to activate. You might try this line of code in its place. It's another method to bring Julia frontmost before issuing the keystroke commands.
tell application "System Events" to tell process "Julia-0.2.1" to set frontmost to true
Note that if this doesn't bring the Julia window frontmost then it's because the process name is wrong. Sometimes the process name is different than the application name. If true you'll have to figure out the name of the Julia process which you can do by running this and finding its name. You may have to use "Terminal" if Julia runs in a Terminal window.
tell application "System Events" to return name of processes
Julia is not scriptable, so you won't be able to send your code this way. You could try this:
do shell script "julia -e '" & the_selection & "'"
This is equivalent to typing a command into a Terminal window. Depending on what exactly is in your selection, you might need to save it as a file first and then pass the file path instead. Also, note that if julia is not in your path (as would be the case if you just copied the Julia app to your Applications folder) you'll need to specify the full path to the actual executable within the .app package: /Applications/Julia-0.2.1.app/Contents/Resources/julia/bin/julia.

How to get name of frontmost app with AppleScript and use it to get the filepath

What I try to do:
When I'm in one of my text editors (TextEdit, Byword, FoldingText) I want this AppleScript to display the file path.
I figured asking for the frontmost window app get's me the apps name nice and easily and then I can ask for the POSIX path in the next step.
The Problem:
The script is already 99% there, but I'm missing something. When I try to use the variable of activeApp it doesn't work and I get this error:
Error Number:System Events got an error: Can’t get application {"TextEdit"}.
-1728
Here's the script:
tell application "System Events"
set activeApp to name of application processes whose frontmost is true
--This doesn't work either:
--do shell script "php -r 'echo urldecode(\"" & activeApp & "\");'"
tell application activeApp
set myPath to POSIX path of (get file of front document)
end tell
display dialog myPath
end tell
If I exchange activeApp with "TextEdit" everything works. Help would be appreciated.
Maybe there's something in here that helps: Get process name from application name and vice versa, using Applescript
Either get the path property of a document or use System Events to get value of attribute "AXDocument":
try
tell application (path to frontmost application as text)
(path of document 1) as text
end tell
on error
try
tell application "System Events" to tell (process 1 where frontmost is true)
value of attribute "AXDocument" of window 1
end tell
do shell script "x=" & quoted form of result & "
x=${x/#file:\\/\\/}
x=${x/#localhost} # 10.8 and earlier
printf ${x//%/\\\\x}"
end try
end try
The first method didn't work with Preview, TextMate 2, Sublime Text, or iChm, and the second method didn't work with Acorn. The second method requires access for assistive devices to be enabled.
You are asking for...
set activeApp to name of application processes whose frontmost is true
Notice "processes", that's plural meaning you can get several processes in response so applescript gives you a list of names. Even though only one application is returned it's still in list format. Also see that your error contains {"TextEdit"}. The brackets around the name mean it's a list, so the error is showing you the problem.
You can't pass a list of names to the next line of code. As such you have a couple of choices. 1) you can ask for only 1 process instead of all processes. That will return a string instead of a list. Try this code...
set activeApp to name of first application process whose frontmost is true
2) you can work with the list by using "item 1 of the list". Try this code...
set activeApps to name of application processes whose frontmost is true
set activeApp to item 1 of activeApps
Finally, you shouldn't be telling system events to tell the application. Separate those 2 tell blocks of code. Here's how I would write your code.
tell application "System Events"
set activeApp to name of first application process whose frontmost is true
end tell
try
tell application activeApp
set myPath to POSIX path of (get file of front document)
end tell
tell me
activate
display dialog myPath
end tell
on error theError number errorNumber
tell me
activate
display dialog "There was an error: " & (errorNumber as text) & return & return & theError buttons {"OK"} default button 1 with icon stop
end tell
end try
I can't promise the "get file of front document" code will work. That depends on the application. Not all applications will understand that request. That's why I used a try block. In any case though you can be certain you are addressing the proper application. Good luck.
I've been using this snippet for a while, seems to work for all Cocoa apps (not sure about X11):
set front_app to (path to frontmost application as Unicode text)
tell application front_app
-- Your code here
end tell
None of this seems to work with a compiled AppleScript saved as an application and placed on the Dock. Whenever you run the application, IT is the frontmost, not the application that is showing its front window. That application becomes inactive as my Applescript runs. How do I write an Applescript application that isn't active when it runs?
I may have found a solution to the problem listed above. Just tell the user to reactivate the desired application, and give them time.
tell application "Finder"
activate
say "Click front window of your application"
delay 5
set myapp to get name of first application process whose frontmost is true
-- etc.
-- your code
end tell

Resources