diff --git a/SwiftShell/Command.swift b/SwiftShell/Command.swift index a43dac2..0b257e4 100644 --- a/SwiftShell/Command.swift +++ b/SwiftShell/Command.swift @@ -16,74 +16,3 @@ public func runLater (shellcommand: String) -> NSTask { return task } - -// TODO: explain thoroughly why this local state monstrosity is necessary. -// Summary: it is used exclusively for sending a stream through the forward operator and use it as standardInput in a run command. -// Required to enable "func run (shellcommand: String) -> ReadableStreamType" to also be run by itself on a single line. -private var _nextinput_: ReadableStreamType? - -/** -Specific handling of func run (shellcommand: String) -> ReadableStreamType on the right side using the stream on the -left side as standard input. - -Warning: is only meant to be used with the "run" command, but could also unintentionally catch other uses of -"ReadableStreamType |> ReadableStreamType", though that statement doesn't make any sense. -*/ -public func |> (lhs: ReadableStreamType, @autoclosure rhs: () -> ReadableStreamType) -> ReadableStreamType { - assert(_nextinput_ == nil) - _nextinput_ = lhs - let result = rhs() - if _nextinput_ != nil { - printErrorAndExit("The statement 'ReadableStreamType |> ReadableStreamType' is invalid.") - } - return result -} - -/** -Run a shell command synchronously with no standard input, -or if to the right of a "ReadableStreamType |> ", use the stream on the left side as standard input. - -- returns: Standard output -*/ -public func run (shellcommand: String) -> ReadableStreamType { - let task = runLater(shellcommand) - - if let input = _nextinput_ { - task.standardInput = input as! FileHandle - _nextinput_ = nil - } else { - // avoids implicit reading of the main script's standardInput - task.standardInput = NSPipe () - } - - let output = NSPipe () - task.standardOutput = output - task.launch() - - // necessary for now to ensure one shellcommand is finished before another begins. - // uncontrolled asynchronous shell processes could be messy. - // but shell commands on the same line connected with the pipe operator should preferably be asynchronous. - task.waitUntilExit() - - return output.fileHandleForReading -} - -/** Shortcut for in-line command, returns output as String. */ -public func $ (shellcommand: String) -> String { - let task = runLater(shellcommand) - - // avoids implicit reading of the main script's standardInput - task.standardInput = NSPipe () - - let output = NSPipe () - task.standardOutput = output - task.launch() - task.waitUntilExit() - - return output.fileHandleForReading.read().trim() -} - -/** Turn a sequence into valid parameters for a shell command, properly quoted */ -public func parameters (sequence: S) -> String { - return " " + " ".join( sequence.map { "\"\($0)\"" } ) -} diff --git a/SwiftShell/FileHandle.swift b/SwiftShell/FileHandle.swift index 7ad3eab..614182c 100644 --- a/SwiftShell/FileHandle.swift +++ b/SwiftShell/FileHandle.swift @@ -9,114 +9,3 @@ import Foundation -public typealias FileHandle = NSFileHandle - -extension FileHandle: ReadableStreamType { - - public func readSome () -> String? { - let data: NSData = self.availableData - if data.length == 0 { - return nil - } else { - if let result = NSString(data: data, encoding: streamencoding) { - return result as String - } else { - printErrorAndExit("Fatal error - could not read stream.") - } - } - } - - public func read () -> String { - let data: NSData = self.readDataToEndOfFile() - if let result = NSString(data: data, encoding: streamencoding) { - return result as String - } else { - printErrorAndExit("Fatal error - could not read stream.") - } - } - - public func lines () -> AnySequence { - return split("\n")(stream: self) - } - - public func writeTo (inout target: Target) { - while let some = self.readSome() { - target.write(some) - } - } -} - -extension FileHandle: WriteableStreamType { - - public func write (string: String) { - writeData(string.dataUsingEncoding(streamencoding, allowLossyConversion:false)!) - } - - public func writeln (string: String) { - self.write(string + "\n") - } - - public func writeln () { - self.write("\n") - } - - public func closeStream () { - self.closeFile() - } -} - -/** Print message to standard error and halt execution. */ -@noreturn public func printErrorAndExit (errormessage: T) { - standarderror.writeln("SwiftShell: \(errormessage)") - exit(EXIT_FAILURE) -} - -/** Open a file for reading, and exit if an error occurs. */ -public func open (path: String) -> ReadableStreamType { - - let url = toURLOrError(path) - do { - let filehandle = try FileHandle(forReadingFromURL: url) - return filehandle - } catch { - do { - try url.checkResourceIsReachable() - } catch { - printErrorAndExit(error) - } - printErrorAndExit(error) - } -} - -/** -Open a file for writing, create it if it doesn't exist, and exit if an error occurs. -If the file already exists and overwrite=false, the writing will begin at the end of the file. - -- parameter overwrite: If true, replace the file if it exists. -*/ -public func open (forWriting path: String, overwrite: Bool = false) -> WriteableStreamType { - - let url = toURLOrError(path) - if overwrite || !File.fileExistsAtPath(url.path!) { - File.createFileAtPath(url.path!, contents: nil, attributes: nil) - } - - do { - let filehandle = try FileHandle(forWritingToURL: url) - filehandle.seekToEndOfFile() - return filehandle - } catch { - do { - try url.checkResourceIsReachable() - } catch { - printErrorAndExit(error) - } - printErrorAndExit(error) - } -} - - -public let environment = NSProcessInfo.processInfo().environment as [String: String] -public let standardinput = FileHandle.fileHandleWithStandardInput() as ReadableStreamType -public let standardoutput = FileHandle.fileHandleWithStandardOutput() as WriteableStreamType -public let standarderror = FileHandle.fileHandleWithStandardError() as WriteableStreamType diff --git a/SwiftShell/Files.swift b/SwiftShell/Files.swift index 152f376..618ec14 100644 --- a/SwiftShell/Files.swift +++ b/SwiftShell/Files.swift @@ -9,51 +9,6 @@ import Foundation -func toURLOrError (path: String) -> NSURL { - // no longer returns an optional. Weird. And it also seems to confuse the compiler (Swift 2 b2) - let result = NSURL.fileURLWithPath(path) - return result -} - /** The default NSFileManager */ -public let File = NSFileManager.defaultManager() +public let Files = NSFileManager.defaultManager() -/** -The tempdirectory is unique each time a script is run and is created the first time it is used. -It lies in the user's temporary directory and will be automatically deleted at some point. -*/ -public let tempdirectory: String = { - let tempdirectory = NSTemporaryDirectory() / "SwiftShell-" + NSProcessInfo.processInfo().globallyUniqueString - do { - try File.createDirectoryAtPath(tempdirectory, withIntermediateDirectories:true, attributes: nil) - } catch let error as NSError { - printErrorAndExit("Could not create new temporary directory '\(tempdirectory)':\n\(error.localizedDescription)") - } catch { - printErrorAndExit("Unexpected error: \(error)") - } - - return tempdirectory - }() - -/** -The current working directory. - -Must be used instead of `run("cd ...")` because all the `run` commands are executed in a -separate process and changing the directory there will not affect the rest of the Swift script. - -This directory is also used as the base for relative URL's. -*/ -public var workdirectory: String { - get { return File.currentDirectoryPath } - set { - if !File.changeCurrentDirectoryPath(newValue) { - printErrorAndExit("Could not change the working directory to \(newValue)") - } - } -} - - -/** Allows for `"/directory" / "file.extension"` etc. */ -public func / (leftpath: String, rightpath: String) -> String { - return toURLOrError(leftpath).URLByAppendingPathComponent(rightpath).path! -} diff --git a/SwiftShell/Pipes.swift b/SwiftShell/Pipes.swift deleted file mode 100644 index cc25ba1..0000000 --- a/SwiftShell/Pipes.swift +++ /dev/null @@ -1,107 +0,0 @@ -/* -* Released under the MIT License (MIT), http://opensource.org/licenses/MIT -* -* Copyright (c) 2014 Kåre Morstøl, NotTooBad Software (nottoobadsoftware.com) -* -* Contributors: -* Kåre Morstøl, https://github.com/kareman - initial API and implementation. -*/ - -/** -This file contains operators and functions inspired by Functional Programming. -It can be used on its own. -*/ - -infix operator |> { precedence 50 associativity left } - -public func |> (lhs: T, rhs: T -> U) -> U { - return rhs(lhs) -} - -/** Lazily return a sequence containing the elements of source, in order, that satisfy the predicate includeElement */ -public func filter - (includeElement: (S.Generator.Element) -> Bool) - (source: S) - -> LazySequence> { - - return lazy(source).filter(includeElement) -} - -/** -Return an `Array` containing the sorted elements of `source` according to 'isOrderedBefore'. - -Requires: `isOrderedBefore` is a `strict weak ordering -` over `elements`. -*/ -public func sorted - (isOrderedBefore: (S.Generator.Element, S.Generator.Element) -> Bool) - (source: S) - -> [S.Generator.Element] { - - return source.sort(isOrderedBefore) -} - -/** Lazily return a sequence containing the results of mapping transform over source. */ -public func map - (transform: (S.Generator.Element) -> T) - (source: S) - -> LazySequence> { - - return lazy(source).map(transform) -} - -/** -Return the result of repeatedly calling combine with an accumulated value -initialized to initial and each element of sequence, in turn. -*/ -public func reduce - (initial: U, combine: (U, S.Generator.Element) -> U) - (sequence: S) - -> U { - - return sequence.reduce(initial, combine: combine) -} - -/** Split text over delimiter, returning an array. */ -public func split (delimiter delimiter: String = "\n")(text: String) -> [String] { - return text.componentsSeparatedByString(delimiter) -} - -/** Insert separator between each item in elements. */ -public func join - (separator: C) - (elements: S) - -> C { - - return join(separator, elements) -} - -/** Turn a sequence into an array. For use after the |> operator. */ -public func toArray (sequence: S) -> [S.Generator.Element] { - return Array(sequence) -} - -/** Discard all elements in `tobedropped` from sequence. */ -public func drop - (tobedropped: [T]) - (sequence: S) - -> LazySequence> { - - return sequence |> filter { !tobedropped.contains($0) } -} - -/** Return at most the first `numbertotake` elements of sequence */ -public func take - (numbertotake: Int)(sequence: S) -> [T] { - - var generator = sequence.generate() - var result = [T]() - for _ in 0.. String? - - /** Read everything at once. */ - func read () -> String - - /** Lazily split the stream into lines. */ - func lines () -> AnySequence - - /** Enable stream to be used by "println" and "toString". */ - func writeTo (inout target: Target) -} - -/** An output stream, like standard output and standard error. */ -public protocol WriteableStreamType : OutputStreamType { - - func write (string: String) - - func writeln (string: String) - - func writeln () - - /** Must be called on local streams when finished writing. */ - func closeStream () -} - -/** Create a stream from a String. */ -public func stream (text: String) -> ReadableStreamType { - let pipe = NSPipe() - let input = pipe.fileHandleForWriting - input.write(text) - input.closeStream() - return pipe.fileHandleForReading -} - -/** -Create a stream from a function returning a generator function, which is called every time the stream is asked for more text. - -stream { - // initialisation... - return { - // called repeatedly by the resulting stream - // return text, or return nil when done. - } -} - -- returns: The output stream. -*/ -public func stream ( closure:() -> () -> String? ) -> ReadableStreamType { - let getmoretext = closure() - let pipe = NSPipe() - - let input: NSFileHandle = pipe.fileHandleForWriting - input.writeabilityHandler = { filehandle in - if let text = getmoretext() { - filehandle.write(text) - } else { - // close the stream - input.writeabilityHandler = nil - } - } - - return pipe.fileHandleForReading -} - -/** Create a stream from a sequence of Strings. */ -public func stream (sequence: Seq) -> ReadableStreamType { - return stream { - var generator = sequence.generate() - return { generator.next() } - } -} - -/** -Return a writable stream and a readable stream. What you write to the 1st one can be read from the 2nd one. -Make sure to call closeStream() on the writable stream before you call read() on the readable one. -*/ -public func streams () -> (WriteableStreamType, ReadableStreamType) { - let pipe = NSPipe() - return (pipe.fileHandleForWriting, pipe.fileHandleForReading) -} - - -/** Split a stream into parts separated by "delimiter". */ -struct StringStreamGenerator : GeneratorType { - private let stream: ReadableStreamType - private let delimiter: String - private var cache = "" - - init (stream: ReadableStreamType, delimiter: String = "\n") { - self.stream = stream - self.delimiter = delimiter - } - - /** Pass on the stream until the next occurrence of "delimiter" */ - mutating func next () -> String? { - let (nextpart, returneddelimiter, remainder) = cache.partition(delimiter) - let delimiterwasfound = returneddelimiter != "" - cache = remainder - - if delimiterwasfound { - return nextpart - } else { - if let newcache = stream.readSome() { - // add the next part of the stream to what's left of the previous one, - // and start again from the beginning of the function. - cache = nextpart + newcache - return next() - } else { - // the stream is empty and there are no more delimiters left. - // return whatever is left, or nil if empty. - return nextpart == "" ? nil : nextpart - } - } - } -} - -/** Split a stream lazily */ -public func split (delimiter: String = "\n")(stream: ReadableStreamType) -> AnySequence { - return AnySequence({StringStreamGenerator (stream: stream, delimiter: delimiter)}) -} - - -/** -Write something to a stream. - - something |> writeTo(writablestream) -*/ -public func writeTo (stream: WriteableStreamType)(input: T) { - stream.write( String(input) ) -} - -// needed to avoid `writeTo(SequenceType)` being called instead, -// treating the string as a sequence of characters. -/** Write a String to a writable stream. */ -public func writeTo (stream: WriteableStreamType)(input: String) { - stream.write(input) -} - -/** Write a sequence to a stream. */ -public func writeTo (stream: WriteableStreamType)(seq: S) { - for item in seq { - item |> writeTo(stream) - } -} - -infix operator |>> { precedence 50 associativity left } - -/** -Write something to a stream. - -something |>> writablestream -*/ -public func |>> (input: T, stream: WriteableStreamType) { - writeTo(stream)(input: input) -} - -// needed to avoid `func |>> ` being called instead, -// treating the string as a sequence of characters. -/** Write a String to a writable stream. */ -public func |>> (text: String, stream: WriteableStreamType) { - writeTo(stream)(input: text) -} - -/** Write a sequence to a stream. */ -public func |>> (seq: S, stream: WriteableStreamType) { - writeTo(stream)(seq: seq) -} diff --git a/SwiftShell/String.swift b/SwiftShell/String.swift index 5ce318c..614182c 100644 --- a/SwiftShell/String.swift +++ b/SwiftShell/String.swift @@ -9,61 +9,3 @@ import Foundation -extension String { - - public func replace (oldString: String, _ newString: String) -> String { - return self.stringByReplacingOccurrencesOfString(oldString, withString: newString) - } - - /** Replace the first `limit` occurrences of oldString with newString. */ - public func replace (oldString: String, _ newString: String, limit: Int) -> String { - let ranges = self.findAll(oldString) |> take(limit) - return ranges.count == 0 - ? self - : self.stringByReplacingOccurrencesOfString(oldString, withString: newString, - range: ranges.first!.startIndex ..< ranges.last!.endIndex) - } - - public func split (sep: String) -> [String] { - return self.componentsSeparatedByString(sep) - } - - public func trim () -> String { - return self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) - } - - public func countOccurrencesOf (substring: String) -> Int { - return (self.findAll(substring) |> toArray).count - } - - /** A lazy sequence of the ranges of `findstring` in this string. */ - public func findAll (findstring: String) -> AnySequence> { - var rangeofremainder: Range = self.startIndex.. (String, String, String) { - if let separatorRange = self.rangeOfString(separator) { - if !separatorRange.isEmpty { - let firstpart = self[self.startIndex ..< separatorRange.startIndex] - let secondpart = self[separatorRange.endIndex ..< self.endIndex] - - return (firstpart, separator, secondpart) - } - } - return (self,"","") - } -} - diff --git a/SwiftShell2.xcodeproj/project.pbxproj b/SwiftShell2.xcodeproj/project.pbxproj index cb5c638..91d2933 100644 --- a/SwiftShell2.xcodeproj/project.pbxproj +++ b/SwiftShell2.xcodeproj/project.pbxproj @@ -11,7 +11,6 @@ BA2E3B331B5C35CC001ED175 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2E3B2D1B5C35CC001ED175 /* Command.swift */; }; BA2E3B341B5C35CC001ED175 /* FileHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2E3B2E1B5C35CC001ED175 /* FileHandle.swift */; }; BA2E3B351B5C35CC001ED175 /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2E3B2F1B5C35CC001ED175 /* Files.swift */; }; - BA2E3B361B5C35CC001ED175 /* Pipes.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2E3B301B5C35CC001ED175 /* Pipes.swift */; }; BA2E3B371B5C35CC001ED175 /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2E3B311B5C35CC001ED175 /* Stream.swift */; }; BA2E3B381B5C35CC001ED175 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2E3B321B5C35CC001ED175 /* String.swift */; }; BA2E3B431B5C3635001ED175 /* Command_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2E3B391B5C3635001ED175 /* Command_Tests.swift */; }; @@ -44,7 +43,6 @@ BA2E3B2D1B5C35CC001ED175 /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = ""; }; BA2E3B2E1B5C35CC001ED175 /* FileHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileHandle.swift; sourceTree = ""; }; BA2E3B2F1B5C35CC001ED175 /* Files.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Files.swift; sourceTree = ""; }; - BA2E3B301B5C35CC001ED175 /* Pipes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pipes.swift; sourceTree = ""; }; BA2E3B311B5C35CC001ED175 /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; BA2E3B321B5C35CC001ED175 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; BA2E3B391B5C3635001ED175 /* Command_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command_Tests.swift; sourceTree = ""; }; @@ -104,7 +102,6 @@ BA2E3B2D1B5C35CC001ED175 /* Command.swift */, BA2E3B2E1B5C35CC001ED175 /* FileHandle.swift */, BA2E3B2F1B5C35CC001ED175 /* Files.swift */, - BA2E3B301B5C35CC001ED175 /* Pipes.swift */, BA2E3B311B5C35CC001ED175 /* Stream.swift */, BA2E3B321B5C35CC001ED175 /* String.swift */, BA2E3B1A1B5C34DD001ED175 /* Info.plist */, @@ -242,7 +239,6 @@ BA2E3B331B5C35CC001ED175 /* Command.swift in Sources */, BA2E3B341B5C35CC001ED175 /* FileHandle.swift in Sources */, BA2E3B351B5C35CC001ED175 /* Files.swift in Sources */, - BA2E3B361B5C35CC001ED175 /* Pipes.swift in Sources */, BA2E3B371B5C35CC001ED175 /* Stream.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/SwiftShellTests/Command_Tests.swift b/SwiftShellTests/Command_Tests.swift index f8cf869..4b11083 100644 --- a/SwiftShellTests/Command_Tests.swift +++ b/SwiftShellTests/Command_Tests.swift @@ -11,39 +11,4 @@ import XCTest class Command_Tests: XCTestCase { - func testSimpleCommand () { - SwiftShell.run("echo") - } - - func testSimpleCommandWithOutput () { - XCTAssertEqual( SwiftShell.run("echo this is streamed").read(), "this is streamed\n" ) - } - - func testChainedCommands () { - let result = SwiftShell.run("echo this is streamed") |> SwiftShell.run("wc -w") - XCTAssertEqual( result.read().trim(), "3", "the number of words should be 3" ) - } - - func testInlineCommand () { - XCTAssertEqual( $("echo one"), "one" ) - } - - func testInlineCommandInsideRunCommandAfterPipe () { - let result = stream("line 1\nline 2\nline 3") |> SwiftShell.run("grep " + $("echo 2")) - XCTAssertEqual( result.read(), "line 2\n" ) - } - - func testParametersFromSequenceOfStrings () { - XCTAssertEqual( parameters(["one", "two", "three"]), " \"one\" \"two\" \"three\"" ) - } - - func testParametersFromSequenceOfStreams () { - let result = AnySequence( [stream("one"), stream("two"), stream("three")].generate() ) |> parameters - - XCTAssertEqual( result, " \"one\" \"two\" \"three\"" ) - } - - func testParametersFromSequenceOfNumbers () { - XCTAssertEqual( parameters([1, 2, 3]), " \"1\" \"2\" \"3\"" ) - } } diff --git a/SwiftShellTests/FileHandle_Tests.swift b/SwiftShellTests/FileHandle_Tests.swift index 07d506f..dad49aa 100644 --- a/SwiftShellTests/FileHandle_Tests.swift +++ b/SwiftShellTests/FileHandle_Tests.swift @@ -11,60 +11,5 @@ import XCTest class FileHandle_Tests: XCTestCase { - func notestOpenForReadingFileWhichDoesNotExist () { - // prints error message and stops execution. - open("file which does not exist") - } - - func testReadFileLineByLine () { - let shorttextpath = pathForTestResource("shorttext", type: "txt") - var contents = "" - - for line in open(shorttextpath).lines() { - contents.write(line) - } - XCTAssertFalse(contents.isEmpty, "could not read from file") - } - - - func testOpenForWritingFileWhichDoesNotExist () { - let path = tempdirectory + "/testOpenForWritingFileWhichDoesNotExist.txt" - let file = open(forWriting: path) - file.writeln( "line 1") - file.closeStream() - - XCTAssertEqual( open(path).read(), "line 1\n" ) - } - - func testOpenForOverWritingFileWhichDoesNotExist () { - let path = tempdirectory + "/testOpenForOverWritingFileWhichDoesNotExist.txt" - let file = open(forWriting: path, overwrite: true) - file.writeln( "line 1") - file.closeStream() - - XCTAssertEqual( open(path).read(), "line 1\n" ) - } - - func testOpenForWritingExistingFile_AppendsFile () { - let path = tempdirectory + "/testOpenForWritingExistingFile_AppendsFile.txt" - SwiftShell.run("echo existing line > " + path) - - let file = open(forWriting: path) - file.writeln( "new line") - file.closeStream() - - XCTAssertEqual( open(path).read(), "existing line\nnew line\n" ) - } - - func testOpenForOverWritingExistingFile () { - let path = tempdirectory + "/testOpenForOverWritingExistingFile.txt" - SwiftShell.run("echo existing line > " + path) - - let file = open(forWriting: path, overwrite: true) - file.writeln( "new line") - file.closeStream() - - XCTAssertEqual( open(path).read(), "new line\n" ) - } } diff --git a/SwiftShellTests/Files_Tests.swift b/SwiftShellTests/Files_Tests.swift index ab0587c..431704f 100644 --- a/SwiftShellTests/Files_Tests.swift +++ b/SwiftShellTests/Files_Tests.swift @@ -11,24 +11,4 @@ import XCTest class Files_Tests: XCTestCase { - func testTempDirectory_IsTheSameAfterRepeatedCalls () { - XCTAssertEqual( tempdirectory, tempdirectory ) - } - - func testWorkDirectory_IsCurrentDirectory () { - XCTAssertEqual( workdirectory, NSFileManager.defaultManager().currentDirectoryPath ) - } - - func testWorkDirectory_CanChange () { - workdirectory = "/tmp" - - XCTAssertEqual( workdirectory, "/private/tmp" ) - XCTAssertEqual( $("pwd"), "/tmp" ) - } - - func testURLConcatenationOperator () { - XCTAssertEqual( "/directory" / "file.extension", "/directory/file.extension" ) - XCTAssertEqual( "/root" / "directory" / "file.extension", "/root/directory/file.extension" ) - XCTAssertEqual( "directory" / "file.extension", workdirectory + "/directory/file.extension" ) - } } diff --git a/SwiftShellTests/Pipes_Tests.swift b/SwiftShellTests/Pipes_Tests.swift index 5556bcb..0823241 100644 --- a/SwiftShellTests/Pipes_Tests.swift +++ b/SwiftShellTests/Pipes_Tests.swift @@ -11,47 +11,5 @@ import XCTest class Pipes_Tests: XCTestCase { - /* - func testSplitMapFilterSortedAndJoinWithPipeForwardOperator () { - let numbers = "4,1,6,2,5,3,9,7,0,8" - - // doing this on one line takes a very very long time to compile (6.1 beta 2) - let numberslessthan5 = numbers |> split(delimiter: ",") |> map {Int($0)!} |> filter {$0<5} - let result = numberslessthan5 |> sorted {$0>$1} |> map {String($0)!} |> join(",") - - XCTAssertEqual( result, "4,3,2,1,0" ) - } - */ - func testSplitAndReduceWithPipeForwardOperator () { - let numbers = "4,1,6,2,5,3,9,7,0,8" - - let result = numbers |> split(delimiter: ",") |> reduce(0) {$0 + Int($1)!} - - XCTAssertEqual( result, 45 ) - } - - func testTurnSequenceIntoArray () { - let numbers = [4,1,6] - - let result = AnySequence(numbers) |> toArray - - XCTAssertEqual( result, [4,1,6] ) - } - - func testDrop () { - let numbers = [1,2,3,4,5,6] - - let result = numbers |> drop([2,3,5]) |> toArray - - XCTAssertEqual( result, [1,4,6] ) - } - - func testTake () { - let numbers = [1,2,3,4,5,6] - - XCTAssertEqual( numbers |> take(3), [1,2,3] ) - XCTAssertEqual( numbers |> take(100), [1,2,3,4,5,6] ) - XCTAssertEqual( numbers |> take(0), [] ) - } } diff --git a/SwiftShellTests/Stream_Iteration_Tests.swift b/SwiftShellTests/Stream_Iteration_Tests.swift index 56ffe3d..9a95c2c 100644 --- a/SwiftShellTests/Stream_Iteration_Tests.swift +++ b/SwiftShellTests/Stream_Iteration_Tests.swift @@ -11,30 +11,6 @@ import SwiftShell class Stream_Iteration_Tests: XCTestCase { - func testIterateOverFileHandle () { - var filehandletest = "" - - for line in stream("line 1\nline 2\n").lines() { - filehandletest += line + "\n" - } - XCTAssertEqual(filehandletest , "line 1\nline 2\n") - - XCTAssertEqual(["line 1","line 2"] , Array(stream("line 1\nline 2").lines())) - XCTAssertEqual(["line 1"] , Array(stream("line 1\n").lines())) - XCTAssertEqual(["line 1"] , Array(stream("line 1").lines())) - XCTAssertEqual(["line 1", "", "line 3"] , Array(stream("line 1\n\nline 3").lines())) - XCTAssertEqual(["", "line 2", "line 3"] , Array(stream("\nline 2\nline 3").lines())) - XCTAssertEqual(["", "", "line 3"] , Array(stream("\n\nline 3").lines())) - } - - func testIterateOverStreamInPieces () { - XCTAssertEqual(["line 1","line 2"] , Array(stream(["line"," 1\nline 2"]).lines())) - XCTAssertEqual(["line 1"] , Array(stream(["line 1","\n"]).lines())) - XCTAssertEqual(["line 1"] , Array(stream(["li","ne"," 1"]).lines())) - XCTAssertEqual(["line 1", "", "line 3"] , Array(stream(["line 1\n","\n","line 3"]).lines())) - XCTAssertEqual(["line 1", "", "line 3"] , Array(stream(["line 1\n","\nline 3"]).lines())) - XCTAssertEqual(["", "line 2", "line 3"] , Array(stream(["\nline 2\n","line 3"]).lines())) - XCTAssertEqual(["", "", "line 3"] , Array(stream(["\n","\nli","ne 3"]).lines())) - } + } diff --git a/SwiftShellTests/Stream_Tests.swift b/SwiftShellTests/Stream_Tests.swift index 58a35c7..7631ee1 100644 --- a/SwiftShellTests/Stream_Tests.swift +++ b/SwiftShellTests/Stream_Tests.swift @@ -10,90 +10,5 @@ import SwiftShell import XCTest class Stream_Tests: XCTestCase { - - func testStreamFromAString () { - XCTAssertEqual( "this is a string", stream("this is a string").read() ) - XCTAssertEqual( "These are weird↔️🐻♨︎", stream("These are weird↔️🐻♨︎").read() ) - } - - func testCustomStream () { - let result = stream ({ - var finished = false - return { - if !finished { - finished = true - return "this is it" - } else { - return nil - } - } - }) - XCTAssertEqual( result.read(), "this is it" ) - } - - func testStreamFromArray () { - XCTAssertEqual( stream(["item 1","item 2"]).read(), "item 1item 2" ) - } - - func testPrintStreamToStream () { - let (writable, readable) = streams() - - stream("this goes in") |>> writable - - XCTAssertEqual( readable.readSome()!, "this goes in" ) - } - func testPrintStreamToStreamInPieces () { - let (writable, readable) = streams() - - stream(["this ", "goes", " in"]) |>> writable - - writable.closeStream() - XCTAssertEqual( readable.read(), "this goes in" ) - } - - func testPrintStringToStream () { - let (writable, readable) = streams() - - "this goes in" |>> writable - - XCTAssertEqual( readable.readSome()!, "this goes in" ) - } - - func testCommandChainToStream () { - let (writable, readable) = streams() - - SwiftShell.run("echo this is streamed") |> SwiftShell.run("wc -w") |>> writable - - XCTAssertEqual( readable.readSome()!.trim(), "3" ) - } - - func testSequenceOfStreamsToStream () { - let (writable, readable) = streams() - - // make sure the array isn't printed as a Printable. - AnySequence([stream("line 1"), stream("line 2"), stream("line 3")].generate()) |>> writable - - XCTAssertEqual( readable.readSome()!.trim(), "line 1line 2line 3" ) - } - - func testChainWithSequenceOfStreamsPrintedToStream () { - let (writable, readable) = streams() - let dict = ["test":"line 1:line 2:line 3"] - - dict["test"]! |> split(delimiter: ":") - |> map { line in SwiftShell.run("echo \(line)") } - |>> writable - - XCTAssertEqual( readable.readSome()!.trim(), "line 1\nline 2\nline 3" ) - } - - func testChainWithSequenceOfStringsPrintedToStream () { - let (writable, readable) = streams() - var i = 1 - - stream("line 1\nline 2\nline 3").lines() |> map {line in "line \(i++): \(line)\n"} |>> writable - - XCTAssertEqual( readable.readSome()!.trim(), "line 1: line 1\nline 2: line 2\nline 3: line 3" ) - } } diff --git a/SwiftShellTests/String_Partition_Tests.swift b/SwiftShellTests/String_Partition_Tests.swift index 518eb5c..ed3a15b 100644 --- a/SwiftShellTests/String_Partition_Tests.swift +++ b/SwiftShellTests/String_Partition_Tests.swift @@ -11,52 +11,6 @@ import SwiftShell class String_Partition_Tests: XCTestCase { - func testPartitionWithSeparatorInTheMiddle () { - let text = "the first part\nthe second part" - let (firstpart, returnedseparator, secondpart) = text.partition ("\n") - XCTAssertEqual( firstpart, "the first part") - XCTAssertEqual( returnedseparator, "\n") - XCTAssertEqual( secondpart, "the second part") - } - - func testPartitionWithNoSeparatorFound () { - let text = "the first partthe second part" - let (firstpart, returnedseparator, secondpart) = text.partition ("\n") - XCTAssertEqual( firstpart, "the first partthe second part") - XCTAssertEqual( returnedseparator, "") - XCTAssertEqual( secondpart, "") - } - - func testPartitionWithSeparatorAtTheEnd () { - let text = "the first partthe second part\n" - let (firstpart, returnedseparator, secondpart) = text.partition ("\n") - XCTAssertEqual( firstpart, "the first partthe second part") - XCTAssertEqual( returnedseparator, "\n") - XCTAssertEqual( secondpart, "") - } - - func testPartitionWithSeparatorAtTheBeginning () { - let text = "\nthe first partthe second part\n" - let (firstpart, returnedseparator, secondpart) = text.partition ("\n") - XCTAssertEqual( firstpart, "") - XCTAssertEqual( returnedseparator, "\n") - XCTAssertEqual( secondpart, "the first partthe second part\n") - } - - func testPartitionWithSeveralSeparators () { - let text = "the first partthe second part" - let (firstpart, returnedseparator, secondpart) = text.partition ("part") - XCTAssertEqual( firstpart, "the first ") - XCTAssertEqual( returnedseparator, "part") - XCTAssertEqual( secondpart, "the second part") - } - - func testPartitionWithEmptyText () { - let text = "" - let (firstpart, returnedseparator, secondpart) = text.partition ("part") - XCTAssertEqual( firstpart, "") - XCTAssertEqual( returnedseparator, "") - XCTAssertEqual( secondpart, "") - } + } diff --git a/SwiftShellTests/String_Tests.swift b/SwiftShellTests/String_Tests.swift index 689af12..718f31b 100644 --- a/SwiftShellTests/String_Tests.swift +++ b/SwiftShellTests/String_Tests.swift @@ -11,53 +11,4 @@ import SwiftShell class String_Tests: XCTestCase { - func testCountOccurrencesOfStringInstring () { - let text = "how many are there here" - - XCTAssertEqual( text.countOccurrencesOf( "e"), 5 ) - XCTAssertEqual( text.countOccurrencesOf( "x"), 0 ) - XCTAssertEqual( text.countOccurrencesOf( "h"), 3 ) - XCTAssertEqual( text.countOccurrencesOf( "ho"), 1 ) - XCTAssertEqual( text.countOccurrencesOf( "re"), 3 ) - XCTAssertEqual( text.countOccurrencesOf( "Not found"), 0 ) - } - - func testFindAll () { - - func ranges(findstring: String) -> [Range] { - let text = "a b c aa bbb cc ab bc ca" - return text.findAll(findstring) |> toArray - } - - XCTAssertEqual( ranges("a").count, 5 ) - XCTAssertEqual( ranges("bb").count, 1 ) - XCTAssertEqual( ranges("a ").count, 2 ) - } - - - func testReplaceStringwithstring () { - let text = "a b c aa bb cc ab bc ca" - - XCTAssertEqual( text.replace("a", "x"), "x b c xx bb cc xb bc cx" ) - XCTAssertEqual( text.replace("b ", "x"), "a xc aa bxcc axbc ca" ) - } - - func testReplaceOnlySomeStringsWithString () { - let text = "a b c aa bb cc ab bc ca" - - XCTAssertEqual( text.replace("a", "x", limit: 0), "a b c aa bb cc ab bc ca" ) - XCTAssertEqual( text.replace("a", "x", limit: 2), "x b c xa bb cc ab bc ca" ) - XCTAssertEqual( text.replace("a", "x", limit: 4), "x b c xx bb cc xb bc ca" ) - XCTAssertEqual( text.replace("a", "x", limit: 5), "x b c xx bb cc xb bc cx" ) - XCTAssertEqual( text.replace("a", "x", limit: 6), "x b c xx bb cc xb bc cx" ) - - XCTAssertEqual( text.replace("a", "[xy]", limit: 4), "[xy] b c [xy][xy] bb cc [xy]b bc ca" ) - XCTAssertEqual( text.replace("a", "[xy]", limit: 5), "[xy] b c [xy][xy] bb cc [xy]b bc c[xy]" ) - XCTAssertEqual( text.replace("a", "[xy]", limit: 6), "[xy] b c [xy][xy] bb cc [xy]b bc c[xy]" ) - - XCTAssertEqual( text.replace("a ", "x", limit: 0), "a b c aa bb cc ab bc ca" ) - XCTAssertEqual( text.replace("a ", "x", limit: 1), "xb c aa bb cc ab bc ca" ) - XCTAssertEqual( text.replace("a ", "x", limit: 2), "xb c axbb cc ab bc ca" ) - XCTAssertEqual( text.replace("a ", "x", limit: 3), "xb c axbb cc ab bc ca" ) - } }