[swift-corelibs-dev] Better integration with UNIX tools
Brent Royal-Gordon
brent at architechies.com
Fri Nov 17 18:47:00 CST 2017
> On Nov 17, 2017, at 11:34 AM, Tony Parker via swift-corelibs-dev <swift-corelibs-dev at swift.org> wrote:
>
> 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?
`Process.run(_:arguments:terminationHandler:)` is not a bad basis for this, other than the first argument being a URL. I might add a variant which does a $PATH search and expands tildes:
extension Process {
class func runInPath(_ commandName: String, with arguments: [String], terminationHandler: ((Process) -> Void)? = nil) -> Process
}
(I would *not* add a variant which simply shells out, or at least I wouldn't make it the only option. Every scripting language I can think of has this feature, and every one of them discourages its use and pushes people towards something else with pre-split arguments and no shell attack surface.)
And then add a method which gathers all stdout output and returns it, along with the termination status (throwing if it's a signal):
extension Process {
func outputAfterExit() throws -> (output: String, status: Int32)
}
The result is not *as* convenient as PHP, but it's a lot safe than running things through a shell, too.
let (output, _) = try Task.runInPath("find", with: ["~/Desktop", "-name", "*.png"]).outputAfterExit()
The biggest problem I see with this design is that expanding tildes in the arguments, but *not* globbing them, happens to be right for this case, but may not be in the general case. One interesting possibility would be to go the custom operator route:
/// Returns an absolute path placing `relativePath` in the user's home directory.
prefix func ~ (relativePath: String) -> String {
return FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(relativePath).path
}
let (output, _) = try Task.runInPath("find", with: [~"Desktop", "-name", "*.png"]).outputAfterExit()
But I'm not sure we'd want that available in million-line Mac apps.
On the other hand, maybe Foundation's APIs in general are too verbose for scripting. I could imagine a "Foundation.Script" module which added some unprincipled but convenient shortcuts:
extension URL: ExpressibleByStringLiteral { // Should be interpolatable too, but we need to redesign that.
public init(stringLiteral value: String) {
self.init(fileURLWithPath: value)
}
}
public var FS { return FileManager.default }
public var ENV { return ProcessInfo.processInfo.environment }
That might be a good place for a leading tilde operator, too.
--
Brent Royal-Gordon
Architechies
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20171117/c6ea0c01/attachment.html>
More information about the swift-corelibs-dev
mailing list