@@ -45,6 +45,54 @@ pub mod color {
4545 pub static BRIGHT_WHITE : Color = 15u16 ;
4646}
4747
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+
4896#[ cfg( not( target_os = "win32" ) ) ]
4997pub struct Terminal {
5098 num_colors : u16 ,
@@ -88,45 +136,100 @@ impl Terminal {
88136 ///
89137 /// If the color is a bright color, but the terminal only supports 8 colors,
90138 /// 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 {
92142 let color = self . dim_if_necessary ( color) ;
93143 if self . num_colors > color {
94144 let s = expand ( * self . ti . strings . find_equiv ( & ( "setaf" ) ) . unwrap ( ) ,
95145 [ Number ( color as int ) ] , & mut Variables :: new ( ) ) ;
96146 if s. is_ok ( ) {
97147 self . out . write ( s. unwrap ( ) ) ;
148+ return true
98149 } else {
99150 warn ! ( "%s" , s. unwrap_err( ) ) ;
100151 }
101152 }
153+ false
102154 }
103155 /// Sets the background color to the given color.
104156 ///
105157 /// If the color is a bright color, but the terminal only supports 8 colors,
106158 /// 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 {
108162 let color = self . dim_if_necessary ( color) ;
109163 if self . num_colors > color {
110164 let s = expand ( * self . ti . strings . find_equiv ( & ( "setab" ) ) . unwrap ( ) ,
111165 [ Number ( color as int ) ] , & mut Variables :: new ( ) ) ;
112166 if s. is_ok ( ) {
113167 self . out . write ( s. unwrap ( ) ) ;
168+ return true
114169 } else {
115170 warn ! ( "%s" , s. unwrap_err( ) ) ;
116171 }
117172 }
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+ }
118197 }
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.
119213 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+ } ;
125226 if s. is_ok ( ) {
126227 self . out . write ( s. unwrap ( ) ) ;
127228 } else if self . num_colors > 0 {
128229 warn ! ( "%s" , s. unwrap_err( ) ) ;
129230 } 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.
130233 debug ! ( "%s" , s. unwrap_err( ) ) ;
131234 }
132235 }
@@ -144,10 +247,20 @@ impl Terminal {
144247 return Ok ( Terminal { out : out, num_colors : 0 } ) ;
145248 }
146249
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
148260 }
149261
150- pub fn bg ( & self , _color : color:: Color ) {
262+ pub fn supports_attr ( & self , _attr : attr:: Attr ) -> bool {
263+ false
151264 }
152265
153266 pub fn reset ( & self ) {
0 commit comments