Added RGB and curstom ANSI value support, and tested resize terminal, safe and restore cursor position for unix terminals. And added options put attributes on font.

This commit is contained in:
Timon Post 2018-01-27 18:26:08 +01:00
parent 0df9ad1015
commit 6be5a41204
19 changed files with 232 additions and 99 deletions

View File

@ -17,7 +17,7 @@ winapi = { version = "0.3", features = ["winbase","winuser","consoleapi","proces
libc = "0.2" libc = "0.2"
[[bin]] [[bin]]
name = "a" name = "example_bin"
path = "./examples/bin.rs" path = "./examples/bin.rs"

View File

@ -1,18 +1,29 @@
//! This bin folder can be used to try the examples out located in the examples directory.
//!
//! All you need to do is:
//!
//! - Download the crossterm source code.
//! - Add this in the Cargo.toml file:
//! ``` [[bin]]
//! name = "example_bin"
//! path = "./examples/bin.rs"
//! ```
//!
//! - Run program with: `cargo run`
// Import crossterm crate.
extern crate crossterm; extern crate crossterm;
use self::crossterm::crossterm_style::*; // Add the usings for the crossterms modules to play with crossterm
use self::crossterm::crossterm_style;
use self::crossterm::crossterm_cursor; use self::crossterm::crossterm_cursor;
use self::crossterm::crossterm_terminal::*; use self::crossterm::crossterm_terminal;
use std::io::{stdin, stdout, Write};
// Import the example modules.
pub mod color; pub mod color;
pub mod cursor; pub mod cursor;
pub mod terminal; pub mod terminal;
fn main() { fn main() {
terminal::resize_terminal();
print!(paint("asdf").with(Color::Black).on(Color::Red).black().red());
println!()
} }

View File

@ -98,3 +98,32 @@ pub fn print_all_background_colors()
println!("Grey : \t\t {}", paint(" ").on(Color::Grey)); println!("Grey : \t\t {}", paint(" ").on(Color::Grey));
println!("White : \t {}", paint(" ").on(Color::White)); println!("White : \t {}", paint(" ").on(Color::White));
} }
/// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely.
#[cfg(unix)]
pub fn print_font_with_attributes()
{
println!("{}", paint("Normal text"));
println!("{}", paint("Bold text").bold());
println!("{}", paint("Italic text").italic());
println!("{}", paint("Slow blinking text").slow_blink());
println!("{}", paint("Rapid blinking text").rapid_blink());
println!("{}", paint("Hidden text").hidden());
println!("{}", paint("Underlined text").underlined());
println!("{}", paint("Reversed color").reverse());
println!("{}", paint("Dim text color").dim());
println!("{}", paint("Crossed out font").crossed_out());
}
/// Print all supported rgb colors
#[cfg(unix)]#[cfg(unix)]
pub fn print_supported_colors()
{
let count = crossterm::crossterm_style::get().get_available_color_count().unwrap();
for i in 0..count
{
println!("{}", paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8)));
}
}

View File

@ -76,16 +76,25 @@ pub fn print()
get().goto(10,5).print("@"); get().goto(10,5).print("@");
} }
/// Save cursor position for recall later /// Save and reset cursor position.
pub fn safe_position() pub fn safe_and_reset_position()
{ {
get().safe_position(); let mut cursor = get();
}
/// Save cursor position for recall later // Goto X: 5 Y: 5
pub fn reset_position() cursor.goto(5,5);
{ // Safe cursor position: X: 5 Y: 5
get().reset_position(); cursor.safe_position();
// Goto X: 5 Y: 20
cursor.goto(5,20);
// Print at X: 5 Y: 20.
print!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.reset_position();
// Print Back at X: 5 Y: 5.
print!("Back");
println!()
} }

View File

@ -111,7 +111,7 @@ pub fn scroll_down()
// Get terminal // Get terminal
let mut terminal = get(); let mut terminal = get();
// Scroll down 10 lines. // Scroll down 10 lines.
let terminal_size = terminal.scroll_down(10); terminal.scroll_down(10);
} }
// scroll down 10 lines // scroll down 10 lines
@ -122,7 +122,7 @@ pub fn scroll_up()
// Get terminal // Get terminal
let mut terminal = get(); let mut terminal = get();
// Scroll up 10 lines. // Scroll up 10 lines.
let terminal_size = terminal.scroll_up(10); terminal.scroll_up(10);
} }
// Resize the terminal to X: 10, Y: 10 // Resize the terminal to X: 10, Y: 10
@ -131,5 +131,5 @@ pub fn resize_terminal()
// Get terminal // Get terminal
let mut terminal = get(); let mut terminal = get();
// Get terminal size // Get terminal size
terminal.set_size(2,2); terminal.set_size(1,1);
} }

View File

@ -45,7 +45,7 @@ impl ITerminalCursor for AnsiCursor {
write!(&mut some_writer, csi!("{}D"), count); write!(&mut some_writer, csi!("{}D"), count);
} }
fn safe_position(&self) fn safe_position(&mut self)
{ {
let mut some_writer = io::stdout(); let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("s")); write!(&mut some_writer, csi!("s"));

View File

@ -3,7 +3,7 @@ use std::io::Write;
use std::string::String; use std::string::String;
use Construct; use Construct;
use super::color::{Color, ColorType}; use super::super::{Color, ColorType};
use super::base_color::ITerminalColor; use super::base_color::ITerminalColor;
@ -19,14 +19,13 @@ impl Construct for ANSIColor {
impl ITerminalColor for ANSIColor { impl ITerminalColor for ANSIColor {
fn set_fg(&self, fg_color: Color) { fn set_fg(&self, fg_color: Color) {
let mut some_writer = io::stdout(); let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("38;5;{}m"), self.color_value(fg_color, ColorType::Foreground)); write!(&mut some_writer, csi!("{}m"), self.color_value(fg_color, ColorType::Foreground));
} }
fn set_bg(&self, bg_color: Color) { fn set_bg(&self, bg_color: Color) {
let mut some_writer = io::stdout(); let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("48;5;{}m"), self.color_value(bg_color, ColorType::Background)); write!(&mut some_writer, csi!("{}m"), self.color_value(bg_color, ColorType::Background));
} }
fn reset(&self) { fn reset(&self) {
@ -36,23 +35,41 @@ impl ITerminalColor for ANSIColor {
fn color_value(&self, color: Color, color_type: ColorType) -> String { fn color_value(&self, color: Color, color_type: ColorType) -> String {
// Construct ANSI escape color code string. ;1 is for the brightness let mut ansi_value = String::new();
match color {
Color::Black => "0", match color_type
Color::Red => "9", {
Color::DarkRed =>"1", ColorType::Foreground => {
Color::Green => "10", ansi_value.push_str("38;")
Color::DarkGreen => "2", },
Color::Yellow => "11", ColorType::Background => {
Color::DarkYellow => "3", ansi_value.push_str("48;")
Color::Blue => "12", },
Color::DarkBlue => "4", }
Color::Magenta => "13",
Color::DarkMagenta => "5", let rgb_val;
Color::Cyan => "14",
Color::DarkCyan => "6", let color_val = match color {
Color::Grey => "15", Color::Black => "5;0",
Color::White => "7", Color::Red => "5;9",
}.to_string() Color::DarkRed =>"5;1",
Color::Green => "5;10",
Color::DarkGreen => "5;2",
Color::Yellow => "5;11",
Color::DarkYellow => "5;3",
Color::Blue => "5;12",
Color::DarkBlue => "5;4",
Color::Magenta => "5;13",
Color::DarkMagenta => "5;5",
Color::Cyan => "5;14",
Color::DarkCyan => "5;6",
Color::Grey => "5;15",
Color::White => "5;7",
Color::Rgb{r,g,b} => { rgb_val = format!("2;{};{};{}", r,g,b); rgb_val.as_str()},
Color::AnsiValue(val) => { rgb_val = format!("5;{}",val); rgb_val.as_str() }
};
ansi_value.push_str(color_val);
ansi_value
} }
} }

View File

@ -2,10 +2,12 @@
//! Like styling the font, foreground color and background color. //! Like styling the font, foreground color and background color.
use std::fmt; use std::fmt;
use std::io;
use Construct; use Construct;
use crossterm_style::{ObjectStyle, StyledObject}; use crossterm_style::{ObjectStyle, StyledObject};
use super::base_color::ITerminalColor; use super::base_color::ITerminalColor;
use super::super::Color;
#[cfg(unix)] #[cfg(unix)]
use super::ANSIColor; use super::ANSIColor;
@ -96,6 +98,23 @@ impl TerminalColor {
terminal_color.reset(); terminal_color.reset();
} }
} }
/// Get available color count.
pub fn get_available_color_count(&self) -> io::Result<u16>
{
use std::env;
Ok(match env::var_os("TERM") {
Some(val) => {
if val.to_str().unwrap_or("").contains("256color") {
256
} else {
8
}
}
None => 8,
})
}
} }
/// Get an concrete ITerminalColor implementation based on the current operating system. /// Get an concrete ITerminalColor implementation based on the current operating system.

View File

@ -16,9 +16,11 @@ pub enum Attribute {
Dim = 2, Dim = 2,
Italic = 3, Italic = 3,
Underlined = 4, Underlined = 4,
Blink = 5, SlowBlink = 5,
RapidBlink = 6,
Reverse = 7, Reverse = 7,
Hidden = 8, Hidden = 8,
CrossedOut = 9
} }
/// Colors that are available for coloring the termainal font. /// Colors that are available for coloring the termainal font.
@ -46,6 +48,11 @@ pub enum Color {
Grey, Grey,
White, White,
#[cfg(unix)]
Rgb { r: u8, g: u8, b:u8 },
#[cfg(unix)]
AnsiValue(u8)
} }
/// Color types that can be used to determine if the Color enum is an Fore- or Background Color /// Color types that can be used to determine if the Color enum is an Fore- or Background Color

View File

@ -55,7 +55,7 @@ impl ObjectStyle {
self self
} }
pub fn add_attr(mut self, attr: Attribute) pub fn add_attr(&mut self, attr: Attribute)
{ {
self.attrs.push(attr); self.attrs.push(attr);
} }

View File

@ -12,11 +12,14 @@ pub struct StyledObject<D> {
} }
impl<D> StyledObject<D> { impl<D> StyledObject<D> {
/// Sets the foreground of the styled object to the passed `Color` /// Set the foreground of the styled object to the passed `Color`
/// ///
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm;
/// use self::crossterm::crossterm_style::{paint,Color};
///
/// // create an styled object with the foreground color red. /// // create an styled object with the foreground color red.
/// let styledobject = paint("I am colored red").with(Color::Red); /// let styledobject = paint("I am colored red").with(Color::Red);
/// // create an styled object with the foreground color blue. /// // create an styled object with the foreground color blue.
@ -34,11 +37,13 @@ impl<D> StyledObject<D> {
self self
} }
/// Sets the background of the styled object to the passed `Color` /// Set the background of the styled object to the passed `Color`
/// ///
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm;
/// use self::crossterm::crossterm_style::{paint,Color};
/// ///
/// // create an styled object with the background color red. /// // create an styled object with the background color red.
/// let styledobject = paint("I am colored red").on(Color::Red); /// let styledobject = paint("I am colored red").on(Color::Red);
@ -57,28 +62,43 @@ impl<D> StyledObject<D> {
self self
} }
pub fn attrs(mut self, attrs: Vec<Attribute>) -> StyledObject<D> /// Set the attribute of an styled object to the passed `Attribute`
{ ///
for attr in attrs.iter() { /// #Example
self.attr(attr); ///
} /// ```rust
///
self /// extern crate crossterm;
} /// use self::crossterm::crossterm_style::{paint,Attribute};
///
/// println!("{}", paint("Bold").attr(Attribute::Bold));
///
/// ```
#[cfg(unix)]
pub fn attr(mut self, attr: Attribute) -> StyledObject<D> pub fn attr(mut self, attr: Attribute) -> StyledObject<D>
{ {
self.object_style.add_attr(attr); &self.object_style.add_attr(attr);
self self
} }
#[inline(always)] pub fn bold(self) -> StyledObject<D> { self.attr(Attribute::Bold) } /// Increase the font intensity.
#[inline(always)] pub fn dim(self) -> StyledObject<D> { self.attr(Attribute::Dim) } #[cfg(unix)]#[inline(always)] pub fn bold(self) -> StyledObject<D> { self.attr(Attribute::Bold) }
#[inline(always)] pub fn italic(self) -> StyledObject<D> { self.attr(Attribute::Italic) } /// Faint (decreased intensity) (Not widely supported).
#[inline(always)] pub fn underlined(self) -> StyledObject<D> { self.attr(Attribute::Underlined) } #[cfg(unix)]#[inline(always)] pub fn dim(self) -> StyledObject<D> { self.attr(Attribute::Dim) }
#[inline(always)] pub fn blink(self) -> StyledObject<D> { self.attr(Attribute::Blink) } /// Make the font italic (Not widely supported; Sometimes treated as inverse).
#[inline(always)] pub fn reverse(self) -> StyledObject<D> { self.attr(Attribute::Reverse) } #[cfg(unix)]#[inline(always)] pub fn italic(self) -> StyledObject<D> { self.attr(Attribute::Italic) }
#[inline(always)] pub fn hidden(self) -> StyledObject<D> { self.attr(Attribute::Hidden) } /// Underline font.
#[cfg(unix)]#[inline(always)] pub fn underlined(self) -> StyledObject<D> { self.attr(Attribute::Underlined) }
/// Slow Blink (less than 150 per minute; not widely supported).
#[cfg(unix)]#[inline(always)] pub fn slow_blink(self) -> StyledObject<D> { self.attr(Attribute::SlowBlink) }
/// Rapid Blink (MS-DOS ANSI.SYS; 150+ per minute; not widely supported).
#[cfg(unix)]#[inline(always)] pub fn rapid_blink(self) -> StyledObject<D> { self.attr(Attribute::RapidBlink) }
/// Swap foreground and background colors.
#[cfg(unix)]#[inline(always)] pub fn reverse(self) -> StyledObject<D> { self.attr(Attribute::Reverse) }
/// Hide text (Not widely supported).
#[cfg(unix)]#[inline(always)] pub fn hidden(self) -> StyledObject<D> { self.attr(Attribute::Hidden) }
/// Characters legible, but marked for deletion. Not widely supported.
#[cfg(unix)]#[inline(always)] pub fn crossed_out(self) -> StyledObject<D> { self.attr(Attribute::CrossedOut) }
} }
/// This is used to make StyledObject able to be displayed. /// This is used to make StyledObject able to be displayed.
@ -104,8 +124,8 @@ macro_rules! impl_fmt
} }
#[cfg(unix)] #[cfg(unix)]
for attr in &self.object_style.attrs.iter() { for attr in self.object_style.attrs.iter() {
write!(f, csi!("{}m"), attr as i16); write!(f, csi!("{}m"), *attr as i16);
reset = true; reset = true;
} }

View File

@ -51,7 +51,7 @@ impl ITerminal for UnixTerminal {
write!(&mut some_writer, csi!("{}T"), count); write!(&mut some_writer, csi!("{}T"), count);
} }
fn set_size(width: i16, height: i16) { fn set_size(&self, width: i16, height: i16) {
let mut some_writer = io::stdout(); let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("8;{};{}t"), width, height); write!(&mut some_writer, csi!("8;{};{}t"), width, height);
} }

View File

@ -121,7 +121,21 @@ impl Terminal {
} }
} }
/// Set the terminal size. /// Set the terminal size. Note that not all terminals can be set to a very small scale.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::crossterm_terminal;
///
/// let mut term = crossterm_terminal::get();
///
/// // Set of the size to X: 10 and Y: 10
/// let size = term.set_size(10,10);
///
/// ```
pub fn set_size(&mut self, width: i16, height: i16) pub fn set_size(&mut self, width: i16, height: i16)
{ {
&self.init(); &self.init();

View File

@ -81,6 +81,7 @@ pub fn winapi_color_val(color: style::Color, color_type: style::ColorType) -> u1
Color::DarkCyan => fg_green | fg_blue, Color::DarkCyan => fg_green | fg_blue,
Color::Grey => fg_intensity, Color::Grey => fg_intensity,
Color::White => fg_intensity | fg_red | fg_green | fg_blue, Color::White => fg_intensity | fg_red | fg_green | fg_blue,
_ => Color::White
}; };
} }
ColorType::Background => { ColorType::Background => {
@ -100,6 +101,7 @@ pub fn winapi_color_val(color: style::Color, color_type: style::ColorType) -> u1
Color::DarkCyan => bg_green | bg_blue, Color::DarkCyan => bg_green | bg_blue,
Color::Grey => bg_intensity, Color::Grey => bg_intensity,
Color::White => bg_intensity | bg_red | bg_green | bg_blue, Color::White => bg_intensity | bg_red | bg_green | bg_blue,
_ => Color::White
}; };
} }
}; };

View File

@ -1,6 +1,7 @@
#[macro_use] #[macro_use]
mod shared; mod shared;
mod kernel; mod kernel;
pub mod crossterm_cursor; pub mod crossterm_cursor;
pub mod crossterm_style; pub mod crossterm_style;
pub mod crossterm_terminal; pub mod crossterm_terminal;

View File

@ -1,3 +0,0 @@
pub fn is_cursor_out_of_range(x: i16, y: i16) {
}

View File

@ -1,4 +1,3 @@
#[macro_use] #[macro_use]
pub mod macros; pub mod macros;
pub mod traits; pub mod traits;
pub mod functions;

View File

@ -6,9 +6,7 @@ pub trait Construct {
Self: Sized; Self: Sized;
} }
/// This trait can be used to create an empty instance of an struct.
/// This trait is used to create an empty instance of an struct.
pub trait Empty { pub trait Empty {
fn empty() -> Self; fn empty() -> Self;
} }

View File

@ -3,3 +3,13 @@ Windows logic clear aan passen before after cursor
ideas: ideas:
https://apple.stackexchange.com/questions/33736/can-a-terminal-window-be-resized-with-a-terminal-command https://apple.stackexchange.com/questions/33736/can-a-terminal-window-be-resized-with-a-terminal-command
new inplemented:
Safe and restore cursor
Resize terminal
Styling font with attributes
RGB color option added for unix
ANSI cutom color value input added for unix