<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I cosign all of this. &nbsp;Nice work, Brent.<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 17, 2017, at 4:47 PM, Brent Royal-Gordon via swift-corelibs-dev &lt;<a href="mailto:swift-corelibs-dev@swift.org" class="">swift-corelibs-dev@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">On Nov 17, 2017, at 11:34 AM, Tony Parker via swift-corelibs-dev &lt;<a href="mailto:swift-corelibs-dev@swift.org" class="">swift-corelibs-dev@swift.org</a>&gt; 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 class="">`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 class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>extension Process {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>class func runInPath(_ commandName: String, with arguments: [String], terminationHandler: ((Process) -&gt; Void)? = nil) -&gt; Process</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class="">(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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>extension Process {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>func&nbsp;outputAfterExit() throws -&gt; (output: String, status: Int32)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class="">The result is not *as* convenient as PHP, but it's a lot safe than running things through a shell, too.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let (output, _) = try&nbsp;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) -&gt; 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 class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let (output, _) = try&nbsp;Task.runInPath("find", with: [~"Desktop", "-name", "*.png"]).outputAfterExit()</div></div><div class=""><br class=""></div><div class="">But I'm not sure we'd want that available in million-line Mac apps.</div><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class=""><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 class=""><span class="Apple-tab-span" style="white-space:pre">                </span>public&nbsp;init(stringLiteral value: String) {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                        </span>self.init(fileURLWithPath: value)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>public var FS { return FileManager.default }</div><div class=""><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="">--&nbsp;</div><div style="font-size: 12px; " class="">Brent Royal-Gordon</div><div style="font-size: 12px; " class="">Architechies</div></div></span>

</div>
<br class=""></div>_______________________________________________<br class="">swift-corelibs-dev mailing list<br class=""><a href="mailto:swift-corelibs-dev@swift.org" class="">swift-corelibs-dev@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-corelibs-dev<br class=""></div></blockquote></div><br class=""></div></body></html>