命令行Swift脚本的最低可行GUI是什么?
我需要一个小助手图形用户界面为我的Swift脚本在macOS上。它只需要一个文本输入字段和一个OK按钮命令行Swift脚本的最低可行GUI是什么?,swift,macos,cocoa,appkit,Swift,Macos,Cocoa,Appkit,我需要一个小助手图形用户界面为我的Swift脚本在macOS上。它只需要一个文本输入字段和一个OK按钮 我不想为了这个小小的弹出窗口而走整个臃肿的Xcode路线。然而,苹果的文档让我失望,因为我的NSWindow没有捕获键盘输入。救命啊 不,多亏了,我终于想出了魔法咒语我写了一个小脚本,可以用swift显示窗口。目标是显示几个shell命令的输出(brew update&brew upgrade&brew cleanup&brew doctor)。如果您不每天执行这些命令,那么这些命令可能会花费
我不想为了这个小小的弹出窗口而走整个臃肿的Xcode路线。然而,苹果的文档让我失望,因为我的NSWindow没有捕获键盘输入。救命啊 不,多亏了,我终于想出了魔法咒语我写了一个小脚本,可以用swift显示窗口。目标是显示几个shell命令的输出(
brew update
&brew upgrade
&brew cleanup
&brew doctor
)。如果您不每天执行这些命令,那么这些命令可能会花费大量的时间,我已经厌倦了只需等待10分钟就可以完成前两个命令
我本可以简单地启动cron作业或使用shell脚本启动,但我希望能够检查命令的成功或失败,尤其是brew doctor
,以了解是否需要执行某些操作来清理我的机器上的自制安装
所以我需要一个窗口来显示错误和命令的标准输出等等,我想生成一个二进制文件
在Google和Github上搜索了一段时间后,我找到了swift sh,它允许导入Github存储库(通过swift Package Manager以标准化的方式),并在swift脚本中使用它,如果需要的话进行编译;和ShellOut,由同一个人开发,它允许从swift脚本执行shell命令,并在swift对象中收集命令的输出
基本上,它应该是一个小窗口,在scrollview中有一个textview,可以滚动显示shell命令的输出
下面是脚本:
#!/usr/bin/swift sh
import AppKit
import Foundation
// importing ShellOut from GitHub repository
// The magic of swift-sh happens
import ShellOut // @JohnSundell
// Declare the Application context
let app = NSApplication.shared
// Create the delegate class responsible for the window and crontrol creation
class AppDelegate: NSObject, NSApplicationDelegate {
var str: String? = ""
// Construct the window
let theWindow = NSWindow(contentRect: NSMakeRect(200, 200, 400, 200),
styleMask: [.titled, .closable, .miniaturizable, .resizable],
backing: .buffered,
defer: false,
screen: nil)
var output: String? = ""
// What happens once application context launched
func applicationDidFinishLaunching(_ notification: Notification) {
var str = ""
// The shell commands and the collect of output
do {
str = try shellOut(to: "brew", arguments: ["update"] )
output = output! + str
} catch {
let error1 = error as! ShellOutError
//print(error1.message)
output = output! + error1.message
}
do {
str = try shellOut(to: "brew", arguments: ["upgrade"] )
output = output! + "\n" + str
//print("step 2")
} catch {
let error2 = error as! ShellOutError
//print(error2.message)
output = output! + "\n" + error2.message
}
do {
str = try shellOut(to: "brew", arguments: ["cleanup"] )
output = output! + "\n" + str
//print("step 3")
} catch {
let error3 = error as! ShellOutError
//print(error3.message)
output = output! + "\n" + error3.message
}
do {
str = try shellOut(to: "brew", arguments: ["doctor"] )
output = output! + "\n" + str
//print("step 4")
} catch {
let error4 = error as! ShellOutError
//print(error4.message)
output = output! + "\n" + error4.message
}
// Controls placement and content goes here
// ScrollView...
var theScrollview = NSScrollView(frame: theWindow.contentView!.bounds)
var contentSize = theScrollview.contentSize
theScrollview.borderType = .noBorder
theScrollview.hasVerticalScroller = true
theScrollview.hasHorizontalScroller = false
theScrollview.autoresizingMask = NSView.AutoresizingMask(rawValue: NSView.AutoresizingMask.width.rawValue | NSView.AutoresizingMask.height.rawValue | NSView.AutoresizingMask.minYMargin.rawValue | NSView.AutoresizingMask.minYMargin.rawValue)
// TextView...
var theTextView = NSTextView(frame: NSMakeRect(0, 0, contentSize.width, contentSize.height))
theTextView.minSize = NSMakeSize(0.0, contentSize.height)
theTextView.maxSize = NSMakeSize(CGFloat.greatestFiniteMagnitude, CGFloat.greatestFiniteMagnitude)
theTextView.isVerticallyResizable = true
theTextView.isHorizontallyResizable = false
theTextView.autoresizingMask = NSView.AutoresizingMask(rawValue: NSView.AutoresizingMask.width.rawValue | NSView.AutoresizingMask.height.rawValue | NSView.AutoresizingMask.minYMargin.rawValue | NSView.AutoresizingMask.minYMargin.rawValue)
theTextView.textContainer?.containerSize = NSMakeSize(contentSize.width, CGFloat.greatestFiniteMagnitude)
theTextView.backgroundColor = .white
theTextView.textContainer?.widthTracksTextView = true
theTextView.textStorage?.append(NSAttributedString(string: output!))
theScrollview.documentView = theTextView
theWindow.contentView = theScrollview
theWindow.makeKeyAndOrderFront(nil)
theWindow.makeFirstResponder(theTextView)
}
// What happens when we click the close button of the window
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true;
}
}
// Instantiation of the application delegate class
// and launching
let delegate = AppDelegate()
app.delegate = delegate
app.run()
尝试event monitor@MarekH谢谢,我仔细研究并尝试了它,但后来偶然发现了解决方案:
app.setActivationPolicy(.regular)
如果您添加#/usr/bin/swift
开始时,您也可以将其作为脚本运行。您需要在app.run之前激活app.activate(忽略其他应用程序:true)以使应用程序窗口显示在所有其他应用程序之上。