[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

-------------- 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