2020-05-12 01:00:55 +00:00
|
|
|
use crate::commands::WholeStreamCommand;
|
2020-04-15 05:43:23 +00:00
|
|
|
use crate::context::CommandRegistry;
|
2020-05-20 17:31:04 +00:00
|
|
|
use crate::data::config;
|
2020-04-15 05:43:23 +00:00
|
|
|
use crate::prelude::*;
|
|
|
|
use nu_errors::ShellError;
|
2020-05-20 17:31:04 +00:00
|
|
|
use nu_protocol::{
|
|
|
|
hir::Block, CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
|
|
|
};
|
2020-04-27 02:04:54 +00:00
|
|
|
use nu_source::Tagged;
|
2020-04-15 05:43:23 +00:00
|
|
|
|
|
|
|
pub struct Alias;
|
|
|
|
|
2020-04-27 02:04:54 +00:00
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct AliasArgs {
|
|
|
|
pub name: Tagged<String>,
|
|
|
|
pub args: Vec<Value>,
|
|
|
|
pub block: Block,
|
2020-05-20 17:31:04 +00:00
|
|
|
pub save: Option<bool>,
|
2020-04-27 02:04:54 +00:00
|
|
|
}
|
|
|
|
|
2020-05-29 08:22:52 +00:00
|
|
|
#[async_trait]
|
2020-04-27 02:04:54 +00:00
|
|
|
impl WholeStreamCommand for Alias {
|
2020-04-15 05:43:23 +00:00
|
|
|
fn name(&self) -> &str {
|
|
|
|
"alias"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signature(&self) -> Signature {
|
|
|
|
Signature::build("alias")
|
|
|
|
.required("name", SyntaxShape::String, "the name of the alias")
|
|
|
|
.required("args", SyntaxShape::Table, "the arguments to the alias")
|
2020-05-09 17:16:14 +00:00
|
|
|
.required(
|
|
|
|
"block",
|
|
|
|
SyntaxShape::Block,
|
|
|
|
"the block to run as the body of the alias",
|
|
|
|
)
|
2020-05-20 17:31:04 +00:00
|
|
|
.switch("save", "save the alias to your config", Some('s'))
|
2020-04-15 05:43:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn usage(&self) -> &str {
|
2020-05-09 17:16:14 +00:00
|
|
|
"Define a shortcut for another command."
|
2020-04-15 05:43:23 +00:00
|
|
|
}
|
|
|
|
|
2020-05-29 08:22:52 +00:00
|
|
|
async fn run(
|
2020-04-15 05:43:23 +00:00
|
|
|
&self,
|
2020-04-27 02:04:54 +00:00
|
|
|
args: CommandArgs,
|
|
|
|
registry: &CommandRegistry,
|
2020-04-15 05:43:23 +00:00
|
|
|
) -> Result<OutputStream, ShellError> {
|
2020-06-12 08:34:41 +00:00
|
|
|
alias(args, registry).await
|
2020-04-15 05:43:23 +00:00
|
|
|
}
|
2020-05-11 20:05:44 +00:00
|
|
|
|
2020-05-18 12:56:01 +00:00
|
|
|
fn examples(&self) -> Vec<Example> {
|
|
|
|
vec![
|
2020-05-11 23:06:40 +00:00
|
|
|
Example {
|
|
|
|
description: "An alias without parameters",
|
|
|
|
example: "alias say-hi [] { echo 'Hello!' }",
|
2020-05-18 12:56:01 +00:00
|
|
|
result: None,
|
2020-05-11 23:06:40 +00:00
|
|
|
},
|
|
|
|
Example {
|
|
|
|
description: "An alias with a single parameter",
|
|
|
|
example: "alias l [x] { ls $x }",
|
2020-05-18 12:56:01 +00:00
|
|
|
result: None,
|
2020-05-11 23:06:40 +00:00
|
|
|
},
|
|
|
|
]
|
2020-05-11 20:05:44 +00:00
|
|
|
}
|
2020-04-15 05:43:23 +00:00
|
|
|
}
|
2020-04-27 02:04:54 +00:00
|
|
|
|
2020-06-12 08:34:41 +00:00
|
|
|
pub async fn alias(
|
|
|
|
args: CommandArgs,
|
|
|
|
registry: &CommandRegistry,
|
|
|
|
) -> Result<OutputStream, ShellError> {
|
2020-05-16 03:18:24 +00:00
|
|
|
let registry = registry.clone();
|
2020-06-12 08:34:41 +00:00
|
|
|
let mut raw_input = args.raw_input.clone();
|
|
|
|
let (
|
|
|
|
AliasArgs {
|
|
|
|
name,
|
|
|
|
args: list,
|
|
|
|
block,
|
|
|
|
save,
|
|
|
|
},
|
|
|
|
_ctx,
|
|
|
|
) = args.process(®istry).await?;
|
|
|
|
let mut processed_args: Vec<String> = vec![];
|
|
|
|
|
|
|
|
if let Some(true) = save {
|
|
|
|
let mut result = crate::data::config::read(name.clone().tag, &None)?;
|
|
|
|
|
|
|
|
// process the alias to remove the --save flag
|
|
|
|
let left_brace = raw_input.find('{').unwrap_or(0);
|
|
|
|
let right_brace = raw_input.rfind('}').unwrap_or_else(|| raw_input.len());
|
|
|
|
let left = raw_input[..left_brace]
|
|
|
|
.replace("--save", "")
|
|
|
|
.replace("-s", "");
|
|
|
|
let right = raw_input[right_brace..]
|
|
|
|
.replace("--save", "")
|
|
|
|
.replace("-s", "");
|
|
|
|
raw_input = format!("{}{}{}", left, &raw_input[left_brace..right_brace], right);
|
|
|
|
|
|
|
|
// create a value from raw_input alias
|
|
|
|
let alias: Value = raw_input.trim().to_string().into();
|
|
|
|
let alias_start = raw_input.find('[').unwrap_or(0); // used to check if the same alias already exists
|
|
|
|
|
|
|
|
// add to startup if alias doesn't exist and replce if it does
|
|
|
|
match result.get_mut("startup") {
|
|
|
|
Some(startup) => {
|
|
|
|
if let UntaggedValue::Table(ref mut commands) = startup.value {
|
|
|
|
if let Some(command) = commands.iter_mut().find(|command| {
|
|
|
|
let cmd_str = command.as_string().unwrap_or_default();
|
|
|
|
cmd_str.starts_with(&raw_input[..alias_start])
|
|
|
|
}) {
|
|
|
|
*command = alias;
|
|
|
|
} else {
|
|
|
|
commands.push(alias);
|
2020-05-20 17:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-12 08:34:41 +00:00
|
|
|
None => {
|
|
|
|
let table = UntaggedValue::table(&[alias]);
|
|
|
|
result.insert("startup".to_string(), table.into_value(Tag::default()));
|
|
|
|
}
|
2020-05-20 17:31:04 +00:00
|
|
|
}
|
2020-06-12 08:34:41 +00:00
|
|
|
config::write(&result, &None)?;
|
|
|
|
}
|
2020-05-20 17:31:04 +00:00
|
|
|
|
2020-06-12 08:34:41 +00:00
|
|
|
for item in list.iter() {
|
|
|
|
if let Ok(string) = item.as_string() {
|
|
|
|
processed_args.push(format!("${}", string));
|
|
|
|
} else {
|
|
|
|
return Err(ShellError::labeled_error(
|
|
|
|
"Expected a string",
|
|
|
|
"expected a string",
|
|
|
|
item.tag(),
|
|
|
|
));
|
2020-04-27 02:04:54 +00:00
|
|
|
}
|
2020-06-12 08:34:41 +00:00
|
|
|
}
|
2020-04-27 02:04:54 +00:00
|
|
|
|
2020-06-12 08:34:41 +00:00
|
|
|
Ok(OutputStream::one(ReturnSuccess::action(
|
|
|
|
CommandAction::AddAlias(name.to_string(), processed_args, block),
|
|
|
|
)))
|
2020-04-27 02:04:54 +00:00
|
|
|
}
|
2020-05-18 12:56:01 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::Alias;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn examples_work_as_expected() {
|
|
|
|
use crate::examples::test as test_examples;
|
|
|
|
|
|
|
|
test_examples(Alias {})
|
|
|
|
}
|
|
|
|
}
|