1use crate::{
2 graph::{Item, ItemType},
3 parser::SmartLogParser,
4};
5
6#[derive(Debug)]
7pub struct SmartLog {
8 pub items: Vec<ItemType>,
9 selection_idx: usize,
10}
11
12impl SmartLog {
13 pub fn new(raw_lines: &[String]) -> Self {
14 let items = SmartLogParser::parse(raw_lines).unwrap();
15 let selection_idx = Self::get_selected_item_index(&items).unwrap();
16 Self {
17 items,
18 selection_idx,
19 }
20 }
21
22 pub fn get_selected_commit_hash(&self) -> Option<&str> {
23 let item = self.items.get(self.selection_idx).unwrap();
24 if let ItemType::Commit(commit) = item {
25 return commit.hash();
26 }
27 None
28 }
29
30 pub fn move_up(&mut self) {
31 if self.selection_idx > 0 {
32 let mut selection_candidate = self.selection_idx;
33 for i in (0..self.selection_idx).rev() {
34 if let ItemType::Commit(_) = self.items[i] {
35 selection_candidate = i;
36 break;
37 }
38 }
39 if selection_candidate == self.selection_idx {
40 return;
41 }
42
43 self.deselect_line_idx(self.selection_idx);
44 self.select_line_index(selection_candidate);
45 }
46 }
47
48 pub fn move_down(&mut self) {
49 if self.selection_idx < self.items.len() - 1 {
50 let mut selection_candidate = self.selection_idx;
51 for i in (self.selection_idx + 1)..self.items.len() {
52 if let ItemType::Commit(_) = self.items[i] {
53 selection_candidate = i;
54 break;
55 }
56 }
57 if selection_candidate == self.selection_idx {
58 return;
59 }
60
61 self.deselect_line_idx(self.selection_idx);
62 self.select_line_index(selection_candidate);
63 }
64 }
65
66 pub fn to_string_vec(&self) -> Vec<String> {
67 self.items
68 .iter()
69 .flat_map(|item| item.to_string_vec())
70 .collect()
71 }
72
73 pub fn select_line_index(&mut self, item_idx: usize) {
74 let item = self.items.get_mut(item_idx).unwrap();
75 if let ItemType::Commit(commit) = item {
76 commit.select();
77 self.selection_idx = item_idx;
78 }
79 }
80
81 pub fn deselect_line_idx(&mut self, item_idx: usize) {
82 let item = self.items.get_mut(item_idx).unwrap();
83 if let ItemType::Commit(commit) = item {
84 commit.deselect();
85 }
86 }
87
88 fn get_selected_item_index(items: &[ItemType]) -> Option<usize> {
89 for (idx, item) in items.iter().enumerate() {
90 if let ItemType::Commit(commit) = item {
91 if commit.selected {
92 return Some(idx);
93 }
94 }
95 }
96 None
97 }
98}