【问题标题】:Launch a terminal editor such as vi or nano in Swift在 Swift 中启动终端编辑器,例如 vi 或 nano
【发布时间】:2020-10-19 11:27:12
【问题描述】:

我正在尝试在用 Swift 编写的命令行程序中启动终端编辑器,例如 vi 或 nano。

这是一个天真的尝试,我猜标准输入和输出应该是不同的。程序什么也不输出。

let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = ["nano"]
task.standardInput = FileHandle(forReadingAtPath: "/dev/tty")
task.standardOutput = FileHandle(forWritingAtPath: "/dev/tty")
task.launch()
task.waitUntilExit()

【问题讨论】:

    标签: swift shell


    【解决方案1】:

    此示例将在终端窗口中启动“vi”编辑器。可以通过将代码复制/粘贴到新添加的“main.swift”文件并删除预先存在的 AppDelegate 来在 Xcode swift 项目中运行。还需要关闭沙盒。

    import Cocoa
    
    let process = Process()
    let pipe = Pipe()
    
    process.executableURL = URL(fileURLWithPath:"/bin/sh/")
    var args : [String]!
    args = []
    args.append("-c")
    args.append("open '/usr/bin/vi'")
    process.arguments = args
    process.standardOutput = pipe
    process.standardError = pipe
    process.terminationHandler = { (process) in
      print("\ndidFinish: \(!process.isRunning)")
    }
    let fileHandle = pipe.fileHandleForReading
    do {
      try process.run()
      let outStr = String(data: fileHandle.readDataToEndOfFile(), encoding: .utf8)
      print(outStr as Any)
    } catch { print(String(data: fileHandle.readDataToEndOfFile(), encoding: .utf8) as Any)}
    
    // **** main.swift **** //
    let app = NSApplication.shared
    app.setActivationPolicy(.regular)
    app.activate(ignoringOtherApps:true)
    app.run()
    
    

    【讨论】:

    • 谢谢。这将在新的终端窗口中打开 vi。我想要做的是在我运行程序的同一个终端中打开 vi。
    【解决方案2】:

    它似乎适用于posix_spawn

    #if os(Linux)
    import Glibc
    #else
    import Darwin
    #endif
    
    public struct PosixProcess {
        public let executablePath: String
        public let arguments: [String]
    
        public init(_ executablePath: String, _ arguments: String...) {
            self.executablePath = executablePath
            self.arguments = arguments
        }
    
        public func spawn() throws {
            var pid: pid_t = 0
            let path = executablePath.withCString(strdup)!
            let args = arguments.map { $0.withCString(strdup)! }
            defer {
                ([path] + args).forEach { free($0) }
            }
            if posix_spawn(&pid, path, nil, nil, [path] + args + [nil], environ) < 0 {
                // throw some error with `errno`
            }
            if waitpid(pid, nil, 0) < 0 {
                // throw some error with `errno`
            }
        }
    }
    
    try PosixProcess("/usr/bin/env", "nano").spawn()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      • 2016-10-20
      相关资源
      最近更新 更多