mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Elide paths in explorer tabs if they are too long
This commit is contained in:
@@ -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`
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user