#![allow(non_upper_case_globals)]
#![cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
#![cfg_attr(feature = "cargo-clippy", allow(match_bool))]
#[cfg(windows)]
extern crate kernel32;
#[macro_use]
extern crate tinf;
extern crate tvis_util;
#[cfg(windows)]
extern crate winapi;
use std::{error, fmt, io};
use tvis_util::Handle;
pub use tvis_util::TerminalMode;
pub use tvis_util::size::WinSize;
#[cfg(windows)]
mod console;
#[cfg(windows)]
pub use self::console::ConStream;
mod buf;
pub use self::buf::BufStream;
mod term;
pub use self::term::TermStream;
pub fn stdout(do_style: DoStyle) -> Box<LockableStream> {
match Handle::Stdout.terminal_mode() {
#[cfg(windows)]
TerminalMode::Console => Box::new(ConStream::stdout(do_style)),
mode => Box::new(TermStream::std(mode, io::stdout(), do_style)),
}
}
pub fn stderr(do_style: DoStyle) -> Box<LockableStream> {
match Handle::Stderr.terminal_mode() {
#[cfg(windows)]
TerminalMode::Console => Box::new(ConStream::stderr(do_style)),
mode => Box::new(TermStream::std(mode, io::stderr(), do_style)),
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DoStyle {
Always,
Auto,
Never,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Color(i32, u16);
pub const Black: Color = Color(0, 0);
pub const Red: Color = Color(1, 4);
pub const Green: Color = Color(2, 2);
pub const Yellow: Color = Color(3, 6);
pub const Blue: Color = Color(4, 1);
pub const Magenta: Color = Color(5, 5);
pub const Cyan: Color = Color(6, 3);
pub const White: Color = Color(7, 7);
pub trait Stream: io::Write {
fn reset(&mut self) -> Result<()>;
fn fg(&mut self, fg: Color) -> Result<()>;
fn em(&mut self) -> Result<()>;
fn is_cli(&self) -> bool;
}
pub trait CLIStream: Stream {
fn rewind_lines(&mut self, count: u16) -> Result<()>;
fn get_size(&self) -> WinSize;
}
impl<'a> Stream for Box<CLIStream + 'a> {
fn reset(&mut self) -> Result<()> {
(**self).reset()
}
fn fg(&mut self, fg: Color) -> Result<()> {
(**self).fg(fg)
}
fn em(&mut self) -> Result<()> {
(**self).em()
}
fn is_cli(&self) -> bool {
(**self).is_cli()
}
}
impl<'a> CLIStream for Box<CLIStream + 'a> {
fn rewind_lines(&mut self, count: u16) -> Result<()> {
(**self).rewind_lines(count)
}
fn get_size(&self) -> WinSize {
(**self).get_size()
}
}
pub trait LockableStream: CLIStream {
fn lock<'a>(&'a self) -> Box<CLIStream + 'a>;
}
impl Stream for Box<LockableStream> {
fn reset(&mut self) -> Result<()> {
(**self).reset()
}
fn fg(&mut self, fg: Color) -> Result<()> {
(**self).fg(fg)
}
fn em(&mut self) -> Result<()> {
(**self).em()
}
fn is_cli(&self) -> bool {
(**self).is_cli()
}
}
impl CLIStream for Box<LockableStream> {
fn rewind_lines(&mut self, count: u16) -> Result<()> {
(**self).rewind_lines(count)
}
fn get_size(&self) -> WinSize {
(**self).get_size()
}
}
#[derive(Debug)]
pub struct Error {
inner: ErrorImpl,
}
#[derive(Debug)]
enum ErrorImpl {
Io(io::Error),
Cap(::tinf::CapError),
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error {
inner: ErrorImpl::Io(err),
}
}
}
impl From<::tinf::CapError> for Error {
fn from(err: ::tinf::CapError) -> Error {
Error {
inner: ErrorImpl::Cap(err),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.inner {
ErrorImpl::Io(ref err) => err.fmt(f),
ErrorImpl::Cap(ref err) => err.fmt(f),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match self.inner {
ErrorImpl::Io(ref err) => err.description(),
ErrorImpl::Cap(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match self.inner {
ErrorImpl::Io(ref err) => Some(err),
ErrorImpl::Cap(ref err) => Some(err),
}
}
}
pub type Result<T> = std::result::Result<T, Error>;