summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/builtins.rs4
-rw-r--r--src/parse.rs63
-rw-r--r--src/state/history.rs21
-rw-r--r--src/state/mod.rs8
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
+ }
}