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