#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum MainVerticalPane {
Results,
Middle,
PackageInfo,
}
pub const DEFAULT_MAIN_PANE_ORDER: [MainVerticalPane; 3] = [
MainVerticalPane::Results,
MainVerticalPane::Middle,
MainVerticalPane::PackageInfo,
];
impl MainVerticalPane {
#[must_use]
pub const fn as_config_token(self) -> &'static str {
match self {
Self::Results => "results",
Self::Middle => "search",
Self::PackageInfo => "package_info",
}
}
#[must_use]
pub fn from_config_token(token: &str) -> Option<Self> {
let t = token.trim().to_ascii_lowercase().replace(['-', ' '], "_");
match t.as_str() {
"results" => Some(Self::Results),
"search" | "middle" => Some(Self::Middle),
"package_info" | "details" | "packageinfo" => Some(Self::PackageInfo),
_ => None,
}
}
}
#[must_use]
pub fn parse_main_pane_order(value: &str) -> Option<[MainVerticalPane; 3]> {
let parts: Vec<&str> = value
.split(',')
.map(str::trim)
.filter(|s| !s.is_empty())
.collect();
if parts.len() != 3 {
return None;
}
let mut seen = [false; 3];
let mut out = [MainVerticalPane::Results; 3];
for (i, part) in parts.iter().enumerate() {
let role = MainVerticalPane::from_config_token(part)?;
let idx = match role {
MainVerticalPane::Results => 0usize,
MainVerticalPane::Middle => 1usize,
MainVerticalPane::PackageInfo => 2usize,
};
if seen[idx] {
return None;
}
seen[idx] = true;
out[i] = role;
}
Some(out)
}
#[must_use]
pub fn format_main_pane_order(order: &[MainVerticalPane; 3]) -> String {
format!(
"{}, {}, {}",
order[0].as_config_token(),
order[1].as_config_token(),
order[2].as_config_token()
)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct VerticalLayoutLimits {
pub min_results: u16,
pub max_results: u16,
pub min_middle: u16,
pub max_middle: u16,
pub min_package_info: u16,
}
impl Default for VerticalLayoutLimits {
fn default() -> Self {
Self {
min_results: 3,
max_results: 17,
min_middle: 3,
max_middle: 5,
min_package_info: 3,
}
}
}
impl VerticalLayoutLimits {
#[must_use]
pub const fn from_u16s(
min_results: u16,
max_results: u16,
min_middle: u16,
max_middle: u16,
min_package_info: u16,
) -> Self {
Self {
min_results,
max_results,
min_middle,
max_middle,
min_package_info,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_order_default_tokens() {
let o = parse_main_pane_order("results, search, package_info").expect("parse");
assert_eq!(o, DEFAULT_MAIN_PANE_ORDER);
}
#[test]
fn parse_order_aliases_and_permutation() {
let o = parse_main_pane_order("package_info,middle,results").expect("parse");
assert_eq!(
o,
[
MainVerticalPane::PackageInfo,
MainVerticalPane::Middle,
MainVerticalPane::Results
]
);
}
#[test]
fn parse_order_rejects_duplicates_and_bad_length() {
assert!(parse_main_pane_order("results,results,middle").is_none());
assert!(parse_main_pane_order("results,middle").is_none());
assert!(parse_main_pane_order("a,b,c").is_none());
}
}