summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-12 23:53:01 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-12 23:53:01 -0500
commit009171812efa815ae6e445178689a08400905c04 (patch)
treef2de72bca3de0af4a57b0097ff11692c22eab06e
parent8177f123ffb5d312ab664936a22f3e04317c0568 (diff)
downloadnbsh-009171812efa815ae6e445178689a08400905c04.tar.gz
nbsh-009171812efa815ae6e445178689a08400905c04.zip
more event loop refactoring
-rw-r--r--src/event.rs3
-rw-r--r--src/history.rs11
-rw-r--r--src/main.rs23
-rw-r--r--src/readline.rs3
-rw-r--r--src/state.rs66
5 files changed, 55 insertions, 51 deletions
diff --git a/src/event.rs b/src/event.rs
index ca44239..62a12c8 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -6,7 +6,6 @@ pub enum Event {
ProcessAlternateScreen,
ProcessExit,
ClockTimer,
- Quit,
}
pub struct Reader {
@@ -119,7 +118,7 @@ impl Pending {
}
Some(Event::ProcessExit) => self.process_exit = true,
Some(Event::ClockTimer) => self.clock_timer = true,
- Some(Event::Quit) | None => self.done = true,
+ None => self.done = true,
}
}
}
diff --git a/src/history.rs b/src/history.rs
index 59cf822..048c1c7 100644
--- a/src/history.rs
+++ b/src/history.rs
@@ -2,7 +2,6 @@ use async_std::io::{ReadExt as _, WriteExt as _};
use futures_lite::future::FutureExt as _;
use pty_process::Command as _;
use std::os::unix::process::ExitStatusExt as _;
-use textmode::Textmode as _;
pub struct History {
size: (u16, u16),
@@ -21,7 +20,7 @@ impl History {
pub async fn render(
&self,
- out: &mut textmode::Output,
+ out: &mut impl textmode::Textmode,
repl_lines: usize,
focus: Option<usize>,
scrolling: bool,
@@ -63,7 +62,7 @@ impl History {
pub async fn render_fullscreen(
&self,
- out: &mut textmode::Output,
+ out: &mut impl textmode::Textmode,
idx: usize,
) {
let mut entry = self.entries[idx].lock_arc().await;
@@ -271,7 +270,7 @@ impl Entry {
fn render(
&mut self,
- out: &mut textmode::Output,
+ out: &mut impl textmode::Textmode,
idx: usize,
entry_count: usize,
width: u16,
@@ -386,7 +385,7 @@ impl Entry {
out.reset_attributes();
}
- fn render_fullscreen(&mut self, out: &mut textmode::Output) {
+ fn render_fullscreen(&mut self, out: &mut impl textmode::Textmode) {
let screen = self.vt.screen();
let new_audible_bell_state = screen.audible_bell_count();
let new_visual_bell_state = screen.visual_bell_count();
@@ -406,7 +405,7 @@ impl Entry {
out.reset_attributes();
}
- fn set_bgcolor(&self, out: &mut textmode::Output, focus: bool) {
+ fn set_bgcolor(&self, out: &mut impl textmode::Textmode, focus: bool) {
if focus {
out.set_bgcolor(textmode::Color::Rgb(32, 32, 64));
} else {
diff --git a/src/main.rs b/src/main.rs
index 225b21b..20e805c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,6 @@
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
+#![allow(clippy::future_not_send)]
#![allow(clippy::missing_const_for_fn)]
#![allow(clippy::struct_excessive_bools)]
#![allow(clippy::too_many_arguments)]
@@ -17,6 +18,7 @@ mod state;
mod util;
use async_std::stream::StreamExt as _;
+use textmode::Textmode as _;
// the time crate is currently unable to get the local offset on unix due to
// soundness concerns, so we have to do it manually/:
@@ -61,7 +63,8 @@ async fn async_main() -> anyhow::Result<()> {
let (event_w, event_r) = async_std::channel::unbounded();
let mut state = state::State::new(get_offset());
- state.render(&mut output, true).await.unwrap();
+ state.render(&mut output).await.unwrap();
+ output.hard_refresh().await?;
{
let mut signals = signal_hook_async_std::Signals::new(&[
@@ -109,7 +112,23 @@ async fn async_main() -> anyhow::Result<()> {
let event_reader = event::Reader::new(event_r);
while let Some(event) = event_reader.recv().await {
- state.handle_event(event, &mut output, &event_w).await;
+ match state.handle_event(event, &event_w).await {
+ Some(state::Action::Refresh) => {
+ state.render(&mut output).await?;
+ output.refresh().await?;
+ }
+ Some(state::Action::HardRefresh) => {
+ state.render(&mut output).await?;
+ output.hard_refresh().await?;
+ }
+ Some(state::Action::Resize(rows, cols)) => {
+ output.set_size(rows, cols);
+ state.render(&mut output).await?;
+ output.hard_refresh().await?;
+ }
+ Some(state::Action::Quit) => break,
+ None => {}
+ }
}
Ok(())
diff --git a/src/readline.rs b/src/readline.rs
index e13c00f..585d6b6 100644
--- a/src/readline.rs
+++ b/src/readline.rs
@@ -1,4 +1,3 @@
-use textmode::Textmode as _;
use unicode_width::{UnicodeWidthChar as _, UnicodeWidthStr as _};
pub struct Readline {
@@ -18,7 +17,7 @@ impl Readline {
pub async fn render(
&self,
- out: &mut textmode::Output,
+ out: &mut impl textmode::Textmode,
entry_count: usize,
focus: bool,
offset: time::UtcOffset,
diff --git a/src/state.rs b/src/state.rs
index a3d251b..cdc3cdb 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -1,5 +1,3 @@
-use textmode::Textmode as _;
-
#[derive(Copy, Clone, Debug)]
enum Focus {
Readline,
@@ -13,6 +11,13 @@ enum Scene {
Fullscreen,
}
+pub enum Action {
+ Refresh,
+ HardRefresh,
+ Resize(u16, u16),
+ Quit,
+}
+
pub struct State {
readline: crate::readline::Readline,
history: crate::history::History,
@@ -38,8 +43,7 @@ impl State {
pub async fn render(
&self,
- out: &mut textmode::Output,
- hard: bool,
+ out: &mut impl textmode::Textmode,
) -> anyhow::Result<()> {
out.clear();
match self.scene {
@@ -119,29 +123,22 @@ impl State {
}
}
}
- if hard {
- out.hard_refresh().await?;
- } else {
- out.refresh().await?;
- }
Ok(())
}
pub async fn handle_event(
&mut self,
event: crate::event::Event,
- out: &mut textmode::Output,
event_w: &async_std::channel::Sender<crate::event::Event>,
- ) {
- let mut hard_refresh = false;
+ ) -> Option<Action> {
match event {
crate::event::Event::Key(key) => {
- let (quit, hard) = if self.escape {
+ return if self.escape {
self.escape = false;
self.handle_key_escape(key).await
} else if key == textmode::Key::Ctrl(b'e') {
self.escape = true;
- (false, false)
+ None
} else {
match self.focus {
Focus::Readline => {
@@ -150,25 +147,18 @@ impl State {
}
Focus::History(idx) => {
self.handle_key_history(key, idx).await;
- (false, false)
+ None
}
Focus::Scrolling(_) => {
self.handle_key_escape(key).await
}
}
};
- if quit {
- event_w.send(crate::event::Event::Quit).await.unwrap();
- }
- if hard {
- hard_refresh = true;
- }
}
crate::event::Event::Resize(new_size) => {
self.readline.resize(new_size).await;
self.history.resize(new_size).await;
- out.set_size(new_size.0, new_size.1);
- hard_refresh = true;
+ return Some(Action::Resize(new_size.0, new_size.1));
}
crate::event::Event::ProcessOutput => {
// the number of visible lines may have changed, so make sure
@@ -201,28 +191,24 @@ impl State {
}
}
crate::event::Event::ClockTimer => {}
- crate::event::Event::Quit => {
- // the debouncer should return None in this case
- unreachable!();
- }
- }
- self.render(out, hard_refresh).await.unwrap();
+ };
+ Some(Action::Refresh)
}
async fn handle_key_escape(
&mut self,
key: textmode::Key,
- ) -> (bool, bool) {
+ ) -> Option<Action> {
match key {
textmode::Key::Ctrl(b'd') => {
- return (true, false);
+ return Some(Action::Quit);
}
textmode::Key::Ctrl(b'e') => {
self.set_focus(Focus::Scrolling(self.focus_idx()), None)
.await;
}
textmode::Key::Ctrl(b'l') => {
- return (false, true);
+ return Some(Action::HardRefresh);
}
textmode::Key::Ctrl(b'm') => {
let idx = self.focus_idx();
@@ -293,26 +279,28 @@ impl State {
textmode::Key::Char('r') => {
self.set_focus(Focus::Readline, None).await;
}
- _ => {}
+ _ => {
+ return None;
+ }
}
- (false, false)
+ Some(Action::Refresh)
}
async fn handle_key_readline(
&mut self,
key: textmode::Key,
event_w: async_std::channel::Sender<crate::event::Event>,
- ) -> (bool, bool) {
+ ) -> Option<Action> {
match key {
textmode::Key::Char(c) => {
self.readline.add_input(&c.to_string());
}
textmode::Key::Ctrl(b'c') => self.readline.clear_input(),
textmode::Key::Ctrl(b'd') => {
- return (true, false);
+ return Some(Action::Quit);
}
textmode::Key::Ctrl(b'l') => {
- return (false, true);
+ return Some(Action::HardRefresh);
}
textmode::Key::Ctrl(b'm') => {
let cmd = self.readline.input();
@@ -336,9 +324,9 @@ impl State {
.await;
}
}
- _ => {}
+ _ => return None,
}
- (false, false)
+ Some(Action::Refresh)
}
async fn handle_key_history(&mut self, key: textmode::Key, idx: usize) {