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",
|
"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]]
|
[[package]]
|
||||||
name = "directories"
|
name = "directories"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
@ -67,6 +92,21 @@ dependencies = [
|
|||||||
"wasi",
|
"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]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.94"
|
version = "0.2.94"
|
||||||
@ -74,10 +114,78 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
|
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "numtoa"
|
name = "lock_api"
|
||||||
version = "0.1.0"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
@ -106,15 +214,6 @@ dependencies = [
|
|||||||
"bitflags",
|
"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]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -127,14 +226,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rpn_rs"
|
name = "rpn_rs"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"confy",
|
"confy",
|
||||||
|
"crossterm",
|
||||||
"serde",
|
"serde",
|
||||||
"termion",
|
|
||||||
"tui",
|
"tui",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.126"
|
version = "1.0.126"
|
||||||
@ -155,6 +260,32 @@ dependencies = [
|
|||||||
"syn",
|
"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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.72"
|
version = "1.0.72"
|
||||||
@ -166,18 +297,6 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"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]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.8"
|
version = "0.5.8"
|
||||||
@ -195,7 +314,7 @@ checksum = "9ced152a8e9295a5b168adc254074525c17ac4a83c90b2716274cc38118bddc9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cassowary",
|
"cassowary",
|
||||||
"termion",
|
"crossterm",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unicode-width",
|
"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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tui = "0.14"
|
# Linux only
|
||||||
termion = "1.5"
|
# 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"]}
|
serde = {version = "1.0", features = ["derive"]}
|
||||||
confy = "0.4.0"
|
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=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
|
BUILD --build-arg TOOLCHAIN=armv7-unknown-linux-musleabi --build-arg STRIP_CMD=arm-linux-gnueabi-strip +build
|
||||||
# TODO: Cross compile to windows
|
# 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::constants::{CalculatorDisplayMode, CalculatorState, RegisterState};
|
||||||
use calc::errors::CalculatorResult;
|
use calc::errors::CalculatorResult;
|
||||||
use calc::Calculator;
|
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::cmp;
|
||||||
use std::convert::TryFrom;
|
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 std::{error::Error, io};
|
||||||
use termion::{event::Key, raw::IntoRawMode, screen::AlternateScreen};
|
// use termion::{event::Key, raw::IntoRawMode, screen::AlternateScreen};
|
||||||
use tui::{
|
use tui::{
|
||||||
backend::TermionBackend,
|
backend::CrosstermBackend,
|
||||||
layout::{Constraint, Direction, Layout},
|
layout::{Constraint, Direction, Layout},
|
||||||
style::{Modifier, Style},
|
style::{Modifier, Style},
|
||||||
terminal::Frame,
|
terminal::Frame,
|
||||||
@ -20,7 +30,9 @@ use tui::{
|
|||||||
widgets::{Block, Borders, Clear, List, ListItem, Paragraph},
|
widgets::{Block, Borders, Clear, List, ListItem, Paragraph},
|
||||||
Terminal,
|
Terminal,
|
||||||
};
|
};
|
||||||
use util::event::{Event, Events};
|
use util::event::Event;
|
||||||
|
|
||||||
|
const TICK_RATE: Duration = Duration::from_millis(250);
|
||||||
|
|
||||||
struct Dimensions {
|
struct Dimensions {
|
||||||
width: u16,
|
width: u16,
|
||||||
@ -58,15 +70,36 @@ impl Default for App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let stdout = io::stdout().into_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
// let stdout = MouseTerminal::from(stdout);
|
|
||||||
let stdout = AlternateScreen::from(stdout);
|
let mut stdout = stdout();
|
||||||
let backend = TermionBackend::new(stdout);
|
execute!(stdout, EnterAlternateScreen, DisableMouseCapture)?;
|
||||||
|
let backend = CrosstermBackend::new(stdout);
|
||||||
let mut terminal = Terminal::new(backend)?;
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
let events = Events::new();
|
let (tx, rx) = mpsc::channel();
|
||||||
let mut app = App::default();
|
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 {
|
'outer: loop {
|
||||||
terminal.draw(|f| {
|
terminal.draw(|f| {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
@ -270,8 +303,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Event::Input(key) = events.next()? {
|
if let Event::Input(key) = rx.recv()? {
|
||||||
app.error_msg = match handle_key(&mut app, &events, key) {
|
app.error_msg = match handle_key(&mut app, key) {
|
||||||
// Exit the program
|
// Exit the program
|
||||||
Ok(CalculatorResponse::Quit) => break 'outer,
|
Ok(CalculatorResponse::Quit) => break 'outer,
|
||||||
Ok(CalculatorResponse::Continue) => None,
|
Ok(CalculatorResponse::Continue) => None,
|
||||||
@ -280,10 +313,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slurp events without a redraw
|
// Slurp events without a redraw
|
||||||
for e in events.try_iter() {
|
for e in rx.try_iter() {
|
||||||
match e {
|
match e {
|
||||||
Event::Input(key) => {
|
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
|
// Exit the program
|
||||||
Ok(CalculatorResponse::Quit) => break 'outer,
|
Ok(CalculatorResponse::Quit) => break 'outer,
|
||||||
Ok(CalculatorResponse::Continue) => None,
|
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())
|
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()) {
|
match (&app.state, app.calculator.get_state()) {
|
||||||
(AppState::Calculator, CalculatorState::Normal) => match key {
|
(AppState::Calculator, CalculatorState::Normal) => match key {
|
||||||
Key::Char('q') => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Char('q'),
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
return Ok(CalculatorResponse::Quit);
|
return Ok(CalculatorResponse::Quit);
|
||||||
}
|
}
|
||||||
Key::Ctrl('s') => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Char('s'),
|
||||||
|
modifiers: KeyModifiers::CONTROL,
|
||||||
|
} => {
|
||||||
app.calculator.save_config()?;
|
app.calculator.save_config()?;
|
||||||
}
|
}
|
||||||
Key::Ctrl('l') => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Char('l'),
|
||||||
|
modifiers: KeyModifiers::CONTROL,
|
||||||
|
} => {
|
||||||
app.calculator = Calculator::load_config()?;
|
app.calculator = Calculator::load_config()?;
|
||||||
}
|
}
|
||||||
Key::Char('h') => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Char('h'),
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
app.state = AppState::Help;
|
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(' ')?;
|
app.calculator.take_input(' ')?;
|
||||||
}
|
}
|
||||||
Key::Right => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Right,
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
app.calculator.take_input('>')?;
|
app.calculator.take_input('>')?;
|
||||||
}
|
}
|
||||||
Key::Down => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Down,
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
app.calculator.edit()?;
|
app.calculator.edit()?;
|
||||||
}
|
}
|
||||||
Key::Backspace => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Backspace,
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
app.calculator.backspace()?;
|
app.calculator.backspace()?;
|
||||||
}
|
}
|
||||||
Key::Char(c) => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Char(c),
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
app.calculator.take_input(c)?;
|
app.calculator.take_input(c)?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
(AppState::Help, _) => match key {
|
(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.state = AppState::Calculator;
|
||||||
app.calculator.cancel()?;
|
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::WaitingForSetting)
|
||||||
| (AppState::Calculator, CalculatorState::WaitingForRegister(_))
|
| (AppState::Calculator, CalculatorState::WaitingForRegister(_))
|
||||||
| (AppState::Calculator, CalculatorState::WaitingForMacro) => match key {
|
| (AppState::Calculator, CalculatorState::WaitingForMacro) => match key {
|
||||||
Key::Esc => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Esc,
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
app.state = AppState::Calculator;
|
app.state = AppState::Calculator;
|
||||||
app.calculator.cancel()?;
|
app.calculator.cancel()?;
|
||||||
}
|
}
|
||||||
Key::Char(c) => {
|
KeyEvent {
|
||||||
|
code: KeyCode::Char(c),
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
} => {
|
||||||
app.calculator.take_input(c)?;
|
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 block = Block::default().title(c.title).borders(Borders::ALL);
|
||||||
let dimensions = c.size();
|
let dimensions = c.size();
|
||||||
let popup_layout = Layout::default()
|
let popup_layout = Layout::default()
|
||||||
|
@ -1,110 +1,105 @@
|
|||||||
use std::io;
|
// use std::io;
|
||||||
use std::sync::mpsc;
|
// use std::sync::mpsc;
|
||||||
use std::sync::mpsc::TryIter;
|
// use std::sync::mpsc::TryIter;
|
||||||
use std::sync::{
|
// use std::sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
// atomic::{AtomicBool, Ordering},
|
||||||
Arc,
|
// Arc,
|
||||||
};
|
// };
|
||||||
use std::thread;
|
// use std::thread;
|
||||||
use std::time::Duration;
|
// use std::time::Duration;
|
||||||
|
|
||||||
use termion::event::Key;
|
// use crossterm::event::{KeyEvent, KeyCode, KeyModifiers};
|
||||||
use termion::input::TermRead;
|
|
||||||
|
|
||||||
pub enum Event<I> {
|
pub enum Event<I> {
|
||||||
Input(I),
|
Input(I),
|
||||||
Tick,
|
Tick,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A small event handler that wrap termion input and tick events. Each event
|
// /// 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`
|
// /// type is handled in its own thread and returned to a common `Receiver`
|
||||||
#[allow(dead_code)]
|
// #[allow(dead_code)]
|
||||||
pub struct Events {
|
// pub struct Events {
|
||||||
rx: mpsc::Receiver<Event<Key>>,
|
// rx: mpsc::Receiver<Event<KeyEvent>>,
|
||||||
tx: mpsc::Sender<Event<Key>>,
|
// tx: mpsc::Sender<Event<KeyEvent>>,
|
||||||
input_handle: thread::JoinHandle<()>,
|
// input_handle: thread::JoinHandle<()>,
|
||||||
ignore_exit_key: Arc<AtomicBool>,
|
// ignore_exit_key: Arc<AtomicBool>,
|
||||||
tick_handle: thread::JoinHandle<()>,
|
// tick_handle: thread::JoinHandle<()>,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
// #[derive(Debug, Clone, Copy)]
|
||||||
pub struct Config {
|
// pub struct Config {
|
||||||
pub exit_key: Key,
|
// pub exit_key: KeyEvent,
|
||||||
pub tick_rate: Duration,
|
// pub tick_rate: Duration,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Default for Config {
|
// impl Default for Config {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
Config {
|
// Config {
|
||||||
exit_key: Key::Char('q'),
|
// exit_key: KeyEvent::new(KeyCode::Char('q'), KeyModifiers::NONE),
|
||||||
tick_rate: Duration::from_millis(250),
|
// tick_rate: Duration::from_millis(250),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Events {
|
// impl Events {
|
||||||
pub fn new() -> Events {
|
// pub fn new() -> Events {
|
||||||
Events::with_config(Config::default())
|
// Events::with_config(Config::default())
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn with_config(config: Config) -> Events {
|
// pub fn with_config(config: Config) -> Events {
|
||||||
let (tx, rx) = mpsc::channel();
|
// let (tx, rx) = mpsc::channel();
|
||||||
let mac_tx = tx.clone();
|
// let mac_tx = tx.clone();
|
||||||
let ignore_exit_key = Arc::new(AtomicBool::new(true));
|
// let ignore_exit_key = Arc::new(AtomicBool::new(true));
|
||||||
let input_handle = {
|
// let input_handle = {
|
||||||
let tx = tx.clone();
|
// let tx = tx.clone();
|
||||||
let ignore_exit_key = ignore_exit_key.clone();
|
// let ignore_exit_key = ignore_exit_key.clone();
|
||||||
thread::spawn(move || {
|
// thread::spawn(move || {
|
||||||
let stdin = io::stdin();
|
// let stdin = io::stdin();
|
||||||
for evt in stdin.keys() {
|
// for evt in stdin.keys() {
|
||||||
if let Ok(key) = evt {
|
// if let Ok(key) = evt {
|
||||||
if let Err(err) = tx.send(Event::Input(key)) {
|
// if let Err(err) = tx.send(Event::Input(key)) {
|
||||||
eprintln!("{}", err);
|
// eprintln!("{}", err);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if !ignore_exit_key.load(Ordering::Relaxed) && key == config.exit_key {
|
// if !ignore_exit_key.load(Ordering::Relaxed) && key == config.exit_key {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
let tick_handle = {
|
// let tick_handle = {
|
||||||
thread::spawn(move || loop {
|
// thread::spawn(move || loop {
|
||||||
if tx.send(Event::Tick).is_err() {
|
// if tx.send(Event::Tick).is_err() {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
thread::sleep(config.tick_rate);
|
// thread::sleep(config.tick_rate);
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
Events {
|
// Events {
|
||||||
rx,
|
// rx,
|
||||||
tx: mac_tx,
|
// tx: mac_tx,
|
||||||
ignore_exit_key,
|
// ignore_exit_key,
|
||||||
input_handle,
|
// input_handle,
|
||||||
tick_handle,
|
// tick_handle,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn next(&self) -> Result<Event<Key>, mpsc::RecvError> {
|
// pub fn next(&self) -> Result<Event<KeyEvent>, mpsc::RecvError> {
|
||||||
self.rx.recv()
|
// self.rx.recv()
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn try_next(&self) -> Result<Event<Key>, mpsc::TryRecvError> {
|
// pub fn try_iter(&self) -> TryIter<Event<KeyEvent>> {
|
||||||
self.rx.try_recv()
|
// self.rx.try_iter()
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn try_iter(&self) -> TryIter<Event<Key>> {
|
// #[allow(dead_code)]
|
||||||
self.rx.try_iter()
|
// pub fn disable_exit_key(&mut self) {
|
||||||
}
|
// self.ignore_exit_key.store(true, Ordering::Relaxed);
|
||||||
|
// }
|
||||||
|
|
||||||
#[allow(dead_code)]
|
// #[allow(dead_code)]
|
||||||
pub fn disable_exit_key(&mut self) {
|
// pub fn enable_exit_key(&mut self) {
|
||||||
self.ignore_exit_key.store(true, Ordering::Relaxed);
|
// 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