sebsto / CLIlib

A library to build command line tools in Swift

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Build And Test language platform license

CLIlib

A set of classes to build command-line (CLI) applications in Swift.

User I/O

Displaying information to users

public protocol DisplayProtocol {
    func display(_ msg: String, terminator: String)
}

Requesting information from users

public protocol ReadLineProtocol {
    func readLine(prompt: String, silent: Bool) -> String?
}

Example usage

// the display implementation to display messages to users, allows to inject a mock for testing
var display: DisplayProtocol = Display()

// the input function to collect user entry, allows to inject a mocked implementation for testing
var input: ReadLineProtocol = ReadLine()

display("Retrieving Apple Developer Portal credentials...")

guard let username = input.readLine(prompt: "⌨️  Enter your Apple ID username: ", silent: false) else {
    throw CLIError.invalidInput
}

guard let password = input.readLine(prompt: "⌨️  Enter your Apple ID password: ", silent: true) else {
    throw CLIError.invalidInput
}

enum CLIError: Error {
    case invalidInput
}

ProgressBar

public enum ProgressBarType {
    
    // 30% [============--------------------]
    case percentProgressAnimation
    
    // [ 1/2 ]
    case countingProgressAnimation

    // [ 1/2 ]
    // [ 2/2 ]
    case countingProgressAnimationMultiLine
}
public protocol ProgressUpdateProtocol {
    /// Update the animation with a new step.
    /// - Parameters:
    ///   - step: The index of the operation's current step.
    ///   - total: The total number of steps before the operation is complete.
    ///   - text: The description of the current step.
    func update(step: Int, total: Int, text: String)

    /// Complete the animation.
    /// - Parameters:
    ///   - success: Defines if the operation the animation represents was succesful.
    func complete(success: Bool)

    /// Clear the animation.
    func clear()
}

Example Usage

let stream: OutputBuffer = FileHandle.standardOutput
let progress = ProgressBar(output: stream, progressBarType: .percentProgressAnimation, title: "Downloading...")
progress.update(1, 10, "Downloading...")
...
progress.update(10, 10, "Downloading...")
progress.complete(true)

Shell

Asynchronously run shell commands.

public protocol AsyncShellProtocol: ShellProtocol {
    func run(_ command: String,
             onCompletion: ((Process) -> Void)?,
             onOutput: ((String) -> Void)?,
             onError: ((String) -> Void)?
            ) throws -> Process
}

Example Usage

public func run(_ command: String) throws -> ShellOutput {

    var stdOutBuffer: String = ""
    var stdErrBuffer: String = ""
    var result: ShellOutput?
    
    let sema: DispatchSemaphoreProtocol = DispatchSemaphore( value: 0 )
    
    let shell = AsyncShell()
    let process = try shell.run(command,
                                onCompletion: { process in
        result = ShellOutput(out: stdOutBuffer, err: stdErrBuffer, code: process.terminationStatus)
        _ = sema.signal()
    },
                                onOutput: { string in
        stdOutBuffer += string
    },
                                onError: { string in
        stdErrBuffer += string
    })
    
    process.waitUntilExit()
    
    // wait for onCompletion callback to finish
    sema.wait()
    
    guard let res = result else {
        fatalError("Process finished but there is no output!")
    }
    return res
}

About

A library to build command line tools in Swift

License:Apache License 2.0


Languages

Language:Swift 100.0%