diff options
-rw-r--r-- | config/keymap.toml | 10 | ||||
-rw-r--r-- | docs/README.md | 4 | ||||
-rw-r--r-- | docs/configuration/keymap.toml.md | 2 | ||||
-rw-r--r-- | src/commands/delete_files.rs | 1 | ||||
-rw-r--r-- | src/commands/file_ops.rs | 13 | ||||
-rw-r--r-- | src/event/process_event.rs | 1 | ||||
-rw-r--r-- | src/io/file_operation.rs | 13 | ||||
-rw-r--r-- | src/io/io_observer.rs | 1 | ||||
-rw-r--r-- | src/io/io_worker.rs | 29 | ||||
-rw-r--r-- | src/key_command/command.rs | 1 | ||||
-rw-r--r-- | src/key_command/constants.rs | 5 | ||||
-rw-r--r-- | src/key_command/impl_appcommand.rs | 1 | ||||
-rw-r--r-- | src/key_command/impl_appexecute.rs | 2 | ||||
-rw-r--r-- | src/key_command/impl_comment.rs | 1 | ||||
-rw-r--r-- | src/key_command/impl_from_str.rs | 2 | ||||
-rw-r--r-- | src/ui/widgets/tui_worker.rs | 8 |
16 files changed, 76 insertions, 18 deletions
diff --git a/config/keymap.toml b/config/keymap.toml index bbc7705..36eef74 100644 --- a/config/keymap.toml +++ b/config/keymap.toml @@ -52,16 +52,16 @@ keymap = [ { keys = [ "c", "d" ], command = ":cd " }, { keys = [ "d", "d" ], command = "cut_files" }, { keys = [ "y", "y" ], command = "copy_files" }, - { keys = [ "p", "p" ], command = "paste_files" }, - { keys = [ "p", "o" ], command = "paste_files --overwrite=true" }, - { keys = [ "y", "n" ], command = "copy_filename" }, { keys = [ "y", "." ], command = "copy_filename_without_extension" }, { keys = [ "y", "p" ], command = "copy_filepath" }, { keys = [ "y", "d" ], command = "copy_dirpath" }, - { keys = [ "delete" ], command = "delete_files" }, - { keys = [ "d", "D" ], command = "delete_files" }, + { keys = [ "delete" ], command = "delete_files --foreground=true" }, + { keys = [ "d", "D" ], command = "delete_files --foreground=true" }, + + { keys = [ "p", "p" ], command = "paste_files" }, + { keys = [ "p", "o" ], command = "paste_files --overwrite=true" }, { keys = [ "a" ], command = "rename_append" }, { keys = [ "A" ], command = "rename_prepend" }, diff --git a/docs/README.md b/docs/README.md index 0a6c0b7..91d65ce 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,6 +2,8 @@ These docs should help you get set up and understand how Joshuto works. + - [command line arguments](/docs/command_arguments.md) - [configuration](/docs/configuration/) - - [contributing](/docs/contributing.md) + - [image previews](/docs/image_previews.md) - [misc](/docs/misc.md) + - [contributing](/docs/contributing.md) diff --git a/docs/configuration/keymap.toml.md b/docs/configuration/keymap.toml.md index 1086f04..e1fb758 100644 --- a/docs/configuration/keymap.toml.md +++ b/docs/configuration/keymap.toml.md @@ -179,8 +179,10 @@ function joshuto() { - `mkdir`: create a new directory (usually used as `:mkdir `) - `cut_files`: store selected files (or current file if none were selected) to be moved later - `copy_files`: store selected files (or current file if none were selected) to be copied later + - `symlink_files`: store selected files (or current file if none were selected) to be symlinked later - `paste_files`: move/copy files stored from a previous `cut_files` or `copy_files` command - `delete_files`: delete selected files (or current file if none were selected). + - `--foreground=true`: will delete files in the foreground - will ***permanently*** delete files if `use_trash` is `false` in [joshuto.toml](https://github.com/kamiyaa/joshuto)/wiki/Configuration#joshutotoml) - if `use_trash` is `true`, this might cause issues with deleting files diff --git a/src/commands/delete_files.rs b/src/commands/delete_files.rs index 272fd1a..987c45e 100644 --- a/src/commands/delete_files.rs +++ b/src/commands/delete_files.rs @@ -53,7 +53,6 @@ fn delete_files( let options = FileOperationOptions { overwrite: false, skip_exist: false, - symlink: false, permanently: !context.config_ref().use_trash, }; diff --git a/src/commands/file_ops.rs b/src/commands/file_ops.rs index ce9b787..c50129b 100644 --- a/src/commands/file_ops.rs +++ b/src/commands/file_ops.rs @@ -31,6 +31,19 @@ pub fn copy(context: &mut AppContext) -> JoshutoResult { Ok(()) } +pub fn link(context: &mut AppContext) -> JoshutoResult { + if let Some(list) = context.tab_context_ref().curr_tab_ref().curr_list_ref() { + let selected = list.get_selected_paths(); + + let mut local_state = LocalStateContext::new(); + local_state.set_paths(selected.into_iter()); + local_state.set_file_op(FileOperation::Symlink); + + context.set_local_state(local_state); + } + Ok(()) +} + pub fn paste(context: &mut AppContext, options: FileOperationOptions) -> JoshutoResult { match context.take_local_state() { Some(state) if !state.paths.is_empty() => { diff --git a/src/event/process_event.rs b/src/event/process_event.rs index 8eb6136..84ef44b 100644 --- a/src/event/process_event.rs +++ b/src/event/process_event.rs @@ -112,6 +112,7 @@ pub fn process_finished_worker( let op = match progress.kind() { FileOperation::Cut => "moved", FileOperation::Copy => "copied", + FileOperation::Symlink => "symlinked", FileOperation::Delete => "deleted", }; let processed_size = format::file_size_to_string(progress.bytes_processed()); diff --git a/src/io/file_operation.rs b/src/io/file_operation.rs index 14693ec..9d39716 100644 --- a/src/io/file_operation.rs +++ b/src/io/file_operation.rs @@ -2,15 +2,26 @@ pub enum FileOperation { Cut, Copy, + Symlink, Delete, } +impl std::fmt::Display for FileOperation { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Cut => write!(f, "Cut"), + Self::Copy => write!(f, "Copy"), + Self::Symlink => write!(f, "Symlink"), + Self::Delete => write!(f, "Delete"), + } + } +} + #[derive(Clone, Copy, Debug, Default)] pub struct FileOperationOptions { // cut, copy pub overwrite: bool, pub skip_exist: bool, - pub symlink: bool, // delete pub permanently: bool, diff --git a/src/io/io_observer.rs b/src/io/io_observer.rs index 2df4842..44d4248 100644 --- a/src/io/io_observer.rs +++ b/src/io/io_observer.rs @@ -37,6 +37,7 @@ impl IoWorkerObserver { let op_str = match progress.kind() { FileOperation::Cut => "Moving", FileOperation::Copy => "Copying", + FileOperation::Symlink => "Symlinking", FileOperation::Delete => "Deleting", }; let processed_size = format::file_size_to_string(progress.bytes_processed()); diff --git a/src/io/io_worker.rs b/src/io/io_worker.rs index 87c5bad..f9d86d9 100644 --- a/src/io/io_worker.rs +++ b/src/io/io_worker.rs @@ -4,6 +4,9 @@ use std::io; use std::path; use std::sync::mpsc; +#[cfg(unix)] +use std::os::unix; + use crate::io::{FileOperation, FileOperationOptions, FileOperationProgress}; use crate::util::name_resolution::rename_filename_conflict; @@ -41,6 +44,7 @@ impl IoWorkerThread { match self.kind() { FileOperation::Cut => self.paste_cut(tx), FileOperation::Copy => self.paste_copy(tx), + FileOperation::Symlink => self.paste_link(tx), FileOperation::Delete => self.delete(tx), } } @@ -83,6 +87,31 @@ impl IoWorkerThread { Ok(progress) } + fn paste_link( + &self, + tx: mpsc::Sender<FileOperationProgress>, + ) -> io::Result<FileOperationProgress> { + let total_files = self.paths.len(); + let total_bytes = total_files as u64; + let mut progress = FileOperationProgress::new(self.kind(), 0, total_files, 0, total_bytes); + + #[cfg(unix)] + for src in self.paths.iter() { + let _ = tx.send(progress.clone()); + let mut dest_buf = self.dest.to_path_buf(); + if let Some(s) = src.file_name() { + dest_buf.push(s); + } + if !self.options.overwrite { + rename_filename_conflict(&mut dest_buf); + } + unix::fs::symlink(src, &dest_buf)?; + progress.set_files_processed(progress.files_processed() + 1); + progress.set_bytes_processed(progress.bytes_processed() + 1); + } + Ok(progress) + } + fn delete( &self, _tx: mpsc::Sender<FileOperationProgress>, diff --git a/src/key_command/command.rs b/src/key_command/command.rs index 8d1110c..9ffbe5c 100644 --- a/src/key_command/command.rs +++ b/src/key_command/command.rs @@ -21,6 +21,7 @@ pub enum Command { CopyFileNameWithoutExtension, CopyFilePath, CopyDirPath, + SymlinkFiles, PasteFiles(FileOperationOptions), DeleteFiles { background: bool }, diff --git a/src/key_command/constants.rs b/src/key_command/constants.rs index ba5db2e..8dd60ed 100644 --- a/src/key_command/constants.rs +++ b/src/key_command/constants.rs @@ -24,7 +24,6 @@ cmd_constants![ (CMD_CLOSE_TAB, "close_tab"), (CMD_CUT_FILES, "cut_files"), (CMD_COPY_FILES, "copy_files"), - (CMD_PASTE_FILES, "paste_files"), (CMD_COPY_FILENAME, "copy_filename"), ( CMD_COPY_FILENAME_WITHOUT_EXTENSION, @@ -32,6 +31,9 @@ cmd_constants![ ), (CMD_COPY_FILEPATH, "copy_filepath"), (CMD_COPY_DIRECTORY_PATH, "copy_dirpath"), + (CMD_SYMLINK_FILES, "symlink_files"), + (CMD_PASTE_FILES, "paste_files"), + (CMD_DELETE_FILES, "delete_files"), (CMD_CURSOR_MOVE_UP, "cursor_move_up"), (CMD_CURSOR_MOVE_DOWN, "cursor_move_down"), (CMD_CURSOR_MOVE_HOME, "cursor_move_home"), @@ -45,7 +47,6 @@ cmd_constants![ (CMD_PARENT_CURSOR_MOVE_DOWN, "parent_cursor_move_down"), (CMD_PREVIEW_CURSOR_MOVE_UP, "preview_cursor_move_up"), (CMD_PREVIEW_CURSOR_MOVE_DOWN, "preview_cursor_move_down"), - (CMD_DELETE_FILES, "delete_files"), (CMD_NEW_DIRECTORY, "mkdir"), (CMD_OPEN_FILE, "open"), (CMD_OPEN_FILE_WITH, "open_with"), diff --git a/src/key_command/impl_appcommand.rs b/src/key_command/impl_appcommand.rs index 7ea8f93..fe7dbc2 100644 --- a/src/key_command/impl_appcommand.rs +++ b/src/key_command/impl_appcommand.rs @@ -24,6 +24,7 @@ impl AppCommand for Command { Self::CopyFileNameWithoutExtension => CMD_COPY_FILENAME_WITHOUT_EXTENSION, Self::CopyFilePath => CMD_COPY_FILEPATH, Self::CopyDirPath => CMD_COPY_DIRECTORY_PATH, + Self::SymlinkFiles => CMD_SYMLINK_FILES, Self::PasteFiles(_) => CMD_PASTE_FILES, Self::DeleteFiles { .. } => CMD_DELETE_FILES, diff --git a/src/key_command/impl_appexecute.rs b/src/key_command/impl_appexecute.rs index 37f0c35..cd7aacc 100644 --- a/src/key_command/impl_appexecute.rs +++ b/src/key_command/impl_appexecute.rs @@ -36,7 +36,7 @@ impl AppExecute for Command { } Self::CopyFilePath => file_ops::copy_filepath(context), Self::CopyDirPath => file_ops::copy_dirpath(context), - + Self::SymlinkFiles => file_ops::link(context), Self::PasteFiles(options) => file_ops::paste(context, *options), Self::DeleteFiles { background: false } => { diff --git a/src/key_command/impl_comment.rs b/src/key_command/impl_comment.rs index a351fed..36697c0 100644 --- a/src/key_command/impl_comment.rs +++ b/src/key_command/impl_comment.rs @@ -31,6 +31,7 @@ impl CommandComment for Command { Self::CopyFileNameWithoutExtension => "Copy filename without extension", Self::CopyFilePath => "Copy path to file", Self::CopyDirPath => "Copy directory name", + Self::SymlinkFiles => "Symlink selected files", Self::PasteFiles(FileOperationOptions { overwrite, diff --git a/src/key_command/impl_from_str.rs b/src/key_command/impl_from_str.rs index 224b8d6..81b8949 100644 --- a/src/key_command/impl_from_str.rs +++ b/src/key_command/impl_from_str.rs @@ -55,7 +55,6 @@ impl std::str::FromStr for Command { simple_command_conversion_case!(command, CMD_CURSOR_MOVE_PAGEEND, Self::CursorMovePageEnd); simple_command_conversion_case!(command, CMD_CUT_FILES, Self::CutFiles); - simple_command_conversion_case!(command, CMD_COPY_FILES, Self::CopyFiles); simple_command_conversion_case!(command, CMD_COPY_FILENAME, Self::CopyFileName); simple_command_conversion_case!( @@ -65,6 +64,7 @@ impl std::str::FromStr for Command { ); simple_command_conversion_case!(command, CMD_COPY_FILEPATH, Self::CopyFilePath); simple_command_conversion_case!(command, CMD_COPY_DIRECTORY_PATH, Self::CopyDirPath); + simple_command_conversion_case!(command, CMD_SYMLINK_FILES, Self::SymlinkFiles); simple_command_conversion_case!(command, CMD_OPEN_FILE, Self::OpenFile); diff --git a/src/ui/widgets/tui_worker.rs b/src/ui/widgets/tui_worker.rs index 06fcd7a..4ac034a 100644 --- a/src/ui/widgets/tui_worker.rs +++ b/src/ui/widgets/tui_worker.rs @@ -25,6 +25,7 @@ impl<'a> Widget for TuiWorker<'a> { let op_str = match progress.kind() { FileOperation::Cut => "Moving", FileOperation::Copy => "Copying", + FileOperation::Symlink => "Symlinking", FileOperation::Delete => "Deleting", }; @@ -61,15 +62,10 @@ impl<'a> Widget for TuiWorker<'a> { let style = Style::default(); for (i, worker) in self.context.iter().enumerate() { - let op_str = match worker.kind() { - FileOperation::Cut => "Move", - FileOperation::Copy => "Copy", - FileOperation::Delete => "Delete", - }; let msg = format!( "{:02} {} {} items {:?}", i + 1, - op_str, + worker.kind(), worker.paths.len(), worker.dest ); |