Skip to content

Commit

Permalink
fix copy to the linux system clipboard (#120)
Browse files Browse the repository at this point in the history
* Fixed the problem the text from vim was not copied in os clipboard

* Remove CopyData action handle, because it's handled in app mod

* cargo fmt fixes

* return CopyData action in editor, and add check to termux arboard clipboard

* remove duplicate code

* fix clippy
  • Loading branch information
Distantoff authored Oct 20, 2024
1 parent 5301bce commit 6ee8551
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 100 deletions.
21 changes: 21 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::{borrow::Borrow, fmt::format, sync::Arc};

#[cfg(not(feature = "termux"))]
use arboard::Clipboard;
use color_eyre::eyre::Result;
use crossterm::event::{Event, KeyCode, KeyEvent, MouseButton, MouseEvent, MouseEventKind};
use futures::{task::Poll, FutureExt};
Expand Down Expand Up @@ -160,6 +162,10 @@ where
let mut tui = tui::Tui::new()?.mouse(self.mouse_mode_override.or(self.config.settings.mouse_mode));
tui.enter()?;

#[allow(unused_mut)]
#[cfg(not(feature = "termux"))]
let mut clipboard = Clipboard::new();

self.components.menu.register_action_handler(action_tx.clone())?;
self.components.editor.register_action_handler(action_tx.clone())?;
self.components.history.register_action_handler(action_tx.clone())?;
Expand Down Expand Up @@ -450,6 +456,21 @@ where
Action::ClearHistory => {
self.clear_history();
},
Action::CopyData(data) => {
#[cfg(not(feature = "termux"))]
{
clipboard.as_mut().map_or_else(
|e| {
log::error!("{e:?}");
},
|clipboard| {
clipboard.set_text(data).unwrap_or_else(|e| {
log::error!("{e:?}");
})
},
);
}
},
_ => {},
}
if !action_consumed {
Expand Down
4 changes: 2 additions & 2 deletions src/components/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub struct Data<'a> {
explain_max_y_offset: u16,
}

impl<'a> Data<'a> {
impl Data<'_> {
pub fn new() -> Self {
Data {
command_tx: None,
Expand Down Expand Up @@ -232,7 +232,7 @@ impl<'a> SettableDataTable<'a> for Data<'a> {
}
}

impl<'a, DB: Database> Component<DB> for Data<'a> {
impl<DB: Database> Component<DB> for Data<'_> {
fn register_action_handler(&mut self, tx: UnboundedSender<Action>) -> Result<()> {
self.command_tx = Some(tx);
Ok(())
Expand Down
31 changes: 8 additions & 23 deletions src/components/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub struct Editor<'a> {
last_query_duration: Option<chrono::Duration>,
}

impl<'a> Editor<'a> {
impl Editor<'_> {
pub fn new() -> Self {
let mut textarea = TextArea::default();
textarea.set_search_pattern(keyword_regex()).unwrap();
Expand All @@ -78,6 +78,7 @@ impl<'a> Editor<'a> {
if let Some(sender) = &self.command_tx {
sender.send(Action::Query(self.textarea.lines().to_vec(), false))?;
self.vim_state = Vim::new(Mode::Normal);
self.vim_state.register_action_handler(self.command_tx.clone())?;
self.cursor_style = Mode::Normal.cursor_style();
}
}
Expand Down Expand Up @@ -107,14 +108,16 @@ impl<'a> Editor<'a> {
Transition::Nop | Transition::Mode(_) => new_vim_state,
Transition::Pending(input) => new_vim_state.with_pending(input),
};
self.vim_state.register_action_handler(self.command_tx.clone())?;
},
};
Ok(())
}
}

impl<'a, DB: Database + DatabaseQueries> Component<DB> for Editor<'a> {
impl<DB: Database + DatabaseQueries> Component<DB> for Editor<'_> {
fn register_action_handler(&mut self, tx: UnboundedSender<Action>) -> Result<()> {
self.vim_state.register_action_handler(self.command_tx.clone())?;
self.command_tx = Some(tx);
Ok(())
}
Expand Down Expand Up @@ -188,31 +191,13 @@ impl<'a, DB: Database + DatabaseQueries> Component<DB> for Editor<'a> {
sender.send(Action::Query(self.textarea.lines().to_vec(), false))?;
}
},
Action::CopyData(data) => {
#[cfg(not(feature = "termux"))]
{
Clipboard::new().map_or_else(
|e| {
log::error!("{e:?}");
},
|mut clipboard| {
clipboard.set_text(data.clone()).unwrap_or_else(|e| {
log::error!("{e:?}");
})
},
);
// also set textarea buffer as a fallback
self.textarea.set_yank_text(data.clone());
}
#[cfg(feature = "termux")]
{
self.textarea.set_yank_text(data);
}
},
Action::HistoryToEditor(lines) => {
self.textarea = TextArea::from(lines.clone());
self.textarea.set_search_pattern(keyword_regex()).unwrap();
},
Action::CopyData(data) => {
self.textarea.set_yank_text(data);
},
_ => {},
}
Ok(None)
Expand Down
2 changes: 1 addition & 1 deletion src/components/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl Menu {
}
}

impl<'a> SettableTableList<'a> for Menu {
impl SettableTableList<'_> for Menu {
fn set_table_list(&mut self, data: Option<Result<Rows, DbError>>) {
log::info!("setting menu table list");
self.table_map = IndexMap::new();
Expand Down
4 changes: 2 additions & 2 deletions src/components/scroll_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ impl<'a> ScrollTable<'a> {
}
}

impl<'a, DB: Database> Component<DB> for ScrollTable<'a> {
impl<DB: Database> Component<DB> for ScrollTable<'_> {
fn draw(&mut self, f: &mut Frame<'_>, area: Rect, app_state: &AppState<'_, DB>) -> Result<()> {
self.parent_area = area;
let render_area = self.block.inner_if_some(area);
Expand Down Expand Up @@ -252,7 +252,7 @@ impl<'a> Renderer<'a> {
}
}

impl<'a> Widget for Renderer<'a> {
impl Widget for Renderer<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let scrollable = self.0;
let table = &scrollable.table;
Expand Down
94 changes: 22 additions & 72 deletions src/vim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ use ratatui::{
widgets::{Block, Borders},
Terminal,
};
use tokio::sync::mpsc::UnboundedSender;
use tui_textarea::{CursorMove, Input, Key, Scrolling, TextArea};

use crate::action::Action;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Mode {
#[default]
Expand Down Expand Up @@ -93,15 +96,21 @@ pub enum Transition {
pub struct Vim {
pub mode: Mode,
pub pending: Input, // Pending input to handle a sequence with two keys like gg
command_tx: Option<UnboundedSender<Action>>,
}

impl Vim {
pub fn new(mode: Mode) -> Self {
Self { mode, pending: Input::default() }
Self { mode, pending: Input::default(), command_tx: None }
}

pub fn with_pending(self, pending: Input) -> Self {
Self { mode: self.mode, pending }
Self { mode: self.mode, pending, command_tx: None }
}

pub fn register_action_handler(&mut self, tx: Option<UnboundedSender<Action>>) -> Result<()> {
self.command_tx = tx;
Ok(())
}

pub fn transition(&self, input: Input, textarea: &mut TextArea<'_>) -> Transition {
Expand Down Expand Up @@ -174,20 +183,7 @@ impl Vim {
}
}
textarea.cut();
let text = textarea.yank_text();
#[cfg(not(feature = "termux"))]
{
Clipboard::new().map_or_else(
|e| {
log::error!("{e:?}");
},
|mut clipboard| {
clipboard.set_text(text).unwrap_or_else(|e| {
log::error!("{e:?}");
})
},
);
}
self.send_copy_action_with_text(textarea.yank_text());
return Transition::Mode(Mode::Normal);
},
Input { key: Key::Char('i'), .. } => {
Expand Down Expand Up @@ -288,20 +284,7 @@ impl Vim {
}
}
textarea.copy();
let text = textarea.yank_text();
#[cfg(not(feature = "termux"))]
{
Clipboard::new().map_or_else(
|e| {
log::error!("{e:?}");
},
|mut clipboard| {
clipboard.set_text(text).unwrap_or_else(|e| {
log::error!("{e:?}");
})
},
);
}
self.send_copy_action_with_text(textarea.yank_text());
return Transition::Mode(Mode::Normal);
},
Input { key: Key::Char('d'), ctrl: false, .. } if self.mode == Mode::Visual => {
Expand All @@ -328,20 +311,7 @@ impl Vim {
}
}
textarea.cut();
let text = textarea.yank_text();
#[cfg(not(feature = "termux"))]
{
Clipboard::new().map_or_else(
|e| {
log::error!("{e:?}");
},
|mut clipboard| {
clipboard.set_text(text).unwrap_or_else(|e| {
log::error!("{e:?}");
})
},
);
}
self.send_copy_action_with_text(textarea.yank_text());
return Transition::Mode(Mode::Insert);
},
Input { key: Key::Esc, .. } => {
Expand All @@ -355,20 +325,7 @@ impl Vim {
match self.mode {
Mode::Operator('y') => {
textarea.copy();
let text = textarea.yank_text();
#[cfg(not(feature = "termux"))]
{
Clipboard::new().map_or_else(
|e| {
log::error!("{e:?}");
},
|mut clipboard| {
clipboard.set_text(text).unwrap_or_else(|e| {
log::error!("{e:?}");
})
},
);
}
self.send_copy_action_with_text(textarea.yank_text());
Transition::Mode(Mode::Normal)
},
Mode::Operator('d') => {
Expand All @@ -377,20 +334,7 @@ impl Vim {
},
Mode::Operator('c') => {
textarea.cut();
let text = textarea.yank_text();
#[cfg(not(feature = "termux"))]
{
Clipboard::new().map_or_else(
|e| {
log::error!("{e:?}");
},
|mut clipboard| {
clipboard.set_text(text).unwrap_or_else(|e| {
log::error!("{e:?}");
})
},
);
}
self.send_copy_action_with_text(textarea.yank_text());
Transition::Mode(Mode::Insert)
},
_ => Transition::Nop,
Expand All @@ -417,4 +361,10 @@ impl Vim {
},
}
}

fn send_copy_action_with_text(&self, text: String) {
if let Some(sender) = &self.command_tx {
sender.send(Action::CopyData(text)).map_or_else(|e| log::error!("{e:?}"), |_| {});
}
}
}

0 comments on commit 6ee8551

Please sign in to comment.