diff --git a/src/builtin/cd.rs b/src/builtin/cd.rs index abcebeb..b06fc7c 100644 --- a/src/builtin/cd.rs +++ b/src/builtin/cd.rs @@ -1,8 +1,9 @@ -use crate::{jobs::JobBldr, libsh::error::ShResult, parse::{NdRule, Node}, prelude::*, state::{self}}; +use crate::{jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{NdRule, Node}, prelude::*, state::{self}}; use super::setup_builtin; pub fn cd(node: Node, job: &mut JobBldr) -> ShResult<()> { + let span = node.get_span(); let NdRule::Command { assignments: _, argv } = node.class else { unreachable!() }; @@ -15,6 +16,26 @@ pub fn cd(node: Node, job: &mut JobBldr) -> ShResult<()> { PathBuf::from(env::var("HOME").unwrap()) }; + if !new_dir.exists() { + return Err( + ShErr::full( + ShErrKind::ExecFail, + format!("cd: No such file or directory '{}'",new_dir.display()), + span, + ) + ) + } + + if !new_dir.is_dir() { + return Err( + ShErr::full( + ShErrKind::ExecFail, + format!("cd: Not a directory '{}'",new_dir.display()), + span, + ) + ) + } + env::set_current_dir(new_dir).unwrap(); let new_dir = env::current_dir().unwrap(); env::set_var("PWD", new_dir); diff --git a/src/builtin/source.rs b/src/builtin/source.rs index a109481..a16ae1e 100644 --- a/src/builtin/source.rs +++ b/src/builtin/source.rs @@ -15,7 +15,7 @@ pub fn source(node: Node, job: &mut JobBldr) -> ShResult<()> { return Err( ShErr::full( ShErrKind::ExecFail, - "source: File not found", + format!("source: File '{}' not found",path.display()), span ) ); @@ -24,7 +24,7 @@ pub fn source(node: Node, job: &mut JobBldr) -> ShResult<()> { return Err( ShErr::full( ShErrKind::ExecFail, - "source: Given path is not a file", + format!("source: Given path '{}' is not a file",path.display()), span ) ); diff --git a/src/parse/execute.rs b/src/parse/execute.rs index 96bcb30..4a1b1a2 100644 --- a/src/parse/execute.rs +++ b/src/parse/execute.rs @@ -450,7 +450,13 @@ impl Dispatcher { let curr_job_mut = self.job_stack.curr_job_mut().unwrap(); let io_stack_mut = &mut self.io_stack; - if cmd_raw.as_str() == "builtin" || cmd_raw.as_str() == "command" { + if cmd_raw.as_str() == "builtin" { + *argv = argv.iter_mut() + .skip(1) + .map(|tk| tk.clone()) + .collect::>(); + return self.exec_builtin(cmd) + } else if cmd_raw.as_str() == "command" { *argv = argv.iter_mut() .skip(1) .map(|tk| tk.clone()) diff --git a/src/parse/lex.rs b/src/parse/lex.rs index 9098d2d..e1765ca 100644 --- a/src/parse/lex.rs +++ b/src/parse/lex.rs @@ -322,6 +322,7 @@ impl LexStream { let slice = self.slice_from_cursor().unwrap().to_string(); let mut pos = self.cursor; let mut chars = slice.chars().peekable(); + let mut can_be_subshell = chars.peek() == Some(&'('); if self.flags.contains(LexFlags::IN_CASE) { if let Some(count) = case_pat_lookahead(chars.clone()) { @@ -501,7 +502,7 @@ impl LexStream { self.cursor = pos; return Ok(cmdsub_tk) } - '(' if self.next_is_cmd() => { + '(' if self.next_is_cmd() && can_be_subshell => { pos += 1; let mut paren_count = 1; let paren_pos = pos; diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 902ee3c..e95f54e 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -691,17 +691,19 @@ impl ParseStream { let mut body: Vec = vec![]; let mut redirs: Vec = vec![]; + if *self.next_tk_class() != TkRule::BraceGrpStart { return Ok(None) } node_tks.push(self.next_tk().unwrap()); + loop { if *self.next_tk_class() == TkRule::BraceGrpEnd { node_tks.push(self.next_tk().unwrap()); break } - if let Some(node) = self.parse_block(true)? { + if let Some(node) = self.parse_cmd_list()? { node_tks.extend(node.tokens.clone()); body.push(node); } diff --git a/src/prompt/readline/mod.rs b/src/prompt/readline/mod.rs index 27f1674..a617a90 100644 --- a/src/prompt/readline/mod.rs +++ b/src/prompt/readline/mod.rs @@ -107,7 +107,7 @@ impl Readline for FernVi { impl FernVi { pub fn new(prompt: Option) -> ShResult { let prompt = prompt.unwrap_or("$ ".styled(Style::Green | Style::Bold)); - let line = LineBuf::new().with_initial(LOREM_IPSUM); + let line = LineBuf::new();//.with_initial(LOREM_IPSUM); let term = Terminal::new(); let history = History::new()?; Ok(Self {