More progress on integrating ariadne's error reporting
This commit is contained in:
@@ -38,19 +38,11 @@ pub fn alias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
} else {
|
||||
for (arg, span) in argv {
|
||||
if arg == "command" || arg == "builtin" {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("alias: Cannot assign alias to reserved name '{arg}'"),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, span, format!("alias: Cannot assign alias to reserved name '{arg}'")));
|
||||
}
|
||||
|
||||
let Some((name, body)) = arg.split_once('=') else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
"alias: Expected an assignment in alias args",
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, span, "alias: Expected an assignment in alias args"));
|
||||
};
|
||||
write_logic(|l| l.insert_alias(name, body));
|
||||
}
|
||||
@@ -88,11 +80,7 @@ pub fn unalias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResul
|
||||
} else {
|
||||
for (arg, span) in argv {
|
||||
if read_logic(|l| l.get_alias(&arg)).is_none() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
format!("unalias: alias '{arg}' not found"),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, span, format!("unalias: alias '{arg}' not found")));
|
||||
};
|
||||
write_logic(|l| l.remove_alias(&arg))
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ fn arr_pop_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: End
|
||||
}
|
||||
|
||||
fn arr_push_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: End) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -99,7 +100,7 @@ fn arr_push_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: En
|
||||
|
||||
let mut argv = argv.into_iter();
|
||||
let Some((name, _)) = argv.next() else {
|
||||
return Err(ShErr::simple(ShErrKind::ExecFail, "push: missing array name".to_string()));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, blame, "push: missing array name".to_string()));
|
||||
};
|
||||
|
||||
for (val, _) in argv {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use ariadne::{Fmt, Label, Span};
|
||||
use ariadne::Fmt;
|
||||
use yansi::Color;
|
||||
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
@@ -12,7 +13,6 @@ use super::setup_builtin;
|
||||
|
||||
pub fn cd(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
let span = node.get_span();
|
||||
let src = span.source();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -32,39 +32,28 @@ pub fn cd(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
};
|
||||
|
||||
if !new_dir.exists() {
|
||||
let color = next_color();
|
||||
let mut err = ShErr::new(
|
||||
ShErrKind::ExecFail,
|
||||
span.clone(),
|
||||
).with_label(src.clone(), Label::new(cd_span.clone()).with_color(color).with_message("Failed to change directory"));
|
||||
).labeled(cd_span.clone(), "Failed to change directory");
|
||||
if let Some(span) = arg_span {
|
||||
let color = next_color();
|
||||
err = err.with_label(src.clone(), Label::new(span).with_color(color).with_message(format!("No such file or directory '{}'", new_dir.display().fg(color))));
|
||||
err = err.labeled(span, format!("No such file or directory '{}'", new_dir.display().fg(next_color())));
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
if !new_dir.is_dir() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("cd: Not a directory '{}'", new_dir.display()),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::new(ShErrKind::ExecFail, span.clone())
|
||||
.labeled(cd_span.clone(), format!("cd: Not a directory '{}'", new_dir.display().fg(next_color()))));
|
||||
}
|
||||
|
||||
if let Err(e) = env::set_current_dir(new_dir) {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("cd: Failed to change directory: {}", e),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::new(ShErrKind::ExecFail, span.clone())
|
||||
.labeled(cd_span.clone(), format!("cd: Failed to change directory: '{}'", e.fg(Color::Red))));
|
||||
}
|
||||
let new_dir = env::current_dir().map_err(|e| {
|
||||
ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("cd: Failed to get current directory: {}", e),
|
||||
span,
|
||||
)
|
||||
ShErr::new(ShErrKind::ExecFail, span.clone())
|
||||
.labeled(cd_span.clone(), format!("cd: Failed to get current directory: '{}'", e.fg(Color::Red)))
|
||||
})?;
|
||||
unsafe { env::set_var("PWD", new_dir) };
|
||||
|
||||
|
||||
@@ -206,11 +206,7 @@ pub fn complete_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -
|
||||
|
||||
if argv.is_empty() {
|
||||
state::set_status(1);
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
"complete: no command specified",
|
||||
blame,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, blame, "complete: no command specified"));
|
||||
}
|
||||
|
||||
let comp_spec = BashCompSpec::from_comp_opts(comp_opts).with_source(src);
|
||||
@@ -285,11 +281,8 @@ pub fn get_comp_opts(opts: Vec<Opt>) -> ShResult<CompOpts> {
|
||||
"dirnames" => comp_opts.opt_flags |= CompOptFlags::DIRNAMES,
|
||||
"space" => comp_opts.opt_flags |= CompOptFlags::SPACE,
|
||||
_ => {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::InvalidOpt,
|
||||
format!("complete: invalid option: {}", opt_flag),
|
||||
Default::default(),
|
||||
));
|
||||
let span: crate::parse::lex::Span = Default::default();
|
||||
return Err(ShErr::at(ShErrKind::InvalidOpt, span, format!("complete: invalid option: {}", opt_flag)));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -47,26 +47,18 @@ fn print_dirs() -> ShResult<()> {
|
||||
|
||||
fn change_directory(target: &PathBuf, blame: Span) -> ShResult<()> {
|
||||
if !target.is_dir() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("not a directory: {}", target.display()),
|
||||
blame,
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("not a directory: {}", target.display()))
|
||||
);
|
||||
}
|
||||
|
||||
if let Err(e) = env::set_current_dir(target) {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("Failed to change directory: {}", e),
|
||||
blame,
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("Failed to change directory: {}", e))
|
||||
);
|
||||
}
|
||||
let new_dir = env::current_dir().map_err(|e| {
|
||||
ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("Failed to get current directory: {}", e),
|
||||
blame,
|
||||
)
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("Failed to get current directory: {}", e))
|
||||
})?;
|
||||
unsafe { env::set_var("PWD", new_dir) };
|
||||
Ok(())
|
||||
@@ -82,32 +74,24 @@ fn parse_stack_idx(arg: &str, blame: Span, cmd: &str) -> ShResult<StackIdx> {
|
||||
};
|
||||
|
||||
if digits.is_empty() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!(
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!(
|
||||
"{cmd}: missing index after '{}'",
|
||||
if from_top { "+" } else { "-" }
|
||||
),
|
||||
blame,
|
||||
));
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
for ch in digits.chars() {
|
||||
if !ch.is_ascii_digit() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("{cmd}: invalid argument: {arg}"),
|
||||
blame,
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("{cmd}: invalid argument: {arg}"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let n = digits.parse::<usize>().map_err(|e| {
|
||||
ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("{cmd}: invalid index: {e}"),
|
||||
blame,
|
||||
)
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("{cmd}: invalid index: {e}"))
|
||||
})?;
|
||||
|
||||
if from_top {
|
||||
@@ -142,26 +126,20 @@ pub fn pushd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
} else if arg == "-n" {
|
||||
no_cd = true;
|
||||
} else if arg.starts_with('-') {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("pushd: invalid option: {arg}"),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("pushd: invalid option: {arg}"))
|
||||
);
|
||||
} else {
|
||||
if dir.is_some() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
"pushd: too many arguments".to_string(),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, "pushd: too many arguments")
|
||||
);
|
||||
}
|
||||
let target = PathBuf::from(&arg);
|
||||
if !target.is_dir() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("pushd: not a directory: {arg}"),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("pushd: not a directory: {arg}"))
|
||||
);
|
||||
}
|
||||
dir = Some(target);
|
||||
}
|
||||
@@ -228,11 +206,9 @@ pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
} else if arg == "-n" {
|
||||
no_cd = true;
|
||||
} else if arg.starts_with('-') {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("popd: invalid option: {arg}"),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("popd: invalid option: {arg}"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,11 +221,9 @@ pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
if let Some(dir) = dir {
|
||||
change_directory(&dir, blame.clone())?;
|
||||
} else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
"popd: directory stack empty".to_string(),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, "popd: directory stack empty")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,11 +233,9 @@ pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
let dirs = m.dirs_mut();
|
||||
let idx = n - 1;
|
||||
if idx >= dirs.len() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("popd: directory index out of range: +{n}"),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame.clone(), format!("popd: directory index out of range: +{n}"))
|
||||
);
|
||||
}
|
||||
dirs.remove(idx);
|
||||
Ok(())
|
||||
@@ -273,11 +245,7 @@ pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
write_meta(|m| -> ShResult<()> {
|
||||
let dirs = m.dirs_mut();
|
||||
let actual = dirs.len().checked_sub(n + 1).ok_or_else(|| {
|
||||
ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("popd: directory index out of range: -{n}"),
|
||||
blame.clone(),
|
||||
)
|
||||
ShErr::at(ShErrKind::ExecFail, blame.clone(), format!("popd: directory index out of range: -{n}"))
|
||||
})?;
|
||||
dirs.remove(actual);
|
||||
Ok(())
|
||||
@@ -297,11 +265,9 @@ pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
change_directory(&dir, blame.clone())?;
|
||||
print_dirs()?;
|
||||
} else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
"popd: directory stack empty".to_string(),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, "popd: directory stack empty")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,18 +306,14 @@ pub fn dirs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
target_idx = Some(parse_stack_idx(&arg, blame.clone(), "dirs")?);
|
||||
}
|
||||
_ if arg.starts_with('-') => {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("dirs: invalid option: {arg}"),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("dirs: invalid option: {arg}"))
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("dirs: unexpected argument: {arg}"),
|
||||
blame.clone(),
|
||||
));
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!("dirs: unexpected argument: {arg}"))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,17 +358,15 @@ pub fn dirs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
if let Some(dir) = target {
|
||||
dirs = vec![dir.clone()];
|
||||
} else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!(
|
||||
return Err(
|
||||
ShErr::at(ShErrKind::ExecFail, blame, format!(
|
||||
"dirs: directory index out of range: {}",
|
||||
match idx {
|
||||
StackIdx::FromTop(n) => format!("+{n}"),
|
||||
StackIdx::FromBottom(n) => format!("-{n}"),
|
||||
}
|
||||
),
|
||||
blame.clone(),
|
||||
));
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use ariadne::Label;
|
||||
use nix::{errno::Errno, unistd::execvpe};
|
||||
|
||||
use crate::{
|
||||
@@ -43,13 +42,9 @@ pub fn exec_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> Sh
|
||||
let cmd_str = cmd.to_str().unwrap().to_string();
|
||||
match e {
|
||||
Errno::ENOENT => Err(
|
||||
ShErr::full(ShErrKind::CmdNotFound, "", span.clone())
|
||||
.with_label(
|
||||
span.span_source().clone(),
|
||||
Label::new(span.clone())
|
||||
.with_message(format!("exec: command not found: {}", cmd_str))
|
||||
)
|
||||
ShErr::new(ShErrKind::CmdNotFound, span.clone())
|
||||
.labeled(span, format!("exec: command not found: {}", cmd_str))
|
||||
),
|
||||
_ => Err(ShErr::full(ShErrKind::Errno(e), format!("{e}"), span)),
|
||||
_ => Err(ShErr::at(ShErrKind::Errno(e), span, format!("{e}"))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,7 @@ pub fn flowctl(node: Node, kind: ShErrKind) -> ShResult<()> {
|
||||
let (arg, span) = argv.into_iter().next().unwrap();
|
||||
|
||||
let Ok(status) = arg.parse::<i32>() else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
format!("{cmd}: Expected a number"),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, span, format!("{cmd}: Expected a number")));
|
||||
};
|
||||
|
||||
code = status;
|
||||
|
||||
@@ -33,17 +33,13 @@ pub fn continue_job(node: Node, job: &mut JobBldr, behavior: JobBehavior) -> ShR
|
||||
let mut argv = argv.into_iter();
|
||||
|
||||
if read_jobs(|j| j.get_fg().is_some()) {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::InternalErr,
|
||||
format!("Somehow called '{}' with an existing foreground job", cmd),
|
||||
blame,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::InternalErr, blame, format!("Somehow called '{}' with an existing foreground job", cmd)));
|
||||
}
|
||||
|
||||
let curr_job_id = if let Some(id) = read_jobs(|j| j.curr_job()) {
|
||||
id
|
||||
} else {
|
||||
return Err(ShErr::full(ShErrKind::ExecFail, "No jobs found", blame));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, blame, "No jobs found"));
|
||||
};
|
||||
|
||||
let tabid = match argv.next() {
|
||||
@@ -57,11 +53,7 @@ pub fn continue_job(node: Node, job: &mut JobBldr, behavior: JobBehavior) -> ShR
|
||||
if query_result.is_some() {
|
||||
Ok(j.remove_job(id.clone()).unwrap())
|
||||
} else {
|
||||
Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("Job id `{}' not found", tabid),
|
||||
blame,
|
||||
))
|
||||
Err(ShErr::at(ShErrKind::ExecFail, blame.clone(), format!("Job id `{}' not found", tabid)))
|
||||
}
|
||||
})?;
|
||||
|
||||
@@ -96,11 +88,7 @@ fn parse_job_id(arg: &str, blame: Span) -> ShResult<usize> {
|
||||
});
|
||||
match result {
|
||||
Some(id) => Ok(id),
|
||||
None => Err(ShErr::full(
|
||||
ShErrKind::InternalErr,
|
||||
"Found a job but no table id in parse_job_id()",
|
||||
blame,
|
||||
)),
|
||||
None => Err(ShErr::at(ShErrKind::InternalErr, blame, "Found a job but no table id in parse_job_id()")),
|
||||
}
|
||||
}
|
||||
} else if arg.chars().all(|ch| ch.is_ascii_digit()) {
|
||||
@@ -120,18 +108,10 @@ fn parse_job_id(arg: &str, blame: Span) -> ShResult<usize> {
|
||||
|
||||
match result {
|
||||
Some(id) => Ok(id),
|
||||
None => Err(ShErr::full(
|
||||
ShErrKind::InternalErr,
|
||||
"Found a job but no table id in parse_job_id()",
|
||||
blame,
|
||||
)),
|
||||
None => Err(ShErr::at(ShErrKind::InternalErr, blame, "Found a job but no table id in parse_job_id()")),
|
||||
}
|
||||
} else {
|
||||
Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
format!("Invalid arg: {}", arg),
|
||||
blame,
|
||||
))
|
||||
Err(ShErr::at(ShErrKind::SyntaxErr, blame, format!("Invalid arg: {}", arg)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,11 +131,7 @@ pub fn jobs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
for (arg, span) in argv {
|
||||
let mut chars = arg.chars().peekable();
|
||||
if chars.peek().is_none_or(|ch| *ch != '-') {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
"Invalid flag in jobs call",
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, span, "Invalid flag in jobs call"));
|
||||
}
|
||||
chars.next();
|
||||
for ch in chars {
|
||||
@@ -166,11 +142,7 @@ pub fn jobs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
'r' => JobCmdFlags::RUNNING,
|
||||
's' => JobCmdFlags::STOPPED,
|
||||
_ => {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
"Invalid flag in jobs call",
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, span, "Invalid flag in jobs call"));
|
||||
}
|
||||
};
|
||||
flags |= flag
|
||||
@@ -199,11 +171,7 @@ pub fn disown(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult
|
||||
let curr_job_id = if let Some(id) = read_jobs(|j| j.curr_job()) {
|
||||
id
|
||||
} else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
"disown: No jobs to disown",
|
||||
blame,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, blame, "disown: No jobs to disown"));
|
||||
};
|
||||
|
||||
let mut tabid = curr_job_id;
|
||||
|
||||
@@ -22,11 +22,7 @@ pub fn shift(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
|
||||
if let Some((arg, span)) = argv.next() {
|
||||
let Ok(count) = arg.parse::<usize>() else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
"Expected a number in shift args",
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, span, "Expected a number in shift args"));
|
||||
};
|
||||
for _ in 0..count {
|
||||
write_vars(|v| v.cur_scope_mut().fpop_arg());
|
||||
|
||||
@@ -23,18 +23,10 @@ pub fn source(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
for (arg, span) in argv {
|
||||
let path = PathBuf::from(arg);
|
||||
if !path.exists() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("source: File '{}' not found", path.display()),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, span, format!("source: File '{}' not found", path.display())));
|
||||
}
|
||||
if !path.is_file() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("source: Given path '{}' is not a file", path.display()),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, span, format!("source: Given path '{}' is not a file", path.display())));
|
||||
}
|
||||
source_file(path)?;
|
||||
}
|
||||
|
||||
@@ -138,11 +138,7 @@ pub fn double_bracket_test(node: Node) -> ShResult<bool> {
|
||||
let operand = operand.expand()?.get_words().join(" ");
|
||||
conjunct_op = conjunct;
|
||||
let TestOp::Unary(op) = TestOp::from_str(operator.as_str())? else {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
"Invalid unary operator",
|
||||
err_span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, err_span, "Invalid unary operator"));
|
||||
};
|
||||
match op {
|
||||
UnaryOp::Exists => {
|
||||
@@ -245,11 +241,7 @@ pub fn double_bracket_test(node: Node) -> ShResult<bool> {
|
||||
let test_op = operator.as_str().parse::<TestOp>()?;
|
||||
match test_op {
|
||||
TestOp::Unary(_) => {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
"Expected a binary operator in this test call; found a unary operator",
|
||||
err_span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, err_span, "Expected a binary operator in this test call; found a unary operator"));
|
||||
}
|
||||
TestOp::StringEq => {
|
||||
let pattern = crate::expand::glob_to_regex(rhs.trim(), true);
|
||||
@@ -265,11 +257,7 @@ pub fn double_bracket_test(node: Node) -> ShResult<bool> {
|
||||
| TestOp::IntGe
|
||||
| TestOp::IntLe
|
||||
| TestOp::IntEq => {
|
||||
let err = ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
format!("Expected an integer with '{}' operator", operator),
|
||||
err_span.clone(),
|
||||
);
|
||||
let err = ShErr::at(ShErrKind::SyntaxErr, err_span.clone(), format!("Expected an integer with '{}' operator", operator));
|
||||
let Ok(lhs) = lhs.trim().parse::<i32>() else {
|
||||
return Err(err);
|
||||
};
|
||||
|
||||
@@ -75,20 +75,12 @@ pub fn unset(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
let argv = argv.unwrap();
|
||||
|
||||
if argv.is_empty() {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::SyntaxErr,
|
||||
"unset: Expected at least one argument",
|
||||
blame,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, blame, "unset: Expected at least one argument"));
|
||||
}
|
||||
|
||||
for (arg, span) in argv {
|
||||
if !read_vars(|v| v.var_exists(&arg)) {
|
||||
return Err(ShErr::full(
|
||||
ShErrKind::ExecFail,
|
||||
format!("unset: No such variable '{arg}'"),
|
||||
span,
|
||||
));
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, span, format!("unset: No such variable '{arg}'")));
|
||||
}
|
||||
write_vars(|v| v.unset_var(&arg))?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user