Elide paths in explorer tabs if they are too long

This commit is contained in:
ChristianVisintin
2020-12-10 09:22:58 +01:00
parent 95ab3daa86
commit 98e3866447
3 changed files with 67 additions and 32 deletions

View File

@@ -12,7 +12,10 @@ Work in progress
- enhancements: - enhancements:
- password prompt: ask before performing terminal clear - password prompt: ask before performing terminal clear
- file explorer: file names are now sorted ignoring capital letters - file explorer:
- file names are now sorted ignoring capital letters
- file names longer than 23, are now cut to 20 and followed by `...`
- paths which exceed tab size in explorer are elided with the following formato `ANCESTOR[1]/.../PARENT/DIRNAME`
- bugfix: - bugfix:
- prevent panic in set_progress, for progress values `> 100.0 or < 0.0` - prevent panic in set_progress, for progress values `> 100.0 or < 0.0`

View File

@@ -178,11 +178,7 @@ impl std::fmt::Display for FsEntry {
write!( write!(
f, f,
"{:24}\t{:12}\t{:12}\t{:9}\t{:17}", "{:24}\t{:12}\t{:12}\t{:9}\t{:17}",
dir_name, dir_name, mode, username, size, datetime
mode,
username,
size,
datetime
) )
} }
FsEntry::File(file) => { FsEntry::File(file) => {
@@ -273,11 +269,7 @@ impl std::fmt::Display for FsEntry {
write!( write!(
f, f,
"{:24}\t{:12}\t{:12}\t{:9}\t{:17}", "{:24}\t{:12}\t{:12}\t{:9}\t{:17}",
file_name, file_name, mode, username, size, datetime
mode,
username,
size,
datetime
) )
} }
} }
@@ -372,11 +364,7 @@ impl std::fmt::Display for FsEntry {
write!( write!(
f, f,
"{:24}\t{:12}\t{:12}\t{:9}\t{:17}", "{:24}\t{:12}\t{:12}\t{:9}\t{:17}",
dir_name, dir_name, mode, username, size, datetime
mode,
username,
size,
datetime
) )
} }
FsEntry::File(file) => { FsEntry::File(file) => {
@@ -461,11 +449,7 @@ impl std::fmt::Display for FsEntry {
write!( write!(
f, f,
"{:24}\t{:12}\t{:12}\t{:9}\t{:17}", "{:24}\t{:12}\t{:12}\t{:9}\t{:17}",
file_name, file_name, mode, username, size, datetime
mode,
username,
size,
datetime
) )
} }
} }

View File

@@ -25,7 +25,7 @@ use super::{
Context, DialogYesNoOption, FileExplorerTab, FileTransferActivity, FsEntry, InputField, Context, DialogYesNoOption, FileExplorerTab, FileTransferActivity, FsEntry, InputField,
InputMode, LogLevel, LogRecord, PopupType, InputMode, LogLevel, LogRecord, PopupType,
}; };
use std::path::PathBuf; use std::path::{Path, PathBuf};
use tui::{ use tui::{
layout::{Constraint, Corner, Direction, Layout, Rect}, layout::{Constraint, Corner, Direction, Layout, Rect},
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
@@ -67,7 +67,7 @@ impl FileTransferActivity {
remote_state.select(Some(self.remote.index)); remote_state.select(Some(self.remote.index));
// Draw tabs // Draw tabs
f.render_stateful_widget( f.render_stateful_widget(
self.draw_local_explorer(local_wrkdir), self.draw_local_explorer(local_wrkdir, tabs_chunks[0].width),
tabs_chunks[0], tabs_chunks[0],
&mut localhost_state, &mut localhost_state,
); );
@@ -77,7 +77,7 @@ impl FileTransferActivity {
Err(_) => PathBuf::from("/"), Err(_) => PathBuf::from("/"),
}; };
f.render_stateful_widget( f.render_stateful_widget(
self.draw_remote_explorer(remote_wrkdir), self.draw_remote_explorer(remote_wrkdir, tabs_chunks[1].width),
tabs_chunks[1], tabs_chunks[1],
&mut remote_state, &mut remote_state,
); );
@@ -141,7 +141,7 @@ impl FileTransferActivity {
/// ### draw_local_explorer /// ### draw_local_explorer
/// ///
/// Draw local explorer list /// Draw local explorer list
pub(super) fn draw_local_explorer(&self, local_wrkdir: PathBuf) -> List { pub(super) fn draw_local_explorer(&self, local_wrkdir: PathBuf, width: u16) -> List {
let hostname: String = match hostname::get() { let hostname: String = match hostname::get() {
Ok(h) => String::from(h.as_os_str().to_string_lossy()), Ok(h) => String::from(h.as_os_str().to_string_lossy()),
Err(_) => String::from("localhost"), Err(_) => String::from("localhost"),
@@ -163,7 +163,16 @@ impl FileTransferActivity {
}, },
_ => Style::default(), _ => Style::default(),
}) })
.title(format!("{}:{} ", hostname, local_wrkdir.display())), .title(format!(
"{}:{} ",
hostname,
FileTransferActivity::elide_wrkdir_path(
local_wrkdir.as_path(),
hostname.as_str(),
width
)
.display()
)),
) )
.start_corner(Corner::TopLeft) .start_corner(Corner::TopLeft)
.highlight_style( .highlight_style(
@@ -176,7 +185,7 @@ impl FileTransferActivity {
/// ### draw_remote_explorer /// ### draw_remote_explorer
/// ///
/// Draw remote explorer list /// Draw remote explorer list
pub(super) fn draw_remote_explorer(&self, remote_wrkdir: PathBuf) -> List { pub(super) fn draw_remote_explorer(&self, remote_wrkdir: PathBuf, width: u16) -> List {
let files: Vec<ListItem> = self let files: Vec<ListItem> = self
.remote .remote
.files .files
@@ -197,7 +206,12 @@ impl FileTransferActivity {
.title(format!( .title(format!(
"{}:{} ", "{}:{} ",
self.params.address, self.params.address,
remote_wrkdir.display() FileTransferActivity::elide_wrkdir_path(
remote_wrkdir.as_path(),
self.params.address.as_str(),
width
)
.display()
)), )),
) )
.start_corner(Corner::TopLeft) .start_corner(Corner::TopLeft)
@@ -305,7 +319,7 @@ impl FileTransferActivity {
let mut lines: Vec<ListItem> = Vec::new(); let mut lines: Vec<ListItem> = Vec::new();
for msg in message_rows.iter() { for msg in message_rows.iter() {
lines.push(ListItem::new(Spans::from( lines.push(ListItem::new(Spans::from(
self.align_text_center(msg, width), FileTransferActivity::align_text_center(msg, width),
))); )));
} }
List::new(lines) List::new(lines)
@@ -328,7 +342,7 @@ impl FileTransferActivity {
let mut lines: Vec<ListItem> = Vec::new(); let mut lines: Vec<ListItem> = Vec::new();
for msg in message_rows.iter() { for msg in message_rows.iter() {
lines.push(ListItem::new(Spans::from( lines.push(ListItem::new(Spans::from(
self.align_text_center(msg, width), FileTransferActivity::align_text_center(msg, width),
))); )));
} }
List::new(lines) List::new(lines)
@@ -386,7 +400,7 @@ impl FileTransferActivity {
let mut lines: Vec<ListItem> = Vec::new(); let mut lines: Vec<ListItem> = Vec::new();
for msg in message_rows.iter() { for msg in message_rows.iter() {
lines.push(ListItem::new(Spans::from( lines.push(ListItem::new(Spans::from(
self.align_text_center(msg, width), FileTransferActivity::align_text_center(msg, width),
))); )));
} }
List::new(lines) List::new(lines)
@@ -590,7 +604,7 @@ impl FileTransferActivity {
/// align_text_center /// align_text_center
/// ///
/// Align text to center for a given width /// Align text to center for a given width
fn align_text_center(&self, text: &str, width: u16) -> String { fn align_text_center(text: &str, width: u16) -> String {
let indent_size: usize = match (width as usize) >= text.len() { let indent_size: usize = match (width as usize) >= text.len() {
// NOTE: The check prevents underflow // NOTE: The check prevents underflow
true => (width as usize - text.len()) / 2, true => (width as usize - text.len()) / 2,
@@ -601,4 +615,38 @@ impl FileTransferActivity {
(0..indent_size).map(|_| " ").collect::<String>().as_str(), (0..indent_size).map(|_| " ").collect::<String>().as_str(),
) )
} }
/// ### elide_wrkdir_path
///
/// Elide working directory path if longer than width + host.len
/// In this case, the path is formatted to {ANCESTOR[0]}/.../{PARENT[0]}/{BASENAME}
fn elide_wrkdir_path(wrkdir: &Path, host: &str, width: u16) -> PathBuf {
let fmt_path: String = format!("{}", wrkdir.display());
// NOTE: +5 is const
match fmt_path.len() + host.len() + 5 > width as usize {
false => PathBuf::from(wrkdir),
true => {
// Elide
let ancestors_len: usize = wrkdir.ancestors().count();
let mut ancestors = wrkdir.ancestors();
let mut elided_path: PathBuf = PathBuf::new();
// If ancestors_len's size is bigger than 2, push count - 2
if ancestors_len > 2 {
elided_path.push(ancestors.nth(ancestors_len - 2).unwrap());
}
// If ancestors_len is bigger than 3, push '...' and parent too
if ancestors_len > 3 {
elided_path.push("...");
if let Some(parent) = wrkdir.ancestors().nth(1) {
elided_path.push(parent.file_name().unwrap());
}
}
// Push file_name
if let Some(name) = wrkdir.file_name() {
elided_path.push(name);
}
elided_path
}
}
}
} }