如何通过ScriptingBridge使用AppleScript获取终端窗口的窗口ID和标签号?

时间:2010-04-26 10:26:42

标签: cocoa applescript appleevents scripting-bridge

我可以使用以下AppleScript打开终端标签:

tell application "Terminal"
    set myTab to do script "exec sleep 1"
    get myTab
end tell

这会返回一个字符串,如:tab 1 of window id 3263 of application "Terminal"。这很棒,我可以看到窗口id 3263 和标签号 1 (虽然我不知道如何只查询 myTab 这些价值观。)

在Cocoa ScriptingBridge中,我可以这样做:

SBApplication  *terminal;
SBObject       *tab;

terminal = [SBApplication applicationWithBundleIdentifier:@"com.apple.terminal"]
tab = [terminal doScript:@"exec sleep 1" in:nil]

如何从标签对象中获取窗口ID和标签号?


编辑2009/4/27 - 为什么?

为了回答我为什么要这样做 - 我在终端窗口中打开一个命令(如上所述),然后回到 tab 对象。但是我想移动/调整此窗口的大小,所以我需要访问选项卡的“窗口”对象。

我正在使用Objective-C(实际上,从Perl桥接的Objective-C),并希望坚持使用标准的OS组件,因此我相信我只能使用NSAppleScript和ScriptingBridge框架(所有perl applescript模块)打破64位碳去除)。我会尝试NSAppleScript,但处理返回的值似乎是黑色的。

我目前的解决方案是获取标签对象的 TTY (保证唯一)并枚举每个窗口的每个标签,直到找到包含标签的窗口。我认为这不是最好的方法(肯定不是很快!)。


编辑2009/4/30 - 解决方案

根据下面“has”的建议,我冒了NSAppleEventDescriptor API。最初,我只能通过NSAppleScript的executeAndReturnError()调用来实现这一目标。但是我发现NSAppleScript比ScriptingBridge慢得多。

使用ClassDump提取更多SBObject调用后,我找到了未记录的specifierDescription()qualifiedSpecifier()调用。前者给了我很好的“窗口ID Y ”字符串的“选项卡X”。后者返回apple事件描述符,然后我可以解码。

我的最终代码(在perl中)是:

use Foundation;

NSBundle->bundleWithPath_('/System/Library/Frameworks/ScriptingBridge.framework')->load;

# Create an OSType (bid endian long) from a string
sub OSType ($) { return unpack('N', $_[0]) }

my $terminal = SBApplication->applicationWithBundleIdentifier_("com.apple.terminal");

my $tab         = $terminal->doScript_in_("exec sleep 1", undef);
my $tab_ev_desc = $tab->qualifiedSpecifier;
my $tab_id      = $tab_ev_desc->descriptorForKeyword_(OSType 'seld')->int32Value;
my $win_ev_desc = $tab_ev_desc->descriptorForKeyword_(OSType 'from');
my $window_id   = $win_ev_desc->descriptorForKeyword_(OSType 'seld')->int32Value;

print "Window:$window_id Tab:$tab_id\n";

3 个答案:

答案 0 :(得分:3)

我知道这是一个老问题,但我今天遇到了这个问题,我在网上找不到好的答案。这对我有用:

tell application "Terminal"
    set newTab to do script "echo hello"
    set theWindow to first window of (every window whose tabs contains newTab)
    set windowId to theWindow's id
    repeat with i from 1 to the count of theWindow's tabs
        if item i of theWindow's tabs is newTab then set tabNumber to i
    end repeat
    get {windowId, tabNumber}
end tell

答案 1 :(得分:1)

技术上你不能;一个更好的问题是为什么要这样做?

(好吧,你可以使用Apple Event Manager API或objc-appscript,这两者都可以为你提供原始的AEDesc / NSAppleEventDescriptor,你可以递归pull apart yourself。或者你可能会戳在SB附近,看看是否有一个未记录的API来获取底层的AEDesc,当然还有一些警告。或者,可能有更好的方法来实现你的实际目标而不诉诸hackery,但你需要提供更多信息。)

答案 2 :(得分:0)

这样的事情很简单:

告诉应用程序“终端”     设置new_win来做脚本“”     将w_id设置为前窗的id 结束告诉