diff options
Diffstat (limited to 'src/nbsh.rs')
-rw-r--r-- | src/nbsh.rs | 219 |
1 files changed, 112 insertions, 107 deletions
diff --git a/src/nbsh.rs b/src/nbsh.rs index 8ba22b2..84d35e3 100644 --- a/src/nbsh.rs +++ b/src/nbsh.rs @@ -1,132 +1,137 @@ use textmode::Textmode as _; -pub struct Nbsh { - repl: crate::repl::Repl, - history: crate::history::History, +pub async fn run() -> anyhow::Result<()> { + let mut input = textmode::Input::new().await?; + let mut output = textmode::Output::new().await?; - 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(action_w.clone()), - history: crate::history::History::new(action_w), - action: action_r, - } - } - - pub async fn run(self) -> 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(); + // 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 Self { - repl, - history, - action, - } = self; + let (action_w, action_r) = async_std::channel::unbounded(); - 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 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, - ) - .await - .unwrap(); + render( + &mut output, + &*repl.lock_arc().await, + &*history.lock_arc().await, + &*input_source.lock_arc().await, + ) + .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); + { + 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.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; - } - } + 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 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 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; - } + 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; + } + } +} - Ok(()) +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(); - history.render(out, repl.lines()).await?; - repl.render(out).await?; + 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(()) } |