@@ -2,78 +2,117 @@ import Foundation
22
33/// Represents a stream that can write text with a specific set of ANSI colors
44protocol ColoredStream : TextOutputStream {
5- mutating func write( _ string: String , with: [ ANSIColor ] )
5+ mutating func write( _ string: String , with: [ ANSIColor ] )
66}
77
88extension ColoredStream {
9- /// Default conformance to TextOutputStream
10- mutating func write( _ string: String ) {
11- write ( string, with: [ ] )
12- }
9+ /// Default conformance to TextOutputStream
10+ mutating func write( _ string: String ) {
11+ write ( string, with: [ ] )
12+ }
1313}
1414
1515/// An output stream that prints to an underlying stream including ANSI color
1616/// codes.
1717class ColoredANSIStream < StreamTy: TextOutputStream > : ColoredStream {
1818
19- typealias StreamType = StreamTy
19+ typealias StreamType = StreamTy
2020
21- var currentColors = [ ANSIColor] ( )
22- var stream : StreamType
23- let colored : Bool
21+ var currentColors = [ ANSIColor] ( )
22+ var stream : StreamType
23+ let colored : Bool
2424
25- /// Creates a new ColoredANSIStream that prints to an underlying stream.
26- ///
27- /// - Parameters:
28- /// - stream: The underlying stream
29- /// - colored: Whether to provide any colors or to pass text through
30- /// unmodified. Set this to false and ColoredANSIStream is
31- /// a transparent wrapper.
32- init ( _ stream: inout StreamType , colored: Bool = true ) {
33- self . stream = stream
34- self . colored = colored
35- }
25+ /// Creates a new ColoredANSIStream that prints to an underlying stream.
26+ ///
27+ /// - Parameters:
28+ /// - stream: The underlying stream
29+ /// - colored: Whether to provide any colors or to pass text through
30+ /// unmodified. Set this to false and ColoredANSIStream is
31+ /// a transparent wrapper.
32+ init ( _ stream: inout StreamType , colored: Bool = true ) {
33+ self . stream = stream
34+ self . colored = colored
35+ }
3636
37- /// Initializes with a stream, always colored.
38- ///
39- /// - Parameter stream: The underlying stream receiving writes.
40- required init ( _ stream: inout StreamType ) {
41- self . stream = stream
42- self . colored = true
43- }
37+ /// Initializes with a stream, always colored.
38+ ///
39+ /// - Parameter stream: The underlying stream receiving writes.
40+ required init ( _ stream: inout StreamType ) {
41+ self . stream = stream
42+ self . colored = true
43+ }
4444
45- /// Adds a color to the in-progress colors.
46- func addColor( _ color: ANSIColor ) {
47- guard colored else { return }
48- stream. write ( color. rawValue)
49- currentColors. append ( color)
50- }
45+ /// Adds a color to the in-progress colors.
46+ func addColor( _ color: ANSIColor ) {
47+ guard colored else { return }
48+ stream. write ( color. rawValue)
49+ currentColors. append ( color)
50+ }
5151
52- /// Resets this stream back to the default color.
53- func reset( ) {
54- if currentColors. isEmpty { return }
55- stream. write ( ANSIColor . reset. rawValue)
56- currentColors = [ ]
57- }
52+ /// Resets this stream back to the default color.
53+ func reset( ) {
54+ if currentColors. isEmpty { return }
55+ stream. write ( ANSIColor . reset. rawValue)
56+ currentColors = [ ]
57+ }
5858
59- /// Sets the current ANSI color codes to the passed-in colors.
60- func setColors( _ colors: [ ANSIColor ] ) {
61- guard colored else { return }
62- reset ( )
63- for color in colors {
64- stream. write ( color. rawValue)
65- }
66- currentColors = colors
59+ /// Sets the current ANSI color codes to the passed-in colors.
60+ func setColors( _ colors: [ ANSIColor ] ) {
61+ guard colored else { return }
62+ reset ( )
63+ for color in colors {
64+ stream. write ( color. rawValue)
6765 }
66+ currentColors = colors
67+ }
6868
69- /// Writes the string to the output with the provided colors.
70- ///
71- /// - Parameters:
72- /// - string: The string to write
73- /// - colors: The colors used on the string
74- func write( _ string: String , with colors: [ ANSIColor ] ) {
75- self . setColors ( colors)
76- stream. write ( string)
77- self . reset ( )
69+ /// Writes the string to the output with the provided colors.
70+ ///
71+ /// - Parameters:
72+ /// - string: The string to write
73+ /// - colors: The colors used on the string
74+ func write( _ string: String , with colors: [ ANSIColor ] ) {
75+ self . setColors ( colors)
76+ stream. write ( string)
77+ self . reset ( )
78+ }
79+ }
80+
81+ /// Represents the possible ANSI color codes.
82+ enum ANSIColor : String {
83+ case black = " \u{001B} [30m "
84+ case red = " \u{001B} [31m "
85+ case green = " \u{001B} [32m "
86+ case yellow = " \u{001B} [33m "
87+ case blue = " \u{001B} [34m "
88+ case magenta = " \u{001B} [35m "
89+ case cyan = " \u{001B} [36m "
90+ case white = " \u{001B} [37m "
91+ case bold = " \u{001B} [1m "
92+ case reset = " \u{001B} [0m "
93+
94+ func name( ) -> String {
95+ switch self {
96+ case . black: return " Black "
97+ case . red: return " Red "
98+ case . green: return " Green "
99+ case . yellow: return " Yellow "
100+ case . blue: return " Blue "
101+ case . magenta: return " Magenta "
102+ case . cyan: return " Cyan "
103+ case . white: return " White "
104+ case . bold: return " Bold "
105+ case . reset: return " Reset "
78106 }
107+ }
108+
109+ static func all( ) -> [ ANSIColor ] {
110+ return [ . black, . red, . green,
111+ . yellow, . blue, . magenta,
112+ . cyan, . white, . bold, . reset]
113+ }
114+ }
115+
116+ func + ( left: ANSIColor , right: String ) -> String {
117+ return left. rawValue + right
79118}
0 commit comments