Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SimpleProgressBar for dumb terminals #1489

Merged
merged 2 commits into from
Feb 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion Sources/Basic/TerminalController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ import func POSIX.getenv
/// Allows operations like cursor movement and colored text output on tty.
public final class TerminalController {

/// The type of terminal.
public enum TerminalType {
/// The terminal is a TTY.
case tty

/// TERM enviornment variable is set to "dumb".
case dumb

/// The terminal is a file stream.
case file
}

/// Terminal color choices.
public enum Color {
case noColor
Expand Down Expand Up @@ -70,7 +82,16 @@ public final class TerminalController {

/// Checks if passed file stream is tty.
public static func isTTY(_ stream: LocalFileOutputByteStream) -> Bool {
return isatty(fileno(stream.filePointer)) != 0
return terminalType(stream) == .tty
}

/// Computes the terminal type of the stream.
public static func terminalType(_ stream: LocalFileOutputByteStream) -> TerminalType {
if POSIX.getenv("TERM") == "dumb" {
return .dumb
}
let isTTY = isatty(fileno(stream.filePointer)) != 0
return isTTY ? .tty : .file
}

/// Tries to get the terminal width first using COLUMNS env variable and
Expand Down
4 changes: 2 additions & 2 deletions Sources/Commands/SwiftTestTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ final class ParallelTestRunner {
init(testPath: AbsolutePath, processSet: ProcessSet) {
self.testPath = testPath
self.processSet = processSet
progressBar = createProgressBar(forStream: stdoutStream, header: "Tests")
progressBar = createProgressBar(forStream: stdoutStream, header: "Testing:")
}

/// Whether to display output from successful tests.
Expand Down Expand Up @@ -539,7 +539,7 @@ final class ParallelTestRunner {

// Wait till all threads finish execution.
workers.forEach { $0.join() }
progressBar.complete()
progressBar.complete(success: outputs.failure.isEmpty)

if shouldOutputSuccess {
printOutput(outputs.success)
Expand Down
57 changes: 53 additions & 4 deletions Sources/Utility/ProgressBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,44 @@ import Basic
/// A protocol to operate on terminal based progress bars.
public protocol ProgressBarProtocol {
func update(percent: Int, text: String)
func complete()
func complete(success: Bool)
}

/// A single line progress bar.
public final class SingleLineProgressBar: ProgressBarProtocol {
private let header: String
private var isClear: Bool
private var stream: OutputByteStream
private var displayed: Set<Int> = []

init(stream: OutputByteStream, header: String) {
self.stream = stream
self.header = header
self.isClear = true
}

public func update(percent: Int, text: String) {
if isClear {
stream <<< header
stream <<< "\n"
stream.flush()
isClear = false
}

let displayPercentage = Int(Double(percent / 10).rounded(.down)) * 10
if percent != 100, !displayed.contains(displayPercentage) {
stream <<< String(displayPercentage) <<< ".. "
displayed.insert(displayPercentage)
}
stream.flush()
}

public func complete(success: Bool) {
if success {
stream <<< "OK"
stream.flush()
}
}
}

/// Simple ProgressBar which shows the update text in new lines.
Expand Down Expand Up @@ -41,7 +78,7 @@ public final class SimpleProgressBar: ProgressBarProtocol {
stream.flush()
}

public func complete() {
public func complete(success: Bool) {
}
}

Expand Down Expand Up @@ -90,15 +127,27 @@ public final class ProgressBar: ProgressBarProtocol {
term.moveCursor(up: 1)
}

public func complete() {
public func complete(success: Bool) {
term.endLine()
}
}

/// Creates colored or simple progress bar based on the provided output stream.
public func createProgressBar(forStream stream: OutputByteStream, header: String) -> ProgressBarProtocol {
if let stdStream = stream as? LocalFileOutputByteStream, let term = TerminalController(stream: stdStream) {
guard let stdStream = stream as? LocalFileOutputByteStream else {
return SimpleProgressBar(stream: stream, header: header)
}

// If we have a terminal, use animated progress bar.
if let term = TerminalController(stream: stdStream) {
return ProgressBar(term: term, header: header)
}

// If the terminal is dumb, use single line progress bar.
if TerminalController.terminalType(stdStream) == .dumb {
return SingleLineProgressBar(stream: stream, header: header)
}

// Use simple progress bar by default.
return SimpleProgressBar(stream: stream, header: header)
}
2 changes: 1 addition & 1 deletion Tests/UtilityTests/ProgressBarTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ final class ProgressBarTests: XCTestCase {
for i in 0...5 {
bar.update(percent: i, text: String(i))
}
bar.complete()
bar.complete(success: true)
}

static var allTests = [
Expand Down