Changed backend to crossterm

This commit is contained in:
RaphyJake 2021-11-02 22:49:03 +01:00
parent 1822cf4237
commit 85880255af
10 changed files with 470 additions and 170 deletions

126
Cargo.lock generated
View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
@ -8,9 +10,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cfg-if"
@ -31,6 +33,31 @@ dependencies = [
"winapi",
]
[[package]]
name = "crossterm"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c"
dependencies = [
"bitflags",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c"
dependencies = [
"winapi",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -40,12 +67,30 @@ dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "libc"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
[[package]]
name = "lock_api"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
@ -82,7 +127,7 @@ name = "nikki"
version = "0.1.0"
dependencies = [
"chrono",
"termion",
"crossterm",
"tokio",
"unicode-segmentation",
"unicode-width",
@ -126,18 +171,37 @@ dependencies = [
"libc",
]
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "once_cell"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "pin-project-lite"
version = "0.2.7"
@ -172,12 +236,30 @@ dependencies = [
]
[[package]]
name = "redox_termios"
version = "0.1.2"
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "signal-hook"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1"
dependencies = [
"redox_syscall",
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
@ -189,6 +271,12 @@ dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "syn"
version = "1.0.74"
@ -200,18 +288,6 @@ dependencies = [
"unicode-xid",
]
[[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 = "time"
version = "0.1.44"

View File

@ -8,8 +8,8 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
termion = "1"
unicode-segmentation = "1"
crossterm = "0.22"
unicode-width = "0.1.7"
tokio = { version = "1", features = ["time", "signal", "rt", "rt-multi-thread", "sync", "macros"] }
chrono = "0.4"
chrono = "0.4"

2
minitest Normal file
View File

@ -0,0 +1,2 @@
Si, si. Porco dio.
Ah ma no eh, FANTASTICO.

View File

@ -1,23 +1,45 @@
use termion::color;
use color::Rgb;
use crossterm::style;
use crossterm::style::Color;
use crossterm::style::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 title: Color,
pub subtitle: Color,
pub text: Color,
pub background: Color,
pub status_text: Color,
pub status_background: Color,
pub currentline: Color,
pub highlighted_background: Color,
pub highlighted_text: Color,
}
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);
pub const WHITE: Color = Rgb {
r: 230,
g: 230,
b: 230,
};
pub const GRAY: Color = Rgb {
r: 163,
g: 163,
b: 163,
};
pub const GRAY2: Color = Rgb {
r: 189,
g: 189,
b: 189,
};
pub const BLACK: Color = Rgb {
r: 40,
g: 40,
b: 40,
};
// pub const BLACK2: Color = Rgb {
// r: 20,
// g: 20,
// b: 20,
// };
impl Colorscheme {
pub fn default() -> Self {

View File

@ -2,6 +2,7 @@ use crate::Position;
use crate::Row;
use std::fs;
use std::io::{Error, Write};
use std::usize;
pub struct Document {
rows: Vec<Row>,
@ -81,6 +82,57 @@ impl Document {
}
}
pub fn insert_text(&mut self, at: &Position, text: String) {
let mut lines: Vec<Row> = text.split('\n').map(Row::from).collect();
let prev_line = self.rows.get_mut(at.y).unwrap();
let end_line = prev_line.split(at.x);
let l = lines.len();
if l == 1 {
let new_row = Row::from(&text[..]);
prev_line.append(&new_row);
prev_line.append(&end_line);
} else {
prev_line.append(&lines[0]);
lines[l - 1].append(&end_line);
(1..lines.len()).for_each(|k| {
let tmp = lines[k].clone();
self.rows.insert(at.y + k, tmp);
});
}
}
// assumes from < to
pub fn remove_text(&mut self, from: &Position, to: &Position) {
let fromx = from.x;
let fromy = from.y;
let tox = to.x;
let toy = to.y;
let curline = self.rows.get_mut(fromy).unwrap();
if fromy == toy {
let mut rest = curline.split(fromx);
curline.append(&rest.split(tox - fromx + 1));
} else {
curline.split(fromx);
let lastline = self.rows.get_mut(toy).unwrap().split(tox + 1);
self.rows[toy] = lastline;
for k in fromy + 1..toy {
self.rows.remove(fromy + 1);
}
}
// self.rows.remove(index);
}
pub fn insert(&mut self, at: &Position, c: char) {
// self.dirty = true;

View File

@ -4,12 +4,12 @@ use crate::Row;
use crate::SharedInfo;
use crate::Statusbar;
use std::env;
use std::error::Error;
use std::sync::Arc;
use termion::event::Key;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
//use termion::event::Key;
use tokio::select;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use tokio::sync::RwLock;
@ -27,18 +27,19 @@ pub struct Editor {
// pub cursor_position: Arc<RwLock<Position>>,
pub shared: Arc<RwLock<SharedInfo>>,
inputreceiver: UnboundedReceiver<Key>,
inputreceiver: UnboundedReceiver<KeyEvent>,
eventsender: UnboundedSender<Events>,
// offset: Position,
rememberx: usize,
quitting: bool,
// colorscheme: Colorscheme,
// config: Config,
selectionstart: Option<Position>,
selectionend: Option<Position>, // colorscheme: Colorscheme,
// config: Config
}
impl Editor {
pub fn default(irt: UnboundedReceiver<Key>, st: UnboundedSender<Events>) -> Self {
pub fn default(irt: UnboundedReceiver<KeyEvent>, st: UnboundedSender<Events>) -> Self {
let args: Vec<String> = env::args().collect();
let document = if args.len() > 1 {
let filename = &args[1];
@ -65,6 +66,9 @@ impl Editor {
// offset: Position::default(),
rememberx: 0,
quitting: false,
selectionstart: None,
selectionend: None
// colorscheme: Colorscheme::default(),
// config: Config::default(),
}
@ -110,7 +114,7 @@ impl Editor {
Ok(())
}
async fn process_keypress(&mut self, k: Key) -> Result<(), Box<dyn Error + Send + Sync>> {
async fn process_keypress(&mut self, k: KeyEvent) -> Result<(), Box<dyn Error + Send + Sync>> {
let sharedarc = self.shared.clone();
let mut sharedlock = sharedarc.write().await;
let shared = &mut *sharedlock;
@ -120,7 +124,10 @@ impl Editor {
let stbar = &mut shared.stbar;
match k {
Key::Ctrl('q') => {
KeyEvent {
code: KeyCode::Char('q'),
modifiers: KeyModifiers::CONTROL,
} => {
if doc.dirty && !self.quitting {
stbar.change_status(
&"Unsaved changes. Are you sure you want to quit? Press ctrl+q again.",
@ -134,20 +141,22 @@ impl Editor {
// At the end of this fucntion.
}
Key::Ctrl('s') => {
KeyEvent {
code: KeyCode::Char('s'),
modifiers: KeyModifiers::CONTROL,
} => {
if doc.dirty {
match doc.save() {
Ok(true) => {
stbar.change_status("Document saved successfully.")?;
}
Ok(false) => {
drop(sharedlock); // DROP THE LOCK BEFORE PROMPTING
let filename = self
.prompt(&String::from("Input filename"), &String::from(""))
.await?;
let sharedarc = self.shared.clone();
let shared = &mut *(*sharedarc).write().await;
let mut doc = &mut shared.doc;
@ -169,8 +178,10 @@ impl Editor {
}
}
Key::Ctrl('o') => {
KeyEvent {
code: KeyCode::Char('o'),
modifiers: KeyModifiers::CONTROL,
} => {
drop(sharedlock); // DROP THE LOCK BEFORE PROMPTING
let filename = self
@ -196,26 +207,102 @@ impl Editor {
}
}
Key::Char(c) => {
// Key::Ctrl('t') => {
// doc.insert_text(cpos, String::from("WHEN THE \nMOON HITS YOU"));
// }
// KeyEvent {
// code: KeyCode::Char('t'),
// modifiers: KeyModifiers::CONTROL,
// } => {
// doc.remove_text(cpos, &Position { x: 2, y: 2 });
// }
//Key:: => {}
KeyEvent {
code: KeyCode::Char(c),
..
} => {
doc.dirty = true;
doc.insert(&cpos, c);
self.move_cursor(Key::Right, doc, cpos).await?;
doc.insert(cpos, c);
self.move_cursor(
KeyEvent {
code: KeyCode::Right,
modifiers: KeyModifiers::NONE,
},
doc,
cpos,
)
.await?;
}
Key::Delete => {
KeyEvent {
code: KeyCode::Enter,
..
} => {
doc.dirty = true;
doc.delete(&cpos)
doc.insert(cpos, '\n');
self.move_cursor(
KeyEvent {
code: KeyCode::Right,
modifiers: KeyModifiers::NONE,
},
doc,
cpos,
)
.await?;
}
Key::Backspace => {
KeyEvent {
code: KeyCode::Delete,
..
} => {
doc.dirty = true;
doc.delete(cpos)
}
KeyEvent {
code: KeyCode::Backspace,
..
} => {
if cpos.x > 0 || cpos.y > 0 {
doc.dirty = true;
self.move_cursor(Key::Left, doc, cpos).await?;
doc.delete(&cpos);
self.move_cursor(
KeyEvent {
code: KeyCode::Left,
modifiers: KeyModifiers::NONE,
},
doc,
cpos,
)
.await?;
doc.delete(cpos);
}
}
Key::Up | Key::Down | Key::Left | Key::Right => {
KeyEvent {
code: KeyCode::Up, ..
}
| KeyEvent {
code: KeyCode::Down,
..
}
| KeyEvent {
code: KeyCode::Left,
..
}
| KeyEvent {
code: KeyCode::Right,
..
} => {
self.move_cursor(k, doc, cpos).await?;
}
_ => (),
// Key::Home => todo!(),
// Key::End => todo!(),
// Key::PageUp => todo!(),
// Key::PageDown => todo!(),
// Key::BackTab => todo!(),
// Key::Insert => todo!(),
// Key::F(_) => todo!(),
// Key::Alt(_) => todo!(),
// Key::Null => todo!(),
// Key::Esc => todo!(),
// Key::__IsNotComplete => todo!(),
_ => {}
}
self.quitting = false;
Ok(())
@ -225,7 +312,12 @@ impl Editor {
// doc.filecheck();
// }
async fn move_cursor(&mut self, key: Key, doc: &Document, cpos: &mut Position) -> Result<(), Box<dyn Error + Sync + Send>> {
async fn move_cursor(
&mut self,
key: KeyEvent,
doc: &Document,
cpos: &mut Position,
) -> Result<(), Box<dyn Error + Sync + Send>> {
// let doc = (*docarc).read().await;
// let mut cpos = (*curarc).write().await;
@ -234,14 +326,16 @@ impl Editor {
let w = doc.row(y).map_or(0, Row::len);
let h = doc.len();
match key {
Key::Up => y = y.saturating_sub(1),
Key::Down => {
let k = key.code;
match k {
KeyCode::Up => y = y.saturating_sub(1),
KeyCode::Down => {
if y < h {
y = y.saturating_add(1)
}
}
Key::Left => {
KeyCode::Left => {
if x > 0 {
x -= 1;
} else if y > 0 {
@ -250,7 +344,7 @@ impl Editor {
}
self.rememberx = x;
}
Key::Right => {
KeyCode::Right => {
if x < w {
x += 1
} else if y < h {
@ -307,20 +401,20 @@ impl Editor {
match k.unwrap() {
Key::Left => {
KeyEvent{ code: KeyCode::Left, modifiers : KeyModifiers::NONE} => {
if pos > 0 {
pos = pos - 1
}
}
Key::Right => {
KeyEvent{ code: KeyCode::Right, modifiers : KeyModifiers::NONE} => {
if pos < r.len() {
pos = pos + 1
}
}
Key::Char('\n')=> {
KeyEvent{ code: KeyCode::Enter, modifiers : KeyModifiers::NONE} => {
stbar.prompting = false;
if r.is_empty() {
return Ok(None)
@ -332,19 +426,19 @@ impl Editor {
}
Key::Esc => {
KeyEvent{ code: KeyCode::Esc, modifiers : KeyModifiers::NONE} => {
stbar.prompting = false;
return Ok(None)
}
Key::Backspace => {
KeyEvent{ code: KeyCode::Backspace, modifiers : KeyModifiers::NONE} => {
if pos > 0 {
r.delete(pos-1);
pos = pos - 1
}
}
Key::Char(c) => {
KeyEvent{ code: KeyCode::Char(c), modifiers : KeyModifiers::NONE} => {
r.insert(pos, c);
pos = pos + 1
}

0
src/helpmenu.rs Normal file
View File

View File

@ -10,7 +10,7 @@ use std::cmp;
use std::error::Error;
use std::sync::Arc;
use termion::event::Key;
use crossterm::event::KeyEvent;
use tokio::select;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
@ -31,7 +31,7 @@ pub struct Renderer {
impl Renderer {
pub fn default(
st: UnboundedSender<Events>,
ist: UnboundedSender<Key>,
ist: UnboundedSender<KeyEvent>,
rt: UnboundedReceiver<Events>,
shared: Arc<RwLock<SharedInfo>>,
) -> Self {
@ -57,13 +57,14 @@ impl Renderer {
}
pub async fn run(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
self.terminal.enable_alt_screen();
self.refresh_screen().await?;
loop {
select! {
event = self.receiver.recv() => {match event.unwrap() {
Events::Quit => {
self.terminal.reset_screen();
break;
},
Events::Refresh => {self.refresh_screen().await?;}
@ -73,6 +74,8 @@ impl Renderer {
}
}
self.terminal.disable_alt_screen();
Ok(())
}
@ -148,16 +151,16 @@ impl Renderer {
println!("{}{}\r", space, r)
}
async fn draw_rows(&self) {
async fn draw_rows(&mut self) {
let sharedarc = self.shared.clone();
let shared = (*sharedarc).read().await;
let doc = &shared.doc;
Terminal::cursor_reset();
Terminal::set_text_color(self.colorscheme.text);
Terminal::set_bg_color(self.colorscheme.background);
self.terminal.cursor_reset();
self.terminal.set_text_color(self.colorscheme.text);
self.terminal.set_bg_color(self.colorscheme.background);
let h = self.terminal.size().height as usize;
// let w = self.terminal.size().width as usize;
@ -167,12 +170,12 @@ impl Renderer {
let trueh = h.saturating_sub(vertical_pad);
for _ in 0..vertical_pad {
Terminal::clear_current_line();
self.terminal.clear_current_line();
println!("\r")
}
for terminal_row in 0..trueh - 2 {
Terminal::clear_current_line();
self.terminal.clear_current_line();
if let Some(row) = doc.row(
terminal_row as usize + self.offset.y.saturating_sub(self.config.vertical_padding),
) {
@ -181,11 +184,10 @@ impl Renderer {
println!("\r");
}
}
Terminal::reset_text_color();
Terminal::reset_bg_color();
// Terminal::reset_color();
}
async fn draw_info(&self) {
async fn draw_info(&mut self) {
let sharedarc = self.shared.clone();
let shared = (*sharedarc).read().await;
@ -194,8 +196,9 @@ impl Renderer {
let cpos = &shared.cpos;
let stbar = &shared.stbar;
Terminal::set_bg_color(self.colorscheme.status_background);
Terminal::set_text_color(self.colorscheme.status_text);
self.terminal
.set_bg_color(self.colorscheme.status_background);
self.terminal.set_text_color(self.colorscheme.status_text);
let width = self.terminal.size().width as usize;
@ -203,13 +206,12 @@ impl Renderer {
let status2 = stbar.status2(&doc, &cpos, width);
Terminal::clear_current_line();
self.terminal.clear_current_line();
println!("{}\r", status);
Terminal::clear_current_line();
self.terminal.clear_current_line();
print!("{}\r", status2);
Terminal::reset_text_color();
Terminal::reset_bg_color();
Terminal::reset_color();
}
async fn scroll(&mut self) {

View File

@ -2,7 +2,7 @@ use std::cmp;
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
#[derive(Default)]
#[derive(Default, Clone)]
pub struct Row {
string: String,
len: usize,

View File

@ -6,15 +6,31 @@ use std::error::Error;
use std::io::{stdin, stdout, Stdout, Write};
use std::sync::{Arc, RwLock};
use std::thread;
use std::time::Duration;
use termion::color;
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::{IntoRawMode, RawTerminal};
use termion::screen::{AlternateScreen, ToMainScreen};
use crossterm::cursor::MoveTo;
use crossterm::cursor::{Hide, Show};
use crossterm::{
cursor, event,
event::KeyEvent,
execute, queue,
style::{Color, Print, ResetColor, SetBackgroundColor, SetForegroundColor},
terminal::{
enable_raw_mode, size, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen,
},
ExecutableCommand, QueueableCommand,
};
use crossterm::event::{poll, read, Event};
//use termion::color;
//use termion::event::Key;
//use termion::input::TermRead;
//use termion::raw::{IntoRawMode, RawTerminal};
//use termion::screen::{AlternateScreen, ToMainScreen};
use tokio::signal::unix::{signal, SignalKind};
use tokio::sync::mpsc::{UnboundedSender};
use tokio::sync::mpsc::UnboundedSender;
#[derive(Clone, Copy)]
pub struct Size {
@ -25,23 +41,27 @@ pub struct Size {
pub struct Terminal {
size: Arc<RwLock<Size>>,
screen: AlternateScreen<RawTerminal<Stdout>>,
//screen: AlternateScreen<RawTerminal<Stdout>>,
pub sender: UnboundedSender<Events>,
stdout: Stdout,
// pub receiver: UnboundedReceiver<Events>,
inputsender: UnboundedSender<Key>,
inputsender: UnboundedSender<KeyEvent>,
// pub inputreceiver: UnboundedReceiver<Key>,
sigthread: Option<tokio::task::JoinHandle<()>>,
// sigthread: Option<tokio::task::JoinHandle<()>>,
keythread: Option<std::thread::JoinHandle<()>>,
}
impl Terminal {
pub fn default(st: UnboundedSender<Events>, ist: UnboundedSender<Key>) -> Result<Self, Box<dyn Error + Send + Sync>> {
let size = termion::terminal_size()?;
let out = stdout().into_raw_mode()?;
let screen = AlternateScreen::from(out);
pub fn default(
st: UnboundedSender<Events>,
ist: UnboundedSender<KeyEvent>,
) -> Result<Self, Box<dyn Error + Send + Sync>> {
let size = size()?;
// let out = stdout().into_raw_mode()?;
// let screen = AlternateScreen::from(out);
enable_raw_mode()?;
let mut stdout = stdout();
// let (st, rt) = unbounded_channel();
// let (ist, irt) = unbounded_channel();
@ -51,64 +71,92 @@ impl Terminal {
width: size.0,
height: size.1,
})),
screen,
stdout,
// screen,
sender: st,
// receiver: rt,
inputsender: ist,
// inputreceiver: irt,
sigthread: None,
// sigthread: None,
keythread: None,
};
res.start_update_thread()?;
res.start_reading_keys()?;
// res.start_update_thread()?;
res.start_reading()?;
Ok(res)
}
pub fn reset_screen(&self) {
println!("{}", ToMainScreen);
}
//pub fn reset_screen(&self) {
// println!("{}", ToMainScreen);
//}
fn start_update_thread(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
let mut signals = signal(SignalKind::window_change())?; // TODO: Support for other signals
// fn start_update_thread(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
// let mut signals = signal(SignalKind::window_change())?; // TODO: Support for other signals
let arcsize = self.size.clone();
// let arcsize = self.size.clone();
let sender = self.sender.clone();
// let sender = self.sender.clone();
let resizethread = tokio::spawn(async move {
loop {
// let resizethread = tokio::spawn(async move {
// loop {
// match signals.recv().await {
// Some(_) => {
// let size = size().unwrap();
// let mut sharedsize = arcsize.write().unwrap();
// *sharedsize = Size {
// width: size.0,
// height: size.1,
// };
match signals.recv().await {
Some(_) => {
let size = termion::terminal_size().unwrap_or_default();
let mut sharedsize = arcsize.write().unwrap();
*sharedsize = Size {
width: size.0,
height: size.1,
};
// sender.send(Events::Refresh);
// }
// None => {}
// }
// }
// });
// self.sigthread = Some(resizethread);
// Ok(())
// }
sender.send(Events::Refresh);
}
None => {}
}
}
});
self.sigthread = Some(resizethread);
pub fn enable_alt_screen(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
execute!(self.stdout, EnterAlternateScreen);
Ok(())
}
fn start_reading_keys(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
let mut reader = stdin().keys();
pub fn disable_alt_screen(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
execute!(self.stdout, LeaveAlternateScreen);
Ok(())
}
fn start_reading(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
//let mut reader = stdin().keys();
let sender = self.inputsender.clone();
let isender = self.inputsender.clone();
let sender = self.sender.clone();
let keythread = thread::spawn(move || loop {
if let Some(key) = reader.next() {
sender.send(key.unwrap());
loop {
if poll(Duration::from_millis(500)).unwrap() {
// It's guaranteed that the `read()` won't block when the `poll()`
// function returns `true`
match read().unwrap() {
Event::Key(event) => {
isender.send(event);
}
Event::Mouse(event) => {} //println!("{:?}", event),
Event::Resize(width, height) => {
sender.send(Events::Refresh);
}
}
}
}
});
// Ok(());
// if let Some(key) = reader.next() {
// sender.send(key.unwrap());
// }
self.keythread = Some(keythread);
Ok(())
}
@ -118,54 +166,58 @@ impl Terminal {
*w
}
pub fn clear_screen() {
print!("{}", termion::clear::All)
pub fn clear_screen(&mut self) {
execute!(self.stdout, Clear(ClearType::All));
}
pub fn cursor_reset() {
print!("{}", termion::cursor::Goto(1, 1))
pub fn clear_current_line(&mut self) {
execute!(self.stdout, Clear(ClearType::CurrentLine));
}
pub fn cursor_position(&self, p: &Position) {
pub fn cursor_reset(&mut self) {
execute!(self.stdout, MoveTo(1, 1));
}
pub fn cursor_position(&mut 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))
let x = cmp::min(*x as u16, s.width);
let y = cmp::min(*y as u16, s.height);
execute!((self.stdout), MoveTo(x, y));
}
pub fn flush(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
self.screen.flush()?;
self.stdout.flush()?;
Ok(())
}
pub fn cursor_hide() {
print!("{}", termion::cursor::Hide);
execute!(stdout(), Hide);
}
pub fn cursor_show() {
print!("{}", termion::cursor::Show);
execute!(stdout(), Show);
}
pub fn clear_current_line() {
print!("{}", termion::clear::CurrentLine);
pub fn set_bg_color(&mut self, color: Color) {
execute!(self.stdout, SetBackgroundColor(color));
}
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(&mut self, color: Color) {
execute!(self.stdout, SetForegroundColor(color));
}
pub fn reset_bg_color() {
print!("{}", color::Bg(color::Reset))
pub fn reset_color() {
execute!(stdout(), ResetColor);
}
pub fn set_text_color(color: color::Rgb) {
print!("{}", color::Fg(color))
}
pub fn reset_text_color() {
print!("{}", color::Fg(color::Reset))
}
// pub fn reset_text_color() {
// print!("{}", color::Fg(color::Reset))
// }
pub fn quit(&self) -> Result<(), Box<dyn Error>> {
self.sender.send(Events::Quit)?;