Compare commits
2 Commits
5d62329e42
...
9c8a5e9348
Author | SHA1 | Date |
---|---|---|
nick | 9c8a5e9348 | |
nick | f4a3a46c71 |
|
@ -191,6 +191,42 @@ impl Directory {
|
||||||
Ok(Message::Nothing)
|
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()
|
||||||
|
+ ¤t.name
|
||||||
|
+ if current.is_file {
|
||||||
|
"\n"
|
||||||
|
} else {
|
||||||
|
"/\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(result)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pane for Directory {
|
impl Pane for Directory {
|
||||||
|
@ -221,57 +257,7 @@ impl Pane for Directory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display(&self, output: OutputSink, area: Rect) {
|
fn display(&self, output: OutputSink, area: Rect) {
|
||||||
let mut iter = self.dirs.iter().enumerate();
|
let rows = self.display_lines()
|
||||||
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()
|
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, s)| {
|
.map(|(i, s)| {
|
||||||
let row = ListItem::new(s);
|
let row = ListItem::new(s);
|
||||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -14,7 +14,7 @@ use terminal::Terminal;
|
||||||
use pane::prelude::*;
|
use pane::prelude::*;
|
||||||
|
|
||||||
use std::fs::{remove_file, OpenOptions};
|
use std::fs::{remove_file, OpenOptions};
|
||||||
use std::io::Error;
|
use std::io::{Error, ErrorKind};
|
||||||
|
|
||||||
use anyhow::{Result as AnyResult, Error as AnyError};
|
use anyhow::{Result as AnyResult, Error as AnyError};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
@ -32,16 +32,22 @@ fn main() -> AnyResult<()> {
|
||||||
.create_new(true)
|
.create_new(true)
|
||||||
.open(LOG_FILE)
|
.open(LOG_FILE)
|
||||||
.map_err(|e| {
|
.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)?;
|
let _redirect = Redirect::stderr(target)?;
|
||||||
|
|
||||||
do_tui(args)?;
|
let result = do_tui(args);
|
||||||
|
|
||||||
remove_file(LOG_FILE)?;
|
remove_file(LOG_FILE)?;
|
||||||
|
|
||||||
Ok(())
|
result.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_tui(args: Args) -> Result<(), Error> {
|
fn do_tui(args: Args) -> Result<(), Error> {
|
||||||
|
|
Loading…
Reference in New Issue