summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/history.rs33
-rw-r--r--src/main.rs41
-rw-r--r--src/nbsh.rs149
-rw-r--r--src/readline.rs (renamed from src/repl.rs)15
-rw-r--r--src/state.rs83
-rw-r--r--src/util.rs5
6 files changed, 151 insertions, 175 deletions
diff --git a/src/history.rs b/src/history.rs
index 00ad39a..bf46693 100644
--- a/src/history.rs
+++ b/src/history.rs
@@ -3,13 +3,13 @@ use pty_process::Command as _;
use textmode::Textmode as _;
pub struct History {
- entries: Vec<async_std::sync::Arc<async_std::sync::Mutex<HistoryEntry>>>,
- action: async_std::channel::Sender<crate::nbsh::Action>,
+ entries: Vec<crate::util::Mutex<HistoryEntry>>,
+ action: async_std::channel::Sender<crate::state::Action>,
}
impl History {
pub fn new(
- action: async_std::channel::Sender<crate::nbsh::Action>,
+ action: async_std::channel::Sender<crate::state::Action>,
) -> Self {
Self {
entries: vec![],
@@ -24,8 +24,9 @@ impl History {
let child = process
.spawn_pty(Some(&pty_process::Size::new(24, 80)))
.unwrap();
- let entry = async_std::sync::Arc::new(async_std::sync::Mutex::new(
- HistoryEntry::new(cmd, child.id().try_into().unwrap()),
+ let entry = crate::util::mutex(HistoryEntry::new(
+ cmd,
+ child.id().try_into().unwrap(),
));
let task_entry = async_std::sync::Arc::clone(&entry);
let task_action = self.action.clone();
@@ -42,29 +43,27 @@ impl History {
}
task_entry.lock_arc().await.running = false;
task_action
- .send(crate::nbsh::Action::UpdateFocus(
- crate::nbsh::InputSource::Repl,
+ .send(crate::state::Action::UpdateFocus(
+ crate::state::Focus::Readline,
))
.await
.unwrap();
- task_action
- .send(crate::nbsh::Action::Render)
- .await
- .unwrap();
break;
}
}
- task_action.send(crate::nbsh::Action::Render).await.unwrap();
+ task_action
+ .send(crate::state::Action::Render)
+ .await
+ .unwrap();
}
});
self.entries.push(entry);
self.action
- .send(crate::nbsh::Action::UpdateFocus(
- crate::nbsh::InputSource::History(self.entries.len() - 1),
+ .send(crate::state::Action::UpdateFocus(
+ crate::state::Focus::History(self.entries.len() - 1),
))
.await
.unwrap();
- self.action.send(crate::nbsh::Action::Render).await.unwrap();
Ok(self.entries.len() - 1)
}
@@ -81,8 +80,8 @@ impl History {
}
textmode::Key::Ctrl(b'z') => {
self.action
- .send(crate::nbsh::Action::UpdateFocus(
- crate::nbsh::InputSource::Repl,
+ .send(crate::state::Action::UpdateFocus(
+ crate::state::Focus::Readline,
))
.await
.unwrap();
diff --git a/src/main.rs b/src/main.rs
index 97624df..666b936 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,11 +4,46 @@
#![allow(clippy::unused_self)]
mod history;
-mod nbsh;
-mod repl;
+mod readline;
+mod state;
+mod util;
async fn async_main() -> anyhow::Result<()> {
- nbsh::run().await
+ let mut input = textmode::Input::new().await?;
+ let mut output = textmode::Output::new().await?;
+
+ // avoid the guards getting stuck in a task that doesn't run to
+ // completion
+ let _input_guard = input.take_raw_guard();
+ let _output_guard = output.take_screen_guard();
+
+ let (action_w, action_r) = async_std::channel::unbounded();
+
+ let state = util::mutex(state::State::new(action_w));
+
+ state.lock_arc().await.render(&mut output).await.unwrap();
+
+ {
+ let state = async_std::sync::Arc::clone(&state);
+ async_std::task::spawn(async move {
+ while let Ok(action) = action_r.recv().await {
+ state
+ .lock_arc()
+ .await
+ .handle_action(action, &mut output)
+ .await;
+ }
+ });
+ }
+
+ loop {
+ let key = input.read_key().await.unwrap();
+ if state.lock_arc().await.handle_input(key).await {
+ break;
+ }
+ }
+
+ Ok(())
}
fn main() {
diff --git a/src/nbsh.rs b/src/nbsh.rs
deleted file mode 100644
index 84d35e3..0000000
--- a/src/nbsh.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use textmode::Textmode as _;
-
-pub async fn run() -> anyhow::Result<()> {
- let mut input = textmode::Input::new().await?;
- let mut output = textmode::Output::new().await?;
-
- // avoid the guards getting stuck in a task that doesn't run to
- // completion
- let _input_guard = input.take_raw_guard();
- let _output_guard = output.take_screen_guard();
-
- let (action_w, action_r) = async_std::channel::unbounded();
-
- let repl = async_std::sync::Arc::new(async_std::sync::Mutex::new(
- crate::repl::Repl::new(action_w.clone()),
- ));
- let history = async_std::sync::Arc::new(async_std::sync::Mutex::new(
- crate::history::History::new(action_w),
- ));
- let input_source = async_std::sync::Arc::new(
- async_std::sync::Mutex::new(InputSource::Repl),
- );
-
- render(
- &mut output,
- &*repl.lock_arc().await,
- &*history.lock_arc().await,
- &*input_source.lock_arc().await,
- )
- .await
- .unwrap();
-
- {
- let repl = async_std::sync::Arc::clone(&repl);
- let history = async_std::sync::Arc::clone(&history);
- let input_source = async_std::sync::Arc::clone(&input_source);
- async_std::task::spawn(async move {
- while let Ok(action) = action_r.recv().await {
- handle_action(
- action,
- &mut output,
- async_std::sync::Arc::clone(&repl),
- async_std::sync::Arc::clone(&history),
- async_std::sync::Arc::clone(&input_source),
- )
- .await;
- }
- });
- }
-
- loop {
- let quit = handle_input(
- &mut input,
- async_std::sync::Arc::clone(&repl),
- async_std::sync::Arc::clone(&history),
- async_std::sync::Arc::clone(&input_source),
- )
- .await;
- if quit {
- break;
- }
- }
-
- Ok(())
-}
-
-async fn handle_action(
- action: Action,
- output: &mut textmode::Output,
- repl: async_std::sync::Arc<async_std::sync::Mutex<crate::repl::Repl>>,
- history: async_std::sync::Arc<
- async_std::sync::Mutex<crate::history::History>,
- >,
- input_source: async_std::sync::Arc<async_std::sync::Mutex<InputSource>>,
-) {
- match action {
- Action::Render => {
- render(
- output,
- &*repl.lock_arc().await,
- &*history.lock_arc().await,
- &*input_source.lock_arc().await,
- )
- .await
- .unwrap();
- }
- Action::Run(ref cmd) => {
- history.lock_arc().await.run(cmd).await.unwrap();
- }
- Action::UpdateFocus(new_input_source) => {
- *input_source.lock_arc().await = new_input_source;
- }
- }
-}
-
-async fn handle_input(
- input: &mut textmode::Input,
- repl: async_std::sync::Arc<async_std::sync::Mutex<crate::repl::Repl>>,
- history: async_std::sync::Arc<
- async_std::sync::Mutex<crate::history::History>,
- >,
- input_source: async_std::sync::Arc<async_std::sync::Mutex<InputSource>>,
-) -> bool {
- let key = input.read_key().await.unwrap();
- if let Some(key) = key {
- let input_source = *input_source.lock_arc().await;
- let quit = match input_source {
- InputSource::Repl => repl.lock_arc().await.handle_key(key).await,
- InputSource::History(idx) => {
- history.lock_arc().await.handle_key(key, idx).await
- }
- };
- if quit {
- return true;
- }
- } else {
- return true;
- }
- false
-}
-
-async fn render(
- out: &mut textmode::Output,
- repl: &crate::repl::Repl,
- history: &crate::history::History,
- input_source: &InputSource,
-) -> anyhow::Result<()> {
- out.clear();
- if let InputSource::Repl = input_source {
- history.render(out, repl.lines()).await?;
- repl.render(out).await?;
- } else {
- history.render(out, 0).await?;
- }
- out.refresh().await?;
- Ok(())
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum InputSource {
- Repl,
- History(usize),
-}
-
-pub enum Action {
- Render,
- Run(String),
- UpdateFocus(InputSource),
-}
diff --git a/src/repl.rs b/src/readline.rs
index 223aa80..8ff001c 100644
--- a/src/repl.rs
+++ b/src/readline.rs
@@ -1,14 +1,14 @@
use textmode::Textmode as _;
-pub struct Repl {
+pub struct Readline {
prompt: String,
input_line: String,
- action: async_std::channel::Sender<crate::nbsh::Action>,
+ action: async_std::channel::Sender<crate::state::Action>,
}
-impl Repl {
+impl Readline {
pub fn new(
- action: async_std::channel::Sender<crate::nbsh::Action>,
+ action: async_std::channel::Sender<crate::state::Action>,
) -> Self {
Self {
prompt: "$ ".into(),
@@ -29,7 +29,7 @@ impl Repl {
}
textmode::Key::Ctrl(b'm') => {
self.action
- .send(crate::nbsh::Action::Run(self.input()))
+ .send(crate::state::Action::Run(self.input()))
.await
.unwrap();
self.clear_input();
@@ -37,7 +37,10 @@ impl Repl {
textmode::Key::Backspace => self.backspace(),
_ => {}
}
- self.action.send(crate::nbsh::Action::Render).await.unwrap();
+ self.action
+ .send(crate::state::Action::Render)
+ .await
+ .unwrap();
false
}
diff --git a/src/state.rs b/src/state.rs
new file mode 100644
index 0000000..b979ed7
--- /dev/null
+++ b/src/state.rs
@@ -0,0 +1,83 @@
+use textmode::Textmode as _;
+
+pub struct State {
+ readline: crate::readline::Readline,
+ history: crate::history::History,
+ focus: Focus,
+}
+
+impl State {
+ pub fn new(actions: async_std::channel::Sender<Action>) -> Self {
+ let readline = crate::readline::Readline::new(actions.clone());
+ let history = crate::history::History::new(actions);
+ let focus = Focus::Readline;
+ Self {
+ readline,
+ history,
+ focus,
+ }
+ }
+
+ pub async fn render(
+ &self,
+ out: &mut textmode::Output,
+ ) -> anyhow::Result<()> {
+ out.clear();
+ if let Focus::Readline = self.focus {
+ self.history.render(out, self.readline.lines()).await?;
+ self.readline.render(out).await?;
+ } else {
+ self.history.render(out, 0).await?;
+ }
+ out.refresh().await?;
+ Ok(())
+ }
+
+ pub async fn handle_action(
+ &mut self,
+ action: Action,
+ output: &mut textmode::Output,
+ ) {
+ match action {
+ Action::Render => {
+ self.render(output).await.unwrap();
+ }
+ Action::Run(ref cmd) => {
+ self.history.run(cmd).await.unwrap();
+ }
+ Action::UpdateFocus(new_focus) => {
+ self.focus = new_focus;
+ self.render(output).await.unwrap();
+ }
+ }
+ }
+
+ pub async fn handle_input(&mut self, key: Option<textmode::Key>) -> bool {
+ if let Some(key) = key {
+ let quit = match self.focus {
+ Focus::Readline => self.readline.handle_key(key).await,
+ Focus::History(idx) => {
+ self.history.handle_key(key, idx).await
+ }
+ };
+ if quit {
+ return true;
+ }
+ } else {
+ return true;
+ }
+ false
+ }
+}
+
+#[derive(Copy, Clone)]
+pub enum Focus {
+ Readline,
+ History(usize),
+}
+
+pub enum Action {
+ Render,
+ Run(String),
+ UpdateFocus(Focus),
+}
diff --git a/src/util.rs b/src/util.rs
new file mode 100644
index 0000000..d792b91
--- /dev/null
+++ b/src/util.rs
@@ -0,0 +1,5 @@
+pub type Mutex<T> = async_std::sync::Arc<async_std::sync::Mutex<T>>;
+
+pub fn mutex<T>(t: T) -> Mutex<T> {
+ async_std::sync::Arc::new(async_std::sync::Mutex::new(t))
+}