How to convert window object to string in AppleScript? - macos

I've an AppleScript that retrieves window id of an app.
Example following script retrieves the window id of Brave Browser.
set urls to {"https://google.com"}
tell application "Brave Browser"
set myNewWindow to make new window
repeat with theURL in urls
tell myNewWindow to open location theURL
end repeat
delay 0.3
log myNewWindow
return class of myNewWindow //comment - returns "window" as a class
end tell
My goal is it possible to convert the window id to a string and vice-versa.
Why conversion?
I want to save window id in UserDefaults on macOS.
Note: This AppleScript is used in macOS app.

To be honest, it's hard for me to understand why the ID should be kept in defaults. Because theID variable will already store this value throughout the script. And at any time you can close the window using a variable in a later part of the script. I can only assume one thing: you want to open a window locally and then close it from other script executed on a remote machine.
And getting the window ID in Brave Browser as text is easy:
set urls to {"https://google.com"}
tell application "Brave Browser"
set myNewWindow to make new window
repeat with theURL in urls
open location theURL
end repeat
delay 0.3
set theID to (id of myNewWindow) as text --> the ID of window in text form
end tell
-- write theID value to defaults here
Closing the window from other script:
-- first, read theID from defaults here
tell application "Brave Browser"
close window id (theID as integer)
end tell

Related

How to launch an iTerm2 profile only once (via AppleScript)

I would like to create an Apple Script which launches an iTerm2 profile exactly once. If a session of this profile is already running, the corresponding window should be focused, otherwise a new session should be launched.
My idea for the implemantation so far is
loop through all windows of iTerm2 and check their name
if the name matches the profile name, focus the window
if none of the names matches the profile name, launch a new session with this profile
However, I haven't managed to loop over the windows and check their names against a predefined string.
After a lot of trial an error, I finally figured it out. The script below takes the name of the profile as the argument and does what I described in the question.
on run argv
set isopen to false
set targetName to (item 1 of argv)
tell application "iTerm2"
repeat with w in windows
set wn to name of w
if wn = targetName then
set isopen to true
tell application "System Events"
perform action "AXRaise" of window (index of w) of process "iTerm2"
end tell
activate
exit repeat
end if
end repeat
if not isopen then
create window with profile targetName
end if
end tell
end run

Is it exit way to close all tabs with CURRENT site in Safari?

As an active browser user, I want to be able to close all tabs related only to a particular site after I have finished the project or finised with current site.
I know there are shortcuts that can quickly close all tabs
- tabs other than current
- web browser
- current window
- etc
But there is no way to close only the desired site.
Is it possible to quickly close only the current site Using
browser or
the terminal with AppleScript or BetterTouchTool
This script closes every tab in every window of Safari that has the same domain as the current tab:
tell application "Safari"
tell window 1
set theURL to URL of current tab
end tell
set theDomain to my domainOfURL(theURL)
set windowList to every window
repeat with aWindow in windowList
tell aWindow
close (every tab whose URL begins with theDomain)
end tell
end repeat
end tell
on domainOfURL(aURL)
set tid to my text item delimiters
set my text item delimiters to "/"
set theDomain to text items 1 through 3 of aURL as text
set my text item delimiters to tid
return theDomain
end domainOfURL

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

How to open a new window and multiple urls in Safari with apple script?

How do you open a new window in safari and then open multiple tabs with different urls in that window using apple script?
The way to create a new window in Safari is to use the make new document command:
make new document at end of documents with properties {URL:the_url}
This will create a new window with a single tab pointing to the_url and make that window frontmost. Note that make new window at end of windows doesn't work, and just errors out with "AppleEvent handler fails".
Similarly, to create a new tab within a window w, you can use make new tab:
make new tab at end of tabs of w with properties {URL:the_url}
This will create a new tab in window w at the end of the list of tabs; this tab will be pointing to the_url, and it won't be the current tab. Instead of explicitly saying tabs of w, you can also use a tell w block:
tell w
make new tab at end of tabs with properties {URL:the_url}
end tell
That way, tabs implicitly refers to tabs of w.
Putting this all together, we get the following script. Given a list of URLs in the_urls, it will open all of them in a new window; if the_urls is empty, it opens a window with a blank tab.
property the_urls : {¬
"http://stackoverflow.com", ¬
"http://tex.stackexchange.com", ¬
"http://apple.stackexchange.com"}
tell application "Safari"
if the_urls = {} then
-- If you don't want to open a new window for an empty list, replace the
-- following line with just "return"
set {first_url, rest_urls} to {"", {}}
else
-- `item 1 of ...` gets the first item of a list, `rest of ...` gets
-- everything after the first item of a list. We treat the two
-- differently because the first item must be placed in a new window, but
-- everything else must be placed in a new tab.
set {first_url, rest_urls} to {item 1 of the_urls, rest of the_urls}
end if
make new document at end of documents with properties {URL:first_url}
tell window 1
repeat with the_url in rest_urls
make new tab at end of tabs with properties {URL:the_url}
end repeat
end tell
end tell
tell application "Safari"
activate
set the URL of document 1 to "http://www.XXXXXXX.com"
my new_tab()
set the URL of document 1 to "http://www.XXXXXX.com"
end tell
on new_tab()
tell application "Safari" to activate
tell application "System Events"
tell process "Safari"
«event prcsclic» «class menI» "New Tab" of «class menE» "File" of «class mbar» 1
end tell
end tell
end new_tab
Replace the X's with whatever sites you want and keep repeating the code (my new_tab() and set the URL... lines) for each page you'd like to have open.
Referring to this page.
Correct me if this isn't what you were talking about.
Base on Pugmatt's answer I got the following to work...
on run {input, parameters}
tell application "Safari"
activate
make new document with properties {URL:"http://www.apple.com"}
my new_tab()
set the URL of document 1 to "http://www.example.com"
end tell
end run
on new_tab()
tell application "Safari" to activate
tell application "System Events"
tell process "Safari"
«event prcsclic» «class menI» "New Tab" of «class menE» "File" of «class mbar» 1
end tell
end tell
end new_tab
I'm not sure if this is the most efficient way of you this.

Applescript studio - how do I get every control in a window

I'm trying to enable or disable all the control in a window as the programme changes from interactive to non-interactive mode. How can I ask a window to give me all its contents?
every control of window "mainWindow"
doesn't work, nor does
contents of window "mainWindow"
Actually, I haven't been able to find any good documentation for interacting with menu items from interface builder at all. Things like how to set the contents of popups, and buttons and so on.
thanks
The way I do it at the moment is:
property onlineControls: {"maxLength", "speed", "accelerationSlider", "accelerationField", "showInfo"} --and so on, listing all the controls by name
on enableControls(theList, enableState)
tell window "mainWindow"
repeat with theControl in theList
set the enabled of control theControl to enableState
end repeat
end tell
enableControls(onlineControls, true)
I've made several lists of controls tht get turned on or off depending on the state the programme is in. But it has to be hard coded, which I don't see as being the best way.
tell application "System Events"
tell process "Adium"
get entire contents of window 1
end tell
end tell
This script will give you as result all contents of front window of Adium: butons of window, tool bars of window, buttons of tool bars, etc. Enjoy =]
I haven't been able to find a way to get all the controls in a window, but here's an example of interacting with the menu of a popup button:
tell menu of popup button "somePopupButton" of window "mainWindow"
delete every menu item
repeat with i in someItems
make new menu item at end of menu items ¬
with properties {title:i, enabled:true}
end repeat
end tell
Is the same script as "BoB1990" with the possibility of getting back the information given by get entire contents of window in a string of whom you can observe or modify all the items listed :
tell application "System Events" to tell process "Adium"
set this_info to {}
try
display alert ((get entire contents of window (x as integer)))
on error errMsg set theText to errMsg
set this_info to do shell script " echo " & theText & " | sed 's#System Events got an error: Can’t make ##g;s# into type string.##g'"
end try
set info to {}
set info to do shell script " echo " & this_info
display alert (info)
end tell

Resources