Re: [swift-corelibs-dev] Better integration with UNIX tools

2017-11-20 Thread Nick Keets via swift-corelibs-dev
Looking at what Python (subprocess) and Go (os.exec) do, it looks like they
agree on the following:
 - executable and arguments are merged in one array
 - they don't require full path for the executable
 - they don't expand tildes
 - blocking calls are the default
 - they are more explicit about stdin, stdout, stderr

Some example scenarios based on that, with possible swift code:

1) Run a command and ignore output

Python:
subprocess.run(["sleep", "1"], stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)

Go:
cmd := exec.Command("sleep", "1")
err := cmd.Run()

Possible Swift:
try Process.run(["sleep", "1"])


2) Run a command and capture stdout

Python:
out = subprocess.check_output(["ls", "-l"])

Go:

cmd := exec.Command("ls", "-l")
out, err := cmd.Output()

Possible Swift:

let proc = try Process.run(["ls", "-l"])
let out = proc.stdout.read() // proc.stdout is OutputStream, assumes
read() exists and returns Data
// stderr available at proc.stderr


3) Run a command and capture both stdout and stder together

Python:
out = subprocess.check_output(["ls", "-l"], stderr=subprocess.STDOUT)

Go:
cmd := exec.Command("ls", "-l")
out, err := cmd.CombinedOutput()

Possible Swift:
let proc = try Process.run(["ls", "-l"], combinedOutput: true)
let out = proc.stdout.read()


4) Shell out

Python:
subprocess.check_output(["ls", "-l"], stderr=subprocess.STDOUT,
shell=True)

Go:
cmd := exec.Command("sh", "-c", "ls -l")
out, err := cmd.CombinedOutput()

Possible Swift:
let proc = try Process.run(["sh", "-c", "ls -l"], combinedOutput: true)
let out = proc.stdout.read()


5) Pipe to stdin

Python:
p = subprocess.Popen(["wc"], stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.stdin.write(b'blah')
p.stdin.close()
out = p.stdout.read()

Go:
cmd := exec.Command("wc")
stdin, err := cmd.StdinPipe()
io.WriteString(stdin, "blah")
out = cmd.CombinedOutput()

Possible Swift:
let stdin = InputStream(data: "blah".data(using: .utf8))
let proc = try Process.run(["wc"], stdin: stdin, combinedOutput: true)
let out = proc.stdout.read()

6) Async

Python:
p = subprocess.Popen(["sleep", "5"])
p.wait()

Go:
cmd := exec.Command("sleep", "5")
err := cmd.Start()
err2 := cmd.Wait()

Possible Swift:
let proc = Process(["sleep", "5"])
try proc.start()
try proc.wait()


On Fri, Nov 17, 2017 at 9:34 PM, Tony Parker via swift-corelibs-dev <
[email protected]> wrote:

> Hi Abhi,
>
> It does seem like there is a possibility of some better convenience API
> here.
>
> Any ideas on what form it would take? A class method on Process that
> returns the output, maybe?
>
> - Tony
>
> On Nov 16, 2017, at 3:34 PM, Abhi Beckert via swift-corelibs-dev <
> [email protected]> wrote:
>
> Swift is a great shell scripting language except for it's lack of any API
> to execute UNIX commands. Compare these two shell scripts:
>
> #!/usr/bin/php
> 
> $files = `find ~/Desktop -name *.png`;
>
> foreach (explode("\n", $files) as $file) {
>   // do something with $file
> }
>
>
> -
>
> #!/usr/bin/swift
>
> import Foundation
>
> let process = Process()
> process.launchPath = "/usr/bin/find"
> process.arguments = [
>   NSString(string:"~/Desktop").expandingTildeInPath,
>   "-name",
>   "*.png"
> ]
>
> let output = Pipe()
> process.standardOutput = output
>
> process.launch()
>
> let files: String
> if let filesUtf8 = NSString(data: 
> output.fileHandleForReading.readDataToEndOfFile(),
> encoding: String.Encoding.utf8.rawValue) {
>   files = filesUtf8 as String
> } else {
>   files = NSString(data: output.fileHandleForReading.readDataToEndOfFile(),
> encoding: String.Encoding.isoLatin1.rawValue) as NSString! as String
> }
>
> files.enumerateLines { file, _ in
>   // do something with file
> }
>
>
> It's a contrived example, I could have used NSFileManager, but I run into
> this all the time integrating with more complex tools such as rsync.
>
> Adding my own high level wrapper around the Process command isn't an
> option since there is no good way to import code from another file when
> executing swift asa shell script. All your code needs to be in one file.
>
> - Abhi
> ___
> swift-corelibs-dev mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
>
>
>
> ___
> swift-corelibs-dev mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
>
>
___
swift-corelibs-dev mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Better integration with UNIX tools

2017-11-30 Thread Nick Keets via swift-corelibs-dev
In that case I think the discussion is kind of moot, scripts are
fundamentally different than apps, being terse is important and almost
always you want to block.

If better scripting support is a non-goal for Foundation then `Process` is
mostly fine as it is. My only wish would be to somehow make it easier to
read and write `Data` to stdin/stdout/stderr.


On Tue, Nov 28, 2017 at 11:30 PM, Tony Parker 
wrote:

> Of course, Foundation API has no way of distinguishing if the caller is
> considered a script or not.
>
> If the API is a bad idea for other kinds of apps then we simply wouldn’t
> add it. So, I think this proposed convenience API needs to consider all of
> the varied clients of Foundation.
>
> - Tony
>
>
> On Nov 28, 2017, at 12:24 PM, Brent Royal-Gordon 
> wrote:
>
> On Nov 28, 2017, at 8:00 AM, Tony Parker  wrote:
>
> Why does it imply a run loop rather than one of many multithreading
> possibilities (dispatch queue, starting one more thread, etc)? And even if
> it did use run loops, why is that a problem?
>
>
> The problem is simply that we're discussing using this feature in Swift
> *scripts*. Swift scripts don't typically invoke `RunLoop.run()` or
> `dispatch_main()`, and without changing the way they generate main()
> functions to intrinsically do so (and then schedule main.swift's body on
> the main runloop/queue), I don't see a good way for it to do so. So an
> async API would be inconvenient to use from a Swift script.
>
> --
> Brent Royal-Gordon
> Architechies
>
>
>
___
swift-corelibs-dev mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev