[+] CLI for selecting multiple flags at random (#487)

This commit is contained in:
2026-04-07 16:13:17 +00:00
parent b05d9c44b4
commit cc5d7570fb
+88 -35
View File
@@ -633,7 +633,7 @@ fn create_config(
); );
printc( printc(
format!( format!(
"Which {preset_default_colored} do you want to use? (default: {})", "Which {preset_default_colored} do you want to use? (default: {}, comma-separated for multiple at random)",
Preset::Rainbow.as_ref() Preset::Rainbow.as_ref()
), ),
color_mode, color_mode,
@@ -643,12 +643,12 @@ fn create_config(
io::stdout().flush().context("failed to flush preset prompt")?; io::stdout().flush().context("failed to flush preset prompt")?;
if let Some(hint) = hint { if let Some(hint) = hint {
println!("{hint}"); println!("\n{hint}");
} }
Ok(()) Ok(())
}; };
let preset: Preset; let selected_preset_names: Vec<String>;
let color_profile; let color_profile;
let mut page: usize = 0; let mut page: usize = 0;
@@ -660,7 +660,9 @@ fn create_config(
.disable() .disable()
.context("failed to disable raw mode for rendering")?; .context("failed to disable raw mode for rendering")?;
let filter_lower = filter.to_ascii_lowercase(); let filter_lower = filter.to_ascii_lowercase();
let filtered_indices = filter_flag_indices(&filter_lower, &flags); let parts: Vec<&str> = filter_lower.split(',').collect();
let current_query = parts.last().cloned().unwrap_or("");
let filtered_indices = filter_flag_indices(current_query, &flags);
let num_pages = filtered_indices.len().div_ceil(flags_per_page).max(1); let num_pages = filtered_indices.len().div_ceil(flags_per_page).max(1);
page = page.min(num_pages - 1); page = page.min(num_pages - 1);
@@ -681,13 +683,37 @@ fn create_config(
match key.code { match key.code {
KeyCode::Enter => { KeyCode::Enter => {
let selection = flags let filter_lower = filter.to_ascii_lowercase();
.iter() let parts: Vec<&str> = filter_lower.split(',').map(|s| s.trim()).filter(|s| !s.is_empty()).collect();
.find(|(_, _, name)| *name == filter_lower) let mut resolved_presets = Vec::new();
.map(|(preset, _, _)| *preset)
.or_else(|| filtered_indices.first().map(|&idx| flags[idx].0)); if parts.is_empty() {
preset = selection.unwrap_or(Preset::Rainbow); // Default to Rainbow if nothing is entered
resolved_presets.push(Preset::Rainbow.as_ref().to_owned());
} else {
for part in parts.iter() {
let selection = flags
.iter()
.find(|(_, _, name)| name == part)
.map(|(preset, _, _)| preset.as_ref().to_owned())
.or_else(|| {
// Fuzzy match each part
let filtered = filter_flag_indices(part, &flags);
filtered.first().map(|&idx| flags[idx].0.as_ref().to_owned())
});
if let Some(p) = selection {
resolved_presets.push(p);
} else {
hint = Some("One or more presets could not be found.");
}
}
}
if hint.is_none() {
selected_preset_names = resolved_presets;
break; break;
}
}, },
KeyCode::Up => { KeyCode::Up => {
page = (page + num_pages - 1) % num_pages; page = (page + num_pages - 1) % num_pages;
@@ -724,30 +750,57 @@ fn create_config(
.disable() .disable()
.context("failed to disable raw mode after preset selection")?; .context("failed to disable raw mode after preset selection")?;
debug!(?preset, "selected preset"); let selected_presets = if selected_preset_names.len() > 1 {
color_profile = preset.color_profile(); PresetValue::Multiple(selected_preset_names.clone())
update_title( } else {
&mut title, PresetValue::Single(selected_preset_names.first().cloned().unwrap_or_else(|| Preset::Rainbow.as_ref().to_owned()))
&mut option_counter, };
"Selected flag",
&color_profile color_profile = {
.with_lightness_adaptive(default_lightness, theme) let first_name = selected_preset_names.first().cloned().unwrap_or_else(|| Preset::Rainbow.as_ref().to_owned());
.color_text( if first_name.contains('#') {
preset.as_ref(), let colors: Vec<String> = first_name.split(',').map(|s| s.trim().to_owned()).collect();
color_mode, build_hex_color_profile(&colors).expect("hex colors should be valid")
ForegroundBackground::Foreground, } else {
false, flags.iter().find(|(_, _, name)| name == &first_name).map(|(p, _, _)| p.color_profile()).unwrap_or_else(|| Preset::Rainbow.color_profile())
) }
.expect("coloring text with selected preset should not fail"), };
);
printc( {
format!( let colored_names = selected_preset_names.iter().map(|name| {
"Which {preset_default_colored} do you want to use? {}\n", let profile = if name.contains('#') {
preset.as_ref() let colors: Vec<String> = name.split(',').map(|s| s.trim().to_owned()).collect();
), build_hex_color_profile(&colors).expect("hex colors should be valid")
color_mode, } else {
) flags.iter().find(|(_, _, n)| n == name).map(|(p, _, _)| p.color_profile()).unwrap_or_else(|| Preset::Rainbow.color_profile())
.context("failed to print preset selection summary")?; };
profile.with_lightness_adaptive(default_lightness, theme)
.color_text(name, color_mode, ForegroundBackground::Foreground, false)
.expect("coloring text should not fail")
}).join(", ");
let label = if selected_preset_names.len() > 1 {
"Selected flags (random)"
} else {
"Selected flag"
};
update_title(
&mut title,
&mut option_counter,
label,
&colored_names,
);
printc(
format!(
"Which {preset_default_colored} do you want to use? {}\n",
colored_names
),
color_mode,
)
.context("failed to print preset selection summary")?;
}
////////////////////////////// //////////////////////////////
// 4. Dim/lighten colors // 4. Dim/lighten colors
@@ -1227,7 +1280,7 @@ fn create_config(
// Create config // Create config
clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?; clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?;
let config = Config { let config = Config {
preset: PresetValue::from(preset.as_ref().to_string()), preset: selected_presets,
mode: color_mode, mode: color_mode,
light_dark: Some(theme), light_dark: Some(theme),
auto_detect_light_dark: Some(det_bg.is_some()), auto_detect_light_dark: Some(det_bg.is_some()),