Compare commits

..

2 Commits

Author SHA1 Message Date
nick 9c8a5e9348 refactored display for decoupling 2024-10-05 20:58:12 -04:00
nick f4a3a46c71 slightly better error handling in main 2024-10-05 20:57:44 -04:00
2 changed files with 51 additions and 59 deletions

View File

@ -191,6 +191,42 @@ impl Directory {
Ok(Message::Nothing)
}
fn display_lines(&self) -> impl Iterator<Item = String> + '_ {
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()
+ &current.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(&current.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);

View File

@ -14,7 +14,7 @@ use terminal::Terminal;
use pane::prelude::*;
use std::fs::{remove_file, OpenOptions};
use std::io::Error;
use std::io::{Error, ErrorKind};
use anyhow::{Result as AnyResult, Error as AnyError};
use clap::Parser;
@ -32,16 +32,22 @@ fn main() -> AnyResult<()> {
.create_new(true)
.open(LOG_FILE)
.map_err(|e| {
<Error as Into<AnyError>>::into(e).context(LOG_FILE).context(LOG_EXISTS_MSG)
let kind = e.kind();
let result = AnyError::from(e).context(LOG_FILE);
if kind == ErrorKind::AlreadyExists {
result.context(LOG_EXISTS_MSG)
} else {
result
}
})?;
let _redirect = Redirect::stderr(target)?;
do_tui(args)?;
let result = do_tui(args);
remove_file(LOG_FILE)?;
Ok(())
result.map_err(Into::into)
}
fn do_tui(args: Args) -> Result<(), Error> {