]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Terminal formatting library. | |
12 | //! | |
13 | //! This crate provides the `Terminal` trait, which abstracts over an [ANSI | |
14 | //! Terminal][ansi] to provide color printing, among other things. There are two implementations, | |
15 | //! the `TerminfoTerminal`, which uses control characters from a | |
16 | //! [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console | |
17 | //! API][win]. | |
18 | //! | |
19 | //! # Examples | |
20 | //! | |
21 | //! ```no_run | |
c34b1796 | 22 | //! # #![feature(rustc_private)] |
1a4d82fc JJ |
23 | //! extern crate term; |
24 | //! | |
c34b1796 AL |
25 | //! use std::io::prelude::*; |
26 | //! | |
1a4d82fc JJ |
27 | //! fn main() { |
28 | //! let mut t = term::stdout().unwrap(); | |
29 | //! | |
30 | //! t.fg(term::color::GREEN).unwrap(); | |
31 | //! (write!(t, "hello, ")).unwrap(); | |
32 | //! | |
33 | //! t.fg(term::color::RED).unwrap(); | |
34 | //! (writeln!(t, "world!")).unwrap(); | |
35 | //! | |
36 | //! t.reset().unwrap(); | |
37 | //! } | |
38 | //! ``` | |
39 | //! | |
40 | //! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code | |
41 | //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx | |
42 | //! [ti]: https://en.wikipedia.org/wiki/Terminfo | |
43 | ||
c34b1796 AL |
44 | // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) |
45 | #![cfg_attr(stage0, feature(custom_attribute))] | |
1a4d82fc | 46 | #![crate_name = "term"] |
85aaf69f | 47 | #![unstable(feature = "rustc_private", |
e9174d1e SL |
48 | reason = "use the crates.io `term` library instead", |
49 | issue = "27812")] | |
1a4d82fc JJ |
50 | #![staged_api] |
51 | #![crate_type = "rlib"] | |
52 | #![crate_type = "dylib"] | |
e9174d1e | 53 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", |
62682a34 | 54 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", |
e9174d1e SL |
55 | html_root_url = "https://doc.rust-lang.org/nightly/", |
56 | html_playground_url = "https://play.rust-lang.org/")] | |
85aaf69f | 57 | #![deny(missing_docs)] |
1a4d82fc | 58 | |
1a4d82fc | 59 | #![feature(box_syntax)] |
85aaf69f SL |
60 | #![feature(rustc_private)] |
61 | #![feature(staged_api)] | |
c34b1796 | 62 | #![feature(str_char)] |
62682a34 | 63 | #![feature(vec_push_all)] |
85aaf69f | 64 | #![cfg_attr(windows, feature(libc))] |
1a4d82fc JJ |
65 | |
66 | #[macro_use] extern crate log; | |
67 | ||
68 | pub use terminfo::TerminfoTerminal; | |
69 | #[cfg(windows)] | |
70 | pub use win::WinConsole; | |
71 | ||
c34b1796 AL |
72 | use std::io::prelude::*; |
73 | use std::io; | |
1a4d82fc JJ |
74 | |
75 | pub mod terminfo; | |
76 | ||
77 | #[cfg(windows)] | |
78 | mod win; | |
79 | ||
c34b1796 AL |
80 | /// A hack to work around the fact that `Box<Write + Send>` does not |
81 | /// currently implement `Write`. | |
1a4d82fc | 82 | pub struct WriterWrapper { |
c34b1796 | 83 | wrapped: Box<Write + Send>, |
1a4d82fc JJ |
84 | } |
85 | ||
c34b1796 | 86 | impl Write for WriterWrapper { |
1a4d82fc | 87 | #[inline] |
c34b1796 AL |
88 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
89 | self.wrapped.write(buf) | |
1a4d82fc JJ |
90 | } |
91 | ||
92 | #[inline] | |
c34b1796 | 93 | fn flush(&mut self) -> io::Result<()> { |
1a4d82fc JJ |
94 | self.wrapped.flush() |
95 | } | |
96 | } | |
97 | ||
98 | #[cfg(not(windows))] | |
99 | /// Return a Terminal wrapping stdout, or None if a terminal couldn't be | |
100 | /// opened. | |
101 | pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> { | |
102 | TerminfoTerminal::new(WriterWrapper { | |
c34b1796 | 103 | wrapped: box std::io::stdout(), |
1a4d82fc JJ |
104 | }) |
105 | } | |
106 | ||
107 | #[cfg(windows)] | |
108 | /// Return a Terminal wrapping stdout, or None if a terminal couldn't be | |
109 | /// opened. | |
110 | pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> { | |
111 | let ti = TerminfoTerminal::new(WriterWrapper { | |
c34b1796 | 112 | wrapped: box std::io::stdout(), |
1a4d82fc JJ |
113 | }); |
114 | ||
115 | match ti { | |
116 | Some(t) => Some(t), | |
117 | None => { | |
118 | WinConsole::new(WriterWrapper { | |
c34b1796 | 119 | wrapped: box std::io::stdout(), |
1a4d82fc JJ |
120 | }) |
121 | } | |
122 | } | |
123 | } | |
124 | ||
125 | #[cfg(not(windows))] | |
126 | /// Return a Terminal wrapping stderr, or None if a terminal couldn't be | |
127 | /// opened. | |
128 | pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> { | |
129 | TerminfoTerminal::new(WriterWrapper { | |
c34b1796 | 130 | wrapped: box std::io::stderr(), |
1a4d82fc JJ |
131 | }) |
132 | } | |
133 | ||
134 | #[cfg(windows)] | |
135 | /// Return a Terminal wrapping stderr, or None if a terminal couldn't be | |
136 | /// opened. | |
137 | pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> { | |
138 | let ti = TerminfoTerminal::new(WriterWrapper { | |
c34b1796 | 139 | wrapped: box std::io::stderr(), |
1a4d82fc JJ |
140 | }); |
141 | ||
142 | match ti { | |
143 | Some(t) => Some(t), | |
144 | None => { | |
145 | WinConsole::new(WriterWrapper { | |
c34b1796 | 146 | wrapped: box std::io::stderr(), |
1a4d82fc JJ |
147 | }) |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | ||
153 | /// Terminal color definitions | |
c1a9b12d | 154 | #[allow(missing_docs)] |
1a4d82fc JJ |
155 | pub mod color { |
156 | /// Number for a terminal color | |
157 | pub type Color = u16; | |
158 | ||
c34b1796 AL |
159 | pub const BLACK: Color = 0; |
160 | pub const RED: Color = 1; | |
161 | pub const GREEN: Color = 2; | |
162 | pub const YELLOW: Color = 3; | |
163 | pub const BLUE: Color = 4; | |
164 | pub const MAGENTA: Color = 5; | |
165 | pub const CYAN: Color = 6; | |
166 | pub const WHITE: Color = 7; | |
167 | ||
168 | pub const BRIGHT_BLACK: Color = 8; | |
169 | pub const BRIGHT_RED: Color = 9; | |
170 | pub const BRIGHT_GREEN: Color = 10; | |
171 | pub const BRIGHT_YELLOW: Color = 11; | |
172 | pub const BRIGHT_BLUE: Color = 12; | |
173 | pub const BRIGHT_MAGENTA: Color = 13; | |
174 | pub const BRIGHT_CYAN: Color = 14; | |
175 | pub const BRIGHT_WHITE: Color = 15; | |
1a4d82fc JJ |
176 | } |
177 | ||
178 | /// Terminal attributes | |
179 | pub mod attr { | |
180 | pub use self::Attr::*; | |
181 | ||
182 | /// Terminal attributes for use with term.attr(). | |
183 | /// | |
184 | /// Most attributes can only be turned on and must be turned off with term.reset(). | |
185 | /// The ones that can be turned off explicitly take a boolean value. | |
186 | /// Color is also represented as an attribute for convenience. | |
c34b1796 | 187 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
188 | pub enum Attr { |
189 | /// Bold (or possibly bright) mode | |
190 | Bold, | |
191 | /// Dim mode, also called faint or half-bright. Often not supported | |
192 | Dim, | |
193 | /// Italics mode. Often not supported | |
194 | Italic(bool), | |
195 | /// Underline mode | |
196 | Underline(bool), | |
197 | /// Blink mode | |
198 | Blink, | |
199 | /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold | |
200 | Standout(bool), | |
201 | /// Reverse mode, inverts the foreground and background colors | |
202 | Reverse, | |
203 | /// Secure mode, also called invis mode. Hides the printed text | |
204 | Secure, | |
205 | /// Convenience attribute to set the foreground color | |
206 | ForegroundColor(super::color::Color), | |
207 | /// Convenience attribute to set the background color | |
208 | BackgroundColor(super::color::Color) | |
209 | } | |
210 | } | |
211 | ||
212 | /// A terminal with similar capabilities to an ANSI Terminal | |
213 | /// (foreground/background colors etc). | |
c34b1796 | 214 | pub trait Terminal<T: Write>: Write { |
1a4d82fc JJ |
215 | /// Sets the foreground color to the given color. |
216 | /// | |
217 | /// If the color is a bright color, but the terminal only supports 8 colors, | |
218 | /// the corresponding normal color will be used instead. | |
219 | /// | |
220 | /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` | |
221 | /// if there was an I/O error. | |
c34b1796 | 222 | fn fg(&mut self, color: color::Color) -> io::Result<bool>; |
1a4d82fc JJ |
223 | |
224 | /// Sets the background color to the given color. | |
225 | /// | |
226 | /// If the color is a bright color, but the terminal only supports 8 colors, | |
227 | /// the corresponding normal color will be used instead. | |
228 | /// | |
229 | /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` | |
230 | /// if there was an I/O error. | |
c34b1796 | 231 | fn bg(&mut self, color: color::Color) -> io::Result<bool>; |
1a4d82fc JJ |
232 | |
233 | /// Sets the given terminal attribute, if supported. Returns `Ok(true)` | |
234 | /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if | |
235 | /// there was an I/O error. | |
c34b1796 | 236 | fn attr(&mut self, attr: attr::Attr) -> io::Result<bool>; |
1a4d82fc JJ |
237 | |
238 | /// Returns whether the given terminal attribute is supported. | |
239 | fn supports_attr(&self, attr: attr::Attr) -> bool; | |
240 | ||
241 | /// Resets all terminal attributes and color to the default. | |
242 | /// Returns `Ok()`. | |
c34b1796 | 243 | fn reset(&mut self) -> io::Result<()>; |
1a4d82fc JJ |
244 | |
245 | /// Gets an immutable reference to the stream inside | |
246 | fn get_ref<'a>(&'a self) -> &'a T; | |
247 | ||
248 | /// Gets a mutable reference to the stream inside | |
249 | fn get_mut<'a>(&'a mut self) -> &'a mut T; | |
250 | } | |
251 | ||
252 | /// A terminal which can be unwrapped. | |
c34b1796 | 253 | pub trait UnwrappableTerminal<T: Write>: Terminal<T> { |
1a4d82fc JJ |
254 | /// Returns the contained stream, destroying the `Terminal` |
255 | fn unwrap(self) -> T; | |
256 | } |