Merge pull request #40 from myfreeweb/gtk-clipboard

Add RPC/GTK clipboard provider
This commit is contained in:
daa84 2018-01-01 17:59:59 +03:00 committed by GitHub
commit b88159630d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 4 deletions

View File

@ -4,6 +4,16 @@ if !has('nvim') || exists('g:GuiLoaded')
endif
let g:GuiLoaded = 1
if !exists('g:GuiExternalClipboard')
function! provider#clipboard#Call(method, args) abort
if a:method == 'get'
return [rpcrequest(1, 'Gui', 'Clipboard', 'Get'), 'v']
elseif a:method == 'set'
call rpcnotify(1, 'Gui', 'Clipboard', 'Set', join(a:args[0], ' '))
endif
endfunction
endif
" Set GUI font
function! GuiFont(fname, ...) abort
call rpcnotify(1, 'Gui', 'Font', s:NvimQtToPangoFont(a:fname))
@ -42,4 +52,3 @@ function s:GuiFontCommand(fname, bang) abort
endfunction
command! -nargs=? -bang Guifont call s:GuiFontCommand("<args>", "<bang>")
command! -nargs=? -bang GuiFont call s:GuiFontCommand("<args>", "<bang>")

View File

@ -1,5 +1,5 @@
use std::result;
use std::sync::Arc;
use std::sync::{Arc, mpsc};
use neovim_lib::{Handler, Value};
@ -24,6 +24,7 @@ impl NvimHandler {
match method {
"redraw" => {
self.safe_call(move |ui| {
let ui = &mut ui.borrow_mut();
let mut repaint_mode = RepaintMode::Nothing;
for ev in params {
@ -63,6 +64,7 @@ impl NvimHandler {
if let Value::String(ev_name) = ev_name {
let args = params_iter.collect();
self.safe_call(move |ui| {
let ui = &mut ui.borrow_mut();
redraw_handler::call_gui_event(
ui,
ev_name.as_str().ok_or_else(|| "Event name does not exists")?,
@ -87,14 +89,56 @@ impl NvimHandler {
}
}
fn nvim_cb_req (&self, method: &str, params: Vec<Value>) -> result::Result<Value, Value> {
match method {
"Gui" => {
if !params.is_empty() {
let mut params_iter = params.into_iter();
if let Some(req_name) = params_iter.next() {
if let Value::String(req_name) = req_name {
let args = params_iter.collect();
let (sender, receiver) = mpsc::channel();
self.safe_call(move |ui| {
sender.send(redraw_handler::call_gui_request(
&ui.clone(),
req_name.as_str().ok_or_else(|| "Event name does not exists")?,
&args,
)).unwrap();
{
let ui = &mut ui.borrow_mut();
ui.on_redraw(&RepaintMode::All);
}
Ok(())
});
Ok(receiver.recv().unwrap()?)
} else {
error!("Unsupported request");
Err(Value::Nil)
}
} else {
error!("Request name does not exist");
Err(Value::Nil)
}
} else {
error!("Unsupported request {:?}", params);
Err(Value::Nil)
}
},
_ => {
error!("Request {}({:?})", method, params);
Err(Value::Nil)
}
}
}
fn safe_call<F>(&self, cb: F)
where
F: FnOnce(&mut shell::State) -> result::Result<(), String> + 'static + Send,
F: FnOnce(&Arc<UiMutex<shell::State>>) -> result::Result<(), String> + 'static + Send,
{
let mut cb = Some(cb);
let shell = self.shell.clone();
glib::idle_add(move || {
if let Err(msg) = cb.take().unwrap()(&mut shell.borrow_mut()) {
if let Err(msg) = cb.take().unwrap()(&shell) {
error!("Error call function: {}", msg);
}
glib::Continue(false)
@ -106,4 +150,8 @@ impl Handler for NvimHandler {
fn handle_notify(&mut self, name: &str, args: Vec<Value>) {
self.nvim_cb(name, args);
}
fn handle_request(&mut self, name: &str, args: Vec<Value>) -> result::Result<Value, Value> {
self.nvim_cb_req(name, args)
}
}

View File

@ -1,9 +1,12 @@
use std::result;
use std::sync::Arc;
use neovim_lib::{Value, UiOption};
use neovim_lib::neovim_api::Tabpage;
use ui::UiMutex;
use shell;
use gtk::ClipboardExt;
use value::ValueMapExt;
@ -111,6 +114,14 @@ pub fn call_gui_event(
) -> result::Result<(), String> {
match method {
"Font" => ui.set_font(try_str!(args[0])),
"Clipboard" => {
match try_str!(args[0]) {
"Set" => {
ui.clipboard_set(try_str!(args[1]));
},
opt => error!("Unknown option {}", opt),
}
},
"Option" => {
match try_str!(args[0]) {
"Popupmenu" => {
@ -137,6 +148,35 @@ pub fn call_gui_event(
Ok(())
}
pub fn call_gui_request(
ui: &Arc<UiMutex<shell::State>>,
method: &str,
args: &Vec<Value>,
) -> result::Result<Value, Value> {
match method {
"Clipboard" => {
match try_str!(args[0]) {
"Get" => {
// NOTE: wait_for_text waits on the main loop. We can't have the ui borrowed
// while it runs, otherwise ui callbacks will get called and try to borrow
// mutably twice!
let clipboard = {
let ui = &mut ui.borrow_mut();
ui.clipboard.clone()
};
let t = clipboard.wait_for_text().unwrap_or_else(|| String::new());
Ok(Value::Array(t.split("\n").map(|s| s.into()).collect::<Vec<Value>>()))
},
opt => {
error!("Unknown option {}", opt);
Err(Value::Nil)
},
}
},
_ => Err(Value::String(format!("Unsupported request {}({:?})", method, args).into())),
}
}
pub fn call(
ui: &mut shell::State,
method: &str,

View File

@ -80,6 +80,7 @@ pub struct State {
cursor: Option<Cursor>,
popup_menu: RefCell<PopupMenu>,
settings: Rc<RefCell<Settings>>,
pub clipboard: gtk::Clipboard,
pub mode: mode::Mode,
@ -113,6 +114,7 @@ impl State {
cursor: None,
popup_menu,
settings,
clipboard: gtk::Clipboard::get(&gdk::Atom::intern("CLIPBOARD")),
mode: mode::Mode::new(),
@ -201,6 +203,10 @@ impl State {
}
}
pub fn clipboard_set(&self, text: &str) {
self.clipboard.set_text(text);
}
fn close_popup_menu(&self) {
if self.popup_menu.borrow().is_open() {
if let Some(mut nvim) = self.nvim() {