kareman / SwiftShell

A Swift framework for shell scripting.
https://kareman.github.io/SwiftShell
MIT License
1.03k stars 87 forks source link

Starting command later #55

Closed Ponyboy47 closed 6 years ago

Ponyboy47 commented 6 years ago

I want to create an AsyncCommand, but not have it be started immediately. Currently, due to the internal protection on the createProcess function, I have to manually create my Process() object to pass to the AsyncCommand's init(unlaunched...).

It seems silly to have that initializer if we can't really even take advantage of it. Making createProcess public should allow the functionality I desire

Ponyboy47 commented 6 years ago

The initializers for AsyncCommand would also need to be made public

kareman commented 6 years ago

Whenever I want delayed execution in Swift I just wrap the code in a closure. Like this:

import SwiftShell

let command = { runAsync("echo", "Hi") }

// later...
print(command().stdout)

Would this work for your use case?

Ponyboy47 commented 6 years ago

I'm don't think so. I'm subclassing Operation and making an asynchronous operation that will start a command and can monitor it's status.

Ponyboy47 commented 6 years ago

I'll probably make a pull request in a little bit. You can decide whether or not to accept the changes

kareman commented 6 years ago

But Operation itself supports writing code that you can start whenever you want. I don't think I'm grasping what you want to do here. Do you have some code (or pseudocode) that could explain it to me?

I'm hesitant to make createProcess public because it is an internal implementation detail users of SwiftShell should not need to know about. But of course if you could show me a useful use case for it I will reconsider.

Ponyboy47 commented 6 years ago

I would like to create the AsyncCommand in the operation's initializer and then start it in the operation's main() method, but I suppose this is not necessary.

Perhaps just make an initializer that calls createProcess and doesn't automatically run the command on initialization? Or add a property to the run/runAsync functions to not start immediately. Then you keep createProcess internal, but can allow the functionality I desire. I feel like this would be useful functionality to have just in general, but possibly not.

I was running into an issue where calling SwiftShell.run() or SwiftShell.runAsync() inside of the operation's main() method wouldn't actually run the command. It will run simple commands like "echo", but never started more complex commands (like Handbrake) which fork multiple processes or are multithreaded. I just realized that this was because I was not overriding the isAsynchronous property of the Operation and so it was not permitting additional threads to be created.

That being said, I was able to get everything working without needing the additional functionality, I will still create a pull request though and if you feel it is a worthy addition then you may add it, but if not then just deny it.

kareman commented 6 years ago

Glad to hear it’s working :) , and thanks for the pull request.