use std::path::Path;
use crate::theme::parsing::strip_inline_comment;
use crate::theme::types::{PackageMarker, Settings};
fn parse_bool(val: &str) -> bool {
let lv = val.to_ascii_lowercase();
lv == "true" || lv == "1" || lv == "yes" || lv == "on"
}
fn parse_layout_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"layout_left_pct" => {
if let Ok(v) = val.parse::<u16>() {
settings.layout_left_pct = v;
}
true
}
"layout_center_pct" => {
if let Ok(v) = val.parse::<u16>() {
settings.layout_center_pct = v;
}
true
}
"layout_right_pct" => {
if let Ok(v) = val.parse::<u16>() {
settings.layout_right_pct = v;
}
true
}
"main_pane_order" | "layout_main_pane_order" => {
if let Some(order) = crate::state::parse_main_pane_order(val) {
settings.main_pane_order = order;
} else {
tracing::warn!(
value = val,
"invalid main_pane_order (need three distinct tokens: results, search, package_info); keeping previous value"
);
}
true
}
"vertical_min_results" => {
if let Ok(v) = val.parse::<u16>() {
settings.vertical_min_results = v;
}
true
}
"vertical_max_results" => {
if let Ok(v) = val.parse::<u16>() {
settings.vertical_max_results = v;
}
true
}
"vertical_min_middle" | "vertical_min_search" => {
if let Ok(v) = val.parse::<u16>() {
settings.vertical_min_middle = v;
}
true
}
"vertical_max_middle" | "vertical_max_search" => {
if let Ok(v) = val.parse::<u16>() {
settings.vertical_max_middle = v;
}
true
}
"vertical_min_package_info" | "vertical_min_details" => {
if let Ok(v) = val.parse::<u16>() {
settings.vertical_min_package_info = v;
}
true
}
_ => false,
}
}
fn parse_app_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"app_dry_run_default" => {
settings.app_dry_run_default = parse_bool(val);
true
}
"sort_mode" | "results_sort" => {
if let Some(sm) = crate::state::SortMode::from_config_key(val) {
settings.sort_mode = sm;
}
true
}
"clipboard_suffix" | "copy_suffix" => {
settings.clipboard_suffix = val.to_string();
true
}
"show_search_history_pane" | "show_recent_pane" | "recent_visible" => {
settings.show_recent_pane = parse_bool(val);
true
}
"show_install_pane" | "install_visible" | "show_install_list" => {
settings.show_install_pane = parse_bool(val);
true
}
"show_keybinds_footer" | "keybinds_visible" => {
settings.show_keybinds_footer = parse_bool(val);
true
}
"package_marker" => {
let lv = val.to_ascii_lowercase();
settings.package_marker = match lv.as_str() {
"full" | "full_line" | "line" | "color_line" | "color" => PackageMarker::FullLine,
"end" | "suffix" => PackageMarker::End,
_ => PackageMarker::Front,
};
true
}
"skip_preflight" | "preflight_skip" | "bypass_preflight" => {
settings.skip_preflight = parse_bool(val);
true
}
_ => false,
}
}
fn parse_scan_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"scan_do_clamav" => {
settings.scan_do_clamav = parse_bool(val);
true
}
"scan_do_trivy" => {
settings.scan_do_trivy = parse_bool(val);
true
}
"scan_do_semgrep" => {
settings.scan_do_semgrep = parse_bool(val);
true
}
"scan_do_shellcheck" => {
settings.scan_do_shellcheck = parse_bool(val);
true
}
"scan_do_virustotal" => {
settings.scan_do_virustotal = parse_bool(val);
true
}
"scan_do_custom" => {
settings.scan_do_custom = parse_bool(val);
true
}
"scan_do_sleuth" => {
settings.scan_do_sleuth = parse_bool(val);
true
}
"pkgbuild_shellcheck_exclude"
| "pkgbuild_shellcheck_ignores"
| "shellcheck_pkgbuild_exclude" => {
settings.pkgbuild_shellcheck_exclude = val.to_string();
true
}
"pkgbuild_checks_show_raw_output"
| "pkgbuild_check_show_raw_output"
| "show_pkgbuild_checks_raw_output" => {
settings.pkgbuild_checks_show_raw_output = parse_bool(val);
true
}
"virustotal_api_key" | "vt_api_key" | "virustotal" => {
settings.virustotal_api_key = val.to_string();
true
}
_ => false,
}
}
fn parse_mirror_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"selected_countries" | "countries" | "country" => {
settings.selected_countries = val.to_string();
true
}
"mirror_count" | "mirrors" => {
if let Ok(v) = val.parse::<u16>() {
settings.mirror_count = v;
}
true
}
_ => false,
}
}
fn parse_news_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"news_read_symbol" | "news_read_mark" => {
settings.news_read_symbol = val.to_string();
true
}
"news_unread_symbol" | "news_unread_mark" => {
settings.news_unread_symbol = val.to_string();
true
}
"news_filter_show_arch_news" | "news_filter_arch" => {
settings.news_filter_show_arch_news = parse_bool(val);
true
}
"news_filter_show_advisories" | "news_filter_advisories" => {
settings.news_filter_show_advisories = parse_bool(val);
true
}
"news_filter_show_pkg_updates" | "news_filter_pkg_updates" | "news_filter_updates" => {
settings.news_filter_show_pkg_updates = parse_bool(val);
true
}
"news_filter_show_aur_updates"
| "news_filter_aur_updates"
| "news_filter_aur_upd"
| "news_filter_aur_upd_updates" => {
settings.news_filter_show_aur_updates = parse_bool(val);
true
}
"news_filter_show_aur_comments" | "news_filter_aur_comments" | "news_filter_comments" => {
settings.news_filter_show_aur_comments = parse_bool(val);
true
}
"news_filter_installed_only" | "news_filter_installed" | "news_installed_only" => {
settings.news_filter_installed_only = parse_bool(val);
true
}
"news_max_age_days" | "news_age_days" | "news_age" => {
let lv = val.trim().to_ascii_lowercase();
settings.news_max_age_days = match lv.as_str() {
"" | "all" | "none" | "unlimited" => None,
_ => val.parse::<u32>().ok(),
};
true
}
"startup_news_configured" => {
settings.startup_news_configured = parse_bool(val);
true
}
"startup_news_show_arch_news" => {
settings.startup_news_show_arch_news = parse_bool(val);
true
}
"startup_news_show_advisories" => {
settings.startup_news_show_advisories = parse_bool(val);
true
}
"startup_news_show_aur_updates" => {
settings.startup_news_show_aur_updates = parse_bool(val);
true
}
"startup_news_show_aur_comments" => {
settings.startup_news_show_aur_comments = parse_bool(val);
true
}
"startup_news_show_pkg_updates" => {
settings.startup_news_show_pkg_updates = parse_bool(val);
true
}
"startup_news_max_age_days" => {
let lv = val.trim().to_ascii_lowercase();
settings.startup_news_max_age_days = match lv.as_str() {
"" | "all" | "none" | "unlimited" => None,
_ => val.parse::<u32>().ok(),
};
true
}
"news_cache_ttl_days" => {
if let Ok(days) = val.parse::<u32>() {
settings.news_cache_ttl_days = days.max(1); }
true
}
_ => false,
}
}
fn parse_search_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"search_startup_mode" | "startup_mode" | "search_mode" => {
let lv = val.to_ascii_lowercase();
settings.search_startup_mode = lv == "true"
|| lv == "1"
|| lv == "yes"
|| lv == "on"
|| lv == "normal_mode"
|| lv == "normal";
true
}
"fuzzy_search" | "fuzzy_search_enabled" | "fuzzy_mode" => {
settings.fuzzy_search = parse_bool(val);
true
}
_ => false,
}
}
fn parse_aur_vote_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"aur_vote_enabled" | "aur_vote" => {
settings.aur_vote_enabled = parse_bool(val);
true
}
"aur_vote_ssh_timeout_seconds" | "aur_vote_ssh_timeout" | "aur_vote_timeout" => {
if let Ok(v) = val.parse::<u32>() {
settings.aur_vote_ssh_timeout_seconds = v.max(1);
}
true
}
"aur_vote_ssh_command" | "aur_vote_ssh" => {
settings.aur_vote_ssh_command = val.to_string();
true
}
_ => false,
}
}
fn parse_results_filter_dynamic(key: &str, val: &str, settings: &mut Settings) -> bool {
const PREFIX: &str = "results_filter_show_";
let Some(suffix) = key.strip_prefix(PREFIX) else {
return false;
};
if suffix.is_empty() {
return false;
}
settings
.results_filter_toggles
.insert(suffix.to_string(), parse_bool(val));
true
}
fn parse_misc_settings(key: &str, val: &str, settings: &mut Settings) -> bool {
match key {
"preferred_terminal" | "terminal_preferred" | "terminal" => {
settings.preferred_terminal = val.to_string();
true
}
"app_start_mode" | "start_mode" | "start_in_news" => {
let lv = val.trim().to_ascii_lowercase();
settings.start_in_news = matches!(lv.as_str(), "news" | "true" | "1" | "on" | "yes");
true
}
"locale" | "language" => {
settings.locale = val.trim().to_string();
true
}
"updates_refresh_interval" | "updates_interval" | "refresh_interval" => {
if let Ok(v) = val.parse::<u64>() {
settings.updates_refresh_interval = v.max(1);
}
true
}
"get_announcement" | "get_announcements" => {
settings.get_announcement = parse_bool(val.trim());
true
}
"installed_packages_mode" | "installed_mode" | "installed_filter" => {
if let Some(mode) = crate::state::InstalledPackagesMode::from_config_key(val) {
settings.installed_packages_mode = mode;
}
true
}
"use_passwordless_sudo" | "passwordless_sudo" | "allow_passwordless_sudo" => {
settings.use_passwordless_sudo = parse_bool(val);
true
}
"privilege_tool" | "privilege_mode" | "priv_tool" => {
if let Some(mode) = crate::logic::privilege::PrivilegeMode::from_config_key(val) {
settings.privilege_mode = mode;
}
true
}
"auth_mode" | "sudo_auth_mode" | "authentication_mode" => {
if let Some(mode) = crate::logic::privilege::AuthMode::from_config_key(val) {
settings.auth_mode = mode;
}
true
}
"use_terminal_theme" | "terminal_theme" => {
settings.use_terminal_theme = parse_bool(val);
true
}
_ => false,
}
}
pub fn parse_settings(content: &str, _settings_path: &Path, settings: &mut Settings) {
for line in content.lines() {
let trimmed = line.trim();
if trimmed.is_empty() || trimmed.starts_with('#') || trimmed.starts_with("//") {
continue;
}
if !trimmed.contains('=') {
continue;
}
let mut parts = trimmed.splitn(2, '=');
let raw_key = parts.next().unwrap_or("");
let key = raw_key.trim().to_lowercase().replace(['.', '-', ' '], "_");
let val_raw = parts.next().unwrap_or("").trim();
let val = strip_inline_comment(val_raw);
let _ = parse_layout_settings(&key, val, settings)
|| parse_app_settings(&key, val, settings)
|| parse_scan_settings(&key, val, settings)
|| parse_mirror_settings(&key, val, settings)
|| parse_news_settings(&key, val, settings)
|| parse_search_settings(&key, val, settings)
|| parse_aur_vote_settings(&key, val, settings)
|| parse_misc_settings(&key, val, settings)
|| parse_results_filter_dynamic(&key, val, settings);
}
}