summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2020-12-15 11:20:35 -0500
committerJiayi Zhao <jeff.no.zhao@gmail.com>2020-12-15 11:20:35 -0500
commitf5902708a6e597064482edfc076248a67882b7c5 (patch)
tree40e97ad84d157bbc670edb97c328ff988f8c8aa6
parent2b29f8485e95fd3cda434ed472992fff2ee8e7a0 (diff)
folder view now always prefix file names with a space
- remove horizontal margins in folder view - move copy/cut methods into separate functions - change some fields to private
-rw-r--r--src/commands/set_mode.rs4
-rw-r--r--src/fs/dirlist.rs2
-rw-r--r--src/fs/entry.rs13
-rw-r--r--src/fs/metadata.rs46
-rw-r--r--src/io/io_worker.rs166
-rw-r--r--src/ui/views/tui_folder_view.rs2
-rw-r--r--src/ui/widgets/tui_dirlist.rs36
-rw-r--r--src/ui/widgets/tui_dirlist_detailed.rs51
-rw-r--r--src/ui/widgets/tui_footer.rs18
-rw-r--r--src/util/sort.rs2
10 files changed, 177 insertions, 163 deletions
diff --git a/src/commands/set_mode.rs b/src/commands/set_mode.rs
index 978bb24..a13cad6 100644
--- a/src/commands/set_mode.rs
+++ b/src/commands/set_mode.rs
@@ -44,7 +44,7 @@ pub fn set_mode(context: &mut JoshutoContext, backend: &mut TuiBackend) -> Joshu
let user_input = match entry {
Some(entry) => {
- let mode = entry.metadata.permissions.mode();
+ let mode = entry.metadata.permissions_ref().mode();
let mode_string = unix::stringify_mode(mode);
TuiTextField::default()
.prompt(":")
@@ -68,7 +68,7 @@ pub fn set_mode(context: &mut JoshutoContext, backend: &mut TuiBackend) -> Joshu
.unwrap();
unix::set_mode(entry.file_path(), mode);
- entry.metadata.permissions.set_mode(mode);
+ entry.metadata.permissions_mut().set_mode(mode);
cursor_move::down(context, 1)?;
}
}
diff --git a/src/fs/dirlist.rs b/src/fs/dirlist.rs
index 0733f0f..797a83e 100644
--- a/src/fs/dirlist.rs
+++ b/src/fs/dirlist.rs
@@ -40,7 +40,7 @@ impl JoshutoDirList {
let metadata = std::fs::symlink_metadata(self.file_path());
match metadata {
Ok(m) => match m.modified() {
- Ok(s) => s > self.metadata.modified,
+ Ok(s) => s > self.metadata.modified(),
_ => false,
},
_ => false,
diff --git a/src/fs/entry.rs b/src/fs/entry.rs
index e6e1ae6..5362c76 100644
--- a/src/fs/entry.rs
+++ b/src/fs/entry.rs
@@ -28,15 +28,14 @@ impl JoshutoDirEntry {
.to_string_lossy()
.to_string();
- let label = name.clone();
let label = if show_icons {
- let icon = match metadata.file_type {
+ let icon = match metadata.file_type() {
FileType::Directory => DIR_NODE_EXACT_MATCHES
- .get(label.as_str())
+ .get(name.as_str())
.cloned()
.unwrap_or(DEFAULT_DIR),
_ => FILE_NODE_EXACT_MATCHES
- .get(label.as_str())
+ .get(name.as_str())
.cloned()
.unwrap_or(match path.extension() {
Some(s) => FILE_NODE_EXTENSIONS
@@ -53,9 +52,9 @@ impl JoshutoDirEntry {
None => DEFAULT_FILE,
}),
};
- format!(" {} {}", icon, label)
+ format!("{} {}", icon, name)
} else {
- label
+ name.clone()
};
Ok(Self {
@@ -100,7 +99,7 @@ impl JoshutoDirEntry {
pub fn get_style(&self) -> Style {
let metadata = &self.metadata;
- let filetype = &metadata.file_type;
+ let filetype = &metadata.file_type();
match filetype {
_ if self.is_selected() => Style::default()
diff --git a/src/fs/metadata.rs b/src/fs/metadata.rs
index e71f793..aa6dcad 100644
--- a/src/fs/metadata.rs
+++ b/src/fs/metadata.rs
@@ -1,4 +1,4 @@
-use std::{fs, path, process, time};
+use std::{fs, io, path, process, time};
#[derive(Clone, Debug)]
pub enum FileType {
@@ -9,10 +9,10 @@ pub enum FileType {
#[derive(Clone, Debug)]
pub struct JoshutoMetadata {
- pub len: u64,
- pub modified: time::SystemTime,
- pub permissions: fs::Permissions,
- pub file_type: FileType,
+ _len: u64,
+ _modified: time::SystemTime,
+ _permissions: fs::Permissions,
+ _file_type: FileType,
pub mimetype: Option<String>,
#[cfg(unix)]
pub uid: u32,
@@ -23,15 +23,15 @@ pub struct JoshutoMetadata {
}
impl JoshutoMetadata {
- pub fn from(path: &path::Path) -> std::io::Result<Self> {
+ pub fn from(path: &path::Path) -> io::Result<Self> {
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
let metadata = fs::symlink_metadata(path)?;
- let len = metadata.len();
- let modified = metadata.modified()?;
- let permissions = metadata.permissions();
+ let _len = metadata.len();
+ let _modified = metadata.modified()?;
+ let _permissions = metadata.permissions();
let file_type = metadata.file_type();
let file_type = if file_type.is_dir() {
@@ -65,10 +65,10 @@ impl JoshutoMetadata {
let mode = metadata.mode();
Ok(Self {
- len,
- modified,
- permissions,
- file_type,
+ _len,
+ _modified,
+ _permissions,
+ _file_type: file_type,
mimetype,
#[cfg(unix)]
uid,
@@ -78,6 +78,26 @@ impl JoshutoMetadata {
mode,
})
}
+
+ pub fn len(&self) -> u64 {
+ self._len
+ }
+
+ pub fn modified(&self) -> time::SystemTime {
+ self._modified
+ }
+
+ pub fn permissions_ref(&self) -> &fs::Permissions {
+ &self._permissions
+ }
+
+ pub fn permissions_mut(&mut self) -> &mut fs::Permissions {
+ &mut self._permissions
+ }
+
+ pub fn file_type(&self) -> &FileType {
+ &self._file_type
+ }
}
fn file_mimetype(path: &path::Path) -> Option<String> {
diff --git a/src/io/io_worker.rs b/src/io/io_worker.rs
index 58347ee..97af52a 100644
--- a/src/io/io_worker.rs
+++ b/src/io/io_worker.rs
@@ -117,7 +117,7 @@ impl IOWorkerThread {
for (i, path) in self.paths.iter().enumerate() {
progress.set_index(i);
let _ = tx.send(progress.clone());
- self.recursive_copy(
+ recursive_copy(
path.as_path(),
self.dest.as_path(),
tx.clone(),
@@ -132,52 +132,12 @@ impl IOWorkerThread {
))
}
- fn recursive_copy(
- &self,
- src: &path::Path,
- dest: &path::Path,
- tx: mpsc::Sender<IOWorkerProgress>,
- progress: &mut IOWorkerProgress,
- ) -> std::io::Result<()> {
- let mut dest_buf = dest.to_path_buf();
- if let Some(s) = src.file_name() {
- dest_buf.push(s);
- }
- rename_filename_conflict(&mut dest_buf);
- let file_type = fs::symlink_metadata(src)?.file_type();
- if file_type.is_dir() {
- fs::create_dir(dest_buf.as_path())?;
- for entry in fs::read_dir(src)? {
- let entry = entry?;
- let entry_path = entry.path();
- self.recursive_copy(
- entry_path.as_path(),
- dest_buf.as_path(),
- tx.clone(),
- progress,
- )?;
- let _ = tx.send(progress.clone());
- }
- Ok(())
- } else if file_type.is_file() {
- let processed = progress.processed() + fs::copy(src, dest_buf)?;
- progress.set_processed(processed);
- Ok(())
- } else if file_type.is_symlink() {
- let link_path = fs::read_link(src)?;
- std::os::unix::fs::symlink(link_path, dest_buf)?;
- Ok(())
- } else {
- Ok(())
- }
- }
-
fn paste_cut(&self, tx: mpsc::Sender<IOWorkerProgress>) -> std::io::Result<IOWorkerProgress> {
let mut progress = IOWorkerProgress::new(self.kind(), 0, self.paths.len(), 0);
for (i, path) in self.paths.iter().enumerate() {
progress.set_index(i);
let _ = tx.send(progress.clone());
- self.recursive_cut(
+ recursive_cut(
path.as_path(),
self.dest.as_path(),
tx.clone(),
@@ -191,55 +151,93 @@ impl IOWorkerThread {
progress.processed(),
))
}
+}
- pub fn recursive_cut(
- &self,
- src: &path::Path,
- dest: &path::Path,
- tx: mpsc::Sender<IOWorkerProgress>,
- progress: &mut IOWorkerProgress,
- ) -> std::io::Result<()> {
- let mut dest_buf = dest.to_path_buf();
- if let Some(s) = src.file_name() {
- dest_buf.push(s);
+pub fn recursive_copy(
+ src: &path::Path,
+ dest: &path::Path,
+ tx: mpsc::Sender<IOWorkerProgress>,
+ progress: &mut IOWorkerProgress,
+) -> std::io::Result<()> {
+ let mut dest_buf = dest.to_path_buf();
+ if let Some(s) = src.file_name() {
+ dest_buf.push(s);
+ }
+ rename_filename_conflict(&mut dest_buf);
+ let file_type = fs::symlink_metadata(src)?.file_type();
+ if file_type.is_dir() {
+ fs::create_dir(dest_buf.as_path())?;
+ for entry in fs::read_dir(src)? {
+ let entry = entry?;
+ let entry_path = entry.path();
+ recursive_copy(
+ entry_path.as_path(),
+ dest_buf.as_path(),
+ tx.clone(),
+ progress,
+ )?;
+ let _ = tx.send(progress.clone());
}
- rename_filename_conflict(&mut dest_buf);
- let metadata = fs::symlink_metadata(src)?;
- let file_type = metadata.file_type();
- if file_type.is_dir() {
- match fs::rename(src, dest_buf.as_path()) {
- Ok(_) => {
- let processed = progress.processed() + metadata.len();
- progress.set_processed(processed);
- }
- Err(_) => {
- fs::create_dir(dest_buf.as_path())?;
- for entry in fs::read_dir(src)? {
- let entry_path = entry?.path();
- self.recursive_cut(
- entry_path.as_path(),
- dest_buf.as_path(),
- tx.clone(),
- progress,
- )?;
- }
- fs::remove_dir(src)?;
- }
- }
- } else if file_type.is_file() {
- if fs::rename(src, dest_buf.as_path()).is_err() {
- fs::copy(src, dest_buf.as_path())?;
- fs::remove_file(src)?;
+ Ok(())
+ } else if file_type.is_file() {
+ let processed = progress.processed() + fs::copy(src, dest_buf)?;
+ progress.set_processed(processed);
+ Ok(())
+ } else if file_type.is_symlink() {
+ let link_path = fs::read_link(src)?;
+ std::os::unix::fs::symlink(link_path, dest_buf)?;
+ Ok(())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn recursive_cut(
+ src: &path::Path,
+ dest: &path::Path,
+ tx: mpsc::Sender<IOWorkerProgress>,
+ progress: &mut IOWorkerProgress,
+) -> std::io::Result<()> {
+ let mut dest_buf = dest.to_path_buf();
+ if let Some(s) = src.file_name() {
+ dest_buf.push(s);
+ }
+ rename_filename_conflict(&mut dest_buf);
+ let metadata = fs::symlink_metadata(src)?;
+ let file_type = metadata.file_type();
+ if file_type.is_dir() {
+ match fs::rename(src, dest_buf.as_path()) {
+ Ok(_) => {
let processed = progress.processed() + metadata.len();
progress.set_processed(processed);
}
- } else if file_type.is_symlink() {
- let link_path = fs::read_link(src)?;
- std::os::unix::fs::symlink(link_path, dest_buf)?;
+ Err(_) => {
+ fs::create_dir(dest_buf.as_path())?;
+ for entry in fs::read_dir(src)? {
+ let entry_path = entry?.path();
+ recursive_cut(
+ entry_path.as_path(),
+ dest_buf.as_path(),
+ tx.clone(),
+ progress,
+ )?;
+ }
+ fs::remove_dir(src)?;
+ }
+ }
+ } else if file_type.is_file() {
+ if fs::rename(src, dest_buf.as_path()).is_err() {
+ fs::copy(src, dest_buf.as_path())?;
fs::remove_file(src)?;
let processed = progress.processed() + metadata.len();
progress.set_processed(processed);
}
- Ok(())
- }
+ } else if file_type.is_symlink() {
+ let link_path = fs::read_link(src)?;
+ std::os::unix::fs::symlink(link_path, dest_buf)?;
+ fs::remove_file(src)?;
+ let processed = progress.processed() + metadata.len();
+ progress.set_processed(processed);
+ }
+ Ok(())
}
diff --git a/src/ui/views/tui_folder_view.rs b/src/ui/views/tui_folder_view.rs
index cd8283d..83af048 100644
--- a/src/ui/views/tui_folder_view.rs
+++ b/src/ui/views/tui_folder_view.rs
@@ -41,7 +41,7 @@ impl<'a> Widget for TuiFolderView<'a> {
};
let layout_rect = Layout::default()
.direction(Direction::Horizontal)
- .margin(1)
+ .vertical_margin(1)
.constraints(constraints.as_ref())
.split(f_size);
diff --git a/src/ui/widgets/tui_dirlist.rs b/src/ui/widgets/tui_dirlist.rs
index afa3258..b19aad7 100644
--- a/src/ui/widgets/tui_dirlist.rs
+++ b/src/ui/widgets/tui_dirlist.rs
@@ -28,8 +28,7 @@ impl<'a> Widget for TuiDirList<'a> {
let x = area.left();
let y = area.top();
- let dir_len = self.dirlist.contents.len();
- if dir_len == 0 {
+ if self.dirlist.contents.len() == 0 {
let style = Style::default().bg(Color::Red).fg(Color::White);
buf.set_stringn(x, y, "empty", area.width as usize, style);
return;
@@ -39,8 +38,10 @@ impl<'a> Widget for TuiDirList<'a> {
let skip_dist = curr_index / area.height as usize * area.height as usize;
let screen_index = curr_index % area.height as usize;
- let area_width = area.width as usize - 1;
- let space_fill = " ".repeat(area_width);
+ let drawing_width = area.width as usize - 2;
+ let space_fill = " ".repeat(drawing_width + 1);
+
+ let x_start = x + 1;
for (i, entry) in self
.dirlist
@@ -60,46 +61,45 @@ impl<'a> Widget for TuiDirList<'a> {
entry.get_style()
};
- let file_type = &entry.metadata.file_type;
- match file_type {
+ match entry.metadata.file_type() {
FileType::Directory => {
- if name_width <= area_width {
- buf.set_stringn(x, y + i as u16, name, area_width, style);
+ if name_width <= drawing_width {
+ buf.set_stringn(x_start, y + i as u16, name, drawing_width, style);
} else {
- buf.set_stringn(x, y + i as u16, name, area_width - 1, style);
- buf.set_string(x + area_width as u16 - 1, y + i as u16, "…", style);
+ buf.set_stringn(x_start, y + i as u16, name, drawing_width - 1, style);
+ buf.set_string(x_start + drawing_width as u16 - 1, y + i as u16, "…", style);
}
}
_ => {
- if name_width < area_width {
- buf.set_stringn(x, y + i as u16, name, area_width, style);
+ if name_width < drawing_width {
+ buf.set_stringn(x_start, y + i as u16, name, drawing_width, style);
} else {
match name.rfind('.') {
None => {
- buf.set_stringn(x, y + i as u16, name, area_width, style);
+ buf.set_stringn(x_start, y + i as u16, name, drawing_width, style);
}
Some(p_ind) => {
let ext_width = name[p_ind..].width();
- let file_name_width = area_width - ext_width - 1;
+ let file_name_width = drawing_width - ext_width - 1;
buf.set_stringn(
- x,
+ x_start,
y + i as u16,
&name[..p_ind],
file_name_width,
style,
);
buf.set_string(
- x + file_name_width as u16,
+ x_start + file_name_width as u16,
y + i as u16,
"…",
style,
);
buf.set_stringn(
- x + file_name_width as u16 + 1,
+ x_start + file_name_width as u16 + 1,
y + i as u16,
&name[p_ind..],
- area_width - file_name_width,
+ drawing_width - file_name_width,
style,
);
}
diff --git a/src/ui/widgets/tui_dirlist_detailed.rs b/src/ui/widgets/tui_dirlist_detailed.rs
index b63ebdb..422793a 100644
--- a/src/ui/widgets/tui_dirlist_detailed.rs
+++ b/src/ui/widgets/tui_dirlist_detailed.rs
@@ -42,8 +42,10 @@ impl<'a> Widget for TuiDirListDetailed<'a> {
let skip_dist = curr_index / area.height as usize * area.height as usize;
let screen_index = curr_index % area.height as usize;
- let area_width = area.width as usize;
- let space_fill = " ".repeat(area_width);
+ let drawing_width = area.width as usize;
+ let space_fill = " ".repeat(drawing_width);
+
+ let x_start = x + 1;
for (i, entry) in self
.dirlist
@@ -63,67 +65,66 @@ impl<'a> Widget for TuiDirListDetailed<'a> {
buf.set_string(x, y + i as u16, space_fill.as_str(), style);
- let file_type = &entry.metadata.file_type;
- match file_type {
+ match entry.metadata.file_type() {
FileType::Directory => {
- if name_width <= area_width {
- buf.set_string(x, y + i as u16, name, style);
+ if name_width <= drawing_width {
+ buf.set_string(x_start, y + i as u16, name, style);
} else {
- buf.set_stringn(x, y + i as u16, name, area_width - 1, style);
- buf.set_string(x + area_width as u16 - 1, y + i as u16, ELLIPSIS, style);
+ buf.set_stringn(x_start, y + i as u16, name, drawing_width - 1, style);
+ buf.set_string(x_start + drawing_width as u16 - 1, y + i as u16, ELLIPSIS, style);
}
}
FileType::Symlink(_) => {
- if name_width < area_width - 4 {
- buf.set_string(x, y + i as u16, name, style);
- buf.set_string(x + area_width as u16 - 4, y + i as u16, "->", style);
+ if name_width < drawing_width - 4 {
+ buf.set_string(x_start, y + i as u16, name, style);
+ buf.set_string(x_start + drawing_width as u16 - 4, y + i as u16, "->", style);
} else {
- buf.set_stringn(x, y + i as u16, name, area_width - 1, style);
- buf.set_string(x + area_width as u16 - 1, y + i as u16, ELLIPSIS, style);
+ buf.set_stringn(x_start, y + i as u16, name, drawing_width - 1, style);
+ buf.set_string(x_start + drawing_width as u16 - 1, y + i as u16, ELLIPSIS, style);
}
}
FileType::File => {
- if name_width < area_width - FILE_SIZE_WIDTH {
- buf.set_stringn(x, y + i as u16, name, area_width - FILE_SIZE_WIDTH, style);
+ if name_width < drawing_width - FILE_SIZE_WIDTH {
+ buf.set_stringn(x_start, y + i as u16, name, drawing_width - FILE_SIZE_WIDTH, style);
} else {
match name.rfind('.') {
None => {
buf.set_stringn(
- x,
+ x_start,
y + i as u16,
name,
- area_width - FILE_SIZE_WIDTH,
+ drawing_width - FILE_SIZE_WIDTH,
style,
);
}
Some(p_ind) => {
let ext_width = name[p_ind..].width();
let file_name_width =
- if ext_width > area_width - FILE_SIZE_WIDTH - 2 {
+ if ext_width > drawing_width - FILE_SIZE_WIDTH - 2 {
0
} else {
- area_width - FILE_SIZE_WIDTH - ext_width - 2
+ drawing_width - FILE_SIZE_WIDTH - ext_width - 2
};
buf.set_stringn(
- x,
+ x_start,
y + i as u16,
&name[..p_ind],
file_name_width,
style,
);
buf.set_string(
- x + file_name_width as u16,
+ x_start + file_name_width as u16,
y + i as u16,
ELLIPSIS,
style,
);
let file_ext_width =
- area_width - file_name_width - FILE_SIZE_WIDTH - 2;
+ drawing_width - file_name_width - FILE_SIZE_WIDTH - 2;
buf.set_stringn(
- x + file_name_width as u16 + 1,
+ x_start + file_name_width as u16 + 1,
y + i as u16,
&name[p_ind..],
file_ext_width,
@@ -132,9 +133,9 @@ impl<'a> Widget for TuiDirListDetailed<'a> {
}
}
}
- let file_size_string = format::file_size_to_string(entry.metadata.len);
+ let file_size_string = format::file_size_to_string(entry.metadata.len());
buf.set_string(
- x + (area_width - FILE_SIZE_WIDTH) as u16,
+ x_start + (drawing_width - FILE_SIZE_WIDTH) as u16,
y + i as u16,
file_size_string,
style,
diff --git a/src/ui/widgets/tui_footer.rs b/src/ui/widgets/tui_footer.rs
index 35189dc..603d5a6 100644
--- a/src/ui/widgets/tui_footer.rs
+++ b/src/ui/widgets/tui_footer.rs
@@ -23,16 +23,12 @@ impl<'a> Widget for TuiFooter<'a> {
match self.list.index {
Some(i) if i < self.list.contents.len() => {
let entry = &self.list.contents[i];
- let mode = entry.metadata.permissions.mode();
- let mode = format::mode_to_string(mode);
let mode_style = Style::default().fg(Color::Cyan);
+ let mode_str = format::mode_to_string(entry.metadata.permissions_ref().mode());
- let mtime = entry.metadata.modified;
- let mtime = format::mtime_to_string(mtime);
-
- let size = entry.metadata.len;
- let size = format::file_size_to_string(size);
+ let mtime_str = format::mtime_to_string(entry.metadata.modified());
+ let size_str = format::file_size_to_string(entry.metadata.len());
#[cfg(unix)]
let mimetype = match entry.metadata.mimetype.as_ref() {
@@ -41,20 +37,20 @@ impl<'a> Widget for TuiFooter<'a> {
};
let mut text = vec![
- Span::styled(mode, mode_style),
+ Span::styled(mode_str, mode_style),
Span::raw(" "),
Span::raw(format!("{}/{}", i + 1, self.list.contents.len())),
Span::raw(" "),
- Span::raw(mtime),
+ Span::raw(mtime_str),
Span::raw(" "),
- Span::raw(size),
+ Span::raw(size_str),
#[cfg(unix)]
Span::raw(" "),
#[cfg(unix)]
Span::raw(mimetype),
];
- if let FileType::Symlink(s) = &entry.metadata.file_type {
+ if let FileType::Symlink(s) = entry.metadata.file_type() {
text.push(Span::styled(" -> ", mode_style));
text.push(Span::styled(s, mode_style));
}
diff --git a/src/util/sort.rs b/src/util/sort.rs
index b4e916e..4544884 100644
--- a/src/util/sort.rs
+++ b/src/util/sort.rs
@@ -161,5 +161,5 @@ fn mtime_sort(file1: &JoshutoDirEntry, file2: &JoshutoDirEntry) -> cmp::Ordering
}
fn size_sort(file1: &JoshutoDirEntry, file2: &JoshutoDirEntry) -> cmp::Ordering {
- file1.metadata.len.cmp(&file2.metadata.len)
+ file1.metadata.len().cmp(&file2.metadata.len())
}