summaryrefslogtreecommitdiffstats
path: root/src/nbsh.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/nbsh.rs')
-rw-r--r--src/nbsh.rs176
1 files changed, 107 insertions, 69 deletions
diff --git a/src/nbsh.rs b/src/nbsh.rs
index 772ff5c..8ba22b2 100644
--- a/src/nbsh.rs
+++ b/src/nbsh.rs
@@ -3,13 +3,17 @@ use textmode::Textmode as _;
pub struct Nbsh {
repl: crate::repl::Repl,
history: crate::history::History,
+
+ action: async_std::channel::Receiver<Action>,
}
impl Nbsh {
pub fn new() -> Self {
+ let (action_w, action_r) = async_std::channel::unbounded();
Self {
- repl: crate::repl::Repl::new(),
- history: crate::history::History::new(),
+ repl: crate::repl::Repl::new(action_w.clone()),
+ history: crate::history::History::new(action_w),
+ action: action_r,
}
}
@@ -22,85 +26,119 @@ impl Nbsh {
let _input_guard = input.take_raw_guard();
let _output_guard = output.take_screen_guard();
- let (run_w, run_r) = async_std::channel::unbounded();
- let (render_w, render_r) = async_std::channel::unbounded();
+ let Self {
+ repl,
+ history,
+ action,
+ } = self;
- self.render(&mut output).await.unwrap();
+ let repl =
+ async_std::sync::Arc::new(async_std::sync::Mutex::new(repl));
+ let history =
+ async_std::sync::Arc::new(async_std::sync::Mutex::new(history));
+ let input_source = async_std::sync::Arc::new(
+ async_std::sync::Mutex::new(InputSource::Repl),
+ );
- let locked_self =
- async_std::sync::Arc::new(async_std::sync::Mutex::new(self));
+ render(
+ &mut output,
+ &*repl.lock_arc().await,
+ &*history.lock_arc().await,
+ )
+ .await
+ .unwrap();
- let readline_self = std::sync::Arc::clone(&locked_self);
- let readline_render = render_w.clone();
- let readline_task = async_std::task::spawn(async move {
- loop {
- let key = input.read_key().await.unwrap();
- let mut self_ = readline_self.lock_arc().await;
- let (last, cmd) = self_.handle_key(key);
- if last {
- break;
- }
- if let Some(cmd) = cmd {
- run_w.send(cmd).await.unwrap();
+ let action_history = async_std::sync::Arc::clone(&history);
+ let action_repl = async_std::sync::Arc::clone(&repl);
+ let action_input_source = async_std::sync::Arc::clone(&input_source);
+ async_std::task::spawn(async move {
+ while let Ok(action) = action.recv().await {
+ match action {
+ Action::Render => {
+ render(
+ &mut output,
+ &*action_repl.lock_arc().await,
+ &*action_history.lock_arc().await,
+ )
+ .await
+ .unwrap();
+ }
+ Action::Run(cmd) => {
+ action_history
+ .lock_arc()
+ .await
+ .run(&cmd)
+ .await
+ .unwrap();
+ }
+ Action::UpdateFocus(new_input_source) => {
+ *action_input_source.lock_arc().await =
+ new_input_source;
+ }
}
- readline_render.send(()).await.unwrap();
}
});
- let history_self = std::sync::Arc::clone(&locked_self);
- let history_render = render_w.clone();
- async_std::task::spawn(async move {
- while let Ok(cmd) = run_r.recv().await {
- let mut self_ = history_self.lock_arc().await;
- self_
- .history
- .run(&cmd, history_render.clone())
- .await
- .unwrap();
+ loop {
+ let input_source = *input_source.lock_arc().await;
+ match input_source {
+ InputSource::Repl => {
+ input.parse_utf8(true);
+ input.parse_ctrl(true);
+ input.parse_meta(true);
+ input.parse_special_keys(true);
+ input.parse_single(false);
+ }
+ InputSource::History(_) => {
+ input.parse_utf8(false);
+ input.parse_ctrl(false);
+ input.parse_meta(false);
+ input.parse_special_keys(false);
+ input.parse_single(false);
+ }
}
- });
-
- let render_self = std::sync::Arc::clone(&locked_self);
- async_std::task::spawn(async move {
- while let Ok(()) = render_r.recv().await {
- while let Ok(()) = render_r.try_recv() {}
- let self_ = render_self.lock_arc().await;
- self_.render(&mut output).await.unwrap();
+ let key = input.read_key().await.unwrap();
+ if let Some(key) = key {
+ 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 {
+ break;
+ }
+ } else {
+ break;
}
- });
-
- readline_task.await;
+ }
Ok(())
}
+}
- fn handle_key(
- &mut self,
- key: Option<textmode::Key>,
- ) -> (bool, Option<String>) {
- let mut cmd = None;
- match key {
- Some(textmode::Key::String(s)) => self.repl.add_input(&s),
- Some(textmode::Key::Char(c)) => {
- self.repl.add_input(&c.to_string());
- }
- Some(textmode::Key::Ctrl(b'c')) => self.repl.clear_input(),
- Some(textmode::Key::Ctrl(b'd')) | None => return (true, None),
- Some(textmode::Key::Ctrl(b'm')) => {
- cmd = Some(self.repl.input());
- self.repl.clear_input();
- }
- Some(textmode::Key::Backspace) => self.repl.backspace(),
- _ => {}
- }
- (false, cmd)
- }
+async fn render(
+ out: &mut textmode::Output,
+ repl: &crate::repl::Repl,
+ history: &crate::history::History,
+) -> anyhow::Result<()> {
+ out.clear();
+ history.render(out, repl.lines()).await?;
+ repl.render(out).await?;
+ out.refresh().await?;
+ Ok(())
+}
- async fn render(&self, out: &mut textmode::Output) -> anyhow::Result<()> {
- out.clear();
- self.history.render(out, self.repl.lines()).await?;
- self.repl.render(out).await?;
- out.refresh().await?;
- Ok(())
- }
+#[derive(Copy, Clone, Debug)]
+pub enum InputSource {
+ Repl,
+ History(usize),
+}
+
+pub enum Action {
+ Render,
+ Run(String),
+ UpdateFocus(InputSource),
}