433 lines
32 KiB
HTML
433 lines
32 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<title>SwiftShell Reference</title>
|
||
<link rel="stylesheet" type="text/css" href="css/jazzy.css" />
|
||
<link rel="stylesheet" type="text/css" href="css/highlight.css" />
|
||
<meta charset='utf-8'>
|
||
<script src="js/jquery.min.js" defer></script>
|
||
<script src="js/jazzy.js" defer></script>
|
||
|
||
</head>
|
||
<body>
|
||
<a title="SwiftShell Reference"></a>
|
||
<header>
|
||
<div class="content-wrapper">
|
||
<p><a href="index.html">SwiftShell Docs</a> (67% documented)</p>
|
||
<p class="header-right"><a href="https://github.com/kareman/SwiftShell"><img src="img/gh.png"/>View on GitHub</a></p>
|
||
</div>
|
||
</header>
|
||
<div class="content-wrapper">
|
||
<p id="breadcrumbs">
|
||
<a href="index.html">SwiftShell Reference</a>
|
||
<img id="carat" src="img/carat.png" />
|
||
SwiftShell Reference
|
||
</p>
|
||
</div>
|
||
<div class="content-wrapper">
|
||
<nav class="sidebar">
|
||
<ul class="nav-groups">
|
||
<li class="nav-group-name">
|
||
<a href="Classes.html">Classes</a>
|
||
<ul class="nav-group-tasks">
|
||
<li class="nav-group-task">
|
||
<a href="Classes/AsyncCommand.html">AsyncCommand</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Classes/FileHandleStream.html">FileHandleStream</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Classes/MainContext.html">MainContext</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Classes/RunOutput.html">RunOutput</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Classes/StdoutStream.html">StdoutStream</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-group-name">
|
||
<a href="Global Variables.html">Global Variables</a>
|
||
<ul class="nav-group-tasks">
|
||
<li class="nav-group-task">
|
||
<a href="Global Variables.html#/s:v10SwiftShell5FilesCSo11FileManager">Files</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Global Variables.html#/s:v10SwiftShell4mainCS_11MainContext">main</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-group-name">
|
||
<a href="Enums.html">Enums</a>
|
||
<ul class="nav-group-tasks">
|
||
<li class="nav-group-task">
|
||
<a href="Enums/CommandError.html">CommandError</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Enums/FileError.html">FileError</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-group-name">
|
||
<a href="Extensions.html">Extensions</a>
|
||
<ul class="nav-group-tasks">
|
||
<li class="nav-group-task">
|
||
<a href="Extensions/FileHandle.html">FileHandle</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Extensions/FileHandle.html">FileHandle</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Extensions/LazyCollectionProtocol.html">LazyCollectionProtocol</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Extensions/Process.html">Process</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Extensions/String.html">String</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-group-name">
|
||
<a href="Functions.html">Functions</a>
|
||
<ul class="nav-group-tasks">
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShelloi1pFTV10Foundation3URLSS_S1_">+(_:_:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShelloi2eeFTOS_12CommandErrorS0__Sb">==(_:_:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell4exitFTPs5Error_4fileSS4lineSi_Os5Never">exit(_:file:line:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell4exiturFT12errormessagex9errorcodeSi4fileSS4lineSi_Os5Never">exit(errormessage:errorcode:file:line:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell4openFzTSS8encodingVE10FoundationSS8Encoding_PS_14ReadableStream_">open(_:encoding:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell4openFzTV10Foundation3URL8encodingVES0_SS8Encoding_PS_14ReadableStream_">open(_:encoding:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell4openFzT10forWritingSS9overwriteSb8encodingVE10FoundationSS8Encoding_PS_14WritableStream_">open(forWriting:overwrite:encoding:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell4openFzT10forWritingV10Foundation3URL9overwriteSb8encodingVES0_SS8Encoding_PS_14WritableStream_">open(forWriting:overwrite:encoding:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell3runFTSSGSaP__13combineOutputSb_CS_9RunOutput">run(_:_:combineOutput:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell3runFT4bashSS13combineOutputSb_CS_9RunOutput">run(bash:combineOutput:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell11runAndPrintFztSSGSaP___T_">runAndPrint(_:_:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell11runAndPrintFzT4bashSS_T_">runAndPrint(bash:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell8runAsyncFTSSGSaP__4fileSS4lineSi_CS_12AsyncCommand">runAsync(_:_:file:line:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell8runAsyncFT4bashSS4fileSS4lineSi_CS_12AsyncCommand">runAsync(bash:file:line:)</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Functions.html#/s:F10SwiftShell7streamsFT_TPS_14WritableStream_PS_14ReadableStream__">streams()</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-group-name">
|
||
<a href="Protocols.html">Protocols</a>
|
||
<ul class="nav-group-tasks">
|
||
<li class="nav-group-task">
|
||
<a href="Protocols.html#/CommandRunning">CommandRunning</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Protocols/CommandRunning.html">CommandRunning</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Protocols/Context.html">Context</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Protocols/ReadableStream.html">ReadableStream</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Protocols/WritableStream.html">WritableStream</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-group-name">
|
||
<a href="Structs.html">Structs</a>
|
||
<ul class="nav-group-tasks">
|
||
<li class="nav-group-task">
|
||
<a href="Structs/CustomContext.html">CustomContext</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Structs/LazySplitSequence.html">LazySplitSequence</a>
|
||
</li>
|
||
<li class="nav-group-task">
|
||
<a href="Structs/PartialSourceLazySplitSequence.html">PartialSourceLazySplitSequence</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
<article class="main-content">
|
||
<section>
|
||
<section class="section">
|
||
|
||
<p>Run shell commands | <a href="https://github.com/kareman/Moderator">Parse command line arguments</a> | <a href="https://github.com/kareman/FileSmith">Handle files and directories</a></p>
|
||
|
||
<hr>
|
||
|
||
<p>Swift 3 | <a href="https://github.com/kareman/SwiftShell/tree/Swift2">Swift 2</a></p>
|
||
|
||
<p align="center">
|
||
<img src="Misc/logo.png" alt="SwiftShell logo" />
|
||
</p>
|
||
|
||
<p><a href="https://travis-ci.org/kareman/SwiftShell"><img src="https://travis-ci.org/kareman/SwiftShell.svg?branch=master" alt="Build Status"></a> <img src="https://img.shields.io/badge/platforms-macOS%20%7C%20Linux-lightgrey.svg" alt="Platforms"> <a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat" alt="Carthage compatible"></a></p>
|
||
<a href='#swiftshell' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h1 id='swiftshell'>SwiftShell</h1>
|
||
|
||
<p>A library for creating command-line applications and running shell commands in Swift. </p>
|
||
<a href='#features' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='features'>Features</h4>
|
||
|
||
<ul>
|
||
<li>[x] run commands, and handle the output.</li>
|
||
<li>[x] run commands asynchronously, and be notified when output is available.</li>
|
||
<li>[x] access the context your application is running in, like environment variables, standard input, standard output, standard error, the current directory and the command line arguments.</li>
|
||
<li>[x] create new such contexts you can run commands in.</li>
|
||
<li>[x] handle errors.</li>
|
||
<li>[x] read and write files.</li>
|
||
</ul>
|
||
<a href='#see-also' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='see-also'>See also</h4>
|
||
|
||
<ul>
|
||
<li><a href="http://kareman.github.io/SwiftShell">Documentation</a> from the source code.</li>
|
||
<li>A <a href="https://www.skilled.io/kare/swiftshell">description</a> of the project on <a href="https://www.skilled.io">skilled.io</a>.</li>
|
||
<li>Example scripts
|
||
|
||
<ul>
|
||
<li>[</li>
|
||
<li><a href="http://blog.nottoobadsoftware.com/swiftshell/move-files-to-the-trash/">Move files to the trash</a></li>
|
||
<li><a href="http://blog.nottoobadsoftware.com/swiftshell/combine-markdown-files-and-convert-to-html-in-a-swift-script/">Combine markdown files and convert to HTML</a> (runs a shell command in the middle of a method chain)</li>
|
||
</ul></li>
|
||
</ul>
|
||
<a href='#example' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h2 id='example'>Example</h2>
|
||
<a href='#print-line-numbers' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='print-line-numbers'>Print line numbers</h4>
|
||
<pre class="highlight swift"><code><span class="cp">#!/usr/bin/env swiftshell</span>
|
||
|
||
<span class="kd">import</span> <span class="kt">SwiftShell</span>
|
||
|
||
<span class="k">do</span> <span class="p">{</span>
|
||
<span class="c1">// If there is an argument, try opening it as a file. Otherwise use standard input.</span>
|
||
<span class="k">let</span> <span class="nv">input</span> <span class="o">=</span> <span class="k">try</span> <span class="n">main</span><span class="o">.</span><span class="n">arguments</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span><span class="k">try</span> <span class="nf">open</span><span class="p">(</span><span class="nv">$0</span><span class="p">)}</span> <span class="p">??</span> <span class="n">main</span><span class="o">.</span><span class="n">stdin</span>
|
||
|
||
<span class="n">input</span><span class="o">.</span><span class="nf">lines</span><span class="p">()</span>
|
||
<span class="o">.</span><span class="nf">enumerated</span><span class="p">()</span><span class="o">.</span><span class="n">forEach</span> <span class="p">{</span> <span class="p">(</span><span class="n">linenr</span><span class="p">,</span><span class="n">line</span><span class="p">)</span> <span class="k">in</span> <span class="nf">print</span><span class="p">(</span><span class="n">linenr</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="s">":"</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span> <span class="p">}</span>
|
||
|
||
<span class="c1">// Add a newline at the end</span>
|
||
<span class="nf">print</span><span class="p">(</span><span class="s">""</span><span class="p">)</span>
|
||
<span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
|
||
<span class="nf">exit</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</code></pre>
|
||
|
||
<p>Launched with e.g. <code>cat long.txt | print_linenumbers.swift</code> or <code>print_linenumbers.swift long.txt</code> this will print the line number at the beginning of each line.</p>
|
||
<a href='#overview' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h2 id='overview'>Overview</h2>
|
||
<a href='#context' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='context'>Context</h3>
|
||
|
||
<p>All commands (a.k.a. <a href="https://en.wikipedia.org/wiki/Process_(computing)">processes</a>) you run in SwiftShell need context: <a href="https://en.wikipedia.org/wiki/Environment_variable">environment variables</a>, the <a href="https://en.wikipedia.org/wiki/Working_directory">current working directory</a>, standard input, standard output and standard error (see <a href="https://en.wikipedia.org/wiki/Standard_streams">standard streams</a>).</p>
|
||
<pre class="highlight swift"><code><span class="kd">public</span> <span class="kd">struct</span> <span class="kt">CustomContext</span><span class="p">:</span> <span class="kt">Context</span><span class="p">,</span> <span class="kt">CommandRunning</span> <span class="p">{</span>
|
||
<span class="kd">public</span> <span class="k">var</span> <span class="nv">env</span><span class="p">:</span> <span class="p">[</span><span class="kt">String</span><span class="p">:</span> <span class="kt">String</span><span class="p">]</span>
|
||
<span class="kd">public</span> <span class="k">var</span> <span class="nv">currentdirectory</span><span class="p">:</span> <span class="kt">String</span>
|
||
<span class="kd">public</span> <span class="k">var</span> <span class="nv">stdin</span><span class="p">:</span> <span class="kt">ReadableStream</span>
|
||
<span class="kd">public</span> <span class="k">var</span> <span class="nv">stdout</span><span class="p">:</span> <span class="kt">WritableStream</span>
|
||
<span class="kd">public</span> <span class="k">var</span> <span class="nv">stderror</span><span class="p">:</span> <span class="kt">WritableStream</span>
|
||
<span class="p">}</span>
|
||
</code></pre>
|
||
|
||
<p>You can create a copy of your application’s context: <code>let context = CustomContext(main)</code>, or create a new empty one: <code>let context = CustomContext()</code>.</p>
|
||
<a href='#main-context' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='main-context'>Main context</h4>
|
||
|
||
<p>The global variable <code>main</code> contains the context for the application itself. In addition to the properties mentioned above it also has these:</p>
|
||
|
||
<ul>
|
||
<li><code>public var encoding: String.Encoding</code>
|
||
The default encoding used when opening files or creating new streams.</li>
|
||
<li><code>public let tempdirectory: String</code>
|
||
A temporary directory the application can use for temporary stuff.</li>
|
||
<li><code>public let arguments: [String]</code>
|
||
The arguments used when launching the application.</li>
|
||
<li><code>public let path: String</code>
|
||
The path to the application.</li>
|
||
</ul>
|
||
|
||
<p>Everything is mutable, so you can set e.g. the text encoding or reroute standard error to a file. But commands can’t change the context they run in (or anything else in your application) so e.g. <code>main.run("cd", "somefolder")</code> will achieve nothing. Use <code>main.currentdirectory = "somefolder"</code> instead.</p>
|
||
<a href='#streams' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='streams'>Streams</h3>
|
||
<a href='#output' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='output'>Output</h4>
|
||
|
||
<p><code>main.stdout</code> is for normal output and <code>main.stderror</code> for errors. You can also write to a file:</p>
|
||
<pre class="highlight swift"><code><span class="n">main</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="nf">print</span><span class="p">(</span><span class="s">"everything is fine"</span><span class="p">)</span>
|
||
<span class="n">main</span><span class="o">.</span><span class="n">stderror</span><span class="o">.</span><span class="nf">print</span><span class="p">(</span><span class="s">"no wait, something went wrong ..."</span><span class="p">)</span>
|
||
|
||
<span class="k">let</span> <span class="nv">file</span> <span class="o">=</span> <span class="k">try</span> <span class="nf">open</span><span class="p">(</span><span class="nv">forWriting</span><span class="p">:</span> <span class="n">path</span><span class="p">)</span>
|
||
<span class="n">file</span><span class="o">.</span><span class="nf">print</span><span class="p">(</span><span class="s">"something"</span><span class="p">)</span>
|
||
</code></pre>
|
||
|
||
<p><code>.write</code> doesn’t add a newline, and you can change the text encoding with <code>.encoding</code>.</p>
|
||
<a href='#input' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='input'>Input</h4>
|
||
|
||
<p>Use <code>main.stdin</code> to read from standard input, or you can read from a file:</p>
|
||
<pre class="highlight swift"><code><span class="k">let</span> <span class="nv">input</span><span class="p">:</span> <span class="kt">String</span><span class="p">?</span> <span class="o">=</span> <span class="n">main</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="nf">readSome</span><span class="p">()</span> <span class="c1">// read what is available, don't wait for end of file </span>
|
||
|
||
<span class="k">let</span> <span class="nv">file</span> <span class="o">=</span> <span class="k">try</span> <span class="nf">open</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
|
||
<span class="k">let</span> <span class="nv">contents</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="nf">read</span><span class="p">()</span> <span class="c1">// read everything</span>
|
||
</code></pre>
|
||
|
||
<p>Using <code>.readSome()</code> you can read piecewise instead of waiting for the input to be finished and then reading everything at once. You can change the text encoding with <code>.encoding</code>.</p>
|
||
<a href='#commands' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='commands'>Commands</h3>
|
||
<a href='#run' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='run'>Run</h4>
|
||
<pre class="highlight swift"><code><span class="k">let</span> <span class="nv">date</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="nf">run</span><span class="p">(</span><span class="s">"date"</span><span class="p">,</span> <span class="s">"-u"</span><span class="p">)</span>
|
||
<span class="nf">print</span><span class="p">(</span><span class="s">"Today's date in UTC is "</span> <span class="o">+</span> <span class="n">date</span><span class="p">)</span>
|
||
</code></pre>
|
||
|
||
<p>Similar to <code>$(cmd)</code> in bash, this just returns the output from the command as a string, ignoring any errors.</p>
|
||
<a href='#print-output' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='print-output'>Print output</h4>
|
||
<pre class="highlight swift"><code><span class="k">try</span> <span class="nf">runAndPrint</span><span class="p">(</span><span class="nv">bash</span><span class="p">:</span> <span class="s">"cmd1 arg | cmd2 arg"</span><span class="p">)</span>
|
||
</code></pre>
|
||
|
||
<p>Run a shell command just like you would in the terminal. The name may seem a bit cumbersome, but it explains exactly what it does. SwiftShell never prints anything without explicitly being told to.</p>
|
||
<a href='#asynchronous' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='asynchronous'>Asynchronous</h4>
|
||
<pre class="highlight swift"><code><span class="k">let</span> <span class="nv">command</span> <span class="o">=</span> <span class="nf">runAsync</span><span class="p">(</span><span class="s">"cmd"</span><span class="p">,</span> <span class="s">"-n"</span><span class="p">,</span> <span class="mi">245</span><span class="p">)</span>
|
||
<span class="c1">// do something with command.stderror or command.stdout</span>
|
||
<span class="k">try</span> <span class="n">command</span><span class="o">.</span><span class="nf">finish</span><span class="p">()</span>
|
||
</code></pre>
|
||
|
||
<p>Launch a command and continue before it’s finished. You can process standard output and standard error, and optionally wait until it’s finished and handle any errors.</p>
|
||
|
||
<p>If you read all of command.stderror or command.stdout it will automatically wait for the command to finish running. You can still call <code>finish()</code> to check for errors.</p>
|
||
<a href='#parameters' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='parameters'>Parameters</h4>
|
||
|
||
<p>The 3 <code>run</code> functions above take 2 different types of parameters:</p>
|
||
<a href='#_-executable-string-_-args-any' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h5 id='_-executable-string-_-args-any'>(_ executable: String, _ args: Any …)</h5>
|
||
|
||
<p>If the path to the executable is without any <code>/</code>, SwiftShell will try to find the full path using the <code>which</code> shell command.</p>
|
||
|
||
<p>The array of arguments can contain any type, since everything is convertible to strings in Swift. If it contains any arrays it will be flattened so only the elements will be used, not the arrays themselves.</p>
|
||
<pre class="highlight swift"><code><span class="k">try</span> <span class="nf">runAndPrint</span><span class="p">(</span><span class="s">"echo"</span><span class="p">,</span> <span class="s">"We are"</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s">"arguments"</span><span class="p">)</span>
|
||
<span class="c1">// echo "We are" 4 arguments</span>
|
||
|
||
<span class="k">let</span> <span class="nv">array</span> <span class="o">=</span> <span class="p">[</span><span class="s">"But"</span><span class="p">,</span> <span class="s">"we"</span><span class="p">,</span> <span class="s">"are"</span><span class="p">]</span>
|
||
<span class="k">try</span> <span class="nf">runAndPrint</span><span class="p">(</span><span class="s">"echo"</span><span class="p">,</span> <span class="n">array</span><span class="p">,</span> <span class="n">array</span><span class="o">.</span><span class="n">count</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="s">"arguments"</span><span class="p">)</span>
|
||
<span class="c1">// echo But we are 5 arguments</span>
|
||
</code></pre>
|
||
<a href='#bash-bashcommand-string' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h5 id='bash-bashcommand-string'>(bash bashcommand: String)</h5>
|
||
|
||
<p>These are the commands you normally use in the Terminal. You can use pipes and redirection and all that good stuff. Support for other shell interpreters can easily be added.</p>
|
||
<a href='#errors' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h4 id='errors'>Errors</h4>
|
||
|
||
<p>If the command provided to <code>runAsync</code> could not be launched for any reason the program will print the error to standard error and exit, as is usual in scripts (it is quite possible SwiftShell should be less usual here).</p>
|
||
|
||
<p>The <code>runAsync("cmd").finish()</code> method on the other hand throws an error if the exit code of the command is anything but 0:</p>
|
||
<pre class="highlight swift"><code><span class="k">let</span> <span class="nv">command</span> <span class="o">=</span> <span class="nf">runAsync</span><span class="p">(</span><span class="s">"cmd"</span><span class="p">,</span> <span class="s">"-n"</span><span class="p">,</span> <span class="mi">245</span><span class="p">)</span>
|
||
<span class="c1">// do something with command.stderror or command.stdout</span>
|
||
<span class="k">do</span> <span class="p">{</span>
|
||
<span class="k">try</span> <span class="n">command</span><span class="o">.</span><span class="nf">finish</span><span class="p">()</span>
|
||
<span class="p">}</span> <span class="k">catch</span> <span class="kt">ShellError</span><span class="o">.</span><span class="kt">ReturnedErrorCode</span><span class="p">(</span><span class="k">let</span> <span class="nv">error</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="c1">// use error.command or error.errorcode</span>
|
||
<span class="p">}</span>
|
||
</code></pre>
|
||
|
||
<p>The <code>runAndPrint</code> command can also throw this error, in addition to this one if the command could not be launched:</p>
|
||
<pre class="highlight swift"><code><span class="p">}</span> <span class="k">catch</span> <span class="kt">ShellError</span><span class="o">.</span><span class="kt">InAccessibleExecutable</span><span class="p">(</span><span class="k">let</span> <span class="nv">path</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="c1">// ‘path’ is the full path to the executable</span>
|
||
<span class="p">}</span>
|
||
</code></pre>
|
||
|
||
<p>Instead of dealing with the values from these errors you can just print them:</p>
|
||
<pre class="highlight swift"><code><span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
|
||
<span class="nf">print</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</code></pre>
|
||
|
||
<p>… or if they are sufficiently serious you can print them to standard error and exit:</p>
|
||
<pre class="highlight swift"><code><span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
|
||
<span class="nf">exit</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</code></pre>
|
||
|
||
<p> </p>
|
||
|
||
<p>When launched from the top level you don’t need to catch any errors, but you still have to use <code>try</code>.</p>
|
||
<a href='#the-terminal' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='the-terminal'>The Terminal</h3>
|
||
<a href='#setup' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h2 id='setup'>Setup</h2>
|
||
|
||
<p>One of the goals of SwiftShell is to be able to run single .swift files directly, like you do with bash and Python files. This is possible now, but every time you upgrade Xcode or Swift you have to recompile all the third party frameworks your Swift script files use (including the SwiftShell framework). This will continue to be a problem until Swift achieves ABI stability in (hopefully) version 5. For now it is more practical to precompile the script into a self-contained executable.</p>
|
||
<a href='#pre-compiled-executable' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='pre-compiled-executable'>Pre-compiled executable</h3>
|
||
|
||
<p>If you put <a href="https://raw.githubusercontent.com/kareman/SwiftShell/master/Misc/swiftshell-init">Misc/swiftshell-init</a> somewhere in your $PATH you can create a new project with <code>swiftshell-init <name></code>. This creates a new folder, initialises a Swift Package Manager executable folder structure, downloads the latest version of SwiftShell, creates an Xcode project and opens it. After running <code>swift build</code> you can find the compiled executable at <code>.build/debug/<name></code>.</p>
|
||
<a href='#shell-script' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='shell-script'>Shell script</h3>
|
||
|
||
<ul>
|
||
<li>In the Terminal, go to where you want to download SwiftShell.</li>
|
||
<li><p>Run</p>
|
||
<pre class="highlight plaintext"><code>git clone https://github.com/kareman/SwiftShell.git
|
||
cd SwiftShell
|
||
</code></pre></li>
|
||
<li><p>Copy/link <code>Misc/swiftshell</code> to your bin folder or anywhere in your PATH.</p></li>
|
||
<li><p>To install the framework itself, run <code>xcodebuild</code> and copy the resulting framework from the build folder to your library folder of choice. If that is not <q>~/Library/Frameworks</q> or <q>/Library/Frameworks</q> then make sure the folder is listed in $SWIFTSHELL_FRAMEWORK_PATH.</p></li>
|
||
</ul>
|
||
|
||
<p>Then include this in the beginning of each script:</p>
|
||
<pre class="highlight swift"><code><span class="cp">#!/usr/bin/env swiftshell</span>
|
||
|
||
<span class="kd">import</span> <span class="kt">SwiftShell</span>
|
||
</code></pre>
|
||
<a href='#a-href-https-github-com-apple-swift-package-manager-swift-package-manager-a' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='a-href-https-github-com-apple-swift-package-manager-swift-package-manager-a'><a href="https://github.com/apple/swift-package-manager">Swift Package Manager</a></h3>
|
||
|
||
<p>Add <code>.Package(url: "https://github.com/kareman/SwiftShell", "3.0.0-beta")</code> to your Package.swift:</p>
|
||
<pre class="highlight swift"><code><span class="kd">import</span> <span class="kt">PackageDescription</span>
|
||
|
||
<span class="k">let</span> <span class="nv">package</span> <span class="o">=</span> <span class="kt">Package</span><span class="p">(</span>
|
||
<span class="nv">name</span><span class="p">:</span> <span class="s">"somecommandlineapp"</span><span class="p">,</span>
|
||
<span class="nv">dependencies</span><span class="p">:</span> <span class="p">[</span>
|
||
<span class="o">.</span><span class="kt">Package</span><span class="p">(</span><span class="nv">url</span><span class="p">:</span> <span class="s">"https://github.com/kareman/SwiftShell.git"</span><span class="p">,</span> <span class="s">"3.0.0-beta"</span><span class="p">)</span>
|
||
<span class="p">]</span>
|
||
<span class="p">)</span>
|
||
</code></pre>
|
||
|
||
<p>and run <code>swift build</code>.</p>
|
||
<a href='#a-href-https-github-com-carthage-carthage-carthage-a' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='a-href-https-github-com-carthage-carthage-carthage-a'><a href="https://github.com/Carthage/Carthage">Carthage</a></h3>
|
||
|
||
<p>Add <code>github "kareman/SwiftShell" "master"</code> to your Cartfile, then run <code>carthage update</code> and add the resulting framework to the <q>Embedded Binaries</q> section of the application. See <a href="https://github.com/Carthage/Carthage#adding-frameworks-to-an-application">Carthage’s README</a> for further instructions.</p>
|
||
<a href='#a-href-https-cocoapods-org-cocoapods-a' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h3 id='a-href-https-cocoapods-org-cocoapods-a'><a href="https://cocoapods.org/">CocoaPods</a></h3>
|
||
|
||
<p>Add <code>SwiftShell</code> to your <code>Podfile</code>.</p>
|
||
<pre class="highlight plaintext"><code>pod 'SwiftShell', '>= 3.0.0-beta'
|
||
</code></pre>
|
||
|
||
<p>Then run <code>pod install</code> to install it.</p>
|
||
<a href='#license' class='anchor' aria-hidden=true><span class="header-anchor"></span></a><h2 id='license'>License</h2>
|
||
|
||
<p>Released under the MIT License (MIT), <a href="http://opensource.org/licenses/MIT">http://opensource.org/licenses/MIT</a></p>
|
||
|
||
<p>Some files are covered by other licences, see <a href="Misc/Included%20Works">included works</a>.</p>
|
||
|
||
<p>Kåre Morstøl, <a href="http://nottoobadsoftware.com">NotTooBad Software</a></p>
|
||
|
||
</section>
|
||
</section>
|
||
<section id="footer">
|
||
<p>© 2017 <a class="link" href="" target="_blank" rel="external">kareman</a>. All rights reserved. (Last updated: 2017-04-05)</p>
|
||
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.7.3</a>, a <a class="link" href="http://realm.io" target="_blank" rel="external">Realm</a> project.</p>
|
||
</section>
|
||
</article>
|
||
</div>
|
||
</body>
|
||
</div>
|
||
</html>
|