How to close terminal window launched using Apple Script in Mac app - macos

I have a Mac application.
This app is executing following apple script using executeAndReturnError method of NSAppleScript class:
set tempDir to path to temporary items as string
set tempFilename to tempDir & "Test_Log.txt"
set tempFilePath to POSIX path of file tempFilename
set wasRunning to application "Terminal"'s running
tell application "Terminal"
if not wasRunning then
close front window saving no
end if
set mytab to do script "ls -l" & quoted form of tempFilePath
set title displays custom title of current settings of mytab to true
set custom title of current settings of mytab to "Test Log"
repeat until busy of mytab is false
delay 1
end repeat
if ((count of windows) = 1) then
quit
else
close (every window whose name contains "Test Log")
end if
end tell
When above apple script is executed by my app for the first time, terminal window remains open.
When above apple script gets executed subsequently, terminal window is closed (as expected).
Can anyone please assist me on how can I close the terminal window always.
Please note that, I want to close the terminal window that has been opened by my apple script mentioned above.
If there is already other terminal window opened (manually by user) before running above apple script, then this manually opened window should not be closed.

Related

reload Terminal preferences .plist after change

I used plutil to edit the plist. then I placed in under /User/<myUsername>/Library/Preferences/com.apple.Terminal.plist. I want it to update the settings without reboot the application. How do I do this? using defaults read com.apple.Terminal doesn't seem to make the changes take effect. I added a terminal profile to the plist and want the changes to take effect.
I tried making an import profile with AppleScript but long story short it's not 100% possible. if you store window 1 so it's the same var in-between delays right after open it errors more times.
on run argv
set importScript to first item of argv
set flag to application "Terminal" is not running
tell application "Terminal"
open importScript
delay 1.0E-5
activate
if flag then close back window
do script "exit" in window 1
delay 0.5
close window 1
end tell
end run
there is no need for editing plists just a simple AppleScript. the limitations of this are you must have _oti_<yourProfileId> in your terminal profile default header and change the title when running your terminal profile to prevent accidental closures when installing the same profile of an already running app
import.applescript
on run argv
set importScript to first item of argv
set closeScript to second item of argv
set profileId to third item of argv
do shell script "open -a Terminal " & importScript
do shell script "osascript " & closeScript & " _oti_" & profileId
end run
closeMe.applescript
on run argv
set c to first item in argv
tell application "Terminal"
set wList to every window
repeat with app_window in wList
set wname to name of app_window
if wname contains c then
do script "exit" in app_window
delay 0.312
close app_window
end if
end repeat
end tell
end run
and then you can call the profile using this AppleScript
on run argv
set flag to application "Terminal" is not running
set scpt to first item in argv
set n to second item in argv
set p to third item in argv
tell application "Terminal"
set newTab to do script scpt
set badFlag to back window is equal to window 1
if p is not equal to "" then set current settings of newTab to settings set p
set custom title of newTab to n
activate
if flag and (not badFlag) then
do script "exit" in back window
delay 0.1
close back window
end if
end tell
end run

Applescript does not run user command

I need the applescript to run tabset test command to change the name of the current tab of iTerm.
-- Launch iTerm and log into multiple servers using SSH
tell application "iTerm"
activate
create window with default profile
set newWindow to (create window with default profile)
set Servers to paragraphs of (do shell script "/bin/cat $HOME/serverlist")
repeat with nextLine in Servers
if length of nextLine is greater than 0 then
tell current window
create tab with default profile
tell current session of newWindow
do shell script "export PATH='/usr/local/bin:$PATH'; tabset test "
end tell
end tell
end if
end repeat
tell first tab of current window
close
end tell
tell second window
close
end tell
end tell
The problem is tabset test does not work, and there is no any error prompted.
The tabset command could be installed via npm install -g iterm2-tab-set
Ted Wrigley is right. I should use iTerm's write command to type the text into the window.

Script to find active wallpaper file in Finder under macOS Catalina

I used to use two AppleScript scripts to find out the file name of the actual wallpaper image from desktop 1 and desktop 2 (dual monitor mode) under macOS Mojave. One script for the main monitor and another one for the second monitor. Under macOS Catalina the scripts are not working anymore.
Here is the script:
tell application "System Events"
set posix_path to (pictures folder of desktop 2)
set picPath to (POSIX file posix_path) as string
end tell
set thePictures to (do shell script "sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db \"SELECT data.value FROM preferences INNER JOIN data on preferences.key=16 and preferences.picture_id=7 and preferences.data_id=data.ROWID\"")
set fullPath to picPath as string
set rotationImage to fullPath & thePictures
tell application "Finder"
try
set aliasItem to item rotationImage
if class of aliasItem is alias file then
reveal original item of aliasItem
end if
end try
end tell
Here is the error message:
tell application "System Events"
get pictures folder of desktop 1
--> "/Users/peter/Library/Caches/com.apple.preference.desktopscreeneffect.desktop/69948584/DSKPhotosRootSource"
get POSIX file "/Users/peter/Library/Caches/com.apple.preference.desktopscreeneffect.desktop/69948584/DSKPhotosRootSource"
--> error number -1728 from POSIX file "/Users/peter/Library/Caches/com.apple.preference.desktopscreeneffect.desktop/69948584/DSKPhotosRootSource"
end tell
tell current application
do shell script "sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db \"SELECT data.value FROM preferences INNER JOIN data on preferences.key=16 and preferences.picture_id=1 and preferences.data_id=data.ROWID\""
--> "13725B"
end tell
tell application "Finder"
get item "Macintosh HD:Users:peter:Library:Caches:com.apple.preference.desktopscreeneffect.desktop:69948584:DSKPhotosRootSource13725B"
--> error number -1728 from item "Macintosh HD:Users:peter:Library:Caches:com.apple.preference.desktopscreeneffect.desktop:69948584:DSKPhotosRootSource13725B"
end tell
Tried to find the problem but couldn't find a solution. I am not an experienced AppleScript writer. Hope somebody can help.
On Catalina and Mojave, I'm able to get the current wallpaper by using a sqlite command similar to yours:
sqlite3 ~/Library/Application\ Support/Dock/desktoppicture.db "select * from data" | tail -2
Or in Applescript:
do shell script "sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db 'select * from data' | tail -2"
On my Mac, the last 2 items in the data table appear to be some combination of the most recently set wallpaper and last 2 displays that were most recently set, so I tail the list. Like you, I'm also using a large folder of wallpapers and I have it set to change every 30 minutes. As long as I don't manually change a wallpaper, the last 2 items are consistently the names of the 2 active wallpapers because both monitors change at the same time every 30 minutes.
Something to note: When you are using a Folder with the "Change picture:" checkbox checked, the items returned from select * data is just the file name (i.e., wallpaper.jpg). If you've set the wallpaper to a single image, the item returned from the select command is the full path of the image (i.e., /path/to/folder/wallpaper.jpg). Since I'm using a folder, so I get just the image names in my select results. Then I can split the 2 names by newline to get each wallpaper name in an array and then open them. Here's my whole script:
#!/bin/bash
#reads and opens the last 2 items from the 'data' table in the desktoppicture.db sqlite db
last_two=`sqlite3 ~/Library/Application\ Support/Dock/desktoppicture.db "select * from data" | tail -2`
IFS=$'\n' read -rd '' -a y <<<"$last_two"
#echo "first is ${y[0]}"
#echo "second is ${y[1]}"
open /Users/myusername/Pictures/Desktop\ Pictures/${y[0]}
open /Users/myusername/Pictures/Desktop\ Pictures/${y[1]}
I realize you asked an AppleScript question and this is largely a bash script answer, but the do shell script item at the top of my answer should get you going enough to be able to capture and manipulate the image names inside of AppleScript.
Just to close this out, I use this bash script in Alfred using a keyword "retire" to retire a wallpaper I'm tired of. I type the keyword, this script runs to open the images in Preview, another script runs to open my Desktop Pictures folder and a Desktop Pictures Retired folder and then I manually move the photo into the Retired folder.
If you currently have two monitors connected and you're simply looking to retrieve the names of the Desktop Wall Papers for each, this following Apple script code should be what you're looking for.
tell application "System Events"
set everyDesktop to desktops
set desktopOnePicture to picture of item 1 of everyDesktop
set desktopTwoPicture to picture of item 2 of everyDesktop
end tell
I can't guarantee the code below will fair any better than the solution already posted, but it should, in theory, target desktop images per screen (monitor) rather than by desktop (space). However, I don't have Mojave or Catalina, or a computer to test this out:
use framework "AppKit"
property NSScreen : a reference to NSScreen in the current application
property NSWorkspace : a reference to NSWorkspace in the current application
property currentScreen : a reference to the mainScreen of NSScreen
on screen(i as integer)
local i
if i = 0 then return the currentScreen()
return NSScreen's screens()'s item i
end screen
on desktopImageURLForScreen:(i as integer)
local i
set S to screen(i)
tell NSWorkspace's sharedWorkspace() to return the ¬
desktopImageURLForScreen_(S) as «class furl»
end desktopImageURLForScreen:
return the POSIX path of my desktopImageURLForScreen:0
The bottom line is the one you will most likely want to experiment with, by changing the index number passed to the handler. If you have three monitors, then they would each be identified by one of the indices 1, 2, or 3 (I can't predict how index corresponds to arrangement of monitors). Index 0 will always refer to the screen that currently has keyboard focus.

Script that launches commands on two Terminals

I need to do a .command file script/batch. Launching it (double-click) it has to to those things:
Open a terminal window (A)
Launching a command that open the folder where the file is (maybe this cd "dirname "$0"")
Launch a command
Open a terminal window (B)
Launching same command at point 2
Launch a command
Given that you explicitly want to create terminal windows, consider creating an application using AppleScript:
Open Script Editor (up to 10.9, AppleScript Editor)
Paste the code below.
Save as an application (via the pop-up list in the Save As dialog) to the desired folder.
# Determine the folder in which this app is located.
set thisFolder to do shell script "dirname " & quoted form of POSIX path of (path to me)
# Sample commands to execute in the new windows.
set cmds to {"date", "echo $$"}
tell application "Terminal"
# Create 2 new windows, change to the
# this app's folder, and execute the respective command.
repeat with i from 1 to 2
do script "cd " & quoted form of thisFolder & "; " & item i of cmds
end repeat
# Activate Terminal.app
activate
end tell
The reason that I recommend using an application over a *.command file is that the latter would itself open in a Terminal window first, before creating the desired windows, which is visually disruptive (and, depending on your Terminal.app preferences, may leave the extra window open).
Alternatively, you could turn that into a virtue and use the *.command file's own window as your 1st terminal window, and only create one additional one.

Open multiple tabs in iTerm2 with specific directories

I would like to be able execute an AppleScript command (from a file) that will open up new tabs for specific directories.
What would be the best way to do this?
Right now I have a node.js script that I loop through each dir and pass the dir to this AppleScript file:
on run arg
set p to arg's first item
set g to "cd " & p & "; clear; pwd"
tell application "iTerm"
make new terminal
tell the current terminal
activate current session
launch session "Default Session"
tell the last session to write text g
end tell
end tell
end run
However, that is not doing what I like (it opens the right amount of tabs, but the last one gets everything written to it).
BONUS: if you can show me how to make the original tab active after opening all the tabs.
tell application "iTerm"
if exists current terminal then
set t to current terminal
else
set t to make new terminal
end if
tell (launch session "Default Session") of t to write text "cd /etc;clear;pwd"
tell (launch session "Default Session") of t to write text "cd /var;clear;pwd"
activate
end tell

Resources