summaryrefslogtreecommitdiffstats
path: root/src/run.rs
blob: bb33c6591ec26bed2de203e8d4b4d842c2f30f5e (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use std::thread;

use crate::commands::{CommandKeybind, CursorMoveUp, JoshutoRunnable};
use crate::config::{JoshutoCommandMapping, JoshutoConfig};
use crate::context::{JoshutoContext, MESSAGE_VISIBLE_DURATION};
use crate::tab::JoshutoTab;
use crate::ui;
use crate::ui::widgets::{TuiCommandMenu, TuiView};
use crate::util::event::Event;

pub fn run(config_t: JoshutoConfig, keymap_t: JoshutoCommandMapping) -> std::io::Result<()> {
    let mut backend: ui::TuiBackend = ui::TuiBackend::new()?;

    let mut context = JoshutoContext::new(config_t);
    let curr_path = std::env::current_dir()?;

    {
        // Initialize an initial tab
        let tab = JoshutoTab::new(curr_path, &context.config_t.sort_option)?;
        context.push_tab(tab);

        // move the cursor by 0 just to trigger a preview of child
        let tmp = CursorMoveUp::new(0);
        tmp.execute(&mut context, &mut backend);

        // render our view
        let mut view = TuiView::new(&context);
        backend.render(&mut view);
    }

    let mut io_handle = None;
    while !context.exit {
        /* checking if there are workers that need to be run */
        if !context.worker_queue.is_empty() {
            if let None = io_handle.as_ref() {
                let worker = context.worker_queue.pop_front().unwrap();
                io_handle = {
                    let event_tx = context.events.event_tx.clone();
                    let thread = thread::spawn(move || {
                        worker.start();
                        while let Ok(evt) = worker.recv() {
                            let _ = event_tx.send(evt);
                        }
                        worker.handle.join();
                        let _ = event_tx.send(Event::IOWorkerResult);
                    });
                    Some(thread)
                };
            }
        }

        match context.events.next() {
            Ok(event) => {
                match event {
                    Event::IOWorkerProgress(p) => {
                        context.worker_msg = Some(format!("bytes copied {}", p));
                    }
                    Event::IOWorkerResult => {
                        match io_handle {
                            Some(handle) => {
                                handle.join();
                                context
                                    .message_queue
                                    .push_back("io_worker done".to_string());
                            }
                            None => {}
                        }
                        io_handle = None;
                        context.worker_msg = None;
                    }
                    Event::Input(key) => {
                        /* Message handling */
                        if !context.message_queue.is_empty() {
                            if context.message_elapse < MESSAGE_VISIBLE_DURATION {
                                context.message_elapse += 1;
                            } else {
                                let _ = context.message_queue.pop_front();
                                context.message_elapse = 0;
                            }
                        }
                        match keymap_t.get(&key) {
                            None => {
                                context
                                    .message_queue
                                    .push_back(format!("Unknown keycode: {:?}", key));
                            }
                            Some(CommandKeybind::SimpleKeybind(command)) => {
                                if let Err(e) = command.execute(&mut context, &mut backend) {
                                    context.message_queue.push_back(e.to_string());
                                }
                            }
                            Some(CommandKeybind::CompositeKeybind(m)) => {
                                let mut map: &JoshutoCommandMapping = &m;

                                let cmd = {
                                    let mut menu = TuiCommandMenu::new();
                                    menu.get_input(&mut backend, &context, map)
                                };

                                if let Some(command) = cmd {
                                    if let Err(e) = command.execute(&mut context, &mut backend) {
                                        context.message_queue.push_back(e.to_string());
                                    }
                                }
                            }
                        }
                    }
                }
                let mut view = TuiView::new(&context);
                backend.render(&mut view);
            }
            Err(e) => {
                context.message_queue.push_back(e.to_string());
                break;
            }
        }
    }
    eprintln!("{:#?}", context.message_queue);
    Ok(())
}