Yay! 256-color mode

This commit is contained in:
Ticki 2016-03-07 17:39:25 +01:00
parent 2f0c72e1e4
commit 6f9addc42b
4 changed files with 124 additions and 4 deletions

View File

@ -1,6 +1,6 @@
extern crate libterm;
use libterm::{TermControl, raw_mode};
use libterm::{TermControl, raw_mode, Color};
use std::io::{Read, Write, stdout, stdin};
fn main() {
@ -21,7 +21,7 @@ fn main() {
match b {
b'q' => return,
b'c' => stdout.clear(),
b'r' => stdout.rendition(91),
b'r' => stdout.color(Color::Rgb(5, 0, 0)),
a => stdout.write(&[a]),
}.unwrap();

84
src/color.rs Normal file
View File

@ -0,0 +1,84 @@
/// A terminal color.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum Color {
/// Black.
Black,
/// Red.
Red,
/// Green.
Green,
/// Yellow.
Yellow,
/// Blue.
Blue,
/// Megenta.
Magenta,
/// Cyan.
Cyan,
/// White.
White,
/// High-intensity black.
HiBlack,
/// High-intensity red.
HiRed,
/// High-intensity green.
HiGreen,
/// High-intensity yellow.
HiYellow,
/// High-intensity blue.
HiBlue,
/// High-intensity megenta.
HiMagenta,
/// High-intensity cyan.
HiCyan,
/// High-intensity white.
HiWhite,
/// 216-color (6, 6, 6) RGB.
Rgb(u8, u8, u8),
/// Grayscale (max value: 24)
Grayscale(u8),
}
use Color::*;
impl Color {
pub fn to_ansi_val(self) -> u8 {
self.debug_check();
match self {
Black => 0x0,
Red => 0x1,
Green => 0x2,
Yellow => 0x3,
Blue => 0x4,
Magenta => 0x5,
Cyan => 0x6,
White => 0x7,
HiBlack => 0x8,
HiRed => 0x9,
HiGreen => 0xA,
HiYellow => 0xB,
HiBlue => 0xC,
HiMagenta => 0xD,
HiCyan => 0xE,
HiWhite => 0xF,
Rgb(r, g, b) => 16 + 36 * r + 6 * g + b,
Grayscale(shade) => 0xE8 + shade,
}
}
pub fn debug_check(self) {
match self {
Rgb(r, g, b) => {
debug_assert!(r <= 5, "Red color fragment (r = {}) is out of bound. Make sure r ≤ 5.", r);
debug_assert!(g <= 5, "Green color fragment (g = {}) is out of bound. Make sure g ≤ 5.", g);
debug_assert!(b <= 5, "Blue color fragment (b = {}) is out of bound. Make sure b ≤ 5.", b);
},
Grayscale(shade) => {
// Unfortunately, there are a little less than fifty shades.
debug_assert!(shade < 24, "Grayscale out of bound (shade = {}). There are only 24 shades of gray.", shade);
},
_ => {},
}
}
}

View File

@ -1,4 +1,5 @@
use std::io::{Write, Result as IoResult};
use Color;
/// Controlling terminals.
pub trait TermControl {
@ -27,9 +28,9 @@ pub trait TermControl {
/// Go to a given position.
fn goto(&mut self, x: u16, y: u16) -> IoResult<usize> {
self.csi(&[
(x / 10000) as u8 + b'0', ((x / 1000) % 10) as u8 + b'0', ((x / 100) % 10) as u8 + b'0', ((x / 10) % 10) as u8 + b'0', (x % 10) as u8 + b'0',
(x / 10000) as u8 + b'0', (x / 1000) as u8 % 10 + b'0', (x / 100) as u8 % 10 + b'0', (x / 10) as u8 % 10 + b'0', x as u8 % 10 + b'0',
b';',
(y / 10000) as u8 + b'0', ((y / 1000) % 10) as u8 + b'0', ((y / 100) % 10) as u8 + b'0', ((y / 10) % 10) as u8 + b'0', (y % 10) as u8 + b'0',
(y / 10000) as u8 + b'0', (y / 1000) as u8 % 10 + b'0', (y / 100) as u8 % 10 + b'0', (y / 10) as u8 % 10 + b'0', y as u8 % 10 + b'0',
b'H',
])
}
@ -40,6 +41,36 @@ pub trait TermControl {
b'm',
])
}
/// Set foreground color
fn color(&mut self, color: Color) -> IoResult<usize> {
let ansi = color.to_ansi_val();
self.csi(&[
b'3',
b'8',
b';',
b'5',
b';',
b'0' + ansi / 100,
b'0' + ansi / 10 % 10,
b'0' + ansi % 10,
b'm',
])
}
/// Set background color
fn bg_color(&mut self, color: Color) -> IoResult<usize> {
let ansi = color.to_ansi_val();
self.csi(&[
b'4',
b'8',
b';',
b'5',
b';',
b'0' + ansi / 100,
b'0' + ansi / 10 % 10,
b'0' + ansi % 10,
b'm',
])
}
}
impl<W: Write> TermControl for W {

View File

@ -1,4 +1,6 @@
#![feature(libc)]
#[warn(missing_docs)]
extern crate libc;
mod termios;
@ -11,3 +13,6 @@ pub use raw::{raw_mode, TerminalRestorer};
mod size;
pub use size::termsize;
mod color;
pub use color::Color;