Add experimental support for flags in custom commands (#2808)

* Add experimental support for flags in custom commands

* clippy
This commit is contained in:
Jonathan Turner 2020-12-21 20:36:59 +13:00 committed by GitHub
parent 67acaae53c
commit c012d648fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 148 additions and 33 deletions

View File

@ -275,6 +275,39 @@ impl WholeStreamCommand for Block {
}
}
}
if let Some(args) = evaluated.args.named {
for named in &block.params.named {
let name = named.0;
if let Some(value) = args.get(name) {
if name.starts_with('$') {
ctx.scope.add_var(name, value.clone());
} else {
ctx.scope.add_var(format!("${}", name), value.clone());
}
} else if name.starts_with('$') {
ctx.scope
.add_var(name, UntaggedValue::nothing().into_untagged_value());
} else {
ctx.scope.add_var(
format!("${}", name),
UntaggedValue::nothing().into_untagged_value(),
);
}
}
} else {
for named in &block.params.named {
let name = named.0;
if name.starts_with('$') {
ctx.scope
.add_var(name, UntaggedValue::nothing().into_untagged_value());
} else {
ctx.scope.add_var(
format!("${}", name),
UntaggedValue::nothing().into_untagged_value(),
);
}
}
}
let result = run_block(&block, &ctx, input).await;
ctx.scope.exit_scope();
result.map(|x| x.to_output_stream())

View File

@ -173,6 +173,29 @@ impl LiteBlock {
Span::new(start, 0)
}
}
pub fn head(&self) -> Option<Spanned<String>> {
if let Some(group) = self.block.get(0) {
if let Some(pipeline) = group.pipelines.get(0) {
if let Some(command) = pipeline.commands.get(0) {
if let Some(head) = command.parts.get(0) {
return Some(head.clone());
}
}
}
}
None
}
pub fn remove_head(&mut self) {
if let Some(group) = self.block.get_mut(0) {
if let Some(pipeline) = group.pipelines.get_mut(0) {
if let Some(command) = pipeline.commands.get_mut(0) {
if !command.parts.is_empty() {
command.parts.remove(0);
}
}
}
}
}
}
#[derive(Clone, Copy)]

View File

@ -2027,36 +2027,76 @@ fn parse_signature(
Expression::Literal(Literal::String(st)) => {
let parts: Vec<_> = st.split(':').collect();
if parts.len() == 1 {
signature.positional.push((
PositionalType::Mandatory(parts[0].to_string(), SyntaxShape::Any),
String::new(),
));
if parts[0].starts_with("--") {
// Flag
let flagname = parts[0][2..].to_string();
signature
.named
.insert(flagname, (NamedType::Switch(None), String::new()));
} else {
// Positional
signature.positional.push((
PositionalType::Mandatory(parts[0].to_string(), SyntaxShape::Any),
String::new(),
));
}
} else if parts.len() == 2 {
let name = parts[0].to_string();
let shape = match parts[1] {
"int" => SyntaxShape::Int,
"string" => SyntaxShape::String,
"path" => SyntaxShape::Path,
"table" => SyntaxShape::Table,
"unit" => SyntaxShape::Unit,
"number" => SyntaxShape::Number,
"pattern" => SyntaxShape::Pattern,
"range" => SyntaxShape::Range,
"block" => SyntaxShape::Block,
"any" => SyntaxShape::Any,
_ => {
if err.is_none() {
err = Some(ParseError::mismatch(
"params with known types",
s.clone(),
));
if parts[0].starts_with("--") {
// Flag
let flagname = parts[0][2..].to_string();
let shape = match parts[1] {
"int" => SyntaxShape::Int,
"string" => SyntaxShape::String,
"path" => SyntaxShape::Path,
"table" => SyntaxShape::Table,
"unit" => SyntaxShape::Unit,
"number" => SyntaxShape::Number,
"pattern" => SyntaxShape::Pattern,
"range" => SyntaxShape::Range,
"block" => SyntaxShape::Block,
"any" => SyntaxShape::Any,
_ => {
if err.is_none() {
err = Some(ParseError::mismatch(
"params with known types",
s.clone(),
));
}
SyntaxShape::Any
}
SyntaxShape::Any
}
};
signature
.positional
.push((PositionalType::Mandatory(name, shape), String::new()));
};
signature.named.insert(
flagname,
(NamedType::Optional(None, shape), String::new()),
);
} else {
// Positional
let name = parts[0].to_string();
let shape = match parts[1] {
"int" => SyntaxShape::Int,
"string" => SyntaxShape::String,
"path" => SyntaxShape::Path,
"table" => SyntaxShape::Table,
"unit" => SyntaxShape::Unit,
"number" => SyntaxShape::Number,
"pattern" => SyntaxShape::Pattern,
"range" => SyntaxShape::Range,
"block" => SyntaxShape::Block,
"any" => SyntaxShape::Any,
_ => {
if err.is_none() {
err = Some(ParseError::mismatch(
"params with known types",
s.clone(),
));
}
SyntaxShape::Any
}
};
signature
.positional
.push((PositionalType::Mandatory(name, shape), String::new()));
}
} else if err.is_none() {
err = Some(ParseError::mismatch("param with type", s.clone()));
}
@ -2246,11 +2286,6 @@ pub fn classify_block(
}
}
// for def in scope.get_definitions() {
// let name = def.params.name.clone();
// output.definitions.insert(name, def.clone());
// }
(output, error)
}

View File

@ -344,6 +344,30 @@ fn run_custom_command() {
assert_eq!(actual.out, "15");
}
#[test]
fn run_custom_command_with_flag() {
let actual = nu!(
cwd: ".",
r#"
def foo [--bar:number] { if $(echo $bar | empty?) { echo "empty" } { echo $bar } }; foo --bar 10
"#
);
assert_eq!(actual.out, "10");
}
#[test]
fn run_custom_command_with_flag_missing() {
let actual = nu!(
cwd: ".",
r#"
def foo [--bar:number] { if $(echo $bar | empty?) { echo "empty" } { echo $bar } }; foo
"#
);
assert_eq!(actual.out, "empty");
}
#[test]
fn set_variable() {
let actual = nu!(