Skip to content

Added ANSIColor and ColoredANSIStream for printing colored diagnostic messages #62

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

Merged
merged 1 commit into from
Feb 8, 2017
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
40 changes: 40 additions & 0 deletions Tests/LLVMTests/ANSIColor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Foundation

/// Represents the possible ANSI color codes.
enum ANSIColor: String {
case black = "\u{001B}[30m"
case red = "\u{001B}[31m"
case green = "\u{001B}[32m"
case yellow = "\u{001B}[33m"
case blue = "\u{001B}[34m"
case magenta = "\u{001B}[35m"
case cyan = "\u{001B}[36m"
case white = "\u{001B}[37m"
case bold = "\u{001B}[1m"
case reset = "\u{001B}[0m"

func name() -> String {
switch self {
case .black: return "Black"
case .red: return "Red"
case .green: return "Green"
case .yellow: return "Yellow"
case .blue: return "Blue"
case .magenta: return "Magenta"
case .cyan: return "Cyan"
case .white: return "White"
case .bold: return "Bold"
case .reset: return "Reset"
}
}

static func all() -> [ANSIColor] {
return [.black, .red, .green,
.yellow, .blue, .magenta,
.cyan, .white, .bold, .reset]
}
}

func + (left: ANSIColor, right: String) -> String {
return left.rawValue + right
}
79 changes: 79 additions & 0 deletions Tests/LLVMTests/ColoredStream.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import Foundation

/// Represents a stream that can write text with a specific set of ANSI colors
protocol ColoredStream: TextOutputStream {
mutating func write(_ string: String, with: [ANSIColor])
}

extension ColoredStream {
/// Default conformance to TextOutputStream
mutating func write(_ string: String) {
write(string, with: [])
}
}

/// An output stream that prints to an underlying stream including ANSI color
/// codes.
class ColoredANSIStream<StreamTy: TextOutputStream>: ColoredStream {

typealias StreamType = StreamTy

var currentColors = [ANSIColor]()
var stream: StreamType
let colored: Bool

/// Creates a new ColoredANSIStream that prints to an underlying stream.
///
/// - Parameters:
/// - stream: The underlying stream
/// - colored: Whether to provide any colors or to pass text through
/// unmodified. Set this to false and ColoredANSIStream is
/// a transparent wrapper.
init(_ stream: inout StreamType, colored: Bool = true) {
self.stream = stream
self.colored = colored
}

/// Initializes with a stream, always colored.
///
/// - Parameter stream: The underlying stream receiving writes.
required init(_ stream: inout StreamType) {
self.stream = stream
self.colored = true
}

/// Adds a color to the in-progress colors.
func addColor(_ color: ANSIColor) {
guard colored else { return }
stream.write(color.rawValue)
currentColors.append(color)
}

/// Resets this stream back to the default color.
func reset() {
if currentColors.isEmpty { return }
stream.write(ANSIColor.reset.rawValue)
currentColors = []
}

/// Sets the current ANSI color codes to the passed-in colors.
func setColors(_ colors: [ANSIColor]) {
guard colored else { return }
reset()
for color in colors {
stream.write(color.rawValue)
}
currentColors = colors
}

/// Writes the string to the output with the provided colors.
///
/// - Parameters:
/// - string: The string to write
/// - colors: The colors used on the string
func write(_ string: String, with colors: [ANSIColor]) {
self.setColors(colors)
stream.write(string)
self.reset()
}
}
24 changes: 21 additions & 3 deletions Tests/LLVMTests/FileCheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1224,16 +1224,34 @@ private struct CheckString {
}
}

private enum DiagnosticKind {
private enum DiagnosticKind: String {
case error
case warning
case note

var color: ANSIColor {
switch self {
case .error: return .red
case .warning: return .magenta
case .note: return .green
}
}
}

struct StdOutStream: TextOutputStream {
mutating func write(_ string: String) {
print(string, terminator: "")
}
}

var stdoutStream = StdOutStream()
var diagnosticStream = ColoredANSIStream(&stdoutStream)

private func diagnose(_ kind : DiagnosticKind, _ loc : CheckLoc, _ message : String) {
print(message)
diagnosticStream.write("\(kind): ", with: [.bold, kind.color])
diagnosticStream.write("\(message)\n", with: [.bold])
let msg = loc.message
if !msg.isEmpty {
print(msg)
diagnosticStream.write("\(msg)\n")
}
}