diff --git a/crates/deno_task_shell/src/shell/commands/args.rs b/crates/deno_task_shell/src/shell/commands/args.rs index d308500..bc687ef 100644 --- a/crates/deno_task_shell/src/shell/commands/args.rs +++ b/crates/deno_task_shell/src/shell/commands/args.rs @@ -1,7 +1,6 @@ // Copyright 2018-2024 the Deno authors. MIT license. -use anyhow::bail; -use anyhow::Result; +use anyhow::{bail, Context, Result}; #[derive(Debug, PartialEq, Eq)] pub enum ArgKind<'a> { @@ -11,7 +10,7 @@ pub enum ArgKind<'a> { } impl<'a> ArgKind<'a> { - pub fn bail_unsupported(&self) -> Result<()> { + pub fn bail_unsupported(&self) -> anyhow::Result<()> { match self { ArgKind::Arg(arg) => { bail!("unsupported argument: {}", arg) @@ -26,31 +25,41 @@ impl<'a> ArgKind<'a> { } } -pub fn parse_arg_kinds(flags: &[String]) -> Vec { +pub fn parse_arg_kinds( + flags: &mut [String], +) -> Result, anyhow::Error> { let mut result = Vec::new(); let mut had_dash_dash = false; - for arg in flags { + let home_str = dirs::home_dir() + .context("Couldn't get home directory")? + .to_string_lossy() + .into_owned(); + for arg in flags.iter_mut() { if had_dash_dash { + let arg_clone = arg.clone(); + arg.replace_range(.., &arg_clone.replace('~', &home_str)); result.push(ArgKind::Arg(arg)); } else if arg == "-" { result.push(ArgKind::Arg("-")); } else if arg == "--" { had_dash_dash = true; - } else if let Some(flag) = arg.strip_prefix("--") { - result.push(ArgKind::LongFlag(flag)); - } else if let Some(flags) = arg.strip_prefix('-') { - if flags.parse::().is_ok() { + } else if arg.starts_with("--") { + result.push(ArgKind::LongFlag(arg.strip_prefix("--").unwrap())); + } else if arg.starts_with('-') { + if arg.parse::().is_ok() { result.push(ArgKind::Arg(arg)); } else { - for c in flags.chars() { + for c in arg.strip_prefix('-').unwrap().chars() { result.push(ArgKind::ShortFlag(c)); } } } else { + let arg_clone = arg.clone(); + arg.replace_range(.., &arg_clone.replace('~', &home_str)); result.push(ArgKind::Arg(arg)); } } - result + Ok(result) } #[cfg(test)] @@ -60,7 +69,7 @@ mod test { #[test] fn parses() { - let data = vec![ + let mut data = vec![ "-f".to_string(), "-ab".to_string(), "--force".to_string(), @@ -72,9 +81,10 @@ mod test { "--test".to_string(), "-t".to_string(), ]; - let args = parse_arg_kinds(&data); + let args = parse_arg_kinds(&mut data); + assert!(args.is_ok()); assert_eq!( - args, + args.unwrap(), vec![ ArgKind::ShortFlag('f'), ArgKind::ShortFlag('a'), diff --git a/crates/deno_task_shell/src/shell/commands/cat.rs b/crates/deno_task_shell/src/shell/commands/cat.rs index 674fe33..ce29669 100644 --- a/crates/deno_task_shell/src/shell/commands/cat.rs +++ b/crates/deno_task_shell/src/shell/commands/cat.rs @@ -73,9 +73,9 @@ struct CatFlags { paths: Vec, } -fn parse_args(args: Vec) -> Result { +fn parse_args(mut args: Vec) -> Result { let mut paths = Vec::new(); - for arg in parse_arg_kinds(&args) { + for arg in parse_arg_kinds(&mut args)? { match arg { ArgKind::Arg(file_name) => { paths.push(file_name.to_string()); diff --git a/crates/deno_task_shell/src/shell/commands/cd.rs b/crates/deno_task_shell/src/shell/commands/cd.rs index b4e1c3a..fcf9af4 100644 --- a/crates/deno_task_shell/src/shell/commands/cd.rs +++ b/crates/deno_task_shell/src/shell/commands/cd.rs @@ -45,12 +45,7 @@ fn execute_cd(cwd: &Path, args: Vec) -> Result { args.push("~".to_string()); } let path = parse_args(args.clone())?; - let new_dir = if path == "~" { - dirs::home_dir() - .ok_or_else(|| anyhow::anyhow!("Home directory not found"))? - } else { - cwd.join(&path) - }; + let new_dir = cwd.join(&path); let new_dir = match new_dir.parse_dot() { Ok(path) => path.to_path_buf(), // fallback to canonicalize path just in case @@ -62,8 +57,8 @@ fn execute_cd(cwd: &Path, args: Vec) -> Result { Ok(new_dir) } -fn parse_args(args: Vec) -> Result { - let args = parse_arg_kinds(&args); +fn parse_args(mut args: Vec) -> Result { + let args = parse_arg_kinds(&mut args)?; let mut paths = Vec::new(); for arg in args { match arg { diff --git a/crates/deno_task_shell/src/shell/commands/cp_mv.rs b/crates/deno_task_shell/src/shell/commands/cp_mv.rs index 5647cfb..b1c1b01 100644 --- a/crates/deno_task_shell/src/shell/commands/cp_mv.rs +++ b/crates/deno_task_shell/src/shell/commands/cp_mv.rs @@ -133,10 +133,10 @@ struct CpFlags { operations: Vec<(PathWithSpecified, PathWithSpecified)>, } -fn parse_cp_args(cwd: &Path, args: Vec) -> Result { +fn parse_cp_args(cwd: &Path, mut args: Vec) -> Result { let mut paths = Vec::new(); let mut recursive = false; - for arg in parse_arg_kinds(&args) { + for arg in parse_arg_kinds(&mut args)? { match arg { ArgKind::Arg(arg) => { paths.push(arg); @@ -211,9 +211,9 @@ struct MvFlags { operations: Vec<(PathWithSpecified, PathWithSpecified)>, } -fn parse_mv_args(cwd: &Path, args: Vec) -> Result { +fn parse_mv_args(cwd: &Path, mut args: Vec) -> Result { let mut paths = Vec::new(); - for arg in parse_arg_kinds(&args) { + for arg in parse_arg_kinds(&mut args)? { match arg { ArgKind::Arg(arg) => { paths.push(arg); diff --git a/crates/deno_task_shell/src/shell/commands/exit.rs b/crates/deno_task_shell/src/shell/commands/exit.rs index 5222c61..7f87871 100644 --- a/crates/deno_task_shell/src/shell/commands/exit.rs +++ b/crates/deno_task_shell/src/shell/commands/exit.rs @@ -40,8 +40,8 @@ fn execute_exit(args: Vec) -> Result { }) } -fn parse_args(args: Vec) -> Result { - let args = parse_arg_kinds(&args); +fn parse_args(mut args: Vec) -> Result { + let args = parse_arg_kinds(&mut args)?; let mut paths = Vec::new(); for arg in args { match arg { diff --git a/crates/deno_task_shell/src/shell/commands/head.rs b/crates/deno_task_shell/src/shell/commands/head.rs index bef3a46..9ebf3da 100644 --- a/crates/deno_task_shell/src/shell/commands/head.rs +++ b/crates/deno_task_shell/src/shell/commands/head.rs @@ -113,10 +113,10 @@ struct HeadFlags { lines: u64, } -fn parse_args(args: Vec) -> Result { +fn parse_args(mut args: Vec) -> Result { let mut path: Option = None; let mut lines: Option = None; - let mut iterator = parse_arg_kinds(&args).into_iter(); + let mut iterator = parse_arg_kinds(&mut args)?.into_iter(); while let Some(arg) = iterator.next() { match arg { ArgKind::Arg(file_name) => { diff --git a/crates/deno_task_shell/src/shell/commands/mkdir.rs b/crates/deno_task_shell/src/shell/commands/mkdir.rs index 25636ca..b074fc9 100644 --- a/crates/deno_task_shell/src/shell/commands/mkdir.rs +++ b/crates/deno_task_shell/src/shell/commands/mkdir.rs @@ -70,10 +70,10 @@ struct MkdirFlags { paths: Vec, } -fn parse_args(args: Vec) -> Result { +fn parse_args(mut args: Vec) -> Result { let mut result = MkdirFlags::default(); - for arg in parse_arg_kinds(&args) { + for arg in parse_arg_kinds(&mut args)? { match arg { ArgKind::LongFlag("parents") | ArgKind::ShortFlag('p') => { result.parents = true; diff --git a/crates/deno_task_shell/src/shell/commands/pwd.rs b/crates/deno_task_shell/src/shell/commands/pwd.rs index 9da211c..c93dbc1 100644 --- a/crates/deno_task_shell/src/shell/commands/pwd.rs +++ b/crates/deno_task_shell/src/shell/commands/pwd.rs @@ -50,9 +50,9 @@ struct PwdFlags { logical: bool, } -fn parse_args(args: Vec) -> Result { +fn parse_args(mut args: Vec) -> Result { let mut logical = false; - for arg in parse_arg_kinds(&args) { + for arg in parse_arg_kinds(&mut args)? { match arg { ArgKind::ShortFlag('L') => { logical = true; diff --git a/crates/deno_task_shell/src/shell/commands/rm.rs b/crates/deno_task_shell/src/shell/commands/rm.rs index 72c1410..ed85fea 100644 --- a/crates/deno_task_shell/src/shell/commands/rm.rs +++ b/crates/deno_task_shell/src/shell/commands/rm.rs @@ -89,10 +89,10 @@ struct RmFlags { paths: Vec, } -fn parse_args(args: Vec) -> Result { +fn parse_args(mut args: Vec) -> Result { let mut result = RmFlags::default(); - for arg in parse_arg_kinds(&args) { + for arg in parse_arg_kinds(&mut args)? { match arg { ArgKind::LongFlag("recursive") | ArgKind::ShortFlag('r') diff --git a/crates/deno_task_shell/src/shell/commands/sleep.rs b/crates/deno_task_shell/src/shell/commands/sleep.rs index f1e68e6..89da117 100644 --- a/crates/deno_task_shell/src/shell/commands/sleep.rs +++ b/crates/deno_task_shell/src/shell/commands/sleep.rs @@ -69,11 +69,11 @@ fn parse_arg(arg: &str) -> Result { Ok(arg.parse()?) } -fn parse_args(args: Vec) -> Result { +fn parse_args(mut args: Vec) -> Result { // the time to sleep is the sum of all the arguments let mut total_time_ms = 0; let mut had_value = false; - for arg in parse_arg_kinds(&args) { + for arg in parse_arg_kinds(&mut args)? { match arg { ArgKind::Arg(arg) => match parse_arg(arg) { Ok(value_s) => { diff --git a/crates/deno_task_shell/src/shell/commands/xargs.rs b/crates/deno_task_shell/src/shell/commands/xargs.rs index 7ff01e1..9839f6d 100644 --- a/crates/deno_task_shell/src/shell/commands/xargs.rs +++ b/crates/deno_task_shell/src/shell/commands/xargs.rs @@ -130,7 +130,7 @@ struct XargsFlags { is_null_delimited: bool, } -fn parse_args(args: Vec) -> Result { +fn parse_args(mut args: Vec) -> Result { fn parse_delimiter(arg: &str) -> Result { let mut chars = arg.chars(); if let Some(first_char) = chars.next() { @@ -160,7 +160,7 @@ fn parse_args(args: Vec) -> Result { let mut initial_args = Vec::new(); let mut delimiter = None; - let mut iterator = parse_arg_kinds(&args).into_iter(); + let mut iterator = parse_arg_kinds(&mut args)?.into_iter(); let mut is_null_delimited = false; while let Some(arg) = iterator.next() { match arg { diff --git a/crates/shell/src/commands.rs b/crates/shell/src/commands.rs index 1467dda..432abcb 100644 --- a/crates/shell/src/commands.rs +++ b/crates/shell/src/commands.rs @@ -16,10 +16,18 @@ impl ShellCommand for LsCommand { fn execute_ls(context: ShellCommandContext) -> ExecuteResult { let mut args: Vec = vec![OsString::from("ls"), OsString::from("--color=auto")]; - context - .args - .iter() - .for_each(|arg| args.push(OsString::from(arg))); + context.args.iter().for_each(|arg| { + let expanded_arg = if arg.contains('~') { + if let Some(home_dir) = dirs::home_dir() { + arg.replace('~', home_dir.to_str().unwrap_or("~")) + } else { + arg.to_string() + } + } else { + arg.to_string() + }; + args.push(OsString::from(expanded_arg)); + }); let exit_code = uu_ls(args.into_iter()); ExecuteResult::from_exit_code(exit_code)