diff --git a/src/directory.rs b/src/directory.rs index 0fda929..a02fec5 100644 --- a/src/directory.rs +++ b/src/directory.rs @@ -92,7 +92,7 @@ impl Directory { } Ok(()) } - + fn delete(&self) -> Result<(), Error> { if self.selected().is_file { remove_file(self.path()) @@ -109,11 +109,11 @@ impl Directory { let idx = self.selection(); &mut self.dirs[idx] } - + pub const fn selection(&self) -> usize { self.selection as usize } - + pub fn update_navigation(&mut self, key: KeyCode) -> Result { match key { KeyCode::Char(c) => { @@ -191,6 +191,42 @@ impl Directory { Ok(Message::Nothing) } + fn display_lines(&self) -> impl Iterator + '_ { + let iter = self.dirs.iter().enumerate(); + + iter.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) + }; + + if i == 0 { return Some(current.name.to_owned() + "/") } + + 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 { + "\n" + } else { + "/\n" + }; + + Some(result) + } + ) + } } impl Pane for Directory { @@ -221,57 +257,7 @@ impl Pane for Directory { } fn display(&self, output: OutputSink, area: Rect) { - let mut iter = self.dirs.iter().enumerate(); - let Some((_, init)) = iter.by_ref() - .next() - else { return }; - - let mut indent_parts = Vec::new(); - let mut result = init.name.clone() + "/\n"; - - for (i, current) in iter { - // first, determine if there is another item at this depth. - // that decides what art we use - 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) - }; - - // setting indent_parts is important. - // indent_parts[i] is the indent for depth i, - // and it needs to be set to what we decided the `continue_part` - // needs to be. - // The if branch is for when we exceed the current depth and must - // add a new indent part. the else branch is when we already - // defined a branch at this point, and we do need to update it - // every time - // TODO: figure out why - if current.depth as usize > indent_parts.len() { - indent_parts.push(continue_part); - } else { - indent_parts[current.depth as usize-1] = continue_part; - } - - // I have inlined this to avoid making extra strings - // because I believe it is less efficient - indent_parts[0 .. current.depth as usize - 1] - .iter() - .copied() - .map(TreePart::display) - .for_each(|s| result += s); - - result.push_str(new_part.display()); - result.push_str(¤t.name); - if !current.is_file { - result.push('/'); - } - result.push('\n'); - } - - let rows = result - .lines() + let rows = self.display_lines() .enumerate() .map(|(i, s)| { let row = ListItem::new(s);