summaryrefslogtreecommitdiffstats
path: root/src/nbsh.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/nbsh.rs')
-rw-r--r--src/nbsh.rs219
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(())
}