Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

file operations export to toml file #520

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 83 additions & 8 deletions src/commands/file_ops.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,72 @@
use std::io;
use std::fs::{self, File};
use std::io::{self, Read};
use std::io::Write;
use std::path;
use std::process::{Command, Stdio};

use crate::config::{search_directories, ConfigType};
use crate::context::{AppContext, LocalStateContext};
use crate::error::{AppError, AppErrorKind, AppResult};
use crate::io::{FileOperation, FileOperationOptions, IoWorkerThread};

fn new_local_state(context: &mut AppContext, file_op: FileOperation) -> Option<()> {
use crate::{BOOKMARKS_T, CONFIG_HIERARCHY};

fn find_state_context_file() -> Option<path::PathBuf> {
for p in CONFIG_HIERARCHY.iter() {
if p.exists() {
return Some(p.clone());
}
}
None
}

fn new_local_state(context: &mut AppContext, file_op: FileOperation) -> Option<LocalStateContext> {
let 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(file_op);

context.set_local_state(local_state);
Some(())
Some(local_state)
}

pub fn cut(context: &mut AppContext) -> AppResult {
new_local_state(context, FileOperation::Cut);
let local_state = new_local_state(context, FileOperation::Cut).unwrap_or(LocalStateContext::new());
context.set_local_state(local_state);
Ok(())
}

pub fn copy(context: &mut AppContext) -> AppResult {
new_local_state(context, FileOperation::Copy);
let local_state = new_local_state(context, FileOperation::Copy).unwrap_or(LocalStateContext::new());
context.set_local_state(local_state);
Ok(())
}

pub fn symlink_absolute(context: &mut AppContext) -> AppResult {
new_local_state(context, FileOperation::Symlink { relative: false });
let local_state = new_local_state(context, FileOperation::Symlink { relative: false }).unwrap_or(LocalStateContext::new());
context.set_local_state(local_state);
Ok(())
}

pub fn symlink_relative(context: &mut AppContext) -> AppResult {
new_local_state(context, FileOperation::Symlink { relative: true });
let local_state = new_local_state(context, FileOperation::Symlink { relative: true }).unwrap_or(LocalStateContext::new());
context.set_local_state(local_state);
Ok(())
}

pub fn save_local_state(local_state: &LocalStateContext) -> AppResult {
let local_state_path = match search_directories(ConfigType::StateContext.as_filename(), &CONFIG_HIERARCHY) {
Some(file_path) => Some(file_path),
None => find_state_context_file(),
};

if let Some(local_state_path) = local_state_path {
if let Ok(content) = toml::to_string(&local_state) {
let mut file = File::create(local_state_path)?;
file.write_all(content.as_bytes())?;
}
}
Ok(())
}

Expand All @@ -52,6 +85,48 @@ pub fn paste(context: &mut AppContext, options: FileOperationOptions) -> AppResu
}
}

pub fn cut_export(context: &mut AppContext) -> AppResult {
let local_state = new_local_state(context, FileOperation::Cut).unwrap_or(LocalStateContext::new());
let _ = save_local_state(&local_state);
Ok(())
}

pub fn copy_export(context: &mut AppContext) -> AppResult {
let local_state = new_local_state(context, FileOperation::Copy).unwrap_or(LocalStateContext::new());
let _ = save_local_state(&local_state);
Ok(())
}
pub fn symlink_absolute_export(context: &mut AppContext) -> AppResult {
let local_state = new_local_state(context, FileOperation::Symlink { relative: false }).unwrap_or(LocalStateContext::new());
let _ = save_local_state(&local_state);
Ok(())
}

pub fn symlink_relative_export(context: &mut AppContext) -> AppResult {
let local_state = new_local_state(context, FileOperation::Symlink { relative: true }).unwrap_or(LocalStateContext::new());
let _ = save_local_state(&local_state);
Ok(())
}

pub fn paste_import(context: &mut AppContext, options: FileOperationOptions) -> AppResult {

let local_state_path = match search_directories(ConfigType::StateContext.as_filename(), &CONFIG_HIERARCHY) {
Some(file_path) => Some(file_path),
None => find_state_context_file(),
};

if let Some(local_state_path) = local_state_path {
let file_contents = fs::read_to_string(&local_state_path)?;
let local_state = toml::from_str::<LocalStateContext>(&file_contents).unwrap();

let dest = context.tab_context_ref().curr_tab_ref().cwd().to_path_buf();
let worker_thread = IoWorkerThread::new(local_state.file_op, local_state.paths, dest, options);
context.worker_context_mut().push_worker(worker_thread);
}
Ok(())
}


pub fn copy_filename(context: &mut AppContext) -> AppResult {
let entry_file_name = context
.tab_context_ref()
Expand Down
6 changes: 5 additions & 1 deletion src/config/config_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum ConfigType {
Preview,
Bookmarks,
Icons,
StateContext,
}

impl std::fmt::Display for ConfigType {
Expand Down Expand Up @@ -35,6 +36,7 @@ impl ConfigType {
Self::Preview,
Self::Bookmarks,
Self::Icons,
Self::StateContext,
]
}

Expand All @@ -47,6 +49,7 @@ impl ConfigType {
Self::Preview => "preview",
Self::Bookmarks => "bookmarks",
Self::Icons => "icons",
Self::StateContext => "state_context",
}
}

Expand All @@ -59,6 +62,7 @@ impl ConfigType {
Self::Preview => "preview.toml",
Self::Bookmarks => "bookmarks.toml",
Self::Icons => "icons.toml",
Self::StateContext => "state_context.toml"
}
}

Expand All @@ -69,7 +73,7 @@ impl ConfigType {
Self::Keymap => Some(clean::keymap::DEFAULT_CONFIG_FILE_PATH),
Self::Theme => Some(clean::theme::DEFAULT_CONFIG_FILE_PATH),
Self::Icons => Some(clean::icon::DEFAULT_CONFIG_FILE_PATH),
Self::Mimetype | Self::Preview | Self::Bookmarks => None,
Self::Mimetype | Self::Preview | Self::Bookmarks | Self::StateContext => None,
}
}
}
2 changes: 2 additions & 0 deletions src/context/local_state.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::io::FileOperation;
use serde::{Serialize, Deserialize};

use std::iter::Iterator;
use std::path;

#[derive(Serialize, Deserialize)]
pub struct LocalStateContext {
pub paths: Vec<path::PathBuf>,
pub file_op: FileOperation,
Expand Down
3 changes: 2 additions & 1 deletion src/io/file_operation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::path;
use serde::{Serialize, Deserialize};

#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum FileOperation {
Cut,
Copy,
Expand Down
9 changes: 9 additions & 0 deletions src/key_command/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ pub enum Command {
options: FileOperationOptions,
},

CutFilesExport,
CopyFilesExport,
SymlinkFilesExport {
relative: bool,
},
PasteFilesImport {
options: FileOperationOptions,
},

DeleteFiles {
background: bool,
permanently: bool,
Expand Down
4 changes: 4 additions & 0 deletions src/key_command/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ cmd_constants![
(CMD_COPY_DIRECTORY_PATH, "copy_dirpath"),
(CMD_SYMLINK_FILES, "symlink_files"),
(CMD_PASTE_FILES, "paste_files"),
(CMD_CUT_FILES_EXPORT, "cut_files_export"),
(CMD_COPY_FILES_EXPORT, "copy_files_export"),
(CMD_SYMLINK_FILES_EXPORT, "symlink_files_export"),
(CMD_PASTE_FILES_IMPORT, "paste_files_import"),
(CMD_DELETE_FILES, "delete_files"),
(CMD_CURSOR_MOVE_UP, "cursor_move_up"),
(CMD_CURSOR_MOVE_DOWN, "cursor_move_down"),
Expand Down
5 changes: 5 additions & 0 deletions src/key_command/impl_appcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ impl AppCommand for Command {
Self::SymlinkFiles { .. } => CMD_SYMLINK_FILES,
Self::PasteFiles { .. } => CMD_PASTE_FILES,

Self::CutFilesExport => CMD_CUT_FILES_EXPORT,
Self::CopyFilesExport => CMD_COPY_FILES_EXPORT,
Self::SymlinkFilesExport { .. } => CMD_SYMLINK_FILES_EXPORT,
Self::PasteFilesImport { .. } => CMD_PASTE_FILES_IMPORT,

Self::DeleteFiles { .. } => CMD_DELETE_FILES,

Self::CursorMoveUp { .. } => CMD_CURSOR_MOVE_UP,
Expand Down
6 changes: 6 additions & 0 deletions src/key_command/impl_appexecute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ impl AppExecute for Command {
Self::SymlinkFiles { relative: false } => file_ops::symlink_absolute(context),
Self::PasteFiles { options } => file_ops::paste(context, *options),

Self::CutFilesExport => file_ops::cut_export(context),
Self::CopyFilesExport => file_ops::copy_export(context),
Self::SymlinkFilesExport { relative: true } => file_ops::symlink_relative_export(context),
Self::SymlinkFilesExport { relative: false } => file_ops::symlink_absolute_export(context),
Self::PasteFilesImport { options } => file_ops::paste_import(context, *options),

Self::DeleteFiles {
background,
permanently,
Expand Down
13 changes: 10 additions & 3 deletions src/key_command/impl_comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ impl CommandComment for Command {
_ => "Open a command line",
},

Self::CutFiles => "Cut selected files",
Self::CopyFiles => "Copy selected files",
Self::CutFiles | Self::CutFilesExport => "Cut selected files",
Self::CopyFiles | Self::CopyFilesExport => "Copy selected files",
Self::CopyFileName => "Copy filename",
Self::CopyFileNameWithoutExtension => "Copy filename without extension",
Self::CopyFilePath { all_selected: true } => "Copy all selected paths to file",
Self::CopyFilePath { .. } => "Copy path to file",
Self::CopyDirPath => "Copy directory name",
Self::SymlinkFiles { .. } => "Symlink selected files",
Self::SymlinkFiles { .. } | Self::SymlinkFilesExport { .. } => "Symlink selected files",

Self::PasteFiles {
options:
Expand All @@ -56,6 +56,13 @@ impl CommandComment for Command {
skip_exist,
..
},
} | Self::PasteFilesImport {
options:
FileOperationOptions {
overwrite,
skip_exist,
..
},
} => match (overwrite, skip_exist) {
(true, false) => "Paste, overwrite",
(false, true) => "Paste, skip existing files",
Expand Down
34 changes: 34 additions & 0 deletions src/key_command/impl_from_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ impl std::str::FromStr for Command {

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_CUT_FILES_EXPORT, Self::CutFilesExport);
simple_command_conversion_case!(command, CMD_COPY_FILES_EXPORT, Self::CopyFilesExport);
simple_command_conversion_case!(command, CMD_COPY_FILENAME, Self::CopyFileName);
simple_command_conversion_case!(
command,
Expand Down Expand Up @@ -230,6 +232,21 @@ impl std::str::FromStr for Command {
}
}
Ok(Self::SymlinkFiles { relative })
} else if command == CMD_SYMLINK_FILES_EXPORT {
let mut relative = false;
for arg in arg.split_whitespace() {
match arg {
"--relative=true" => relative = true,
"--relative=false" => relative = false,
_ => {
return Err(AppError::new(
AppErrorKind::UnrecognizedArgument,
format!("{}: unknown option '{}'", command, arg),
));
}
}
}
Ok(Self::SymlinkFilesExport { relative })
} else if command == CMD_COPY_FILEPATH {
let mut all_selected = false;
for arg in arg.split_whitespace() {
Expand Down Expand Up @@ -262,6 +279,23 @@ impl std::str::FromStr for Command {
}
}
Ok(Self::PasteFiles { options })
} else if command == CMD_PASTE_FILES_IMPORT {
let mut options = FileOperationOptions::default();
for arg in arg.split_whitespace() {
match arg {
"--overwrite=true" => options.overwrite = true,
"--skip_exist=true" => options.skip_exist = true,
"--overwrite=false" => options.overwrite = false,
"--skip_exist=false" => options.skip_exist = false,
_ => {
return Err(AppError::new(
AppErrorKind::UnrecognizedArgument,
format!("{}: unknown option '{}'", command, arg),
));
}
}
}
Ok(Self::PasteFilesImport { options })
} else if command == CMD_DELETE_FILES {
let [mut permanently, mut background, mut noconfirm] = [false; 3];
for arg in arg.split_whitespace() {
Expand Down
Loading