From 8a8644da48e2218ac7e1cacc83616912a5e2da2b Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Tue, 10 Sep 2024 09:30:30 -0400 Subject: [PATCH 1/2] implement alias --- crates/deno_task_shell/src/shell/execute.rs | 11 +++++++ crates/deno_task_shell/src/shell/types.rs | 32 ++++++++++++++++--- crates/shell/src/commands.rs | 35 ++++++++++++++++++++- crates/shell/src/main.rs | 20 +++++++++--- 4 files changed, 88 insertions(+), 10 deletions(-) diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index 62daa5d..773390b 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -643,8 +643,19 @@ fn execute_command_args( let command_name = if args.is_empty() { String::new() } else { + // check if the command name is in the alias hashmap + if let Some(value) = state.alias_map().get(&args[0]) { + args.remove(0); + args = value + .iter() + .chain(args.iter()) + .cloned() + .collect::>(); + } + args.remove(0) }; + if state.token().is_cancelled() { Box::pin(future::ready(ExecuteResult::for_cancellation())) } else if let Some(stripped_name) = command_name.strip_prefix('!') { diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index ec21772..c2b681f 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -27,8 +27,12 @@ pub struct ShellState { /// Variables that should be evaluated within the shell and /// not passed down to any sub commands. shell_vars: HashMap, + /// The current working directory of the shell cwd: PathBuf, + /// The commands that are available in the shell commands: Rc>>, + /// A map of aliases for commands (e.g. `ll=ls -al`) + alias: HashMap>, /// Token to cancel execution. token: CancellationToken, /// Git repository handling. @@ -50,6 +54,7 @@ impl ShellState { let mut result = Self { env_vars: Default::default(), shell_vars: Default::default(), + alias: Default::default(), cwd: PathBuf::new(), commands: Rc::new(commands), token: CancellationToken::default(), @@ -70,6 +75,10 @@ impl ShellState { &self.cwd } + pub fn alias_map(&self) -> &HashMap> { + &self.alias + } + pub fn git_repository(&self) -> bool { self.git_repository } @@ -121,7 +130,7 @@ impl ShellState { } } - // TODO: set_cwd() is being called twice + /// Set the current working directory of this shell pub fn set_cwd(&mut self, cwd: &Path) { self.cwd = cwd.to_path_buf(); // $PWD holds the current working directory, so we keep cwd and $PWD in sync @@ -194,6 +203,16 @@ impl ShellState { self.set_cwd(new_dir); self.last_command_cd = true; } + EnvChange::AliasCommand(alias, cmd) => { + self.alias.insert( + alias.clone(), + cmd.split_whitespace().map(ToString::to_string).collect(), + ); + }, + EnvChange::UnAliasCommand(alias) => { + println!("unalias {}", alias); + self.alias.remove(alias); + } } } @@ -254,12 +273,17 @@ impl ShellState { #[derive(Debug, PartialEq, Eq)] pub enum EnvChange { - // `export ENV_VAR=VALUE` + /// `export ENV_VAR=VALUE` SetEnvVar(String, String), - // `ENV_VAR=VALUE` + /// `ENV_VAR=VALUE` SetShellVar(String, String), - // `unset ENV_VAR` + /// Create an alias for a command (e.g. ll=ls -al) + AliasCommand(String, String), + /// Remove an alias + UnAliasCommand(String), + /// `unset ENV_VAR` UnsetVar(String), + /// Set the current working directory to the new Path Cd(PathBuf), } diff --git a/crates/shell/src/commands.rs b/crates/shell/src/commands.rs index 1467dda..ebb407f 100644 --- a/crates/shell/src/commands.rs +++ b/crates/shell/src/commands.rs @@ -1,11 +1,44 @@ use std::ffi::OsString; -use deno_task_shell::{ExecuteResult, ShellCommand, ShellCommandContext}; +use deno_task_shell::{EnvChange, ExecuteResult, ShellCommand, ShellCommandContext}; use futures::future::LocalBoxFuture; use uu_ls::uumain as uu_ls; pub struct LsCommand; +pub struct AliasCommand; + +pub struct UnAliasCommand; + +impl ShellCommand for AliasCommand { + fn execute(&self, context: ShellCommandContext) -> LocalBoxFuture<'static, ExecuteResult> { + if context.args.len() != 1 { + return Box::pin(futures::future::ready(ExecuteResult::from_exit_code(1))); + } + + // parse the args + let env_change = if let Some((alias, cmd)) = context.args[0].split_once("=") { + vec![EnvChange::AliasCommand(alias.into(), cmd.into())] + } else { + return Box::pin(futures::future::ready(ExecuteResult::from_exit_code(1))); + }; + + let result = ExecuteResult::Continue(0, env_change, Vec::default()); + Box::pin(futures::future::ready(result)) + } +} + +impl ShellCommand for UnAliasCommand { + fn execute(&self, context: ShellCommandContext) -> LocalBoxFuture<'static, ExecuteResult> { + if context.args.len() != 1 { + return Box::pin(futures::future::ready(ExecuteResult::from_exit_code(1))); + } + + let result = ExecuteResult::Continue(0, vec![EnvChange::UnAliasCommand(context.args[0].clone())], Vec::default()); + Box::pin(futures::future::ready(result)) + } +} + impl ShellCommand for LsCommand { fn execute(&self, context: ShellCommandContext) -> LocalBoxFuture<'static, ExecuteResult> { let result = execute_ls(context); diff --git a/crates/shell/src/main.rs b/crates/shell/src/main.rs index 454c464..69eb357 100644 --- a/crates/shell/src/main.rs +++ b/crates/shell/src/main.rs @@ -17,10 +17,20 @@ mod completion; mod helper; fn commands() -> HashMap> { - HashMap::from([( - "ls".to_string(), - Rc::new(commands::LsCommand) as Rc, - )]) + HashMap::from([ + ( + "ls".to_string(), + Rc::new(commands::LsCommand) as Rc, + ), + ( + "alias".to_string(), + Rc::new(commands::AliasCommand) as Rc, + ), + ( + "unalias".to_string(), + Rc::new(commands::AliasCommand) as Rc, + ), + ]) } async fn execute(text: &str, state: &mut ShellState) -> anyhow::Result { @@ -48,8 +58,8 @@ async fn execute(text: &str, state: &mut ShellState) -> anyhow::Result { match result { ExecuteResult::Continue(exit_code, changes, _) => { - state.apply_changes(&changes); // set CWD to the last command's CWD + state.apply_changes(&changes); std::env::set_current_dir(state.cwd()).context("Failed to set CWD")?; Ok(exit_code) } From 9b941d8882e98caae61dbf6ac426935593ca96dd Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Tue, 10 Sep 2024 13:53:45 -0700 Subject: [PATCH 2/2] fmt/clippy --- crates/deno_task_shell/src/shell/types.rs | 3 +-- crates/shell/src/commands.rs | 8 ++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index c2b681f..8906b16 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -208,9 +208,8 @@ impl ShellState { alias.clone(), cmd.split_whitespace().map(ToString::to_string).collect(), ); - }, + } EnvChange::UnAliasCommand(alias) => { - println!("unalias {}", alias); self.alias.remove(alias); } } diff --git a/crates/shell/src/commands.rs b/crates/shell/src/commands.rs index ebb407f..66c8f24 100644 --- a/crates/shell/src/commands.rs +++ b/crates/shell/src/commands.rs @@ -17,7 +17,7 @@ impl ShellCommand for AliasCommand { } // parse the args - let env_change = if let Some((alias, cmd)) = context.args[0].split_once("=") { + let env_change = if let Some((alias, cmd)) = context.args[0].split_once('=') { vec![EnvChange::AliasCommand(alias.into(), cmd.into())] } else { return Box::pin(futures::future::ready(ExecuteResult::from_exit_code(1))); @@ -34,7 +34,11 @@ impl ShellCommand for UnAliasCommand { return Box::pin(futures::future::ready(ExecuteResult::from_exit_code(1))); } - let result = ExecuteResult::Continue(0, vec![EnvChange::UnAliasCommand(context.args[0].clone())], Vec::default()); + let result = ExecuteResult::Continue( + 0, + vec![EnvChange::UnAliasCommand(context.args[0].clone())], + Vec::default(), + ); Box::pin(futures::future::ready(result)) } }