diff options
author | Canop <cano.petrole@gmail.com> | 2021-10-29 17:31:19 +0200 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2021-10-29 17:31:19 +0200 |
commit | 5fe9b447a45a7a0396b584107a422b424e9737c5 (patch) | |
tree | 3b5b2493d1e97c4dfef837a7cdb029ad58802041 /src | |
parent | 395c8510fff4bbe511a922a38f549678a31fefdf (diff) |
bunch of small improvements of clipboard & input field
Diffstat (limited to 'src')
-rw-r--r-- | src/app/app.rs | 58 | ||||
-rw-r--r-- | src/app/panel.rs | 4 | ||||
-rw-r--r-- | src/command/panel_input.rs | 82 | ||||
-rw-r--r-- | src/task_sync.rs | 16 | ||||
-rw-r--r-- | src/tree/tree.rs | 2 | ||||
-rw-r--r-- | src/verb/internal.rs | 2 |
6 files changed, 103 insertions, 61 deletions
diff --git a/src/app/app.rs b/src/app/app.rs index 31d4c16..f25f777 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -19,14 +19,14 @@ use { Sender, unbounded, }, - crossterm::event::KeyModifiers, + crossterm::event::Event, std::{ io::Write, path::PathBuf, sync::{Arc, Mutex}, }, strict::NonEmptyVec, - termimad::{Event, EventSource}, + termimad::EventSource, }; @@ -663,6 +663,13 @@ impl App { con: &AppContext, conf: &Conf, ) -> Result<Option<Launchable>, ProgramError> { + #[cfg(feature = "clipboard")] + { + // different systems have different clipboard capabilities + // and it may be useful to know which one we have + debug!("Clipboard backend: {:?}", terminal_clipboard::get_type()); + } + // we listen for events in a separate thread so that we can go on listening // when a long search is running, and interrupt it if needed let event_source = EventSource::new()?; @@ -709,33 +716,36 @@ impl App { match dam.next(&self.rx_seqs) { Either::First(Some(event)) => { info!("event: {:?}", &event); - match event { - Event::Click(x, y, KeyModifiers::NONE) - if self.clicked_panel_index(x, y) != self.active_panel_idx => - { + let mut handled = false; + + // app level handling + if let Some((x, y)) = event.as_click() { + if self.clicked_panel_index(x, y) != self.active_panel_idx { // panel activation click - // this will be cleaner when if let will be allowed in match guards with - // chaining (currently experimental) self.active_panel_idx = self.clicked_panel_index(x, y); + handled = true; } - Event::Resize(w, h) => { - self.screen.set_terminal_size(w, h, con); - Areas::resize_all( - self.panels.as_mut_slice(), - self.screen, - self.preview_panel.is_some(), - )?; - for panel in &mut self.panels { - panel.mut_state().refresh(self.screen, con); - } - } - _ => { - // event handled by the panel - let cmd = self.mut_panel().add_event(w, event, &app_state, con)?; - debug!("command after add_event: {:?}", &cmd); - self.apply_command(w, cmd, &skin.focused, &mut app_state, con)?; + } else if let Event::Resize(w, h) = event.event { + self.screen.set_terminal_size(w, h, con); + Areas::resize_all( + self.panels.as_mut_slice(), + self.screen, + self.preview_panel.is_some(), + )?; + for panel in &mut self.panels { + panel.mut_state().refresh(self.screen, con); } + handled = true; } + + // event handled by the panel + if !handled { + let cmd = self.mut_panel().add_event(w, event, &app_state, con)?; + debug!("command after add_event: {:?}", &cmd); + self.apply_command(w, cmd, &skin.focused, &mut app_state, con)?; + + } + event_source.unblock(self.quitting); } Either::First(None) => { diff --git a/src/app/panel.rs b/src/app/panel.rs index 57aa2f3..24ee154 100644 --- a/src/app/panel.rs +++ b/src/app/panel.rs @@ -19,7 +19,7 @@ use { }, termimad::{ minimad::{Alignment, Composite}, - Event, + TimedEvent, }, }; @@ -126,7 +126,7 @@ impl Panel { pub fn add_event( &mut self, w: &mut W, - event: Event, + event: TimedEvent, app_state: &AppState, con: &AppContext, ) -> Result<Command, ProgramError> { diff --git a/src/command/panel_input.rs b/src/command/panel_input.rs index b387c88..419447b 100644 --- a/src/command/panel_input.rs +++ b/src/command/panel_input.rs @@ -10,10 +10,17 @@ use { }, crossterm::{ cursor, - event::KeyEvent, + event::{ + Event, + KeyEvent, + KeyModifiers, + MouseButton, + MouseEvent, + MouseEventKind, + }, queue, }, - termimad::{Area, Event, InputField}, + termimad::{Area, TimedEvent, InputField}, }; /// Wrap the input of a panel, receive events and make commands @@ -69,7 +76,7 @@ impl PanelInput { pub fn on_event( &mut self, w: &mut W, - event: Event, + event: TimedEvent, con: &AppContext, sel_info: SelInfo<'_>, app_state: &AppState, @@ -109,6 +116,22 @@ impl PanelInput { Internal::input_go_to_start => self.input_field.move_to_start(), Internal::input_go_to_end => self.input_field.move_to_end(), #[cfg(feature = "clipboard")] + Internal::input_selection_cut => { + let s = self.input_field.cut_selection(); + if let Err(err) = terminal_clipboard::set_string(s) { + warn!("error in writing into clipboard: {}", err); + } + true + } + #[cfg(feature = "clipboard")] + Internal::input_selection_copy => { + let s = self.input_field.copy_selection(); + if let Err(err) = terminal_clipboard::set_string(s) { + warn!("error in writing into clipboard: {}", err); + } + true + } + #[cfg(feature = "clipboard")] Internal::input_paste => { match terminal_clipboard::get_string() { Ok(pasted) => { @@ -158,22 +181,40 @@ impl PanelInput { /// - build a command fn get_command( &mut self, - event: Event, + timed_event: TimedEvent, con: &AppContext, sel_info: SelInfo<'_>, app_state: &AppState, mode: Mode, ) -> Command { - match event { - Event::Click(x, y, ..) => { - return if self.input_field.apply_event(&event) { + match timed_event.event { + Event::Mouse(MouseEvent { kind, column, row, modifiers: KeyModifiers::NONE }) => { + if self.input_field.apply_timed_event(timed_event) { Command::empty() } else { - Command::Click(x, y) - }; - } - Event::DoubleClick(x, y) => { - return Command::DoubleClick(x, y); + match kind { + MouseEventKind::Up(MouseButton::Left) => { + if timed_event.double_click { + Command::DoubleClick(column, row) + } else { + Command::Click(column, row) + } + } + MouseEventKind::ScrollDown => { + Command::Internal { + internal: Internal::line_down_no_cycle, + input_invocation: None, + } + } + MouseEventKind::ScrollUp => { + Command::Internal { + internal: Internal::line_up_no_cycle, + input_invocation: None, + } + } + _ => Command::None, + } + } } Event::Key(key) => { // value of raw and parts before any key related change @@ -310,25 +351,14 @@ impl PanelInput { // input field management if mode == Mode::Input { - if self.input_field.apply_event(&event) { + if self.input_field.apply_timed_event(timed_event) { return Command::from_raw(self.input_field.get_content(), false); } } + Command::None } - Event::Wheel(lines_count) => { - let internal = if lines_count > 0 { - Internal::line_down_no_cycle - } else { - Internal::line_up_no_cycle - }; - return Command::Internal { - internal, - input_invocation: None, - }; - } - _ => {} + _ => Command::None, } - Command::None } } diff --git a/src/task_sync.rs b/src/task_sync.rs index d1dc926..d34d309 100644 --- a/src/task_sync.rs +++ b/src/task_sync.rs @@ -1,7 +1,7 @@ use { crossbeam::channel::{self, bounded, select, Receiver}, std::thread, - termimad::Event, + termimad::TimedEvent, }; pub enum Either<A, B> { @@ -36,12 +36,12 @@ impl<V> ComputationResult<V> { /// to stop (the computation function checking `has_event`) /// or drop the computation. pub struct Dam { - receiver: Receiver<Event>, - in_dam: Option<Event>, + receiver: Receiver<TimedEvent>, + in_dam: Option<TimedEvent>, } impl Dam { - pub fn from(receiver: Receiver<Event>) -> Self { + pub fn from(receiver: Receiver<TimedEvent>) -> Self { Self { receiver, in_dam: None, @@ -120,7 +120,7 @@ impl Dam { /// no event means the source is dead (i.e. we /// must quit broot) /// There's no event kept in dam after this call. - pub fn next_event(&mut self) -> Option<Event> { + pub fn next_event(&mut self) -> Option<TimedEvent> { if self.in_dam.is_some() { self.in_dam.take() } else { @@ -134,8 +134,8 @@ impl Dam { } } - // or maybed return either Option<Event> or Option<T> ? - pub fn next<T>(&mut self, other: &Receiver<T>) -> Either<Option<Event>, Option<T>> { + // or maybed return either Option<TimedEvent> or Option<T> ? + pub fn next<T>(&mut self, other: &Receiver<T>) -> Either<Option<TimedEvent>, Option<T>> { if self.in_dam.is_some() { Either::First(self.in_dam.take()) } else { @@ -160,7 +160,7 @@ impl Dam { } pub struct DamObserver { - receiver: Receiver<Event>, + receiver: Receiver<TimedEvent>, } impl DamObserver { pub fn from(dam: &Dam) -> Self { diff --git a/src/tree/tree.rs b/src/tree/tree.rs index 4515bbb..822f4e5 100644 --- a/src/tree/tree.rs +++ b/src/tree/tree.rs @@ -81,7 +81,7 @@ impl Tree { if let Some(parent_bid) = line.parent_bid { bid_parents.insert(line.bid, parent_bid); } - bid_lines.insert(line.bid, &line); + bid_lines.insert(line.bid, line); } let mut sort_paths: FnvHashMap<BId, String> = FnvHashMap::default(); for line in self.lines[1..].iter() { diff --git a/src/verb/internal.rs b/src/verb/internal.rs index 9e96181..136e718 100644 --- a/src/verb/internal.rs +++ b/src/verb/internal.rs @@ -72,6 +72,8 @@ Internals! { input_go_to_start: "move the cursor to the start of input" false, input_go_word_left: "move the cursor one word to the left" false, input_go_word_right: "move the cursor one word to the right" false, + input_selection_copy: "copy the selected part of the input into the selection" false, + input_selection_cut: "cut the selected part of the input into the selection" false, input_paste: "paste the clipboard content into the input" false, line_down: "move one line down" false, line_up: "move one line up" false, |