15
15
16
16
use std:: io:: { Decorator , Writer } ;
17
17
18
- #[ cfg( not( target_os = "win32" ) ) ] use std:: os;
19
- #[ cfg( not( target_os = "win32" ) ) ] use terminfo:: * ;
20
- #[ cfg( not( target_os = "win32" ) ) ] use terminfo:: searcher:: open;
21
- #[ cfg( not( target_os = "win32" ) ) ] use terminfo:: parser:: compiled:: parse;
22
- #[ cfg( not( target_os = "win32" ) ) ] use terminfo:: parm:: { expand, Number , Variables } ;
23
-
24
- // FIXME (#2807): Windows support.
18
+ use std:: os;
19
+ use terminfo:: * ;
20
+ use terminfo:: searcher:: open;
21
+ use terminfo:: parser:: compiled:: parse;
22
+ use terminfo:: parm:: { expand, Number , Variables } ;
25
23
26
24
pub mod color {
27
25
pub type Color = u16 ;
@@ -74,7 +72,6 @@ pub mod attr {
74
72
}
75
73
}
76
74
77
- #[ cfg( not( target_os = "win32" ) ) ]
78
75
fn cap_for_attr ( attr : attr:: Attr ) -> & ' static str {
79
76
match attr {
80
77
attr:: Bold => "bold" ,
@@ -93,29 +90,24 @@ fn cap_for_attr(attr: attr::Attr) -> &'static str {
93
90
}
94
91
}
95
92
96
- #[ cfg( not( target_os = "win32" ) ) ]
97
93
pub struct Terminal < T > {
98
94
priv num_colors : u16 ,
99
95
priv out: T ,
100
- priv ti: ~TermInfo
96
+ priv ti: Option < ~TermInfo >
101
97
}
102
98
103
- #[ cfg( target_os = "win32" ) ]
104
- pub struct Terminal < T > {
105
- priv num_colors : u16 ,
106
- priv out: T ,
107
- }
108
-
109
- #[ cfg( not( target_os = "win32" ) ) ]
110
99
impl < T : Writer > Terminal < T > {
111
100
pub fn new ( out : T ) -> Result < Terminal < T > , ~str > {
112
- let term = os:: getenv ( "TERM" ) ;
113
- if term . is_none ( ) {
114
- return Err ( ~" TERM environment variable undefined" ) ;
115
- }
101
+ let term = match os:: getenv ( "TERM" ) {
102
+ None => return Err ( ~" TERM environment variable undefined" ) ,
103
+ Some ( t ) => t
104
+ } ;
116
105
117
- let entry = open ( term. unwrap ( ) ) ;
106
+ let entry = open ( term) ;
118
107
if entry. is_err ( ) {
108
+ if term == ~"cygwin" {
109
+ return Ok ( Terminal { out : out, ti : None , num_colors : 16 } ) ;
110
+ }
119
111
return Err ( entry. unwrap_err ( ) ) ;
120
112
}
121
113
@@ -130,47 +122,56 @@ impl<T: Writer> Terminal<T> {
130
122
inf. numbers . find_equiv ( & ( "colors" ) ) . map_default ( 0 , |& n| n)
131
123
} else { 0 } ;
132
124
133
- return Ok ( Terminal { out : out, ti : inf, num_colors : nc} ) ;
125
+ return Ok ( Terminal { out : out, ti : Some ( inf) , num_colors : nc} ) ;
134
126
}
127
+
128
+ /// Helper function, see fg and bg.
129
+ fn set_color ( & mut self , color : color:: Color , cap : & str ) -> bool {
130
+ let color = self . dim_if_necessary ( color) ;
131
+ if self . num_colors > color {
132
+ match self . ti {
133
+ None => {
134
+ let ansi = if color < 8 {
135
+ format ! ( "\x1b [{}m" , 30 + color)
136
+ } else {
137
+ format ! ( "\x1b [{};1m" , 22 + color)
138
+ } ;
139
+ self . out . write ( ansi. as_bytes ( ) ) ;
140
+ return true
141
+ } ,
142
+ Some ( ref ti) => {
143
+ let s = expand ( * ti. strings . find_equiv ( & ( cap) ) . unwrap ( ) ,
144
+ [ Number ( color as int ) ] , & mut Variables :: new ( ) ) ;
145
+ if s. is_ok ( ) {
146
+ self . out . write ( s. unwrap ( ) ) ;
147
+ return true
148
+ } else {
149
+ warn ! ( "{}" , s. unwrap_err( ) ) ;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ false
155
+ }
156
+
135
157
/// Sets the foreground color to the given color.
136
158
///
137
159
/// If the color is a bright color, but the terminal only supports 8 colors,
138
160
/// the corresponding normal color will be used instead.
139
161
///
140
162
/// Returns true if the color was set, false otherwise.
141
163
pub fn fg ( & mut self , color : color:: Color ) -> bool {
142
- let color = self . dim_if_necessary ( color) ;
143
- if self . num_colors > color {
144
- let s = expand ( * self . ti . strings . find_equiv ( & ( "setaf" ) ) . unwrap ( ) ,
145
- [ Number ( color as int ) ] , & mut Variables :: new ( ) ) ;
146
- if s. is_ok ( ) {
147
- self . out . write ( s. unwrap ( ) ) ;
148
- return true
149
- } else {
150
- warn ! ( "{}" , s. unwrap_err( ) ) ;
151
- }
152
- }
153
- false
164
+ self . set_color ( color, "setaf" )
154
165
}
166
+
155
167
/// Sets the background color to the given color.
156
168
///
157
169
/// If the color is a bright color, but the terminal only supports 8 colors,
158
170
/// the corresponding normal color will be used instead.
159
171
///
160
172
/// Returns true if the color was set, false otherwise.
161
173
pub fn bg ( & mut self , color : color:: Color ) -> bool {
162
- let color = self . dim_if_necessary ( color) ;
163
- if self . num_colors > color {
164
- let s = expand ( * self . ti . strings . find_equiv ( & ( "setab" ) ) . unwrap ( ) ,
165
- [ Number ( color as int ) ] , & mut Variables :: new ( ) ) ;
166
- if s. is_ok ( ) {
167
- self . out . write ( s. unwrap ( ) ) ;
168
- return true
169
- } else {
170
- warn ! ( "{}" , s. unwrap_err( ) ) ;
171
- }
172
- }
173
- false
174
+ self . set_color ( color, "setab" )
174
175
}
175
176
176
177
/// Sets the given terminal attribute, if supported.
@@ -180,18 +181,23 @@ impl<T: Writer> Terminal<T> {
180
181
attr:: ForegroundColor ( c) => self . fg ( c) ,
181
182
attr:: BackgroundColor ( c) => self . bg ( c) ,
182
183
_ => {
183
- let cap = cap_for_attr ( attr) ;
184
- let parm = self . ti . strings . find_equiv ( & cap) ;
185
- if parm. is_some ( ) {
186
- let s = expand ( * parm. unwrap ( ) , [ ] , & mut Variables :: new ( ) ) ;
187
- if s. is_ok ( ) {
188
- self . out . write ( s. unwrap ( ) ) ;
189
- return true
190
- } else {
191
- warn ! ( "{}" , s. unwrap_err( ) ) ;
184
+ match self . ti {
185
+ None => return false ,
186
+ Some ( ref ti) => {
187
+ let cap = cap_for_attr ( attr) ;
188
+ let parm = ti. strings . find_equiv ( & cap) ;
189
+ if parm. is_some ( ) {
190
+ let s = expand ( * parm. unwrap ( ) , [ ] , & mut Variables :: new ( ) ) ;
191
+ if s. is_ok ( ) {
192
+ self . out . write ( s. unwrap ( ) ) ;
193
+ return true
194
+ } else {
195
+ warn ! ( "{}" , s. unwrap_err( ) ) ;
196
+ }
197
+ }
198
+ false
192
199
}
193
200
}
194
- false
195
201
}
196
202
}
197
203
}
@@ -204,34 +210,44 @@ impl<T: Writer> Terminal<T> {
204
210
}
205
211
_ => {
206
212
let cap = cap_for_attr ( attr) ;
207
- self . ti . strings . find_equiv ( & cap) . is_some ( )
213
+ match self . ti {
214
+ None => return false ,
215
+ Some ( ref ti) => ti. strings . find_equiv ( & cap) . is_some ( )
216
+ }
208
217
}
209
218
}
210
219
}
211
220
212
221
/// Resets all terminal attributes and color to the default.
213
222
pub fn reset ( & mut self ) {
214
- let mut cap = self . ti . strings . find_equiv ( & ( "sgr0" ) ) ;
215
- if cap. is_none ( ) {
216
- // are there any terminals that have color/attrs and not sgr0?
217
- // Try falling back to sgr, then op
218
- cap = self . ti . strings . find_equiv ( & ( "sgr" ) ) ;
219
- if cap. is_none ( ) {
220
- cap = self . ti . strings . find_equiv ( & ( "op" ) ) ;
223
+ match self . ti {
224
+ None => if self . num_colors > 0 {
225
+ self . out . write ( [ 27u8 , 91u8 , 51u8 , 57u8 , 59u8 , 52u8 , 57u8 , 109u8 ] )
226
+ } ,
227
+ Some ( ref ti) => {
228
+ let mut cap = ti. strings . find_equiv ( & ( "sgr0" ) ) ;
229
+ if cap. is_none ( ) {
230
+ // are there any terminals that have color/attrs and not sgr0?
231
+ // Try falling back to sgr, then op
232
+ cap = ti. strings . find_equiv ( & ( "sgr" ) ) ;
233
+ if cap. is_none ( ) {
234
+ cap = ti. strings . find_equiv ( & ( "op" ) ) ;
235
+ }
236
+ }
237
+ let s = cap. map_default ( Err ( ~"can' t find terminfo capability `sgr0`") , |op| {
238
+ expand ( * op, [ ] , & mut Variables :: new ( ) )
239
+ } ) ;
240
+ if s. is_ok ( ) {
241
+ self . out . write ( s. unwrap ( ) ) ;
242
+ } else if self . num_colors > 0 {
243
+ warn ! ( "{}" , s. unwrap_err( ) ) ;
244
+ } else {
245
+ // if we support attributes but not color, it would be nice to still warn!()
246
+ // but it's not worth testing all known attributes just for this.
247
+ debug ! ( "{}" , s. unwrap_err( ) ) ;
248
+ }
221
249
}
222
250
}
223
- let s = cap. map_default ( Err ( ~"can' t find terminfo capability `sgr0`") , |op| {
224
- expand ( * op, [ ] , & mut Variables :: new ( ) )
225
- } ) ;
226
- if s. is_ok ( ) {
227
- self . out . write ( s. unwrap ( ) ) ;
228
- } else if self . num_colors > 0 {
229
- warn ! ( "{}" , s. unwrap_err( ) ) ;
230
- } else {
231
- // if we support attributes but not color, it would be nice to still warn!()
232
- // but it's not worth testing all known attributes just for this.
233
- debug ! ( "{}" , s. unwrap_err( ) ) ;
234
- }
235
251
}
236
252
237
253
fn dim_if_necessary ( & self , color : color:: Color ) -> color:: Color {
@@ -241,32 +257,6 @@ impl<T: Writer> Terminal<T> {
241
257
}
242
258
}
243
259
244
- #[ cfg( target_os = "win32" ) ]
245
- impl < T : Writer > Terminal < T > {
246
- pub fn new ( out : T ) -> Result < Terminal < T > , ~str > {
247
- return Ok ( Terminal { out : out, num_colors : 0 } ) ;
248
- }
249
-
250
- pub fn fg ( & mut self , _color : color:: Color ) -> bool {
251
- false
252
- }
253
-
254
- pub fn bg ( & mut self , _color : color:: Color ) -> bool {
255
- false
256
- }
257
-
258
- pub fn attr ( & mut self , _attr : attr:: Attr ) -> bool {
259
- false
260
- }
261
-
262
- pub fn supports_attr ( & self , _attr : attr:: Attr ) -> bool {
263
- false
264
- }
265
-
266
- pub fn reset ( & self ) {
267
- }
268
- }
269
-
270
260
impl < T : Writer > Decorator < T > for Terminal < T > {
271
261
fn inner ( self ) -> T {
272
262
self . out
0 commit comments