<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Nov 17, 2017, at 11:34 AM, Tony Parker via swift-corelibs-dev <<a href="mailto:swift-corelibs-dev@swift.org" class="">swift-corelibs-dev@swift.org</a>> wrote:</div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class="">It does seem like there is a possibility of some better convenience API here.</blockquote><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Any ideas on what form it would take? A class method on Process that returns the output, maybe?</div></div></blockquote><br class=""></div><div>`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:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>extension Process {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>class func runInPath(_ commandName: String, with arguments: [String], terminationHandler: ((Process) -> Void)? = nil) -> Process</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div>(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.)</div><div><br class=""></div><div>And then add a method which gathers all stdout output and returns it, along with the termination status (throwing if it's a signal):</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>extension Process {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func outputAfterExit() throws -> (output: String, status: Int32)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div>The result is not *as* convenient as PHP, but it's a lot safe than running things through a shell, too.</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>let (output, _) = try Task.runInPath("find", with: ["~/Desktop", "-name", "*.png"]).outputAfterExit()</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// Returns an absolute path placing `relativePath` in the user's home directory.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>prefix func ~ (relativePath: String) -> String {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>return FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(relativePath).path</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class=""><div><span class="Apple-tab-span" style="white-space: pre;">        </span>let (output, _) = try Task.runInPath("find", with: [~"Desktop", "-name", "*.png"]).outputAfterExit()</div></div><div><br class=""></div><div>But I'm not sure we'd want that available in million-line Mac apps.</div><div><br class=""></div><div>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:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>extension URL: ExpressibleByStringLiteral {<span class="Apple-tab-span" style="white-space:pre">        </span>// Should be interpolatable too, but we need to redesign that.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>public init(stringLiteral value: String) {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self.init(fileURLWithPath: value)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public var FS { return FileManager.default }</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public var ENV { return ProcessInfo.processInfo.environment }</div><div class=""><br class=""></div><div class="">That might be a good place for a leading tilde operator, too.</div><br class=""><div class="">
<span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-east-asian: normal; font-variant-position: normal; line-height: normal; border-spacing: 0px;"><div class=""><div style="font-size: 12px; " class="">-- </div><div style="font-size: 12px; " class="">Brent Royal-Gordon</div><div style="font-size: 12px; " class="">Architechies</div></div></span>
</div>
<br class=""></body></html>