summaryrefslogtreecommitdiffstats
path: root/src/commands/delete_files.rs
blob: 4f062bc48c92c6cad2c94adb065127da5afb9351 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::path;
use std::sync::mpsc;

use termion::event::Key;

use crate::context::AppContext;
use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult};
use crate::history::DirectoryHistory;
use crate::io::{FileOperation, FileOperationOptions, IoWorkerThread};
use crate::ui::widgets::TuiPrompt;
use crate::ui::AppBackend;

fn delete_files(
    context: &mut AppContext,
    backend: &mut AppBackend,
    background: bool,
    permanently: bool,
) -> JoshutoResult<()> {
    let paths = context
        .tab_context_ref()
        .curr_tab_ref()
        .curr_list_ref()
        .map(|s| s.get_selected_paths())
        .unwrap_or_default();
    let paths_len = paths.len();
    if paths_len == 0 {
        let err = JoshutoError::new(
            JoshutoErrorKind::InvalidParameters,
            "no files selected".to_string(),
        );
        return Err(err);
    }

    let ch = {
        let prompt_str = format!("Delete {} files? (Y/n)", paths_len);
        let mut prompt = TuiPrompt::new(&prompt_str);
        prompt.get_key(backend, context)
    };

    match ch {
        Key::Char('Y') | Key::Char('y') | Key::Char('\n') => {
            let confirm_delete = if paths_len > 1 {
                // prompt user again for deleting multiple files
                let ch = {
                    let prompt_str = "Are you sure? (y/N)";
                    let mut prompt = TuiPrompt::new(prompt_str);
                    prompt.get_key(backend, context)
                };
                ch == Key::Char('y')
            } else {
                true
            };
            if confirm_delete {
                let file_op = FileOperation::Delete;
                let options = FileOperationOptions {
                    overwrite: false,
                    skip_exist: false,
                    permanently: !context.config_ref().use_trash || permanently,
                };

                let dest = path::PathBuf::new();
                let worker_thread = IoWorkerThread::new(file_op, paths.clone(), dest, options);
                if background {
                    context.worker_context_mut().push_worker(worker_thread);
                } else {
                    let (wtx, _) = mpsc::channel();
                    worker_thread.start(wtx)?;
                }

                let history = context.tab_context_mut().curr_tab_mut().history_mut();
                for path in paths.iter().filter(|p| p.is_dir()) {
                    history.remove(path);
                }
            }
            Ok(())
        }
        _ => Ok(()),
    }
}

pub fn delete_selected_files(
    context: &mut AppContext,
    backend: &mut AppBackend,
    background: bool,
    permanently: bool,
) -> JoshutoResult {
    delete_files(context, backend, background, permanently)?;

    let curr_tab = context.tab_context_ref().curr_tab_ref();
    let options = context.config_ref().display_options_ref().clone();
    let curr_path = curr_tab.cwd().to_path_buf();
    for (_, tab) in context.tab_context_mut().iter_mut() {
        let tab_options = tab.option_ref().clone();
        tab.history_mut()
            .reload(&curr_path, &options, &tab_options)?;
    }
    Ok(())
}