getargs-derive-macros 0.1.0

Internal implementation detail of getargs-derive. Not meant for direct use; depend on getargs-derive instead.
Documentation
use crate::model::{FieldKind, FieldModel};

pub(super) const ARGUMENTS: &str = "Arguments";
pub(super) const OPTIONS: &str = "Options";

pub(super) struct Section<'a> {
    pub(super) title: &'a str,
    pub(super) fields: Vec<&'a FieldModel>,
}

pub(super) fn sections(fields: &[FieldModel]) -> Vec<Section<'_>> {
    let mut sections: Vec<(Section, Vec<usize>)> = [ARGUMENTS, OPTIONS]
        .into_iter()
        .map(|title| {
            (
                Section {
                    title,
                    fields: Vec::new(),
                },
                Vec::new(),
            )
        })
        .collect();

    for (index, field) in fields.iter().enumerate().filter(|(_, field)| !field.hide) {
        let title = field.help_heading.as_deref().unwrap_or(match field.kind {
            FieldKind::Positional => ARGUMENTS,
            FieldKind::Flag(_) | FieldKind::Option => OPTIONS,
        });
        let position = match sections
            .iter()
            .position(|(section, _)| section.title == title)
        {
            Some(position) => position,
            None => {
                sections.push((
                    Section {
                        title,
                        fields: Vec::new(),
                    },
                    Vec::new(),
                ));
                sections.len() - 1
            }
        };
        let (section, orders) = &mut sections[position];
        section.fields.push(field);
        orders.push(field.display_order.unwrap_or(index));
    }

    sections
        .into_iter()
        .map(|(section, orders)| {
            let mut keyed: Vec<_> = orders.into_iter().zip(section.fields).collect();
            keyed.sort_by_key(|(order, _)| *order);
            Section {
                title: section.title,
                fields: keyed.into_iter().map(|(_, field)| field).collect(),
            }
        })
        .collect()
}