Amadan
Amadan

Reputation: 198324

Identifying Terminal window in AppleScript

I'm trying to make my Terminal change profiles when I run ssh. To this end, I wrote this script (and defined an alias so ssh would run it):

#!/bin/bash

osascript -e "tell application \"Terminal\" to set current settings \
of front window to first settings set whose name is \"AmadanRemote\""

/usr/bin/ssh "$*"

osascript -e "tell application \"Terminal\" to set current settings \
of front window to first settings set whose name is \"AmadanLocal\""

This almost does what I want. (It paints successive tabs in the same window wrong because profile is apparently window-wide, but I don't use tabs.) The issue is that if the connection closes while another Terminal window is on top, AmadanLocal profile will get applied to the wrong window.

Thus, the question: Is there any way to unambiguously identify the Terminal window or tab by the Terminal's tty device, or any other feature (instead of the fickle front window)?

If not, is there any identifying feature the first osascript invocation can return that would unambiguously identify the same window/tab in the second osascript invocation?

(Doesn't have to be AppleScript - if JavaScript makes it possible, JavaScript is fine, too.)

EDIT: If anyone is interested, the final shape of the script is:

#!/bin/bash

tty=`tty`

osascript <<EOF
tell application "Terminal"
    set W to the first window whose tty of tab 1 is "$tty"
    set T to tab 1 of W
    set the current settings of T to the first settings set whose name is "AmadanRemote"
end tell
EOF

/usr/bin/ssh "$*"

osascript <<EOF
tell application "Terminal"
    set W to the first window whose tty of tab 1 is "$tty"
    set T to tab 1 of W
    set the current settings of T to the first settings set whose name is "AmadanLocal"
end tell
EOF

Bonus: this actually does the right thing per each tab! <3

Upvotes: 2

Views: 3548

Answers (1)

CJK
CJK

Reputation: 6092

Yes, there is. In Script Editor, I can run this command:

tell application "Terminal" to get {properties, properties of tab 1} of window 1

This will get me all the properties of both the front window and its active tab. Here's the output:

{
    {
    selected tab:tab 1 of window id 15491 of application "Terminal",
    closeable:true,
    size:{550,777},
    zoomed:false,
    frame:{730,0,1280,777},
    index:1,
    visible:true,
    position:{730,23},
    class:window,
    origin:{730,0},
    name:"~ — fish  /Users/CK — ttys001",
    miniaturizable:true,
    frontmost:false,
    id:15491, <---------------------------------------① 
    miniaturized:false,
    resizable:true,
    bounds:{730,23,1280,800},
    zoomable:true
    },
    {
    font:"mononoki-Regular",
    title displays device name:true,
    cursor color:{64587,609,65480},
    current settings:current settings of tab 1 of window id 15491 of application "Terminal",
    title displays shell path:false,
    tty:"/dev/ttys001", <-----------------------------② 
    normal text color:{52428,52428,52427},
    title displays window size:false,
    title displays custom title:true,
    contents:"Last login: Mon Jun 18 04:54:37 on ttys001\nCK@CK-mac ~> ",
    row:39,
    process:{
        "login",
        "-fish"
        },
    clean commands:{
        "screen",
        "tmux"
        },
    font antialiasing:true,
    background color:{16383,16383,16383},
    title:"fish  /Users/CK",
    class:tab,
    title displays file name:false,
    history:"Last login: Mon Jun 18 04:54:37 on ttys001\nCK@CK-mac ~> ",
    selected:true,
    size:16,
    bold text color:{65535,65535,65535},
    busy status:false,
    column:60
    }
}

The first half of that output are the properties of the window, and the second half of the output are the properties of the tab in that same window.

I've labelled two properties of note with numbered arrows ① and ②.

Property ① belongs to the window, and it's the unique id of the window. This will be fixed and unchanging throughout the lifespan of the window. Therefore, at some point in your script, store the id of the front window in a variable, and reference the window through that:

tell application "Terminal"
    set wID to the id of the front window
    set visible of window id wID to false
end tell

In fact, you needn't bother with referencing the id at all if you choose to store the actual window object in a variable instead of its id:

tell application "Terminal"
    set W to the front window
    set visible of W to false
end tell

As the window object is referenced by AppleScript through the window's id value, it is equally as reliable and unchanging to do it that way.

From the list of available properties for a window, I don't see a current settings property. There is, however, a current settings property for the tab. I know you don't use tabs, but in AppleScript, each tab of Terminal in fact only belongs to one window, in a really counter-intuitive tab-window relationship.

So, a window containing three tabs should, you would expect, have an AppleScript reference to a single window object and three tab objects. Referring to them by index (which can change, so is not a good way to reference them in code), you would expect there would be tab 1 of window 1, tab 2 of window 1 and tab 3 of window 1. Instead, what you get is tab 1 of window 1, tab 1 of window 2, and tab 1 of window 3.

I have no idea why it's been implemented like that. But, essentially, the tab object and window object can seem to refer to the same framed interface that you see on screen, wishing to call it a window when in fact it might be, for certain purposes, the tab.

current settings is one of those times when you might think you're wanting to set it for the window, but you actually want to set it for the tab.

Tabs have a property, as you were hoping, called tty, which is a string value identifying the terminal that tab is using. In my case, it was "/dev/ttys001". However, as I explained just now, each window object actually only ever contains a single tab object from AppleScript's strange point-of-view. So referencing the tab is simple if you have a reference to the window containing it: it'll always be tab 1 of window id wID or tab 1 of W, however you stored your variable earlier.

But the tty property belonging to the tab can be used to reference its containing window, meaning if you know what terminal you're in, you'll always be able to identify and reference the correct tab in the correct window. And you do it like this:

tell application "Terminal"
    set W to the first window whose tty of tab 1 contains "ttys001"
    set T to tab 1 of W
    set the current settings of T to the first settings set whose name is "AmadanLocal"
end tell

Upvotes: 5

Related Questions