diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-12-15 11:20:35 -0500 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-12-15 11:20:35 -0500 |
commit | f5902708a6e597064482edfc076248a67882b7c5 (patch) | |
tree | 40e97ad84d157bbc670edb97c328ff988f8c8aa6 | |
parent | 2b29f8485e95fd3cda434ed472992fff2ee8e7a0 (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.rs | 4 | ||||
-rw-r--r-- | src/fs/dirlist.rs | 2 | ||||
-rw-r--r-- | src/fs/entry.rs | 13 | ||||
-rw-r--r-- | src/fs/metadata.rs | 46 | ||||
-rw-r--r-- | src/io/io_worker.rs | 166 | ||||
-rw-r--r-- | src/ui/views/tui_folder_view.rs | 2 | ||||
-rw-r--r-- | src/ui/widgets/tui_dirlist.rs | 36 | ||||
-rw-r--r-- | src/ui/widgets/tui_dirlist_detailed.rs | 51 | ||||
-rw-r--r-- | src/ui/widgets/tui_footer.rs | 18 | ||||
-rw-r--r-- | src/util/sort.rs | 2 |
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()) } |