diff --git a/src/directory.rs b/src/directory.rs index 7547713..e5cc39d 100644 --- a/src/directory.rs +++ b/src/directory.rs @@ -80,6 +80,8 @@ impl Directory { } pub fn insert(&mut self, name: String, is_file: bool) { + self.selected_mut().expanded = true; + let current_depth = self.selected().depth; let depth = if self.selected().is_file { @@ -142,7 +144,7 @@ impl Directory { index..end } - + /// Get the current "subtree", where /// a subtree is the slice of `self.dirs` /// that are contained within the current @@ -322,8 +324,11 @@ impl Directory { KeyCode::End => { self.selection = u16::try_from(self.dirs.len()-1).unwrap_or(u16::MAX); if self.selection > self.display_start + self.height { - self.display_start = self.selection - self.height + self.display_start = self.selection - self.height; } + }, + KeyCode::Tab if !self.selected().is_file => { + self.selected_mut().expanded ^= true; } _ => (), } @@ -373,38 +378,57 @@ impl Directory { } fn display_lines(&self) -> impl Iterator + '_ { - self.dirs.iter().enumerate().scan( - Vec::new(), - |indent_parts, (i, current)| { - let is_last_at_this_depth = is_last_at_this_depth(&self.dirs[i+1..], current.depth); - let (new_part, continue_part) = if is_last_at_this_depth { - (TreePart::Last, TreePart::Blank) - } else { - (TreePart::First, TreePart::Wait) - }; + let scan_fn = |(indent_parts, unexpanded_depth): &mut (Vec, Option), (i, current): (usize, &Item)| -> Option { + if unexpanded_depth.is_some_and(|d| current.depth > d) { + return Some(String::new()); + } - if i == 0 { return Some(current.name.clone() + "/") } - + if current.expanded { + *unexpanded_depth = None; + } else { + *unexpanded_depth = Some(current.depth); + } + + let is_last_at_this_depth = is_last_at_this_depth(&self.dirs[i+1..], current.depth); + let (new_part, continue_part) = if is_last_at_this_depth { + (TreePart::Last, TreePart::Blank) + } else { + (TreePart::First, TreePart::Wait) + }; + + let mut result = if i == 0 { + String::new() + } else { if current.depth as usize > indent_parts.len() { indent_parts.push(continue_part); } else { indent_parts[current.depth as usize-1] = continue_part; } - let result = indent_parts[0 .. current.depth as usize - 1] - .iter() - .fold(String::new(), |result, t| result + t.display()) - + new_part.display() - + ¤t.name - + if current.is_file { - "" - } else { - "/" - }; + indent_parts[0 .. current.depth as usize - 1] + .iter() + .fold(String::new(), |result, t| result + t.display()) + + new_part.display() + }; - Some(result) + result += ¤t.name; + + if !current.is_file { + result += "/"; } - ) + if !current.expanded { + result += "..."; + }; + + Some(result) + }; + + let initial_state = (Vec::new(), None); + + self.dirs.iter() + .enumerate() + .scan(initial_state, scan_fn) + .filter(|s| !s.is_empty()) } }