mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 01:26:04 -08:00
Copy feature in ui; new keybinding <C>
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
|
||||
## 0.2.0
|
||||
|
||||
Released on ??
|
||||
Released on 21/12/2020
|
||||
|
||||
> The Bookmarks Update
|
||||
|
||||
@@ -24,6 +24,9 @@ Released on ??
|
||||
- **Text Editor**
|
||||
- Added text editor feature to explorer view
|
||||
- Added `o` to keybindings to open a text file
|
||||
- Keybindings:
|
||||
- `C`: Copy file/directory
|
||||
- `O`: Open text file in editor
|
||||
- Enhancements:
|
||||
- User interface
|
||||
- Collpased borders to make everything more *aesthetic*
|
||||
|
||||
@@ -244,6 +244,7 @@ Text editor is automatically found using this [awesome crate](https://github.com
|
||||
| `<PGDOWN>` | Move down in selected list by 8 rows |
|
||||
| `<ENTER>` | Enter directory |
|
||||
| `<SPACE>` | Upload / download selected file |
|
||||
| `<C>` | Copy file/directory |
|
||||
| `<D>` | Make directory |
|
||||
| `<E>` | Delete file (Same as `CANC`) |
|
||||
| `<G>` | Go to supplied path |
|
||||
|
||||
@@ -830,7 +830,7 @@ mod tests {
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
#[test]
|
||||
fn test_host_copy_file() {
|
||||
fn test_host_copy_file_absolute() {
|
||||
let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap();
|
||||
// Create file in tmpdir
|
||||
let mut file1_path: PathBuf = PathBuf::from(tmpdir.path());
|
||||
@@ -851,6 +851,28 @@ mod tests {
|
||||
assert_eq!(host.files.len(), 2);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
#[test]
|
||||
fn test_host_copy_file_relative() {
|
||||
let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap();
|
||||
// Create file in tmpdir
|
||||
let mut file1_path: PathBuf = PathBuf::from(tmpdir.path());
|
||||
file1_path.push("foo.txt");
|
||||
// Write file 1
|
||||
let mut file1: File = File::create(file1_path.as_path()).ok().unwrap();
|
||||
assert!(file1.write_all(b"Hello world!\n").is_ok());
|
||||
// Get file 2 path
|
||||
let file2_path: PathBuf = PathBuf::from("bar.txt");
|
||||
// Create host
|
||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||
let file1_entry: FsEntry = host.files.get(0).unwrap().clone();
|
||||
assert_eq!(file1_entry.get_name(), String::from("foo.txt"));
|
||||
// Copy
|
||||
assert!(host.copy(&file1_entry, file2_path.as_path()).is_ok());
|
||||
// Verify host has two files
|
||||
assert_eq!(host.files.len(), 2);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
#[test]
|
||||
fn test_hop_copy_directory_absolute() {
|
||||
|
||||
@@ -62,6 +62,77 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
/// ### callback_copy
|
||||
///
|
||||
/// Callback for COPY command (both from local and remote)
|
||||
pub(super) fn callback_copy(&mut self, input: String) {
|
||||
let dest_path: PathBuf = PathBuf::from(input);
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => {
|
||||
// Get selected entry
|
||||
if self.local.files.get(self.local.index).is_some() {
|
||||
let entry: FsEntry = self.local.files.get(self.local.index).unwrap().clone();
|
||||
if let Some(ctx) = self.context.as_mut() {
|
||||
match ctx.local.copy(&entry, dest_path.as_path()) {
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Copied \"{}\" to \"{}\"",
|
||||
entry.get_abs_path().display(),
|
||||
dest_path.display()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
// Reload entries
|
||||
let wrkdir: PathBuf = self.local.wrkdir.clone();
|
||||
self.local_scan(wrkdir.as_path());
|
||||
}
|
||||
Err(err) => self.log_and_alert(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not copy \"{}\" to \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
dest_path.display(),
|
||||
err
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FileExplorerTab::Remote => {
|
||||
// Get selected entry
|
||||
if self.remote.files.get(self.remote.index).is_some() {
|
||||
let entry: FsEntry = self.remote.files.get(self.remote.index).unwrap().clone();
|
||||
match self.client.as_mut().copy(&entry, dest_path.as_path()) {
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Copied \"{}\" to \"{}\"",
|
||||
entry.get_abs_path().display(),
|
||||
dest_path.display()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
self.reload_remote_dir();
|
||||
}
|
||||
Err(err) => self.log_and_alert(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not copy \"{}\" to \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
dest_path.display(),
|
||||
err
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ### callback_mkdir
|
||||
///
|
||||
/// Callback for MKDIR command (supports both local and remote)
|
||||
|
||||
@@ -177,6 +177,20 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
KeyCode::Char(ch) => match ch {
|
||||
'c' | 'C' => {
|
||||
// Copy
|
||||
self.input_mode = InputMode::Popup(PopupType::Input(
|
||||
String::from("Insert destination name"),
|
||||
FileTransferActivity::callback_copy,
|
||||
));
|
||||
}
|
||||
'd' | 'D' => {
|
||||
// Make directory
|
||||
self.input_mode = InputMode::Popup(PopupType::Input(
|
||||
String::from("Insert directory name"),
|
||||
FileTransferActivity::callback_mkdir,
|
||||
));
|
||||
}
|
||||
'e' | 'E' => {
|
||||
// Get file at index
|
||||
if let Some(entry) = self.local.files.get(self.local.index) {
|
||||
@@ -201,13 +215,6 @@ impl FileTransferActivity {
|
||||
FileTransferActivity::callback_change_directory,
|
||||
));
|
||||
}
|
||||
'd' | 'D' => {
|
||||
// Make directory
|
||||
self.input_mode = InputMode::Popup(PopupType::Input(
|
||||
String::from("Insert directory name"),
|
||||
FileTransferActivity::callback_mkdir,
|
||||
));
|
||||
}
|
||||
'h' | 'H' => {
|
||||
// Show help
|
||||
self.input_mode = InputMode::Popup(PopupType::Help);
|
||||
@@ -389,6 +396,20 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
KeyCode::Char(ch) => match ch {
|
||||
'c' | 'C' => {
|
||||
// Copy
|
||||
self.input_mode = InputMode::Popup(PopupType::Input(
|
||||
String::from("Insert destination name"),
|
||||
FileTransferActivity::callback_copy,
|
||||
));
|
||||
}
|
||||
'd' | 'D' => {
|
||||
// Make directory
|
||||
self.input_mode = InputMode::Popup(PopupType::Input(
|
||||
String::from("Insert directory name"),
|
||||
FileTransferActivity::callback_mkdir,
|
||||
));
|
||||
}
|
||||
'e' | 'E' => {
|
||||
// Get file at index
|
||||
if let Some(entry) = self.remote.files.get(self.remote.index) {
|
||||
@@ -405,13 +426,6 @@ impl FileTransferActivity {
|
||||
))
|
||||
}
|
||||
}
|
||||
'd' | 'D' => {
|
||||
// Make directory
|
||||
self.input_mode = InputMode::Popup(PopupType::Input(
|
||||
String::from("Insert directory name"),
|
||||
FileTransferActivity::callback_mkdir,
|
||||
));
|
||||
}
|
||||
'g' | 'G' => {
|
||||
// Goto
|
||||
// Show input popup
|
||||
|
||||
@@ -716,6 +716,16 @@ impl FileTransferActivity {
|
||||
Span::raw(" "),
|
||||
Span::raw("Delete file"),
|
||||
])),
|
||||
ListItem::new(Spans::from(vec![
|
||||
Span::styled(
|
||||
"<C>",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
),
|
||||
Span::raw(" "),
|
||||
Span::raw("Copy"),
|
||||
])),
|
||||
ListItem::new(Spans::from(vec![
|
||||
Span::styled(
|
||||
"<D>",
|
||||
|
||||
Reference in New Issue
Block a user