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

William Dillon wdillon at deluge.housedillon.com
Fri Nov 17 21:10:11 CST 2017


I cosign all of this.  Nice work, Brent.

> On Nov 17, 2017, at 4:47 PM, Brent Royal-Gordon via swift-corelibs-dev <swift-corelibs-dev at swift.org> wrote:
> 
>> On Nov 17, 2017, at 11:34 AM, Tony Parker via swift-corelibs-dev <swift-corelibs-dev at swift.org <mailto: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
> 
> _______________________________________________
> swift-corelibs-dev mailing list
> swift-corelibs-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20171117/2a8079cf/attachment.html>


More information about the swift-corelibs-dev mailing list