new: give wizard select labels their own separator
CI / build (push) Failing after 2m47s
CI / test (push) Skipped
CI / snap (push) Skipped

This commit is contained in:
2026-09-16 14:01:23 +02:00
parent 9b98f5c7c3
commit 9228ff448b
+38 -9
View File
@@ -51,6 +51,26 @@ pub const KNOWN_LICENSES: [&str; 9] = [
"ISC",
];
/// Labels of the interactive `select` questions. `prompt::select` renders
/// `> <label><answer>` verbatim — unlike [`prompt::text`], it appends no
/// formatting of its own — so each label carries its own separator:
/// field-style prompts end with `": "`, question-style ones with `"? "`.
const LANGUAGE_LABEL: &str = "Which language/build system is your program using? ";
const SOURCE_LABEL: &str = "Where is the source code? ";
const LICENSE_LABEL: &str = "License: ";
const DIST_LABEL: &str = "Target distribution: ";
const SERIES_LABEL: &str = "Target series: ";
/// All select labels, so the separator test can check them in one place.
#[cfg(test)]
const SELECT_LABELS: [&str; 5] = [
LANGUAGE_LABEL,
SOURCE_LABEL,
LICENSE_LABEL,
DIST_LABEL,
SERIES_LABEL,
];
/// Run the `pkh new` flow: the wizard on an interactive terminal, plain
/// [`options::resolve`] otherwise (and with `--defaults`).
pub async fn run(cli: NewCli) -> Result<NewOptions, Box<dyn Error>> {
@@ -154,7 +174,7 @@ async fn run_wizard(mut cli: NewCli) -> Result<NewOptions, Box<dyn Error>> {
} else {
SOURCE_HERE
};
let answer = select_from("Where is the source code?", &options, default, |answer| {
let answer = select_from(SOURCE_LABEL, &options, default, |answer| {
options.contains(&answer.to_string())
})?;
if answer == SOURCE_HERE {
@@ -234,7 +254,7 @@ async fn run_wizard(mut cli: NewCli) -> Result<NewOptions, Box<dyn Error>> {
.or_else(|| detect::sniff_license(&detect_dir));
let (default, custom_default) = license_question_default(detected.as_deref());
let options = license_menu();
let answer = select_from("License", &options, &default, |answer| {
let answer = select_from(LICENSE_LABEL, &options, &default, |answer| {
options.contains(&answer.to_string())
})?;
if answer == LICENSE_OTHER {
@@ -304,7 +324,7 @@ async fn run_wizard(mut cli: NewCli) -> Result<NewOptions, Box<dyn Error>> {
} else {
"ubuntu".to_string()
};
let answer = select_from("Target distribution", &options, &default, |answer| {
let answer = select_from(DIST_LABEL, &options, &default, |answer| {
answer == "ubuntu" || answer == "debian"
})?;
cli.dist = Some(answer);
@@ -318,7 +338,7 @@ async fn run_wizard(mut cli: NewCli) -> Result<NewOptions, Box<dyn Error>> {
if cli.series.is_none() {
match crate::distro_info::get_ordered_series_name(&dist).await {
Ok(series) if !series.is_empty() => {
let answer = prompt::select("Target series", &series, &series[0])?;
let answer = prompt::select(SERIES_LABEL, &series, &series[0])?;
cli.series = Some(answer);
}
_ => {
@@ -552,11 +572,7 @@ fn license_question_default(probe_license: Option<&str>) -> (String, String) {
/// identifier) is answered — the selector allows typing arbitrary text.
fn select_template(options: &[String], default: &str) -> Result<TemplateId, Box<dyn Error>> {
loop {
let answer = prompt::select(
"Which language/build system is your program using?",
options,
default,
)?;
let answer = prompt::select(LANGUAGE_LABEL, options, default)?;
match TemplateId::from_label(&answer) {
Some(id) => return Ok(id),
None => log::warn!(
@@ -945,4 +961,17 @@ mod tests {
assert!(required_answer("x")("").is_err());
assert!(required_answer("x")("ok").is_ok());
}
#[test]
fn select_labels_carry_their_own_separator() {
// prompt::select renders `> <label><answer>` verbatim; a label
// without a trailing separator glues the answer to the prompt
// (regression: the wizard once rendered "> LicenseMIT").
for label in SELECT_LABELS {
assert!(
label.ends_with(": ") || label.ends_with("? "),
"select label {label:?} lacks a trailing separator"
);
}
}
}