@@ -13,7 +13,44 @@ import Basic
13
13
/// A protocol to operate on terminal based progress bars.
14
14
public protocol ProgressBarProtocol {
15
15
func update( percent: Int , text: String )
16
- func complete( )
16
+ func complete( success: Bool )
17
+ }
18
+
19
+ /// A single line progress bar.
20
+ public final class SingleLineProgressBar : ProgressBarProtocol {
21
+ private let header : String
22
+ private var isClear : Bool
23
+ private var stream : OutputByteStream
24
+ private var displayed : Set < Int > = [ ]
25
+
26
+ init ( stream: OutputByteStream , header: String ) {
27
+ self . stream = stream
28
+ self . header = header
29
+ self . isClear = true
30
+ }
31
+
32
+ public func update( percent: Int , text: String ) {
33
+ if isClear {
34
+ stream <<< header
35
+ stream <<< " \n "
36
+ stream. flush ( )
37
+ isClear = false
38
+ }
39
+
40
+ let displayPercentage = Int ( Double ( percent / 10 ) . rounded ( . down) ) * 10
41
+ if percent != 100 , !displayed. contains ( displayPercentage) {
42
+ stream <<< String ( displayPercentage) <<< " .. "
43
+ displayed. insert ( displayPercentage)
44
+ }
45
+ stream. flush ( )
46
+ }
47
+
48
+ public func complete( success: Bool ) {
49
+ if success {
50
+ stream <<< " OK "
51
+ stream. flush ( )
52
+ }
53
+ }
17
54
}
18
55
19
56
/// Simple ProgressBar which shows the update text in new lines.
@@ -41,7 +78,7 @@ public final class SimpleProgressBar: ProgressBarProtocol {
41
78
stream. flush ( )
42
79
}
43
80
44
- public func complete( ) {
81
+ public func complete( success : Bool ) {
45
82
}
46
83
}
47
84
@@ -90,15 +127,27 @@ public final class ProgressBar: ProgressBarProtocol {
90
127
term. moveCursor ( up: 1 )
91
128
}
92
129
93
- public func complete( ) {
130
+ public func complete( success : Bool ) {
94
131
term. endLine ( )
95
132
}
96
133
}
97
134
98
135
/// Creates colored or simple progress bar based on the provided output stream.
99
136
public func createProgressBar( forStream stream: OutputByteStream , header: String ) -> ProgressBarProtocol {
100
- if let stdStream = stream as? LocalFileOutputByteStream , let term = TerminalController ( stream: stdStream) {
137
+ guard let stdStream = stream as? LocalFileOutputByteStream else {
138
+ return SimpleProgressBar ( stream: stream, header: header)
139
+ }
140
+
141
+ // If we have a terminal, use animated progress bar.
142
+ if let term = TerminalController ( stream: stdStream) {
101
143
return ProgressBar ( term: term, header: header)
102
144
}
145
+
146
+ // If the terminal is dumb, use single line progress bar.
147
+ if TerminalController . terminalType ( stdStream) == . dumb {
148
+ return SingleLineProgressBar ( stream: stream, header: header)
149
+ }
150
+
151
+ // Use simple progress bar by default.
103
152
return SimpleProgressBar ( stream: stream, header: header)
104
153
}
0 commit comments