Skip to content

Commit

Permalink
feat: implement alias (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfv authored Sep 10, 2024
1 parent 6227f71 commit 648cbd4
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 10 deletions.
11 changes: 11 additions & 0 deletions crates/deno_task_shell/src/shell/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<String>>();
}

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('!') {
Expand Down
31 changes: 27 additions & 4 deletions crates/deno_task_shell/src/shell/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String>,
/// The current working directory of the shell
cwd: PathBuf,
/// The commands that are available in the shell
commands: Rc<HashMap<String, Rc<dyn ShellCommand>>>,
/// A map of aliases for commands (e.g. `ll=ls -al`)
alias: HashMap<String, Vec<String>>,
/// Token to cancel execution.
token: CancellationToken,
/// Git repository handling.
Expand All @@ -51,6 +55,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(),
Expand All @@ -72,6 +77,10 @@ impl ShellState {
&self.cwd
}

pub fn alias_map(&self) -> &HashMap<String, Vec<String>> {
&self.alias
}

pub fn git_repository(&self) -> bool {
self.git_repository
}
Expand Down Expand Up @@ -131,7 +140,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
Expand Down Expand Up @@ -204,6 +213,15 @@ 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) => {
self.alias.remove(alias);
}
}
}

Expand Down Expand Up @@ -264,12 +282,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),
}

Expand Down
39 changes: 38 additions & 1 deletion crates/shell/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,48 @@
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);
Expand Down
20 changes: 15 additions & 5 deletions crates/shell/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,20 @@ mod completion;
mod helper;

fn commands() -> HashMap<String, Rc<dyn ShellCommand>> {
HashMap::from([(
"ls".to_string(),
Rc::new(commands::LsCommand) as Rc<dyn ShellCommand>,
)])
HashMap::from([
(
"ls".to_string(),
Rc::new(commands::LsCommand) as Rc<dyn ShellCommand>,
),
(
"alias".to_string(),
Rc::new(commands::AliasCommand) as Rc<dyn ShellCommand>,
),
(
"unalias".to_string(),
Rc::new(commands::AliasCommand) as Rc<dyn ShellCommand>,
),
])
}

async fn execute(text: &str, state: &mut ShellState) -> anyhow::Result<i32> {
Expand Down Expand Up @@ -48,8 +58,8 @@ async fn execute(text: &str, state: &mut ShellState) -> anyhow::Result<i32> {

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)
}
Expand Down

0 comments on commit 648cbd4

Please sign in to comment.