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
|
endif
|
||||||
let g:GuiLoaded = 1
|
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
|
" Set GUI font
|
||||||
function! GuiFont(fname, ...) abort
|
function! GuiFont(fname, ...) abort
|
||||||
call rpcnotify(1, 'Gui', 'Font', s:NvimQtToPangoFont(a:fname))
|
call rpcnotify(1, 'Gui', 'Font', s:NvimQtToPangoFont(a:fname))
|
||||||
@ -42,4 +52,3 @@ function s:GuiFontCommand(fname, bang) abort
|
|||||||
endfunction
|
endfunction
|
||||||
command! -nargs=? -bang Guifont call s:GuiFontCommand("<args>", "<bang>")
|
command! -nargs=? -bang Guifont call s:GuiFontCommand("<args>", "<bang>")
|
||||||
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::result;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, mpsc};
|
||||||
|
|
||||||
use neovim_lib::{Handler, Value};
|
use neovim_lib::{Handler, Value};
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ impl NvimHandler {
|
|||||||
match method {
|
match method {
|
||||||
"redraw" => {
|
"redraw" => {
|
||||||
self.safe_call(move |ui| {
|
self.safe_call(move |ui| {
|
||||||
|
let ui = &mut ui.borrow_mut();
|
||||||
let mut repaint_mode = RepaintMode::Nothing;
|
let mut repaint_mode = RepaintMode::Nothing;
|
||||||
|
|
||||||
for ev in params {
|
for ev in params {
|
||||||
@ -63,6 +64,7 @@ impl NvimHandler {
|
|||||||
if let Value::String(ev_name) = ev_name {
|
if let Value::String(ev_name) = ev_name {
|
||||||
let args = params_iter.collect();
|
let args = params_iter.collect();
|
||||||
self.safe_call(move |ui| {
|
self.safe_call(move |ui| {
|
||||||
|
let ui = &mut ui.borrow_mut();
|
||||||
redraw_handler::call_gui_event(
|
redraw_handler::call_gui_event(
|
||||||
ui,
|
ui,
|
||||||
ev_name.as_str().ok_or_else(|| "Event name does not exists")?,
|
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)
|
fn safe_call<F>(&self, cb: F)
|
||||||
where
|
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 mut cb = Some(cb);
|
||||||
let shell = self.shell.clone();
|
let shell = self.shell.clone();
|
||||||
glib::idle_add(move || {
|
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);
|
error!("Error call function: {}", msg);
|
||||||
}
|
}
|
||||||
glib::Continue(false)
|
glib::Continue(false)
|
||||||
@ -106,4 +150,8 @@ impl Handler for NvimHandler {
|
|||||||
fn handle_notify(&mut self, name: &str, args: Vec<Value>) {
|
fn handle_notify(&mut self, name: &str, args: Vec<Value>) {
|
||||||
self.nvim_cb(name, args);
|
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::result;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use neovim_lib::{Value, UiOption};
|
use neovim_lib::{Value, UiOption};
|
||||||
use neovim_lib::neovim_api::Tabpage;
|
use neovim_lib::neovim_api::Tabpage;
|
||||||
|
|
||||||
|
use ui::UiMutex;
|
||||||
use shell;
|
use shell;
|
||||||
|
use gtk::ClipboardExt;
|
||||||
|
|
||||||
use value::ValueMapExt;
|
use value::ValueMapExt;
|
||||||
|
|
||||||
@ -111,6 +114,14 @@ pub fn call_gui_event(
|
|||||||
) -> result::Result<(), String> {
|
) -> result::Result<(), String> {
|
||||||
match method {
|
match method {
|
||||||
"Font" => ui.set_font(try_str!(args[0])),
|
"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" => {
|
"Option" => {
|
||||||
match try_str!(args[0]) {
|
match try_str!(args[0]) {
|
||||||
"Popupmenu" => {
|
"Popupmenu" => {
|
||||||
@ -137,6 +148,35 @@ pub fn call_gui_event(
|
|||||||
Ok(())
|
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(
|
pub fn call(
|
||||||
ui: &mut shell::State,
|
ui: &mut shell::State,
|
||||||
method: &str,
|
method: &str,
|
||||||
|
@ -80,6 +80,7 @@ pub struct State {
|
|||||||
cursor: Option<Cursor>,
|
cursor: Option<Cursor>,
|
||||||
popup_menu: RefCell<PopupMenu>,
|
popup_menu: RefCell<PopupMenu>,
|
||||||
settings: Rc<RefCell<Settings>>,
|
settings: Rc<RefCell<Settings>>,
|
||||||
|
pub clipboard: gtk::Clipboard,
|
||||||
|
|
||||||
pub mode: mode::Mode,
|
pub mode: mode::Mode,
|
||||||
|
|
||||||
@ -113,6 +114,7 @@ impl State {
|
|||||||
cursor: None,
|
cursor: None,
|
||||||
popup_menu,
|
popup_menu,
|
||||||
settings,
|
settings,
|
||||||
|
clipboard: gtk::Clipboard::get(&gdk::Atom::intern("CLIPBOARD")),
|
||||||
|
|
||||||
mode: mode::Mode::new(),
|
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) {
|
fn close_popup_menu(&self) {
|
||||||
if self.popup_menu.borrow().is_open() {
|
if self.popup_menu.borrow().is_open() {
|
||||||
if let Some(mut nvim) = self.nvim() {
|
if let Some(mut nvim) = self.nvim() {
|
||||||
|
Loading…
Reference in New Issue
Block a user