use crate::tui::component::ClideComponent; use anyhow::Result; use ratatui::buffer::Buffer; use ratatui::layout::{Alignment, Rect}; use ratatui::prelude::Style; use ratatui::style::Color; use ratatui::widgets::{Block, Borders, Widget}; use std::fs; use tui_tree_widget::{Tree, TreeItem}; use uuid::Uuid; #[derive(Clone, Debug)] pub struct Explorer<'a> { root_path: &'a std::path::Path, tree_items: TreeItem<'a, String>, } impl<'a> Explorer<'a> { pub fn new(path: &'a std::path::Path) -> Self { let explorer = Explorer { root_path: path, tree_items: Self::build_tree_from_path(path.into()), }; explorer } fn build_tree_from_path(path: std::path::PathBuf) -> TreeItem<'static, String> { let mut children = vec![]; if let Ok(entries) = fs::read_dir(&path) { let mut paths = entries .map(|res| res.map(|e| e.path())) .collect::, std::io::Error>>() .expect(""); paths.sort(); for path in paths { if path.is_dir() { children.push(Self::build_tree_from_path(path)); } else { children.push(TreeItem::new_leaf( Uuid::new_v4().to_string(), path.file_name().unwrap().to_string_lossy().to_string(), )); } } } TreeItem::new( Uuid::new_v4().to_string(), path.file_name() .unwrap_or_default() .to_string_lossy() .to_string(), children, ) .expect("Failed to build tree from path.") } } impl<'a> Widget for &Explorer<'a> { fn render(self, area: Rect, buf: &mut Buffer) { Tree::new(&self.tree_items.children()) .expect("Failed to build tree.") .style(Style::default()) .block( Block::default() .borders(Borders::ALL) .title( self.root_path .file_name() .expect("Failed to get file name from path.") .to_string_lossy(), ) .title_style(Style::default().fg(Color::Green)) .title_alignment(Alignment::Center), ) .render(area, buf); } } impl<'a> ClideComponent for Explorer<'a> {}