如何使用 Perl 中的 OS-X ScriptingBridge 框架关闭窗口?

发布于 2024-08-28 16:41:45 字数 2687 浏览 5 评论 0原文

问题...

自从MacPerl 不再支持 64 位 perl,我正在尝试替代框架来控制 Terminal.app。

我正在尝试 ScriptingBridge,但遇到了使用 PerlObjCBridge

我想打电话:

typedef enum {
    TerminalSaveOptionsYes = 'yes ' /* Save the file. */,
    TerminalSaveOptionsNo = 'no  '  /* Do not save the file. */,
    TerminalSaveOptionsAsk = 'ask ' /* Ask the user whether or not to save the file. */
} TerminalSaveOptions;

- (void) closeSaving:(TerminalSaveOptions)saving savingIn:(NSURL *)savingIn;  // Close a document.

尝试的解决方案...

我已经尝试过:

#!/usr/bin/perl

use strict;
use warnings;
use Foundation;

# Load the ScriptingBridge framework
NSBundle->bundleWithPath_('/System/Library/Frameworks/ScriptingBridge.framework')->load;
@SBApplication::ISA = qw(PerlObjCBridge);

# Set up scripting bridge for Terminal.app
my $terminal = SBApplication->applicationWithBundleIdentifier_("com.apple.terminal");

# Open a new window, get back the tab
my $tab = $terminal->doScript_in_('exec sleep 60', undef);
warn "Opened tty: ".$tab->tty->UTF8String; # Yes, it is a tab

# Now try to close it

# Simple idea
eval { $tab->closeSaving_savingIn_('no  ', undef) }; warn $@ if $@;

# Try passing a string ref
my $no = 'no  ';
eval { $tab->closeSaving_savingIn_(\$no, undef) }; warn $@ if $@;

# Ok - get a pointer to the string
my $pointer = pack("P4", $no);
eval { $tab->closeSaving_savingIn_($pointer, undef) }; warn $@ if $@;
eval { $tab->closeSaving_savingIn_(\$pointer, undef) }; warn $@ if $@;

# Try a pointer decodes as an int, like PerlObjCBridge uses
my $int_pointer = unpack("L!", $pointer);
eval { $tab->closeSaving_savingIn_($int_pointer,  undef) }; warn $@ if $@;
eval { $tab->closeSaving_savingIn_(\$int_pointer, undef) }; warn $@ if $@;

# Aaarrgghhhh....

如您所见,我对如何传递枚举字符串的所有猜测都失败了。

在你攻击我之前...

  • 我知道我可以使用另一种语言(ruby、python、cocoa)来做到这一点,但这需要翻译其余的代码。
  • 我也许可以使用 CamelBones,但我不想假设我的用户拥有它安装。
  • 我还可以使用 NSAppleScript 框架(假设我费尽心思找到选项卡和窗口 ID),但仅仅为了这一次调用就必须求助于它似乎很奇怪。

Problem...

Since MacPerl is no longer supported on 64bit perl, I am trying alternative frameworks to control Terminal.app.

I am trying the ScriptingBridge, but have run into a problem passing an enumerated string to the closeSaving method using the PerlObjCBridge.

I want to call:

typedef enum {
    TerminalSaveOptionsYes = 'yes ' /* Save the file. */,
    TerminalSaveOptionsNo = 'no  '  /* Do not save the file. */,
    TerminalSaveOptionsAsk = 'ask ' /* Ask the user whether or not to save the file. */
} TerminalSaveOptions;

- (void) closeSaving:(TerminalSaveOptions)saving savingIn:(NSURL *)savingIn;  // Close a document.

Attempted Solution...

I have tried:

#!/usr/bin/perl

use strict;
use warnings;
use Foundation;

# Load the ScriptingBridge framework
NSBundle->bundleWithPath_('/System/Library/Frameworks/ScriptingBridge.framework')->load;
@SBApplication::ISA = qw(PerlObjCBridge);

# Set up scripting bridge for Terminal.app
my $terminal = SBApplication->applicationWithBundleIdentifier_("com.apple.terminal");

# Open a new window, get back the tab
my $tab = $terminal->doScript_in_('exec sleep 60', undef);
warn "Opened tty: ".$tab->tty->UTF8String; # Yes, it is a tab

# Now try to close it

# Simple idea
eval { $tab->closeSaving_savingIn_('no  ', undef) }; warn $@ if $@;

# Try passing a string ref
my $no = 'no  ';
eval { $tab->closeSaving_savingIn_(\$no, undef) }; warn $@ if $@;

# Ok - get a pointer to the string
my $pointer = pack("P4", $no);
eval { $tab->closeSaving_savingIn_($pointer, undef) }; warn $@ if $@;
eval { $tab->closeSaving_savingIn_(\$pointer, undef) }; warn $@ if $@;

# Try a pointer decodes as an int, like PerlObjCBridge uses
my $int_pointer = unpack("L!", $pointer);
eval { $tab->closeSaving_savingIn_($int_pointer,  undef) }; warn $@ if $@;
eval { $tab->closeSaving_savingIn_(\$int_pointer, undef) }; warn $@ if $@;

# Aaarrgghhhh....

As you can see, all my guesses at how to pass the enumerated string fail.

Before you flame me...

  • I know that I could use another language (ruby, python, cocoa) to do this but that would require translating the rest of the code.
  • I might be able to use CamelBones, but I don't want to assume my users have it installed.
  • I could also use the NSAppleScript framework (assuming I went to the trouble of finding the Tab and Window IDs) but it seems odd to have to resort to it for just this one call.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾城泪 2024-09-04 16:41:45
typedef 枚举 {
    TerminalSaveOptionsYes = 'yes ' /* 保存文件。 */,
    TerminalSaveOptionsNo = 'no ' /* 不保存文件。 */,
    TerminalSaveOptionsAsk = 'ask ' /* 询问用户是否保存文件。 */
终端保存选项;

enum 不命名字符串常量;它命名为int 常量。这些名称中的每一个都是一个 int 值。

因此,请尝试打包为 aI。或者,同时执行这两种操作:打包为 a,然后解包为 I 并传递该数字。

typedef enum {
    TerminalSaveOptionsYes = 'yes ' /* Save the file. */,
    TerminalSaveOptionsNo = 'no  '  /* Do not save the file. */,
    TerminalSaveOptionsAsk = 'ask ' /* Ask the user whether or not to save the file. */
} TerminalSaveOptions;

enum does not name string constants; it names int constants. Each of these names is of an int value.

So, try packing as a or I instead. Or, do both: Pack as a, then unpack as I and pass that number.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文