diff --git a/README.md b/README.md index f68c38c..31d9b51 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ print( "The time and date is " + $("date -u") ) #### Pipe several commands together ```swift -run("echo piped to the next command") |> run("wc -w") |> standardoutput +run("echo piped to the next command") |> run("wc -w") |> write(standardoutput) ``` #### Read a file line by line @@ -40,7 +40,7 @@ for line in open(filename).lines() { ```swift let directories = environment["PATH"]!.split(":") for directory in directories { - run("find \"\(directory)\" -type f -perm +ugo+x -print") |> standardoutput + run("find \"\(directory)\" -type f -perm +ugo+x -print") |> write(standardoutput) } ``` @@ -49,7 +49,7 @@ or more Functionally: ```swift environment["PATH"]! |> split(":") |> map { dir in run("find \"\(dir)\" -type f -perm +ugo+x -print") } - |> standardoutput + |> write(standardoutput) ``` #### Print standard input with line numbers @@ -62,6 +62,13 @@ for line in standardinput.lines() { } ``` +or + +```swift +var i = 1 +standardinput.lines() |> map {line in "line \(i++): \(line)\n"} |> write(standardoutput) +``` + Launch with e.g. `ls | print_linenumbers.swift` ## Installation diff --git a/SwiftShell/Stream.swift b/SwiftShell/Stream.swift index 9930ffb..9b4c849 100644 --- a/SwiftShell/Stream.swift +++ b/SwiftShell/Stream.swift @@ -40,7 +40,7 @@ public protocol WriteableStreamType : OutputStreamType { func write(string: String) - /** Must be called on local streams when done writing. */ + /** Must be called on local streams when finished writing. */ func closeStream() } @@ -141,13 +141,13 @@ public func split(delimiter: String = "\n")(stream: ReadableStreamType) -> Seque } /* crashes the compiler (6.1 beta). -Should replace other implementations of "|> (lhs: , rhs: WriteableStreamType)" +Should replace other implementations of "write (stream: WriteableStreamType)(input: ReadableStreamType)" as it is more general and will also work with strings. -public func |> (lhs: Streamable, inout rhs: OutputStreamType) { +public func write (stream: WriteableStreamType)(input: Streamable) { // specifically it's these that crash the compiler, not the function definition. -// lhs.writeTo(&rhs) -// print(lhs, &rhs) +// input.writeTo(&stream) +// print(input, &stream) } */ @@ -155,27 +155,35 @@ public func |> (lhs: Streamable, inout rhs: OutputStreamType) { /** Writes one stream to another. -readablestream |> writablestream +readablestream |> write(writablestream) */ -public func |> (lhs: ReadableStreamType, rhs: WriteableStreamType) { - while let some = lhs.readSome() { - rhs.write(some) +public func write (stream: WriteableStreamType)(input: ReadableStreamType) { + while let some = input.readSome() { + stream.write(some) } } /** Writes something Printable to a writable stream. */ -public func |> (lhs: Printable, rhs: WriteableStreamType) { - rhs.write(lhs.description) +public func write (stream: WriteableStreamType)(input: Printable) { + stream.write(input.description) } /** Writes a String to a writable stream. */ -public func |> (lhs: String, rhs: WriteableStreamType) { - rhs.write(lhs) +public func write (stream: WriteableStreamType)(input: String) { + stream.write(input) } -/** Writes a sequence of streams to another stream. */ -public func |> (lhs: S, rhs: WriteableStreamType) { - for stream in lhs { - stream |> rhs +/* Me and Swift (6.1 GM 2) are having a disagreement over whether or not it should be possible to define multiple functions which only differ in the generic “where” clause. Me and the language reference say yes, Swift says "Basic Block in function ' something something USs12SequenceType_USs13GeneratorType__FQ_Si' does not have terminator!". So until Swift comes to its senses there can only be one "write" function which takes a sequence, and that will have to be the unholy mess seen below. +*/ +/** Writes a sequence of streams or strings to another stream. */ +public func write (stream: WriteableStreamType)(seq: S) { + for item in seq { + if let inputstream = item as? FileHandle { + inputstream as ReadableStreamType |> write(stream) + } else if let text = item as? String { + stream.write(text) + } else { + preconditionFailure("SwiftShell error: Currently only sequences of strings and readable streams can be written directly to a writable stream with the global 'write' function") + } } } diff --git a/SwiftShellTests/Scripts/callswiftscriptfromswift.swift b/SwiftShellTests/Scripts/callswiftscriptfromswift.swift index 2b80ed4..2afc5f2 100755 --- a/SwiftShellTests/Scripts/callswiftscriptfromswift.swift +++ b/SwiftShellTests/Scripts/callswiftscriptfromswift.swift @@ -2,4 +2,4 @@ import SwiftShell -run("./listallexecutablesinpath.swift") |> run("./print_linenumbers.swift") |> standardoutput +run("./listallexecutablesinpath.swift") |> run("./print_linenumbers.swift") |> write(standardoutput) diff --git a/SwiftShellTests/Scripts/listallexecutablesinpath.swift b/SwiftShellTests/Scripts/listallexecutablesinpath.swift index 4608647..724523d 100755 --- a/SwiftShellTests/Scripts/listallexecutablesinpath.swift +++ b/SwiftShellTests/Scripts/listallexecutablesinpath.swift @@ -6,10 +6,10 @@ import SwiftShell let directories = environment["PATH"]!.split(":") for directory in directories { - run("find \"\(directory)\" -type f -perm +ugo+x -print") |> standardoutput + run("find \"\(directory)\" -type f -perm +ugo+x -print") |> write(standardoutput) } */ environment["PATH"]! |> split(":") |> map { directory in run("find \"\(directory)\" -type f -perm +ugo+x -print") } - |> standardoutput + |> write(standardoutput) diff --git a/SwiftShellTests/Scripts/print_linenumbers.swift b/SwiftShellTests/Scripts/print_linenumbers.swift index 4ff3593..91a9d36 100755 --- a/SwiftShellTests/Scripts/print_linenumbers.swift +++ b/SwiftShellTests/Scripts/print_linenumbers.swift @@ -2,9 +2,13 @@ import SwiftShell +/* var i = 1 for line in standardinput.lines() { print("line \(i++): ") println(line) } +*/ +var i = 1 +standardinput.lines() |> map {line in "line \(i++): \(line)\n"} |> write(standardoutput) diff --git a/SwiftShellTests/Scripts/stream_out.swift b/SwiftShellTests/Scripts/stream_out.swift index 136ea3b..65b2018 100755 --- a/SwiftShellTests/Scripts/stream_out.swift +++ b/SwiftShellTests/Scripts/stream_out.swift @@ -2,5 +2,5 @@ import SwiftShell -run("echo this is streamed") |> run("wc -w") |> standardoutput +run("echo this is streamed") |> run("wc -w") |> write(standardoutput) diff --git a/SwiftShellTests/Stream_Tests.swift b/SwiftShellTests/Stream_Tests.swift index 6effdf3..443375a 100644 --- a/SwiftShellTests/Stream_Tests.swift +++ b/SwiftShellTests/Stream_Tests.swift @@ -38,7 +38,7 @@ class Stream_Tests: XCTestCase { func testPrintStreamToStream () { var (writable, readable) = streams() - stream("this goes in") |> writable + stream("this goes in") |> write(writable) XCTAssertEqual( readable.readSome()!, "this goes in") } @@ -46,7 +46,7 @@ class Stream_Tests: XCTestCase { func testPrintStreamToStreamInPieces () { var (writable, readable) = streams() - stream(["this ", "goes", " in"]) |> writable + stream(["this ", "goes", " in"]) |> write(writable) writable.closeStream() XCTAssertEqual( readable.read(), "this goes in") @@ -55,7 +55,7 @@ class Stream_Tests: XCTestCase { func testPrintStringToStream () { var (writable, readable) = streams() - "this goes in" |> writable + "this goes in" |> write(writable) XCTAssertEqual( readable.readSome()!, "this goes in") } @@ -63,7 +63,7 @@ class Stream_Tests: XCTestCase { func testCommandChainToStream () { var (writable, readable) = streams() - SwiftShell.run("echo this is streamed") |> SwiftShell.run("wc -w") |> writable + SwiftShell.run("echo this is streamed") |> SwiftShell.run("wc -w") |> write(writable) XCTAssertEqual( readable.readSome()!.trim(), "3") } @@ -72,7 +72,7 @@ class Stream_Tests: XCTestCase { var (writable, readable) = streams() // make sure the array isn't printed as a Printable. - SequenceOf([stream("line 1"), stream("line 2"), stream("line 3")].generate()) |> writable + SequenceOf([stream("line 1"), stream("line 2"), stream("line 3")].generate()) |> write(writable) XCTAssertEqual( readable.readSome()!.trim(), "line 1line 2line 3") } @@ -83,9 +83,18 @@ class Stream_Tests: XCTestCase { dict["test"]! |> split(":") |> map { line in SwiftShell.run("echo \(line)") } - |> writable + |> write(writable) XCTAssertEqual( readable.readSome()!.trim(), "line 1\nline 2\nline 3") } + func testChainWithSequenceOfStringsPrintedToStream () { + var (writable, readable) = streams() + var i = 1 + + stream("line 1\nline 2\nline 3").lines() |> map {line in "line \(i++): \(line)\n"} |> write(writable) + + XCTAssertEqual( readable.readSome()!.trim(), "line 1: line 1\nline 2: line 2\nline 3: line 3") + } + }