initial commit
This commit is contained in:
commit
6c141ee0b5
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -0,0 +1,63 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
|
||||
|
||||
[[package]]
|
||||
name = "nikki"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"termion",
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
|
||||
dependencies = [
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"numtoa",
|
||||
"redox_syscall",
|
||||
"redox_termios",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "nikki"
|
||||
version = "0.1.0"
|
||||
authors = ["Raphael Jacobs <raphy@airmail.cc>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
termion = "1"
|
||||
unicode-segmentation = "1"
|
|
@ -0,0 +1,38 @@
|
|||
use termion::color;
|
||||
|
||||
use color::Rgb;
|
||||
|
||||
pub struct Colorscheme {
|
||||
pub title: Rgb,
|
||||
pub subtitle: Rgb,
|
||||
pub text: Rgb,
|
||||
pub background: Rgb,
|
||||
pub status_text: Rgb,
|
||||
pub status_background: Rgb,
|
||||
pub currentline: Rgb,
|
||||
pub highlighted_background: Rgb,
|
||||
pub highlighted_text: Rgb,
|
||||
}
|
||||
|
||||
|
||||
pub const WHITE : Rgb = Rgb(230, 230, 230);
|
||||
pub const GRAY : Rgb = Rgb(163, 163, 163);
|
||||
pub const GRAY2 : Rgb = Rgb(189, 189, 189);
|
||||
pub const BLACK : Rgb = Rgb(40, 40, 40);
|
||||
|
||||
|
||||
impl Colorscheme {
|
||||
pub fn default() -> Self {
|
||||
Self {
|
||||
title: GRAY,
|
||||
subtitle: GRAY,
|
||||
text: WHITE,
|
||||
background: BLACK,
|
||||
status_text: BLACK,
|
||||
status_background: WHITE,
|
||||
currentline: GRAY2,
|
||||
highlighted_background: WHITE,
|
||||
highlighted_text: GRAY,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
|
||||
pub struct Config {
|
||||
pub maxwidth: usize,
|
||||
pub vertical_padding: usize,
|
||||
pub horizontal_scrollspace: usize,
|
||||
pub vertical_scrollspace: usize
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn default() -> Self {
|
||||
Self {
|
||||
maxwidth: 80,
|
||||
vertical_padding: 5,
|
||||
horizontal_scrollspace: 10,
|
||||
vertical_scrollspace: 5}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
use crate::Row;
|
||||
use crate::Position;
|
||||
use std::fs;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Document {
|
||||
rows: Vec<Row>
|
||||
}
|
||||
|
||||
impl Document {
|
||||
pub fn open(filename: &str) -> Result<Self, std::io::Error> {
|
||||
let contents = fs::read_to_string(filename)?;
|
||||
let mut rows = Vec::new();
|
||||
for value in contents.lines() {
|
||||
rows.push(Row::from(value))
|
||||
}
|
||||
Ok(Self {rows})
|
||||
}
|
||||
|
||||
pub fn row(&self, index : usize) -> Option<&Row> {
|
||||
self.rows.get(index)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.rows.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.rows.len()
|
||||
}
|
||||
|
||||
pub fn insert_newline(&mut self, at: &Position) {
|
||||
if at.y > self.len() {
|
||||
return;
|
||||
}
|
||||
|
||||
if at.y == self.len() {
|
||||
self.rows.push(Row::default());
|
||||
} else {
|
||||
let new_row = self.rows.get_mut(at.y).unwrap().split(at.x);
|
||||
self.rows.insert(at.y + 1, new_row)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, at: &Position, c: char) {
|
||||
if c == '\n' {
|
||||
self.insert_newline(at);
|
||||
return;
|
||||
}
|
||||
|
||||
if at.y == self.len() {
|
||||
let mut row = Row::default();
|
||||
row.insert(0, c);
|
||||
self.rows.push(row);
|
||||
} else if at.y < self.len() {
|
||||
let row = self.rows.get_mut(at.y).unwrap();
|
||||
row.insert(at.x, c);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete(&mut self, at: &Position) {
|
||||
|
||||
let len = self.len();
|
||||
|
||||
if at.y >= self.len() {
|
||||
return;
|
||||
}
|
||||
|
||||
if at.x == self.rows.get_mut(at.y).unwrap().len() && at.y < len - 1 {
|
||||
let next_row = self.rows.remove(at.y + 1);
|
||||
let row = self.rows.get_mut(at.y).unwrap();
|
||||
row.append(&next_row);
|
||||
} else {
|
||||
let row = self.rows.get_mut(at.y).unwrap();
|
||||
row.delete(at.x);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
use crate::Terminal;
|
||||
use crate::Document;
|
||||
use crate::Row;
|
||||
use crate::Colorscheme;
|
||||
use crate::Config;
|
||||
use std::env;
|
||||
use std::cmp;
|
||||
use termion::event::Key;
|
||||
use termion::color;
|
||||
use std::{time, thread};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Position {
|
||||
pub x: usize,
|
||||
pub y: usize
|
||||
}
|
||||
|
||||
pub struct Editor {
|
||||
should_quit: bool,
|
||||
terminal: Terminal,
|
||||
cursor_position: Position,
|
||||
offset: Position,
|
||||
document: Document,
|
||||
rememberx: usize,
|
||||
colorscheme: Colorscheme,
|
||||
config: Config
|
||||
}
|
||||
|
||||
|
||||
fn die(e: std::io::Error) {
|
||||
panic!("{}", e);
|
||||
}
|
||||
|
||||
|
||||
impl Editor {
|
||||
pub fn default() -> Self {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let document = if args.len() > 1 {
|
||||
let filename = &args[1];
|
||||
Document::open(&filename).unwrap_or_default()
|
||||
} else {
|
||||
Document::default()
|
||||
};
|
||||
|
||||
|
||||
Self {
|
||||
should_quit: false,
|
||||
terminal: Terminal::default().expect("Failed to initialize terminal"),
|
||||
cursor_position: Position::default(),
|
||||
offset: Position::default(),
|
||||
document,
|
||||
rememberx:0,
|
||||
colorscheme: Colorscheme::default(),
|
||||
config: Config::default()
|
||||
// document: Document::open(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
|
||||
loop {
|
||||
if let Err(e) = self.refresh_screen() {
|
||||
die(e)
|
||||
}
|
||||
if self.should_quit {
|
||||
break;
|
||||
}
|
||||
if let Err(e) = self.process_keypress() {
|
||||
die(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn refresh_screen(&self) -> Result<(), std::io::Error> {
|
||||
Terminal::cursor_hide();
|
||||
self.draw_rows();
|
||||
self.draw_info();
|
||||
|
||||
let Position{x, y} = self.cursor_position;
|
||||
let Position{x : ox, y : oy} = self.offset;
|
||||
|
||||
let w = self.terminal.size().width as usize;
|
||||
|
||||
let maxw = self.config.maxwidth;
|
||||
|
||||
let wpad = (w.saturating_sub(maxw))/2;
|
||||
let ypad = self.config.vertical_padding;
|
||||
|
||||
|
||||
let relativep = Position{ x: x.saturating_sub(ox) + wpad, y: (y + ypad).saturating_sub(oy)};
|
||||
|
||||
|
||||
self.terminal.cursor_position(&relativep);
|
||||
Terminal::cursor_show();
|
||||
Terminal::flush()
|
||||
}
|
||||
|
||||
// TODO: horizontal padding
|
||||
pub fn draw_row(&self, row: &Row) {
|
||||
let w = self.terminal.size().width as usize;
|
||||
|
||||
let maxw = self.config.maxwidth;
|
||||
|
||||
let pad = (w.saturating_sub(maxw))/2;
|
||||
|
||||
let start = self.offset.x;
|
||||
let end = self.offset.x + w - pad*2;
|
||||
let r = row.render(start, end);
|
||||
let space = &" ".repeat(pad);
|
||||
println!("{}{}\r", space, r)
|
||||
}
|
||||
|
||||
fn draw_rows(&self) {
|
||||
Terminal::cursor_reset();
|
||||
Terminal::set_text_color(self.colorscheme.text);
|
||||
Terminal::set_bg_color(self.colorscheme.background);
|
||||
// Terminal::clear_screen();
|
||||
let h = self.terminal.size().height as usize;
|
||||
let w = self.terminal.size().width as usize;
|
||||
|
||||
let vertical_pad = self.config.vertical_padding.saturating_sub(self.offset.y);
|
||||
// let vertical_pad = 5;
|
||||
let trueh = h.saturating_sub(vertical_pad);
|
||||
|
||||
for _ in 0..vertical_pad {
|
||||
// thread::sleep(time::Duration::from_millis(500));
|
||||
Terminal::clear_current_line();
|
||||
println!("\r")
|
||||
}
|
||||
// thread::sleep(time::Duration::from_millis(500));
|
||||
|
||||
for terminal_row in 0..trueh {
|
||||
Terminal::clear_current_line();
|
||||
// thread::sleep(time::Duration::from_millis(50));
|
||||
if let Some(row) = self.document.row(terminal_row as usize + self.offset.y.saturating_sub(self.config.vertical_padding)) {
|
||||
self.draw_row(row);
|
||||
} else {
|
||||
println!("\r");
|
||||
}
|
||||
}
|
||||
Terminal::reset_text_color();
|
||||
Terminal::reset_bg_color();
|
||||
}
|
||||
|
||||
fn draw_info(&self) {
|
||||
Terminal::set_bg_color(self.colorscheme.status_background);
|
||||
Terminal::set_text_color(self.colorscheme.status_text);
|
||||
|
||||
let width = self.terminal.size().width as usize;
|
||||
let mut status = format!("Terminal size is {}, {}", self.terminal.size().width, self.terminal.size().height);
|
||||
let mut status2 = format!("Position: x: {} y :{} - Offset: x: {}, y: {} ", self.cursor_position.x, self.cursor_position.y, self.offset.x, self.offset.y);
|
||||
|
||||
if width > status.len() {
|
||||
status.push_str(&" ".repeat(width - status.len()))
|
||||
} else {
|
||||
status.truncate(width);
|
||||
}
|
||||
if width > status2.len() {
|
||||
status2.push_str(&" ".repeat(width - status.len()))
|
||||
} else {
|
||||
status2.truncate(width);
|
||||
}
|
||||
Terminal::clear_current_line();
|
||||
println!("{}\r", status);
|
||||
Terminal::clear_current_line();
|
||||
print!("{}\r", status2);
|
||||
Terminal::reset_text_color();
|
||||
Terminal::reset_bg_color();
|
||||
}
|
||||
|
||||
fn process_keypress(&mut self) -> Result<(), std::io::Error>{
|
||||
let pressed_key = Terminal::read_key()?;
|
||||
match pressed_key {
|
||||
Key::Ctrl('q') => self.should_quit = true,
|
||||
Key::Char(c) => {
|
||||
self.document.insert(&self.cursor_position, c);
|
||||
self.move_cursor(Key::Right);
|
||||
}
|
||||
Key::Delete => self.document.delete(&self.cursor_position),
|
||||
Key::Backspace => {
|
||||
if self.cursor_position.x > 0 || self.cursor_position.y > 0 {
|
||||
self.move_cursor(Key::Left);
|
||||
self.document.delete(&self.cursor_position);
|
||||
}
|
||||
}
|
||||
Key::Up | Key::Down | Key::Left | Key::Right => self.move_cursor(pressed_key),
|
||||
_ => (),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn move_cursor(&mut self, key: Key) {
|
||||
let Position {mut y, mut x} = self.cursor_position;
|
||||
|
||||
|
||||
let w = self.document.row(y).map_or(0, Row::len);
|
||||
let h = self.document.len();
|
||||
|
||||
|
||||
match key {
|
||||
Key::Up => y = y.saturating_sub(1),
|
||||
Key::Down => {if y < h
|
||||
{y = y.saturating_add(1)}},
|
||||
Key::Left => {
|
||||
if x > 0 {
|
||||
x -= 1;
|
||||
} else if y > 0 {
|
||||
y -= 1;
|
||||
x = self.document.row(y).map_or(0, Row::len);
|
||||
}
|
||||
self.rememberx = x;
|
||||
},
|
||||
Key::Right => {
|
||||
if x < w {
|
||||
x += 1
|
||||
} else if y < h {
|
||||
y += 1;
|
||||
x = 0;
|
||||
}
|
||||
self.rememberx = x;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let neww = self.document.row(y).map_or(0, Row::len);
|
||||
|
||||
if neww <= self.rememberx {
|
||||
x = neww;
|
||||
} else {
|
||||
x = self.rememberx
|
||||
};
|
||||
|
||||
self.cursor_position = Position {x, y};
|
||||
self.scroll();
|
||||
}
|
||||
|
||||
pub fn scroll(&mut self) { // TODO: leave 4-5 lines of space above and below
|
||||
let Position {x, y} = self.cursor_position;
|
||||
let s = self.terminal.size();
|
||||
let w = s.width as usize;
|
||||
let h = s.height as usize;
|
||||
|
||||
let yscroll = self.config.vertical_scrollspace;
|
||||
let xscroll = self.config.horizontal_scrollspace;
|
||||
|
||||
let ypad = self.config.vertical_padding;
|
||||
let maxw = self.config.maxwidth;
|
||||
|
||||
let mut offset = &mut self.offset;
|
||||
|
||||
|
||||
|
||||
let true_w = cmp::min(w, maxw);
|
||||
|
||||
let true_h = h.saturating_sub(ypad.saturating_sub(offset.y));
|
||||
|
||||
|
||||
if y - offset.y.saturating_sub(ypad) + 1 > h - ypad.saturating_sub(offset.y) {
|
||||
offset.y = y.saturating_sub(h - ypad).saturating_add(1);
|
||||
} else if y < offset.y {
|
||||
offset.y = y;
|
||||
}
|
||||
|
||||
if x + 1 > offset.x.saturating_add(true_w) {
|
||||
offset.x = x.saturating_sub(true_w).saturating_add(1);
|
||||
} else if x < offset.x {
|
||||
offset.x = x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// #![warn(clippy::all, clippy::pedantic)]
|
||||
mod editor;
|
||||
mod terminal;
|
||||
mod document;
|
||||
mod row;
|
||||
mod colorscheme;
|
||||
mod config;
|
||||
|
||||
pub use terminal::Terminal;
|
||||
pub use editor::Position;
|
||||
pub use document::Document;
|
||||
pub use row::Row;
|
||||
pub use colorscheme::Colorscheme;
|
||||
pub use config::Config;
|
||||
use editor::Editor;
|
||||
|
||||
|
||||
|
||||
fn main() {
|
||||
|
||||
|
||||
let mut edit = Editor::default();
|
||||
edit.run();
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
use std::cmp;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Row {
|
||||
string: String,
|
||||
len: usize
|
||||
}
|
||||
|
||||
impl From<&str> for Row {
|
||||
fn from(slice: &str) -> Self {
|
||||
let mut row = Self {string: String::from(slice),
|
||||
len : 0};
|
||||
|
||||
row.update_len();
|
||||
row
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Row {
|
||||
pub fn render(&self, s: usize, e: usize) -> String {
|
||||
let end = cmp::min(e, self.len);
|
||||
let start = cmp::min(s, end);
|
||||
let mut result = String::new();
|
||||
for grapheme in self.string[..].graphemes(true).skip(start).take(end - start) {
|
||||
if grapheme == "\t" {
|
||||
result.push_str(" ")
|
||||
} else {
|
||||
result.push_str(grapheme)
|
||||
}
|
||||
}
|
||||
result
|
||||
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
pub fn update_len(&mut self) {
|
||||
self.len = self.string[..].graphemes(true).count();
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, at: usize, c: char) {
|
||||
if at >= self.len() {
|
||||
self.string.push(c);
|
||||
} else {
|
||||
let mut result: String = self.string[..].graphemes(true).take(at).collect();
|
||||
let remainder: String = self.string[..].graphemes(true).skip(at).collect();
|
||||
result.push(c);
|
||||
result.push_str(&remainder);
|
||||
self.string = result;
|
||||
}
|
||||
self.update_len();
|
||||
}
|
||||
pub fn delete(&mut self, at:usize) {
|
||||
if at >= self.len() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut result: String = self.string[..].graphemes(true).take(at).collect();
|
||||
let remainder: String = self.string[..].graphemes(true).skip(at + 1).collect();
|
||||
result.push_str(&remainder);
|
||||
self.string = result;
|
||||
|
||||
self.update_len();
|
||||
}
|
||||
|
||||
pub fn split(&mut self, at: usize) -> Self {
|
||||
let beginning: String = self.string[..].graphemes(true).take(at).collect();
|
||||
let remainder: String = self.string[..].graphemes(true).skip(at).collect();
|
||||
self.string = beginning;
|
||||
self.update_len();
|
||||
Self::from(&remainder[..])
|
||||
}
|
||||
|
||||
pub fn append(&mut self, new: &Self) {
|
||||
self.string = format!("{}{}", self.string, new.string);
|
||||
self.update_len()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
use std::io::{self, stdout, stdin, Write, Stdout};
|
||||
use std::cmp;
|
||||
use termion::event::Key;
|
||||
use termion::input::TermRead;
|
||||
use termion::raw::{IntoRawMode, RawTerminal};
|
||||
use termion::screen::AlternateScreen;
|
||||
// use std::fmt::Display;
|
||||
use crate::Position;
|
||||
use termion::color;
|
||||
|
||||
pub struct Size {
|
||||
pub width: u16,
|
||||
pub height: u16
|
||||
}
|
||||
pub struct Terminal {
|
||||
size: Size,
|
||||
screen: AlternateScreen<RawTerminal<Stdout>>,
|
||||
// _stdout: RawTerminal<std::io::Stdout>
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
/// # Errors
|
||||
/// Will return Err if terminal cannot be initialized
|
||||
/// Will return Err if termius fails to initialize stdout to raw more
|
||||
pub fn default() -> Result<Self, std::io::Error> {
|
||||
let size = termion::terminal_size()?;
|
||||
let out = stdout().into_raw_mode()?;
|
||||
let screen = AlternateScreen::from(out);
|
||||
|
||||
Ok(Self {
|
||||
size : Size {
|
||||
width : size.0,
|
||||
height : size.1 - 2
|
||||
},
|
||||
screen,
|
||||
})
|
||||
}
|
||||
|
||||
// fn print2scr<T : Display>(&self, p:T) {
|
||||
// write!(self.screen, "{}", p)
|
||||
// }
|
||||
|
||||
pub fn size(&self) -> &Size {
|
||||
&self.size
|
||||
}
|
||||
|
||||
pub fn clear_screen() {
|
||||
let k = termion::clear::All;
|
||||
print!("{}", termion::clear::All)
|
||||
}
|
||||
|
||||
pub fn cursor_reset() {
|
||||
print!("{}", termion::cursor::Goto(1,1))
|
||||
}
|
||||
|
||||
pub fn cursor_position(&self, p : &Position) {
|
||||
let Position{x, y} = p;
|
||||
let s = self.size();
|
||||
let x = cmp::min(x.saturating_add(1) as u16, s.width);
|
||||
let y = cmp::min(y.saturating_add(1) as u16, s.height);
|
||||
print!("{}", termion::cursor::Goto(x, y))
|
||||
}
|
||||
|
||||
|
||||
/// # Errors
|
||||
pub fn flush() -> Result<(), std::io::Error> {
|
||||
io::stdout().flush()
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
pub fn read_key() -> Result<Key, std::io::Error> {
|
||||
loop {
|
||||
if let Some(key) = stdin().lock().keys().next() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_hide() {
|
||||
print!("{}", termion::cursor::Hide);
|
||||
}
|
||||
|
||||
pub fn cursor_show() {
|
||||
print!("{}", termion::cursor::Show);
|
||||
}
|
||||
|
||||
pub fn clear_current_line() {
|
||||
print!("{}", termion::clear::CurrentLine);
|
||||
}
|
||||
|
||||
pub fn set_bg_color(color: color::Rgb) {
|
||||
print!("{}", color::Bg(color))
|
||||
}
|
||||
|
||||
pub fn reset_bg_color() {
|
||||
print!("{}", color::Bg(color::Reset))
|
||||
}
|
||||
|
||||
pub fn set_text_color(color: color::Rgb) {
|
||||
print!("{}", color::Fg(color))
|
||||
}
|
||||
|
||||
pub fn reset_text_color() {
|
||||
print!("{}", color::Fg(color::Reset))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue