ratatui_toolkit/widgets/code_diff/extensions/file_tree/methods/
add_file.rs1use crate::primitives::tree_view::TreeNode;
4use crate::widgets::code_diff::diff_file_tree::DiffFileEntry;
5use crate::widgets::code_diff::diff_file_tree::DiffFileTree;
6use crate::widgets::code_diff::diff_file_tree::FileStatus;
7
8impl DiffFileTree {
9 pub fn add_file(&mut self, path: &str, status: FileStatus) {
16 let parts: Vec<&str> = path.split('/').collect();
17
18 if parts.is_empty() {
19 return;
20 }
21
22 if parts.len() == 1 {
23 let entry = DiffFileEntry::file(parts[0], path, status);
25 self.nodes.push(TreeNode::new(entry));
26 } else {
27 let root_dir = parts[0];
29
30 let dir_idx = self
32 .nodes
33 .iter()
34 .position(|n| n.data.is_dir && n.data.name == root_dir);
35
36 if let Some(idx) = dir_idx {
37 add_to_directory(&mut self.nodes[idx], &parts[1..], path, status, root_dir);
39 } else {
40 let mut dir_node = TreeNode::with_children(
42 DiffFileEntry::directory(root_dir, root_dir),
43 Vec::new(),
44 );
45 add_to_directory(&mut dir_node, &parts[1..], path, status, root_dir);
46 self.nodes.push(dir_node);
47 }
48 }
49
50 self.nodes.sort_by(|a, b| {
52 let a_is_dir = a.data.is_dir;
53 let b_is_dir = b.data.is_dir;
54 match (a_is_dir, b_is_dir) {
55 (true, false) => std::cmp::Ordering::Less,
56 (false, true) => std::cmp::Ordering::Greater,
57 _ => a.data.name.to_lowercase().cmp(&b.data.name.to_lowercase()),
58 }
59 });
60 }
61}
62
63fn add_to_directory(
65 node: &mut TreeNode<DiffFileEntry>,
66 remaining_parts: &[&str],
67 full_path: &str,
68 status: FileStatus,
69 current_path: &str,
70) {
71 if remaining_parts.is_empty() {
72 return;
73 }
74
75 if remaining_parts.len() == 1 {
76 let file_name = remaining_parts[0];
78 let entry = DiffFileEntry::file(file_name, full_path, status);
79 node.children.push(TreeNode::new(entry));
80 node.expandable = true;
81 } else {
82 let subdir_name = remaining_parts[0];
84 let subdir_path = format!("{}/{}", current_path, subdir_name);
85
86 let subdir_idx = node
88 .children
89 .iter()
90 .position(|n| n.data.is_dir && n.data.name == subdir_name);
91
92 if let Some(idx) = subdir_idx {
93 add_to_directory(
94 &mut node.children[idx],
95 &remaining_parts[1..],
96 full_path,
97 status,
98 &subdir_path,
99 );
100 } else {
101 let mut subdir_node = TreeNode::with_children(
102 DiffFileEntry::directory(subdir_name, &subdir_path),
103 Vec::new(),
104 );
105 add_to_directory(
106 &mut subdir_node,
107 &remaining_parts[1..],
108 full_path,
109 status,
110 &subdir_path,
111 );
112 node.children.push(subdir_node);
113 node.expandable = true;
114 }
115 }
116
117 node.children.sort_by(|a, b| {
119 let a_is_dir = a.data.is_dir;
120 let b_is_dir = b.data.is_dir;
121 match (a_is_dir, b_is_dir) {
122 (true, false) => std::cmp::Ordering::Less,
123 (false, true) => std::cmp::Ordering::Greater,
124 _ => a.data.name.to_lowercase().cmp(&b.data.name.to_lowercase()),
125 }
126 });
127}