Change --eval
to print variable value only (#806)
This commit is contained in:
parent
b8a65149be
commit
09b370e10d
@ -375,20 +375,20 @@ impl Config {
|
||||
(false, false) => {},
|
||||
(true, false) => {
|
||||
return Err(ConfigError::SubcommandOverrides {
|
||||
subcommand: format!("--{}", subcommand.to_lowercase()),
|
||||
subcommand,
|
||||
overrides,
|
||||
});
|
||||
},
|
||||
(false, true) => {
|
||||
return Err(ConfigError::SubcommandArguments {
|
||||
subcommand: format!("--{}", subcommand.to_lowercase()),
|
||||
arguments: positional.arguments,
|
||||
subcommand,
|
||||
});
|
||||
},
|
||||
(true, true) => {
|
||||
return Err(ConfigError::SubcommandOverridesAndArguments {
|
||||
subcommand: format!("--{}", subcommand.to_lowercase()),
|
||||
arguments: positional.arguments,
|
||||
subcommand,
|
||||
overrides,
|
||||
});
|
||||
},
|
||||
@ -420,8 +420,19 @@ impl Config {
|
||||
name: name.to_owned(),
|
||||
}
|
||||
} else if matches.is_present(cmd::EVALUATE) {
|
||||
if positional.arguments.len() > 1 {
|
||||
return Err(ConfigError::SubcommandArguments {
|
||||
subcommand: cmd::EVALUATE,
|
||||
arguments: positional
|
||||
.arguments
|
||||
.into_iter()
|
||||
.skip(1)
|
||||
.collect::<Vec<String>>(),
|
||||
});
|
||||
}
|
||||
|
||||
Subcommand::Evaluate {
|
||||
variables: positional.arguments,
|
||||
variable: positional.arguments.into_iter().next(),
|
||||
overrides,
|
||||
}
|
||||
} else if matches.is_present(cmd::VARIABLES) {
|
||||
@ -811,7 +822,7 @@ impl Config {
|
||||
} else {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("Justfile does not contain recipe `{}`.", name);
|
||||
if let Some(suggestion) = justfile.suggest(name) {
|
||||
if let Some(suggestion) = justfile.suggest_recipe(name) {
|
||||
eprintln!("{}", suggestion);
|
||||
}
|
||||
}
|
||||
@ -1330,7 +1341,7 @@ ARGS:
|
||||
args: ["--evaluate"],
|
||||
subcommand: Subcommand::Evaluate {
|
||||
overrides: map!{},
|
||||
variables: vec![],
|
||||
variable: None,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1339,7 +1350,7 @@ ARGS:
|
||||
args: ["--evaluate", "x=y"],
|
||||
subcommand: Subcommand::Evaluate {
|
||||
overrides: map!{"x": "y"},
|
||||
variables: vec![],
|
||||
variable: None,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1348,7 +1359,7 @@ ARGS:
|
||||
args: ["--evaluate", "x=y", "foo"],
|
||||
subcommand: Subcommand::Evaluate {
|
||||
overrides: map!{"x": "y"},
|
||||
variables: vec!["foo".to_owned()],
|
||||
variable: Some("foo".to_owned()),
|
||||
},
|
||||
}
|
||||
|
||||
@ -1577,7 +1588,7 @@ ARGS:
|
||||
args: ["--completions", "zsh", "foo"],
|
||||
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--completions");
|
||||
assert_eq!(subcommand, cmd::COMPLETIONS);
|
||||
assert_eq!(arguments, &["foo"]);
|
||||
},
|
||||
}
|
||||
@ -1587,7 +1598,7 @@ ARGS:
|
||||
args: ["--list", "bar"],
|
||||
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--list");
|
||||
assert_eq!(subcommand, cmd::LIST);
|
||||
assert_eq!(arguments, &["bar"]);
|
||||
},
|
||||
}
|
||||
@ -1597,7 +1608,7 @@ ARGS:
|
||||
args: ["--dump", "bar"],
|
||||
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--dump");
|
||||
assert_eq!(subcommand, cmd::DUMP);
|
||||
assert_eq!(arguments, &["bar"]);
|
||||
},
|
||||
}
|
||||
@ -1607,7 +1618,7 @@ ARGS:
|
||||
args: ["--edit", "bar"],
|
||||
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--edit");
|
||||
assert_eq!(subcommand, cmd::EDIT);
|
||||
assert_eq!(arguments, &["bar"]);
|
||||
},
|
||||
}
|
||||
@ -1617,7 +1628,7 @@ ARGS:
|
||||
args: ["--init", "bar"],
|
||||
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--init");
|
||||
assert_eq!(subcommand, cmd::INIT);
|
||||
assert_eq!(arguments, &["bar"]);
|
||||
},
|
||||
}
|
||||
@ -1627,7 +1638,7 @@ ARGS:
|
||||
args: ["--show", "foo", "bar"],
|
||||
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--show");
|
||||
assert_eq!(subcommand, cmd::SHOW);
|
||||
assert_eq!(arguments, &["bar"]);
|
||||
},
|
||||
}
|
||||
@ -1637,7 +1648,7 @@ ARGS:
|
||||
args: ["--summary", "bar"],
|
||||
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--summary");
|
||||
assert_eq!(subcommand, cmd::SUMMARY);
|
||||
assert_eq!(arguments, &["bar"]);
|
||||
},
|
||||
}
|
||||
@ -1647,7 +1658,7 @@ ARGS:
|
||||
args: ["--summary", "bar=baz", "bar"],
|
||||
error: ConfigError::SubcommandOverridesAndArguments { subcommand, arguments, overrides },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--summary");
|
||||
assert_eq!(subcommand, cmd::SUMMARY);
|
||||
assert_eq!(overrides, map!{"bar": "baz"});
|
||||
assert_eq!(arguments, &["bar"]);
|
||||
},
|
||||
@ -1658,7 +1669,7 @@ ARGS:
|
||||
args: ["--summary", "bar=baz"],
|
||||
error: ConfigError::SubcommandOverrides { subcommand, overrides },
|
||||
check: {
|
||||
assert_eq!(subcommand, "--summary");
|
||||
assert_eq!(subcommand, cmd::SUMMARY);
|
||||
assert_eq!(overrides, map!{"bar": "baz"});
|
||||
},
|
||||
}
|
||||
|
@ -16,33 +16,33 @@ pub(crate) enum ConfigError {
|
||||
))]
|
||||
SearchDirConflict,
|
||||
#[snafu(display(
|
||||
"`{}` used with unexpected {}: {}",
|
||||
subcommand,
|
||||
"`--{}` used with unexpected {}: {}",
|
||||
subcommand.to_lowercase(),
|
||||
Count("argument", arguments.len()),
|
||||
List::and_ticked(arguments)
|
||||
))]
|
||||
SubcommandArguments {
|
||||
subcommand: String,
|
||||
subcommand: &'static str,
|
||||
arguments: Vec<String>,
|
||||
},
|
||||
#[snafu(display(
|
||||
"`{}` used with unexpected overrides: {}; and arguments: {}",
|
||||
subcommand,
|
||||
"`--{}` used with unexpected overrides: {}; and arguments: {}",
|
||||
subcommand.to_lowercase(),
|
||||
List::and_ticked(overrides.iter().map(|(key, value)| format!("{}={}", key, value))),
|
||||
List::and_ticked(arguments)))
|
||||
]
|
||||
SubcommandOverridesAndArguments {
|
||||
subcommand: String,
|
||||
subcommand: &'static str,
|
||||
overrides: BTreeMap<String, String>,
|
||||
arguments: Vec<String>,
|
||||
},
|
||||
#[snafu(display(
|
||||
"`{}` used with unexpected overrides: {}",
|
||||
subcommand,
|
||||
"`--{}` used with unexpected overrides: {}",
|
||||
subcommand.to_lowercase(),
|
||||
List::and_ticked(overrides.iter().map(|(key, value)| format!("{}={}", key, value))),
|
||||
))]
|
||||
SubcommandOverrides {
|
||||
subcommand: String,
|
||||
subcommand: &'static str,
|
||||
overrides: BTreeMap<String, String>,
|
||||
},
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ impl<'src> Justfile<'src> {
|
||||
self.recipes.len()
|
||||
}
|
||||
|
||||
pub(crate) fn suggest(&self, input: &str) -> Option<Suggestion> {
|
||||
pub(crate) fn suggest_recipe(&self, input: &str) -> Option<Suggestion> {
|
||||
let mut suggestions = self
|
||||
.recipes
|
||||
.keys()
|
||||
@ -54,6 +54,26 @@ impl<'src> Justfile<'src> {
|
||||
.next()
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_variable(&self, input: &str) -> Option<Suggestion> {
|
||||
let mut suggestions = self
|
||||
.assignments
|
||||
.keys()
|
||||
.map(|name| {
|
||||
(edit_distance(name, input), Suggestion {
|
||||
name,
|
||||
target: None,
|
||||
})
|
||||
})
|
||||
.filter(|(distance, _suggestion)| distance < &3)
|
||||
.collect::<Vec<(usize, Suggestion)>>();
|
||||
suggestions.sort_by_key(|(distance, _suggestion)| *distance);
|
||||
|
||||
suggestions
|
||||
.into_iter()
|
||||
.map(|(_distance, suggestion)| suggestion)
|
||||
.next()
|
||||
}
|
||||
|
||||
pub(crate) fn run<'run>(
|
||||
&'run self,
|
||||
config: &'run Config,
|
||||
@ -107,26 +127,24 @@ impl<'src> Justfile<'src> {
|
||||
)?
|
||||
};
|
||||
|
||||
if let Subcommand::Evaluate { variables, .. } = &config.subcommand {
|
||||
if let Subcommand::Evaluate { variable, .. } = &config.subcommand {
|
||||
if let Some(variable) = variable {
|
||||
if let Some(value) = scope.value(variable) {
|
||||
print!("{}", value);
|
||||
} else {
|
||||
return Err(RuntimeError::EvalUnknownVariable {
|
||||
suggestion: self.suggest_variable(&variable),
|
||||
variable: variable.to_owned(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let mut width = 0;
|
||||
|
||||
for name in scope.names() {
|
||||
if !variables.is_empty() && !variables.iter().any(|variable| variable == name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
width = cmp::max(name.len(), width);
|
||||
}
|
||||
|
||||
for binding in scope.bindings() {
|
||||
if !variables.is_empty()
|
||||
&& !variables
|
||||
.iter()
|
||||
.any(|variable| variable == binding.name.lexeme())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
println!(
|
||||
"{0:1$} := \"{2}\"",
|
||||
binding.name.lexeme(),
|
||||
@ -134,6 +152,7 @@ impl<'src> Justfile<'src> {
|
||||
binding.value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
@ -186,7 +205,7 @@ impl<'src> Justfile<'src> {
|
||||
|
||||
if !missing.is_empty() {
|
||||
let suggestion = if missing.len() == 1 {
|
||||
self.suggest(missing.first().unwrap())
|
||||
self.suggest_recipe(missing.first().unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -25,6 +25,10 @@ pub(crate) enum RuntimeError<'src> {
|
||||
Dotenv {
|
||||
dotenv_error: dotenv::Error,
|
||||
},
|
||||
EvalUnknownVariable {
|
||||
variable: String,
|
||||
suggestion: Option<Suggestion<'src>>,
|
||||
},
|
||||
FunctionCall {
|
||||
function: Name<'src>,
|
||||
message: String,
|
||||
@ -106,6 +110,15 @@ impl<'src> Display for RuntimeError<'src> {
|
||||
write!(f, "{}", message.prefix())?;
|
||||
|
||||
match self {
|
||||
EvalUnknownVariable {
|
||||
variable,
|
||||
suggestion,
|
||||
} => {
|
||||
write!(f, "Justfile does not contain variable `{}`.", variable,)?;
|
||||
if let Some(suggestion) = *suggestion {
|
||||
write!(f, "\n{}", suggestion)?;
|
||||
}
|
||||
},
|
||||
UnknownRecipes {
|
||||
recipes,
|
||||
suggestion,
|
||||
|
@ -13,7 +13,7 @@ pub(crate) enum Subcommand {
|
||||
Edit,
|
||||
Evaluate {
|
||||
overrides: BTreeMap<String, String>,
|
||||
variables: Vec<String>,
|
||||
variable: Option<String>,
|
||||
},
|
||||
Init,
|
||||
List,
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::common::*;
|
||||
|
||||
test! {
|
||||
name: evaluate,
|
||||
justfile: r#"
|
||||
@ -29,15 +31,49 @@ test! {
|
||||
}
|
||||
|
||||
test! {
|
||||
name: evaluate_arguments,
|
||||
name: evaluate_multiple,
|
||||
justfile: "
|
||||
a := 'x'
|
||||
b := 'y'
|
||||
c := 'z'
|
||||
",
|
||||
args: ("--evaluate", "a", "c"),
|
||||
stdout: r#"
|
||||
a := "x"
|
||||
c := "z"
|
||||
"#,
|
||||
stderr: "error: `--evaluate` used with unexpected argument: `c`\n",
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: evaluate_single,
|
||||
justfile: "
|
||||
a := 'x'
|
||||
b := 'y'
|
||||
c := 'z'
|
||||
",
|
||||
args: ("--evaluate", "b"),
|
||||
stdout: "y",
|
||||
}
|
||||
|
||||
test! {
|
||||
name: evaluate_no_suggestion,
|
||||
justfile: "
|
||||
abc := 'x'
|
||||
",
|
||||
args: ("--evaluate", "aby"),
|
||||
stderr: "
|
||||
error: Justfile does not contain variable `aby`.
|
||||
Did you mean `abc`?
|
||||
",
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: evaluate_suggestion,
|
||||
justfile: "
|
||||
hello := 'x'
|
||||
",
|
||||
args: ("--evaluate", "goodbye"),
|
||||
stderr: "
|
||||
error: Justfile does not contain variable `goodbye`.
|
||||
",
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user