Migrate termion to crossterm
This commit is contained in:
parent
b47d41b615
commit
c0cd93d0a5
173
Cargo.lock
generated
173
Cargo.lock
generated
@ -35,6 +35,31 @@ dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e86d73f2a0b407b5768d10a8c720cf5d2df49a9efc10ca09176d201ead4b7fb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"signal-hook",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm_winapi"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2265c3f8e080075d9b6417aa72293fc71662f34b4af2612d8d1b074d29510db"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "2.0.2"
|
||||
@ -67,6 +92,21 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.94"
|
||||
@ -74,10 +114,78 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
name = "lock_api"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
@ -106,15 +214,6 @@ 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 = "redox_users"
|
||||
version = "0.4.0"
|
||||
@ -127,14 +226,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rpn_rs"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"confy",
|
||||
"crossterm",
|
||||
"serde",
|
||||
"termion",
|
||||
"tui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.126"
|
||||
@ -155,6 +260,32 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.72"
|
||||
@ -166,18 +297,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 = "toml"
|
||||
version = "0.5.8"
|
||||
@ -195,7 +314,7 @@ checksum = "9ced152a8e9295a5b168adc254074525c17ac4a83c90b2716274cc38118bddc9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cassowary",
|
||||
"termion",
|
||||
"crossterm",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
|
10
Cargo.toml
10
Cargo.toml
@ -10,7 +10,13 @@ categories = ["command-line-utilities"]
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tui = "0.14"
|
||||
termion = "1.5"
|
||||
# Linux only
|
||||
# tui = "0.14"
|
||||
# termion = "1.5"
|
||||
|
||||
# Windows support
|
||||
crossterm = "0.18"
|
||||
tui = { version = "0.14", default-features = false, features = ['crossterm'] }
|
||||
|
||||
serde = {version = "1.0", features = ["derive"]}
|
||||
confy = "0.4.0"
|
||||
|
@ -44,4 +44,4 @@ all:
|
||||
BUILD --build-arg TOOLCHAIN=arm-unknown-linux-musleabi --build-arg STRIP_CMD=arm-linux-gnueabi-strip +build
|
||||
BUILD --build-arg TOOLCHAIN=armv7-unknown-linux-musleabi --build-arg STRIP_CMD=arm-linux-gnueabi-strip +build
|
||||
# TODO: Cross compile to windows
|
||||
# BUILD --build-arg TOOLCHAIN=x86_64-pc-windows-gnu +build
|
||||
BUILD --build-arg TOOLCHAIN=x86_64-pc-windows-gnu +build
|
||||
|
136
src/main.rs
136
src/main.rs
@ -7,12 +7,22 @@ mod util;
|
||||
use calc::constants::{CalculatorDisplayMode, CalculatorState, RegisterState};
|
||||
use calc::errors::CalculatorResult;
|
||||
use calc::Calculator;
|
||||
use crossterm::{
|
||||
event::{self, DisableMouseCapture, Event as CEvent, KeyCode, KeyEvent, KeyModifiers},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use io::stdout;
|
||||
use std::cmp;
|
||||
use std::convert::TryFrom;
|
||||
use std::io::Write;
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{error::Error, io};
|
||||
use termion::{event::Key, raw::IntoRawMode, screen::AlternateScreen};
|
||||
// use termion::{event::Key, raw::IntoRawMode, screen::AlternateScreen};
|
||||
use tui::{
|
||||
backend::TermionBackend,
|
||||
backend::CrosstermBackend,
|
||||
layout::{Constraint, Direction, Layout},
|
||||
style::{Modifier, Style},
|
||||
terminal::Frame,
|
||||
@ -20,7 +30,9 @@ use tui::{
|
||||
widgets::{Block, Borders, Clear, List, ListItem, Paragraph},
|
||||
Terminal,
|
||||
};
|
||||
use util::event::{Event, Events};
|
||||
use util::event::Event;
|
||||
|
||||
const TICK_RATE: Duration = Duration::from_millis(250);
|
||||
|
||||
struct Dimensions {
|
||||
width: u16,
|
||||
@ -58,15 +70,36 @@ impl Default for App {
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let stdout = io::stdout().into_raw_mode()?;
|
||||
// let stdout = MouseTerminal::from(stdout);
|
||||
let stdout = AlternateScreen::from(stdout);
|
||||
let backend = TermionBackend::new(stdout);
|
||||
enable_raw_mode()?;
|
||||
|
||||
let mut stdout = stdout();
|
||||
execute!(stdout, EnterAlternateScreen, DisableMouseCapture)?;
|
||||
let backend = CrosstermBackend::new(stdout);
|
||||
let mut terminal = Terminal::new(backend)?;
|
||||
|
||||
let events = Events::new();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let mut app = App::default();
|
||||
|
||||
thread::spawn(move || {
|
||||
let mut last_tick = Instant::now();
|
||||
loop {
|
||||
// poll for tick rate duration, if no events, sent tick event.
|
||||
let timeout = TICK_RATE
|
||||
.checked_sub(last_tick.elapsed())
|
||||
.unwrap_or_else(|| Duration::from_secs(0));
|
||||
if event::poll(timeout).unwrap() {
|
||||
if let CEvent::Key(key) = event::read().unwrap() {
|
||||
tx.send(Event::Input(key)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
if last_tick.elapsed() >= TICK_RATE {
|
||||
tx.send(Event::Tick).unwrap();
|
||||
last_tick = Instant::now();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
'outer: loop {
|
||||
terminal.draw(|f| {
|
||||
let chunks = Layout::default()
|
||||
@ -270,8 +303,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
})?;
|
||||
|
||||
if let Event::Input(key) = events.next()? {
|
||||
app.error_msg = match handle_key(&mut app, &events, key) {
|
||||
if let Event::Input(key) = rx.recv()? {
|
||||
app.error_msg = match handle_key(&mut app, key) {
|
||||
// Exit the program
|
||||
Ok(CalculatorResponse::Quit) => break 'outer,
|
||||
Ok(CalculatorResponse::Continue) => None,
|
||||
@ -280,10 +313,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
// Slurp events without a redraw
|
||||
for e in events.try_iter() {
|
||||
for e in rx.try_iter() {
|
||||
match e {
|
||||
Event::Input(key) => {
|
||||
app.error_msg = match handle_key(&mut app, &events, key) {
|
||||
app.error_msg = match handle_key(&mut app, key) {
|
||||
// Exit the program
|
||||
Ok(CalculatorResponse::Quit) => break 'outer,
|
||||
Ok(CalculatorResponse::Continue) => None,
|
||||
@ -294,43 +327,88 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
}
|
||||
disable_raw_mode()?;
|
||||
execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
app.calculator.close().map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<CalculatorResponse> {
|
||||
fn handle_key(app: &mut App, key: KeyEvent) -> CalculatorResult<CalculatorResponse> {
|
||||
match (&app.state, app.calculator.get_state()) {
|
||||
(AppState::Calculator, CalculatorState::Normal) => match key {
|
||||
Key::Char('q') => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('q'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
return Ok(CalculatorResponse::Quit);
|
||||
}
|
||||
Key::Ctrl('s') => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('s'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
} => {
|
||||
app.calculator.save_config()?;
|
||||
}
|
||||
Key::Ctrl('l') => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('l'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
} => {
|
||||
app.calculator = Calculator::load_config()?;
|
||||
}
|
||||
Key::Char('h') => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('h'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.state = AppState::Help;
|
||||
}
|
||||
Key::Char('\n') | Key::Char(' ') => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('\n'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
}
|
||||
| KeyEvent {
|
||||
code: KeyCode::Char(' '),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.calculator.take_input(' ')?;
|
||||
}
|
||||
Key::Right => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Right,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.calculator.take_input('>')?;
|
||||
}
|
||||
Key::Down => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Down,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.calculator.edit()?;
|
||||
}
|
||||
Key::Backspace => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Backspace,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.calculator.backspace()?;
|
||||
}
|
||||
Key::Char(c) => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char(c),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.calculator.take_input(c)?;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
(AppState::Help, _) => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Esc,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
}
|
||||
| KeyEvent {
|
||||
code: KeyCode::Char('q'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel()?;
|
||||
}
|
||||
@ -340,11 +418,17 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<Calc
|
||||
| (AppState::Calculator, CalculatorState::WaitingForSetting)
|
||||
| (AppState::Calculator, CalculatorState::WaitingForRegister(_))
|
||||
| (AppState::Calculator, CalculatorState::WaitingForMacro) => match key {
|
||||
Key::Esc => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Esc,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel()?;
|
||||
}
|
||||
Key::Char(c) => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char(c),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
} => {
|
||||
app.calculator.take_input(c)?;
|
||||
}
|
||||
_ => {}
|
||||
@ -371,7 +455,7 @@ impl ClippyRectangle<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<TermionBackend<T>>) {
|
||||
fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<CrosstermBackend<T>>) {
|
||||
let block = Block::default().title(c.title).borders(Borders::ALL);
|
||||
let dimensions = c.size();
|
||||
let popup_layout = Layout::default()
|
||||
|
@ -1,110 +1,105 @@
|
||||
use std::io;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::TryIter;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
// use std::io;
|
||||
// use std::sync::mpsc;
|
||||
// use std::sync::mpsc::TryIter;
|
||||
// use std::sync::{
|
||||
// atomic::{AtomicBool, Ordering},
|
||||
// Arc,
|
||||
// };
|
||||
// use std::thread;
|
||||
// use std::time::Duration;
|
||||
|
||||
use termion::event::Key;
|
||||
use termion::input::TermRead;
|
||||
// use crossterm::event::{KeyEvent, KeyCode, KeyModifiers};
|
||||
|
||||
pub enum Event<I> {
|
||||
Input(I),
|
||||
Tick,
|
||||
}
|
||||
|
||||
/// A small event handler that wrap termion input and tick events. Each event
|
||||
/// type is handled in its own thread and returned to a common `Receiver`
|
||||
#[allow(dead_code)]
|
||||
pub struct Events {
|
||||
rx: mpsc::Receiver<Event<Key>>,
|
||||
tx: mpsc::Sender<Event<Key>>,
|
||||
input_handle: thread::JoinHandle<()>,
|
||||
ignore_exit_key: Arc<AtomicBool>,
|
||||
tick_handle: thread::JoinHandle<()>,
|
||||
}
|
||||
// /// A small event handler that wrap termion input and tick events. Each event
|
||||
// /// type is handled in its own thread and returned to a common `Receiver`
|
||||
// #[allow(dead_code)]
|
||||
// pub struct Events {
|
||||
// rx: mpsc::Receiver<Event<KeyEvent>>,
|
||||
// tx: mpsc::Sender<Event<KeyEvent>>,
|
||||
// input_handle: thread::JoinHandle<()>,
|
||||
// ignore_exit_key: Arc<AtomicBool>,
|
||||
// tick_handle: thread::JoinHandle<()>,
|
||||
// }
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Config {
|
||||
pub exit_key: Key,
|
||||
pub tick_rate: Duration,
|
||||
}
|
||||
// #[derive(Debug, Clone, Copy)]
|
||||
// pub struct Config {
|
||||
// pub exit_key: KeyEvent,
|
||||
// pub tick_rate: Duration,
|
||||
// }
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Config {
|
||||
exit_key: Key::Char('q'),
|
||||
tick_rate: Duration::from_millis(250),
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl Default for Config {
|
||||
// fn default() -> Self {
|
||||
// Config {
|
||||
// exit_key: KeyEvent::new(KeyCode::Char('q'), KeyModifiers::NONE),
|
||||
// tick_rate: Duration::from_millis(250),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Events {
|
||||
pub fn new() -> Events {
|
||||
Events::with_config(Config::default())
|
||||
}
|
||||
// impl Events {
|
||||
// pub fn new() -> Events {
|
||||
// Events::with_config(Config::default())
|
||||
// }
|
||||
|
||||
pub fn with_config(config: Config) -> Events {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let mac_tx = tx.clone();
|
||||
let ignore_exit_key = Arc::new(AtomicBool::new(true));
|
||||
let input_handle = {
|
||||
let tx = tx.clone();
|
||||
let ignore_exit_key = ignore_exit_key.clone();
|
||||
thread::spawn(move || {
|
||||
let stdin = io::stdin();
|
||||
for evt in stdin.keys() {
|
||||
if let Ok(key) = evt {
|
||||
if let Err(err) = tx.send(Event::Input(key)) {
|
||||
eprintln!("{}", err);
|
||||
return;
|
||||
}
|
||||
if !ignore_exit_key.load(Ordering::Relaxed) && key == config.exit_key {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
let tick_handle = {
|
||||
thread::spawn(move || loop {
|
||||
if tx.send(Event::Tick).is_err() {
|
||||
break;
|
||||
}
|
||||
thread::sleep(config.tick_rate);
|
||||
})
|
||||
};
|
||||
Events {
|
||||
rx,
|
||||
tx: mac_tx,
|
||||
ignore_exit_key,
|
||||
input_handle,
|
||||
tick_handle,
|
||||
}
|
||||
}
|
||||
// pub fn with_config(config: Config) -> Events {
|
||||
// let (tx, rx) = mpsc::channel();
|
||||
// let mac_tx = tx.clone();
|
||||
// let ignore_exit_key = Arc::new(AtomicBool::new(true));
|
||||
// let input_handle = {
|
||||
// let tx = tx.clone();
|
||||
// let ignore_exit_key = ignore_exit_key.clone();
|
||||
// thread::spawn(move || {
|
||||
// let stdin = io::stdin();
|
||||
// for evt in stdin.keys() {
|
||||
// if let Ok(key) = evt {
|
||||
// if let Err(err) = tx.send(Event::Input(key)) {
|
||||
// eprintln!("{}", err);
|
||||
// return;
|
||||
// }
|
||||
// if !ignore_exit_key.load(Ordering::Relaxed) && key == config.exit_key {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// };
|
||||
// let tick_handle = {
|
||||
// thread::spawn(move || loop {
|
||||
// if tx.send(Event::Tick).is_err() {
|
||||
// break;
|
||||
// }
|
||||
// thread::sleep(config.tick_rate);
|
||||
// })
|
||||
// };
|
||||
// Events {
|
||||
// rx,
|
||||
// tx: mac_tx,
|
||||
// ignore_exit_key,
|
||||
// input_handle,
|
||||
// tick_handle,
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn next(&self) -> Result<Event<Key>, mpsc::RecvError> {
|
||||
self.rx.recv()
|
||||
}
|
||||
// pub fn next(&self) -> Result<Event<KeyEvent>, mpsc::RecvError> {
|
||||
// self.rx.recv()
|
||||
// }
|
||||
|
||||
pub fn try_next(&self) -> Result<Event<Key>, mpsc::TryRecvError> {
|
||||
self.rx.try_recv()
|
||||
}
|
||||
// pub fn try_iter(&self) -> TryIter<Event<KeyEvent>> {
|
||||
// self.rx.try_iter()
|
||||
// }
|
||||
|
||||
pub fn try_iter(&self) -> TryIter<Event<Key>> {
|
||||
self.rx.try_iter()
|
||||
}
|
||||
// #[allow(dead_code)]
|
||||
// pub fn disable_exit_key(&mut self) {
|
||||
// self.ignore_exit_key.store(true, Ordering::Relaxed);
|
||||
// }
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn disable_exit_key(&mut self) {
|
||||
self.ignore_exit_key.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn enable_exit_key(&mut self) {
|
||||
self.ignore_exit_key.store(false, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
// #[allow(dead_code)]
|
||||
// pub fn enable_exit_key(&mut self) {
|
||||
// self.ignore_exit_key.store(false, Ordering::Relaxed);
|
||||
// }
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user