Add RPC/GTK clipboard provider
This commit is contained in:
parent
ae3bc7b0af
commit
fbf6625059
@ -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>")
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user