diff options
-rw-r--r-- | src/builtins.rs | 4 | ||||
-rw-r--r-- | src/parse.rs | 63 | ||||
-rw-r--r-- | src/state/history.rs | 21 | ||||
-rw-r--r-- | src/state/mod.rs | 8 |
4 files changed, 79 insertions, 17 deletions
diff --git a/src/builtins.rs b/src/builtins.rs index 8494c7e..e8f87da 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -2,10 +2,10 @@ pub fn is(exe: &str) -> bool { matches!(exe, "cd") } -pub fn run(exe: &str, args: &[String]) -> u8 { +pub fn run<'a>(exe: &str, args: impl IntoIterator<Item = &'a str>) -> u8 { match exe { "cd" => impls::cd( - args.iter() + args.into_iter() .map(std::convert::AsRef::as_ref) .next() .unwrap_or(""), diff --git a/src/parse.rs b/src/parse.rs index 84e8daa..42ead6e 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,8 +1,57 @@ -pub fn cmd(full_cmd: &str) -> (String, Vec<String>) { - let mut parts = full_cmd.split(' '); - let cmd = parts.next().unwrap(); - ( - cmd.to_string(), - parts.map(std::string::ToString::to_string).collect(), - ) +pub struct Word { + word: String, + interpolate: bool, +} + +impl Word { + fn new(word: String) -> Self { + Self { + word, + interpolate: true, + } + } + + fn literal(word: String) -> Self { + Self { + word, + interpolate: false, + } + } +} + +pub struct Exe { + exe: Word, + args: Vec<Word>, +} + +impl Exe { + pub fn exe(&self) -> &str { + &self.exe.word + } + + pub fn args(&self) -> impl Iterator<Item = &str> { + self.args.iter().map(|arg| arg.word.as_ref()) + } +} + +pub enum Command { + Exe(Exe), + And(Vec<Command>), + Or(Vec<Command>), + Both(Vec<Command>), + Pipe(Vec<Command>), +} + +impl Command { + pub fn parse(full_cmd: &str) -> Self { + let mut parts = full_cmd.split(' '); + let cmd = parts.next().unwrap(); + Self::Exe(Exe { + exe: Word::new(cmd.to_string()), + args: parts + .map(std::string::ToString::to_string) + .map(Word::new) + .collect(), + }) + } } diff --git a/src/state/history.rs b/src/state/history.rs index af8e07a..856153d 100644 --- a/src/state/history.rs +++ b/src/state/history.rs @@ -85,17 +85,24 @@ impl History { pub async fn run( &mut self, - cmd: &str, + cmd: &crate::parse::Command, event_w: async_std::channel::Sender<crate::event::Event>, ) -> anyhow::Result<usize> { - let (exe, args) = crate::parse::cmd(cmd); let (input_w, input_r) = async_std::channel::unbounded(); let (resize_w, resize_r) = async_std::channel::unbounded(); + + // for now + let cmd = match cmd { + crate::parse::Command::Exe(exe) => exe, + _ => todo!(), + }; + let entry = async_std::sync::Arc::new(async_std::sync::Mutex::new( - Entry::new(cmd, self.size, input_w, resize_w), + Entry::new(cmd.exe(), self.size, input_w, resize_w), )); - if crate::builtins::is(&exe) { - let code: i32 = crate::builtins::run(&exe, &args).into(); + if crate::builtins::is(cmd.exe()) { + let code: i32 = + crate::builtins::run(cmd.exe(), cmd.args()).into(); entry.lock_arc().await.exit_info = Some(ExitInfo::new( async_std::process::ExitStatus::from_raw(code << 8), )); @@ -104,8 +111,8 @@ impl History { .await .unwrap(); } else { - let mut process = async_std::process::Command::new(&exe); - process.args(&args); + let mut process = async_std::process::Command::new(cmd.exe()); + process.args(cmd.args()); let child = process .spawn_pty(Some(&pty_process::Size::new( self.size.0, diff --git a/src/state/mod.rs b/src/state/mod.rs index e64ba96..8547fc1 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -309,7 +309,7 @@ impl State { return Some(Action::HardRefresh); } textmode::Key::Ctrl(b'm') => { - let cmd = self.readline.input(); + let cmd = self.parse(&self.readline.input()); self.readline.clear_input(); let idx = self.history.run(&cmd, event_w.clone()).await.unwrap(); @@ -439,4 +439,10 @@ impl State { } self.focus_idx().map_or(Focus::Readline, Focus::History) } + + fn parse(&self, cmd: &str) -> crate::parse::Command { + let cmd = crate::parse::Command::parse(cmd); + // todo: interpolate + cmd + } } |