]>
Commit | Line | Data |
---|---|---|
92a42be0 | 1 | // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
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 | |
92a42be0 SL |
14 | //! Terminal][ansi] to provide color printing, among other things. There are two |
15 | //! implementations, the `TerminfoTerminal`, which uses control characters from | |
16 | //! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console | |
1a4d82fc JJ |
17 | //! API][win]. |
18 | //! | |
19 | //! # Examples | |
20 | //! | |
21 | //! ```no_run | |
c34b1796 | 22 | //! # #![feature(rustc_private)] |
1a4d82fc | 23 | //! extern crate term; |
c34b1796 AL |
24 | //! use std::io::prelude::*; |
25 | //! | |
1a4d82fc JJ |
26 | //! fn main() { |
27 | //! let mut t = term::stdout().unwrap(); | |
28 | //! | |
29 | //! t.fg(term::color::GREEN).unwrap(); | |
92a42be0 | 30 | //! write!(t, "hello, ").unwrap(); |
1a4d82fc JJ |
31 | //! |
32 | //! t.fg(term::color::RED).unwrap(); | |
92a42be0 | 33 | //! writeln!(t, "world!").unwrap(); |
1a4d82fc | 34 | //! |
92a42be0 | 35 | //! assert!(t.reset().unwrap()); |
1a4d82fc JJ |
36 | //! } |
37 | //! ``` | |
38 | //! | |
39 | //! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code | |
40 | //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx | |
41 | //! [ti]: https://en.wikipedia.org/wiki/Terminfo | |
42 | ||
43 | #![crate_name = "term"] | |
1a4d82fc JJ |
44 | #![crate_type = "rlib"] |
45 | #![crate_type = "dylib"] | |
e9174d1e | 46 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", |
62682a34 | 47 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", |
e9174d1e | 48 | html_root_url = "https://doc.rust-lang.org/nightly/", |
92a42be0 SL |
49 | html_playground_url = "https://play.rust-lang.org/", |
50 | test(attr(deny(warnings))))] | |
85aaf69f | 51 | #![deny(missing_docs)] |
32a655c1 | 52 | #![deny(warnings)] |
1a4d82fc | 53 | |
85aaf69f | 54 | #![feature(staged_api)] |
85aaf69f | 55 | #![cfg_attr(windows, feature(libc))] |
92a42be0 SL |
56 | // Handle rustfmt skips |
57 | #![feature(custom_attribute)] | |
58 | #![allow(unused_attributes)] | |
1a4d82fc | 59 | |
7cac9316 XL |
60 | #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] |
61 | #![cfg_attr(stage0, feature(staged_api))] | |
62 | ||
92a42be0 | 63 | use std::io::prelude::*; |
1a4d82fc JJ |
64 | |
65 | pub use terminfo::TerminfoTerminal; | |
66 | #[cfg(windows)] | |
67 | pub use win::WinConsole; | |
68 | ||
92a42be0 | 69 | use std::io::{self, Stdout, Stderr}; |
1a4d82fc JJ |
70 | |
71 | pub mod terminfo; | |
72 | ||
73 | #[cfg(windows)] | |
74 | mod win; | |
75 | ||
92a42be0 | 76 | /// Alias for stdout terminals. |
9cc50fc6 | 77 | pub type StdoutTerminal = Terminal<Output = Stdout> + Send; |
92a42be0 | 78 | /// Alias for stderr terminals. |
9cc50fc6 | 79 | pub type StderrTerminal = Terminal<Output = Stderr> + Send; |
1a4d82fc JJ |
80 | |
81 | #[cfg(not(windows))] | |
82 | /// Return a Terminal wrapping stdout, or None if a terminal couldn't be | |
83 | /// opened. | |
92a42be0 SL |
84 | pub fn stdout() -> Option<Box<StdoutTerminal>> { |
85 | TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>) | |
1a4d82fc JJ |
86 | } |
87 | ||
88 | #[cfg(windows)] | |
89 | /// Return a Terminal wrapping stdout, or None if a terminal couldn't be | |
90 | /// opened. | |
92a42be0 SL |
91 | pub fn stdout() -> Option<Box<StdoutTerminal>> { |
92 | TerminfoTerminal::new(io::stdout()) | |
93 | .map(|t| Box::new(t) as Box<StdoutTerminal>) | |
94 | .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>)) | |
1a4d82fc JJ |
95 | } |
96 | ||
97 | #[cfg(not(windows))] | |
98 | /// Return a Terminal wrapping stderr, or None if a terminal couldn't be | |
99 | /// opened. | |
92a42be0 SL |
100 | pub fn stderr() -> Option<Box<StderrTerminal>> { |
101 | TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box<StderrTerminal>) | |
1a4d82fc JJ |
102 | } |
103 | ||
104 | #[cfg(windows)] | |
105 | /// Return a Terminal wrapping stderr, or None if a terminal couldn't be | |
106 | /// opened. | |
92a42be0 SL |
107 | pub fn stderr() -> Option<Box<StderrTerminal>> { |
108 | TerminfoTerminal::new(io::stderr()) | |
109 | .map(|t| Box::new(t) as Box<StderrTerminal>) | |
110 | .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box<StderrTerminal>)) | |
1a4d82fc JJ |
111 | } |
112 | ||
113 | ||
114 | /// Terminal color definitions | |
c1a9b12d | 115 | #[allow(missing_docs)] |
1a4d82fc JJ |
116 | pub mod color { |
117 | /// Number for a terminal color | |
118 | pub type Color = u16; | |
119 | ||
92a42be0 SL |
120 | pub const BLACK: Color = 0; |
121 | pub const RED: Color = 1; | |
122 | pub const GREEN: Color = 2; | |
123 | pub const YELLOW: Color = 3; | |
124 | pub const BLUE: Color = 4; | |
c34b1796 | 125 | pub const MAGENTA: Color = 5; |
92a42be0 SL |
126 | pub const CYAN: Color = 6; |
127 | pub const WHITE: Color = 7; | |
128 | ||
129 | pub const BRIGHT_BLACK: Color = 8; | |
130 | pub const BRIGHT_RED: Color = 9; | |
131 | pub const BRIGHT_GREEN: Color = 10; | |
132 | pub const BRIGHT_YELLOW: Color = 11; | |
133 | pub const BRIGHT_BLUE: Color = 12; | |
c34b1796 | 134 | pub const BRIGHT_MAGENTA: Color = 13; |
92a42be0 SL |
135 | pub const BRIGHT_CYAN: Color = 14; |
136 | pub const BRIGHT_WHITE: Color = 15; | |
1a4d82fc JJ |
137 | } |
138 | ||
92a42be0 SL |
139 | /// Terminal attributes for use with term.attr(). |
140 | /// | |
141 | /// Most attributes can only be turned on and must be turned off with term.reset(). | |
142 | /// The ones that can be turned off explicitly take a boolean value. | |
143 | /// Color is also represented as an attribute for convenience. | |
144 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | |
145 | pub enum Attr { | |
146 | /// Bold (or possibly bright) mode | |
147 | Bold, | |
148 | /// Dim mode, also called faint or half-bright. Often not supported | |
149 | Dim, | |
150 | /// Italics mode. Often not supported | |
151 | Italic(bool), | |
152 | /// Underline mode | |
153 | Underline(bool), | |
154 | /// Blink mode | |
155 | Blink, | |
156 | /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold | |
157 | Standout(bool), | |
158 | /// Reverse mode, inverts the foreground and background colors | |
159 | Reverse, | |
160 | /// Secure mode, also called invis mode. Hides the printed text | |
161 | Secure, | |
162 | /// Convenience attribute to set the foreground color | |
163 | ForegroundColor(color::Color), | |
164 | /// Convenience attribute to set the background color | |
165 | BackgroundColor(color::Color), | |
1a4d82fc JJ |
166 | } |
167 | ||
168 | /// A terminal with similar capabilities to an ANSI Terminal | |
169 | /// (foreground/background colors etc). | |
92a42be0 SL |
170 | pub trait Terminal: Write { |
171 | /// The terminal's output writer type. | |
172 | type Output: Write; | |
173 | ||
1a4d82fc JJ |
174 | /// Sets the foreground color to the given color. |
175 | /// | |
176 | /// If the color is a bright color, but the terminal only supports 8 colors, | |
177 | /// the corresponding normal color will be used instead. | |
178 | /// | |
179 | /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` | |
180 | /// if there was an I/O error. | |
c34b1796 | 181 | fn fg(&mut self, color: color::Color) -> io::Result<bool>; |
1a4d82fc JJ |
182 | |
183 | /// Sets the background color to the given color. | |
184 | /// | |
185 | /// If the color is a bright color, but the terminal only supports 8 colors, | |
186 | /// the corresponding normal color will be used instead. | |
187 | /// | |
188 | /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` | |
189 | /// if there was an I/O error. | |
c34b1796 | 190 | fn bg(&mut self, color: color::Color) -> io::Result<bool>; |
1a4d82fc JJ |
191 | |
192 | /// Sets the given terminal attribute, if supported. Returns `Ok(true)` | |
193 | /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if | |
194 | /// there was an I/O error. | |
92a42be0 | 195 | fn attr(&mut self, attr: Attr) -> io::Result<bool>; |
1a4d82fc JJ |
196 | |
197 | /// Returns whether the given terminal attribute is supported. | |
92a42be0 | 198 | fn supports_attr(&self, attr: Attr) -> bool; |
1a4d82fc | 199 | |
92a42be0 SL |
200 | /// Resets all terminal attributes and colors to their defaults. |
201 | /// | |
202 | /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there | |
203 | /// was an I/O error. | |
204 | /// | |
205 | /// *Note: This does not flush.* | |
206 | /// | |
207 | /// That means the reset command may get buffered so, if you aren't planning on doing anything | |
208 | /// else that might flush stdout's buffer (e.g. writing a line of text), you should flush after | |
209 | /// calling reset. | |
210 | fn reset(&mut self) -> io::Result<bool>; | |
1a4d82fc JJ |
211 | |
212 | /// Gets an immutable reference to the stream inside | |
7453a54e | 213 | fn get_ref(&self) -> &Self::Output; |
1a4d82fc JJ |
214 | |
215 | /// Gets a mutable reference to the stream inside | |
7453a54e | 216 | fn get_mut(&mut self) -> &mut Self::Output; |
1a4d82fc | 217 | |
1a4d82fc | 218 | /// Returns the contained stream, destroying the `Terminal` |
92a42be0 | 219 | fn into_inner(self) -> Self::Output where Self: Sized; |
1a4d82fc | 220 | } |