@@ -45,6 +45,54 @@ pub mod color {
45
45
pub static BRIGHT_WHITE : Color = 15u16 ;
46
46
}
47
47
48
+ pub mod attr {
49
+ /// Terminal attributes for use with term.attr().
50
+ /// Most attributes can only be turned on and must be turned off with term.reset().
51
+ /// The ones that can be turned off explicitly take a boolean value.
52
+ /// Color is also represented as an attribute for convenience.
53
+ pub enum Attr {
54
+ /// Bold (or possibly bright) mode
55
+ Bold ,
56
+ /// Dim mode, also called faint or half-bright. Often not supported
57
+ Dim ,
58
+ /// Italics mode. Often not supported
59
+ Italic ( bool ) ,
60
+ /// Underline mode
61
+ Underline ( bool ) ,
62
+ /// Blink mode
63
+ Blink ,
64
+ /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
65
+ Standout ( bool ) ,
66
+ /// Reverse mode, inverts the foreground and background colors
67
+ Reverse ,
68
+ /// Secure mode, also called invis mode. Hides the printed text
69
+ Secure ,
70
+ /// Convenience attribute to set the foreground color
71
+ ForegroundColor ( super :: color:: Color ) ,
72
+ /// Convenience attribute to set the background color
73
+ BackgroundColor ( super :: color:: Color )
74
+ }
75
+ }
76
+
77
+ #[ cfg( not( target_os = "win32" ) ) ]
78
+ priv fn cap_for_attr ( attr : attr:: Attr ) -> & ' static str {
79
+ match attr {
80
+ attr:: Bold => "bold" ,
81
+ attr:: Dim => "dim" ,
82
+ attr:: Italic ( true ) => "sitm" ,
83
+ attr:: Italic ( false ) => "ritm" ,
84
+ attr:: Underline ( true ) => "smul" ,
85
+ attr:: Underline ( false ) => "rmul" ,
86
+ attr:: Blink => "blink" ,
87
+ attr:: Standout ( true ) => "smso" ,
88
+ attr:: Standout ( false ) => "rmso" ,
89
+ attr:: Reverse => "rev" ,
90
+ attr:: Secure => "invis" ,
91
+ attr:: ForegroundColor ( _) => "setaf" ,
92
+ attr:: BackgroundColor ( _) => "setab"
93
+ }
94
+ }
95
+
48
96
#[ cfg( not( target_os = "win32" ) ) ]
49
97
pub struct Terminal {
50
98
num_colors : u16 ,
@@ -88,45 +136,100 @@ impl Terminal {
88
136
///
89
137
/// If the color is a bright color, but the terminal only supports 8 colors,
90
138
/// the corresponding normal color will be used instead.
91
- pub fn fg ( & self , color : color:: Color ) {
139
+ ///
140
+ /// Returns true if the color was set, false otherwise.
141
+ pub fn fg ( & self , color : color:: Color ) -> bool {
92
142
let color = self . dim_if_necessary ( color) ;
93
143
if self . num_colors > color {
94
144
let s = expand ( * self . ti . strings . find_equiv ( & ( "setaf" ) ) . unwrap ( ) ,
95
145
[ Number ( color as int ) ] , & mut Variables :: new ( ) ) ;
96
146
if s. is_ok ( ) {
97
147
self . out . write ( s. unwrap ( ) ) ;
148
+ return true
98
149
} else {
99
150
warn ! ( "%s" , s. unwrap_err( ) ) ;
100
151
}
101
152
}
153
+ false
102
154
}
103
155
/// Sets the background color to the given color.
104
156
///
105
157
/// If the color is a bright color, but the terminal only supports 8 colors,
106
158
/// the corresponding normal color will be used instead.
107
- pub fn bg ( & self , color : color:: Color ) {
159
+ ///
160
+ /// Rturns true if the color was set, false otherwise.
161
+ pub fn bg ( & self , color : color:: Color ) -> bool {
108
162
let color = self . dim_if_necessary ( color) ;
109
163
if self . num_colors > color {
110
164
let s = expand ( * self . ti . strings . find_equiv ( & ( "setab" ) ) . unwrap ( ) ,
111
165
[ Number ( color as int ) ] , & mut Variables :: new ( ) ) ;
112
166
if s. is_ok ( ) {
113
167
self . out . write ( s. unwrap ( ) ) ;
168
+ return true
114
169
} else {
115
170
warn ! ( "%s" , s. unwrap_err( ) ) ;
116
171
}
117
172
}
173
+ false
174
+ }
175
+
176
+ /// Sets the given terminal attribute, if supported.
177
+ /// Returns true if the attribute was supported, false otherwise.
178
+ pub fn attr ( & self , attr : attr:: Attr ) -> bool {
179
+ match attr {
180
+ attr:: ForegroundColor ( c) => self . fg ( c) ,
181
+ attr:: BackgroundColor ( c) => self . bg ( c) ,
182
+ _ => {
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" , s. unwrap_err( ) ) ;
192
+ }
193
+ }
194
+ false
195
+ }
196
+ }
118
197
}
198
+
199
+ /// Returns whether the given terminal attribute is supported.
200
+ pub fn supports_attr ( & self , attr : attr:: Attr ) -> bool {
201
+ match attr {
202
+ attr:: ForegroundColor ( _) | attr:: BackgroundColor ( _) => {
203
+ self . num_colors > 0
204
+ }
205
+ _ => {
206
+ let cap = cap_for_attr ( attr) ;
207
+ self . ti . strings . find_equiv ( & cap) . is_some ( )
208
+ }
209
+ }
210
+ }
211
+
212
+ /// Resets all terminal attributes and color to the default.
119
213
pub fn reset ( & self ) {
120
- let mut vars = Variables :: new ( ) ;
121
- let s = do self . ti . strings . find_equiv ( & ( "op" ) )
122
- . map_consume_default ( Err ( ~"can' t find terminfo capability `op`") ) |op| {
123
- expand ( copy * op, [ ] , & mut vars)
124
- } ;
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" ) ) ;
221
+ }
222
+ }
223
+ let s = do cap. map_consume_default ( Err ( ~"can' t find terminfo capability `sgr0`") ) |op| {
224
+ expand ( * op, [ ] , & mut Variables :: new ( ) )
225
+ } ;
125
226
if s. is_ok ( ) {
126
227
self . out . write ( s. unwrap ( ) ) ;
127
228
} else if self . num_colors > 0 {
128
229
warn ! ( "%s" , s. unwrap_err( ) ) ;
129
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.
130
233
debug ! ( "%s" , s. unwrap_err( ) ) ;
131
234
}
132
235
}
@@ -144,10 +247,20 @@ impl Terminal {
144
247
return Ok ( Terminal { out : out, num_colors : 0 } ) ;
145
248
}
146
249
147
- pub fn fg ( & self , _color : color:: Color ) {
250
+ pub fn fg ( & self , _color : color:: Color ) -> bool {
251
+ false
252
+ }
253
+
254
+ pub fn bg ( & self , _color : color:: Color ) -> bool {
255
+ false
256
+ }
257
+
258
+ pub fn attr ( & self , _attr : attr:: Attr ) -> bool {
259
+ false
148
260
}
149
261
150
- pub fn bg ( & self , _color : color:: Color ) {
262
+ pub fn supports_attr ( & self , _attr : attr:: Attr ) -> bool {
263
+ false
151
264
}
152
265
153
266
pub fn reset ( & self ) {
0 commit comments