summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2021-10-29 17:31:19 +0200
committerCanop <cano.petrole@gmail.com>2021-10-29 17:31:19 +0200
commit5fe9b447a45a7a0396b584107a422b424e9737c5 (patch)
tree3b5b2493d1e97c4dfef837a7cdb029ad58802041 /src
parent395c8510fff4bbe511a922a38f549678a31fefdf (diff)
bunch of small improvements of clipboard & input field
Diffstat (limited to 'src')
-rw-r--r--src/app/app.rs58
-rw-r--r--src/app/panel.rs4
-rw-r--r--src/command/panel_input.rs82
-rw-r--r--src/task_sync.rs16
-rw-r--r--src/tree/tree.rs2
-rw-r--r--src/verb/internal.rs2
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,