cargo-port 0.2.1

A TUI for inspecting and managing Rust projects
use crate::project::ProjectFields;
use crate::project::RootItem;
use crate::project::RustProject;
use crate::tui;
use crate::tui::app::App;
use crate::tui::app::VisibleRow;
use crate::tui::panes::DetailPaneData;

impl App {
    /// Build per-pane data for the currently selected row, resolving through
    /// the `project_list_items` hierarchy.
    pub(super) fn build_selected_pane_data(&self) -> Option<DetailPaneData> {
        let row = self.project_list.selected_row()?;
        match row {
            VisibleRow::Root { node_index } => {
                let item = self.project_list.get(node_index)?;
                Some(tui::panes::build_pane_data(self, item))
            },
            VisibleRow::Member {
                node_index,
                group_index,
                member_index,
            } => {
                let item = self.project_list.get(node_index)?;
                let pkg = item.resolve_member(group_index, member_index)?;
                Some(tui::panes::build_pane_data_for_member(self, pkg))
            },
            VisibleRow::MemberVendored {
                node_index,
                group_index,
                member_index,
                vendored_index,
            } => self.build_member_vendored_detail(
                node_index,
                group_index,
                member_index,
                vendored_index,
            ),
            VisibleRow::Vendored {
                node_index,
                vendored_index,
            } => {
                let item = self.project_list.get(node_index)?;
                let vendored = item.resolve_vendored(vendored_index)?;
                Some(tui::panes::build_pane_data_for_vendored(self, vendored))
            },
            VisibleRow::GroupHeader { node_index, .. } => {
                // Group headers show the parent project's detail
                let item = self.project_list.get(node_index)?;
                Some(tui::panes::build_pane_data(self, item))
            },
            VisibleRow::WorktreeEntry {
                node_index,
                worktree_index,
            }
            | VisibleRow::WorktreeGroupHeader {
                node_index,
                worktree_index,
                ..
            } => {
                let item = self.project_list.get(node_index)?;
                self.build_worktree_detail(item, worktree_index)
            },
            VisibleRow::WorktreeMember {
                node_index,
                worktree_index,
                group_index,
                member_index,
            } => self.build_worktree_member_detail(
                node_index,
                worktree_index,
                group_index,
                member_index,
            ),
            VisibleRow::WorktreeMemberVendored {
                node_index,
                worktree_index,
                group_index,
                member_index,
                vendored_index,
            } => self.build_worktree_member_vendored_detail(
                node_index,
                worktree_index,
                group_index,
                member_index,
                vendored_index,
            ),
            VisibleRow::WorktreeVendored {
                node_index,
                worktree_index,
                vendored_index,
            } => self.build_worktree_vendored_detail(node_index, worktree_index, vendored_index),
            VisibleRow::Submodule {
                node_index,
                submodule_index,
            } => {
                let item = self.project_list.get(node_index)?;
                let submodule = item.submodules().get(submodule_index)?;
                Some(tui::panes::build_pane_data_for_submodule(self, submodule))
            },
        }
    }

    fn build_member_vendored_detail(
        &self,
        node_index: usize,
        group_index: usize,
        member_index: usize,
        vendored_index: usize,
    ) -> Option<DetailPaneData> {
        let item = self.project_list.get(node_index)?;
        let vendored = item.resolve_member_vendored(group_index, member_index, vendored_index)?;
        Some(tui::panes::build_pane_data_for_vendored(self, vendored))
    }

    /// Build pane data for a worktree entry (a linked workspace or package).
    fn build_worktree_detail(
        &self,
        item: &RootItem,
        worktree_index: usize,
    ) -> Option<DetailPaneData> {
        match item {
            RootItem::Worktrees(group) => match group.entry(worktree_index)? {
                RustProject::Workspace(ws) => {
                    let display_path = ws.display_path();
                    Some(tui::panes::build_pane_data_for_workspace_ref(
                        self,
                        ws,
                        display_path.as_str(),
                    ))
                },
                RustProject::Package(pkg) => {
                    Some(tui::panes::build_pane_data_for_member(self, pkg))
                },
            },
            _ => None,
        }
    }

    fn build_worktree_member_detail(
        &self,
        node_index: usize,
        worktree_index: usize,
        group_index: usize,
        member_index: usize,
    ) -> Option<DetailPaneData> {
        let item = self.project_list.get(node_index)?;
        let RootItem::Worktrees(worktree_group) = &**item else {
            return None;
        };
        let pkg = worktree_group.member_ref(worktree_index, group_index, member_index)?;
        Some(tui::panes::build_pane_data_for_member(self, pkg))
    }

    fn build_worktree_member_vendored_detail(
        &self,
        node_index: usize,
        worktree_index: usize,
        group_index: usize,
        member_index: usize,
        vendored_index: usize,
    ) -> Option<DetailPaneData> {
        let item = self.project_list.get(node_index)?;
        let RootItem::Worktrees(worktree_group) = &**item else {
            return None;
        };
        let vendored = worktree_group.member_vendored_ref(
            worktree_index,
            group_index,
            member_index,
            vendored_index,
        )?;
        Some(tui::panes::build_pane_data_for_vendored(self, vendored))
    }

    fn build_worktree_vendored_detail(
        &self,
        node_index: usize,
        worktree_index: usize,
        vendored_index: usize,
    ) -> Option<DetailPaneData> {
        let item = self.project_list.get(node_index)?;
        let RootItem::Worktrees(worktree_group) = &**item else {
            return None;
        };
        let vendored = worktree_group.vendored_ref(worktree_index, vendored_index)?;
        Some(tui::panes::build_pane_data_for_vendored(self, vendored))
    }
}