rust/src/libterm/lib.rs

256 lines
8.0 KiB
Rust
Raw Normal View History

// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Terminal formatting library.
//!
//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
2014-05-22 07:50:31 -05:00
//! Terminal][ansi] to provide color printing, among other things. There are two implementations,
//! the `TerminfoTerminal`, which uses control characters from a
//! [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
//! API][win].
//!
//! # Examples
//!
//! ```no_run
//! extern crate term;
//!
//! fn main() {
2014-05-11 19:10:03 -05:00
//! let mut t = term::stdout().unwrap();
//!
2014-05-11 19:10:03 -05:00
//! t.fg(term::color::GREEN).unwrap();
//! (write!(t, "hello, ")).unwrap();
//!
2014-05-11 19:10:03 -05:00
//! t.fg(term::color::RED).unwrap();
//! (writeln!(t, "world!")).unwrap();
//!
2014-05-11 19:10:03 -05:00
//! t.reset().unwrap();
//! }
//! ```
//!
//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo
#![crate_name = "term"]
#![unstable(feature = "rustc_private",
reason = "use the crates.io `term` library instead")]
Preliminary feature staging This partially implements the feature staging described in the [release channel RFC][rc]. It does not yet fully conform to the RFC as written, but does accomplish its goals sufficiently for the 1.0 alpha release. It has three primary user-visible effects: * On the nightly channel, use of unstable APIs generates a warning. * On the beta channel, use of unstable APIs generates a warning. * On the beta channel, use of feature gates generates a warning. Code that does not trigger these warnings is considered 'stable', modulo pre-1.0 bugs. Disabling the warnings for unstable APIs continues to be done in the existing (i.e. old) style, via `#[allow(...)]`, not that specified in the RFC. I deem this marginally acceptable since any code that must do this is not using the stable dialect of Rust. Use of feature gates is itself gated with the new 'unstable_features' lint, on nightly set to 'allow', and on beta 'warn'. The attribute scheme used here corresponds to an older version of the RFC, with the `#[staged_api]` crate attribute toggling the staging behavior of the stability attributes, but the user impact is only in-tree so I'm not concerned about having to make design changes later (and I may ultimately prefer the scheme here after all, with the `#[staged_api]` crate attribute). Since the Rust codebase itself makes use of unstable features the compiler and build system to a midly elaborate dance to allow it to bootstrap while disobeying these lints (which would otherwise be errors because Rust builds with `-D warnings`). This patch includes one significant hack that causes a regression. Because the `format_args!` macro emits calls to unstable APIs it would trigger the lint. I added a hack to the lint to make it not trigger, but this in turn causes arguments to `println!` not to be checked for feature gates. I don't presently understand macro expansion well enough to fix. This is bug #20661. Closes #16678 [rc]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md
2015-01-06 08:26:08 -06:00
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/",
html_playground_url = "http://play.rust-lang.org/")]
#![deny(missing_docs)]
#![feature(core)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(int_uint)]
#![feature(io)]
#![feature(path)]
#![feature(rustc_private)]
#![feature(slicing_syntax)]
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(unicode)]
std: Add a new `env` module This is an implementation of [RFC 578][rfc] which adds a new `std::env` module to replace most of the functionality in the current `std::os` module. More details can be found in the RFC itself, but as a summary the following methods have all been deprecated: [rfc]: https://github.com/rust-lang/rfcs/pull/578 * `os::args_as_bytes` => `env::args` * `os::args` => `env::args` * `os::consts` => `env::consts` * `os::dll_filename` => no replacement, use `env::consts` directly * `os::page_size` => `env::page_size` * `os::make_absolute` => use `env::current_dir` + `join` instead * `os::getcwd` => `env::current_dir` * `os::change_dir` => `env::set_current_dir` * `os::homedir` => `env::home_dir` * `os::tmpdir` => `env::temp_dir` * `os::join_paths` => `env::join_paths` * `os::split_paths` => `env::split_paths` * `os::self_exe_name` => `env::current_exe` * `os::self_exe_path` => use `env::current_exe` + `pop` * `os::set_exit_status` => `env::set_exit_status` * `os::get_exit_status` => `env::get_exit_status` * `os::env` => `env::vars` * `os::env_as_bytes` => `env::vars` * `os::getenv` => `env::var` or `env::var_string` * `os::getenv_as_bytes` => `env::var` * `os::setenv` => `env::set_var` * `os::unsetenv` => `env::remove_var` Many function signatures have also been tweaked for various purposes, but the main changes were: * `Vec`-returning APIs now all return iterators instead * All APIs are now centered around `OsString` instead of `Vec<u8>` or `String`. There is currently on convenience API, `env::var_string`, which can be used to get the value of an environment variable as a unicode `String`. All old APIs are `#[deprecated]` in-place and will remain for some time to allow for migrations. The semantics of the APIs have been tweaked slightly with regard to dealing with invalid unicode (panic instead of replacement). The new `std::env` module is all contained within the `env` feature, so crates must add the following to access the new APIs: #![feature(env)] [breaking-change]
2015-01-27 14:20:58 -06:00
#![feature(env)]
#![cfg_attr(windows, feature(libc))]
#[macro_use] extern crate log;
pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
pub use win::WinConsole;
2015-01-22 18:31:00 -06:00
use std::old_io::IoResult;
2013-05-30 01:13:35 -05:00
pub mod terminfo;
#[cfg(windows)]
mod win;
/// A hack to work around the fact that `Box<Writer + Send>` does not
/// currently implement `Writer`.
pub struct WriterWrapper {
wrapped: Box<Writer + Send>,
}
impl Writer for WriterWrapper {
#[inline]
fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
self.wrapped.write_all(buf)
}
#[inline]
fn flush(&mut self) -> IoResult<()> {
self.wrapped.flush()
}
}
#[cfg(not(windows))]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
2014-10-01 01:01:08 -05:00
TerminfoTerminal::new(WriterWrapper {
2015-01-22 18:31:00 -06:00
wrapped: box std::old_io::stdout() as Box<Writer + Send>,
2014-10-01 01:01:08 -05:00
})
}
#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
2014-10-20 16:59:00 -05:00
let ti = TerminfoTerminal::new(WriterWrapper {
2015-01-22 18:31:00 -06:00
wrapped: box std::old_io::stdout() as Box<Writer + Send>,
2014-10-20 16:59:00 -05:00
});
match ti {
2014-10-20 16:59:00 -05:00
Some(t) => Some(t),
None => {
2014-10-20 16:59:00 -05:00
WinConsole::new(WriterWrapper {
2015-01-22 18:31:00 -06:00
wrapped: box std::old_io::stdout() as Box<Writer + Send>,
2014-10-20 16:59:00 -05:00
})
}
}
}
#[cfg(not(windows))]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
2014-10-01 01:01:08 -05:00
TerminfoTerminal::new(WriterWrapper {
2015-01-22 18:31:00 -06:00
wrapped: box std::old_io::stderr() as Box<Writer + Send>,
2014-10-01 01:01:08 -05:00
})
}
#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
2014-11-26 13:17:23 -06:00
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
2014-10-20 16:59:00 -05:00
let ti = TerminfoTerminal::new(WriterWrapper {
2015-01-22 18:31:00 -06:00
wrapped: box std::old_io::stderr() as Box<Writer + Send>,
2014-10-20 16:59:00 -05:00
});
match ti {
2014-10-20 16:59:00 -05:00
Some(t) => Some(t),
None => {
2014-10-20 16:59:00 -05:00
WinConsole::new(WriterWrapper {
2015-01-22 18:31:00 -06:00
wrapped: box std::old_io::stderr() as Box<Writer + Send>,
2014-10-20 16:59:00 -05:00
})
}
}
}
2014-03-16 17:15:55 -05:00
/// Terminal color definitions
pub mod color {
2014-03-16 17:15:55 -05:00
/// Number for a terminal color
pub type Color = u16;
2014-10-06 18:31:39 -05:00
pub const BLACK: Color = 0u16;
pub const RED: Color = 1u16;
pub const GREEN: Color = 2u16;
pub const YELLOW: Color = 3u16;
pub const BLUE: Color = 4u16;
pub const MAGENTA: Color = 5u16;
pub const CYAN: Color = 6u16;
pub const WHITE: Color = 7u16;
pub const BRIGHT_BLACK: Color = 8u16;
pub const BRIGHT_RED: Color = 9u16;
pub const BRIGHT_GREEN: Color = 10u16;
pub const BRIGHT_YELLOW: Color = 11u16;
pub const BRIGHT_BLUE: Color = 12u16;
pub const BRIGHT_MAGENTA: Color = 13u16;
pub const BRIGHT_CYAN: Color = 14u16;
pub const BRIGHT_WHITE: Color = 15u16;
}
2014-03-16 17:15:55 -05:00
/// Terminal attributes
pub mod attr {
pub use self::Attr::*;
/// Terminal attributes for use with term.attr().
2014-03-16 17:15:55 -05:00
///
/// Most attributes can only be turned on and must be turned off with term.reset().
/// The ones that can be turned off explicitly take a boolean value.
/// Color is also represented as an attribute for convenience.
#[derive(Copy)]
pub enum Attr {
/// Bold (or possibly bright) mode
Bold,
/// Dim mode, also called faint or half-bright. Often not supported
Dim,
/// Italics mode. Often not supported
Italic(bool),
/// Underline mode
Underline(bool),
/// Blink mode
Blink,
/// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
Standout(bool),
/// Reverse mode, inverts the foreground and background colors
Reverse,
/// Secure mode, also called invis mode. Hides the printed text
Secure,
/// Convenience attribute to set the foreground color
ForegroundColor(super::color::Color),
/// Convenience attribute to set the background color
BackgroundColor(super::color::Color)
}
}
/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal<T: Writer>: Writer {
/// Sets the foreground color to the given color.
///
/// If the color is a bright color, but the terminal only supports 8 colors,
/// the corresponding normal color will be used instead.
///
2014-03-16 17:15:55 -05:00
/// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
/// if there was an I/O error.
fn fg(&mut self, color: color::Color) -> IoResult<bool>;
/// Sets the background color to the given color.
///
/// If the color is a bright color, but the terminal only supports 8 colors,
/// the corresponding normal color will be used instead.
///
2014-03-16 17:15:55 -05:00
/// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
/// if there was an I/O error.
fn bg(&mut self, color: color::Color) -> IoResult<bool>;
/// Sets the given terminal attribute, if supported. Returns `Ok(true)`
/// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
/// there was an I/O error.
fn attr(&mut self, attr: attr::Attr) -> IoResult<bool>;
/// Returns whether the given terminal attribute is supported.
fn supports_attr(&self, attr: attr::Attr) -> bool;
/// Resets all terminal attributes and color to the default.
2014-03-16 17:15:55 -05:00
/// Returns `Ok()`.
fn reset(&mut self) -> IoResult<()>;
2014-03-16 17:15:55 -05:00
/// Gets an immutable reference to the stream inside
fn get_ref<'a>(&'a self) -> &'a T;
2013-11-24 05:53:08 -06:00
2014-03-16 17:15:55 -05:00
/// Gets a mutable reference to the stream inside
fn get_mut<'a>(&'a mut self) -> &'a mut T;
2013-11-24 05:53:08 -06:00
}
2014-10-01 01:01:08 -05:00
/// A terminal which can be unwrapped.
pub trait UnwrappableTerminal<T: Writer>: Terminal<T> {
/// Returns the contained stream, destroying the `Terminal`
fn unwrap(self) -> T;
}