Piping console output to different destinations

I have a situation where I need to pipe my console output for several external processes.

Some of these should be "silent" (i.e. the console output gets piped to a variable for parsing of the data) while one of them should be displayed in an NSTextField as a progress indicator for the user.

Since this is rather a big chunk of code, I'd like to write the function so that I can give it a destination parameter, but I'm still pretty new at this and I can't quite make it work.

Here is what I have so far:

func pipeOutput(task: Process, destination: String) {
    let pipe = Pipe()
    task.standardError = pipe
    task.standardOutput = pipe
    let outHandle = pipe.fileHandleForReading
    outHandle.waitForDataInBackgroundAndNotify()
    var obs1 : NSObjectProtocol!
    obs1 = NotificationCenter.default
        .addObserver(
            forName: NSNotification.Name.NSFileHandleDataAvailable,
            object: outHandle, queue: nil) {
                notification -> Void in
                let data = outHandle.availableData
                if data.count > 0 {
                    if let str = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
                        destination += ("\(str)")
                        let range = NSRange(location:destination.count,length:0)
                        destination.scrollRangeToVisible(range)
                    }
                    outHandle.waitForDataInBackgroundAndNotify()
                }
                else {
                    print("EOF on stderr from process")
                    NotificationCenter.default.removeObserver(obs1!)
                }
    }
    var obs2 : NSObjectProtocol!
    obs2 = NotificationCenter.default
        .addObserver(
            forName: Process.didTerminateNotification,
            object: task, queue: nil) {
                notification -> Void in
                print("terminated")
                NotificationCenter.default.removeObserver(obs2!)
    }
}

I only need the
let range = NSRange(location:destination.count,length:0) destination.scrollRangeToVisible(range)
part when the destination is the NSTextField. In the other cases, I just need destination += ("\(str)")

I assume it would require writing a method along the lines of:

func getOutputDestination(processType: String) -> String {
    let process = processType
    switch process {
    case "silent" :
        outputDestination = "outputString"
    default :
        outputDestination = "textField"
        where "textField" =
    outputTextDisplay.string += ("\(str)")
    let range = NSRange(location:outputTextDisplay.string.count,length:0)
    outputTextDisplay.scrollRangeToVisible(range)
}
    return outputDestination
}

And then somehow designating the various external processes as "silent" or otherwise. But I'm not quite sure how to get it to work.

How do I make this happen?

(Note to others: This is continued from a conversation elsewhere.)

I can help you with this when you actually get to it. Right now your priority is to consolidate your various refactors into a single coherent branch. Choose something as the master copy, and we can work from there.

Thanks. I was working on it but then I came to the point where I needed to include the first instance of piping and it was either figure that part out now, or stick a // TO DO note in there.

Terms of Service

Privacy Policy

Cookie Policy