2017-10-15 11:34:48 +00:00
|
|
|
use std::ops::{Deref, DerefMut};
|
2017-11-10 15:36:54 +00:00
|
|
|
use std::cell::{Cell, RefCell, RefMut};
|
|
|
|
use std::sync::{Arc, Mutex, MutexGuard};
|
2017-10-15 11:34:48 +00:00
|
|
|
|
2017-12-11 20:15:17 +00:00
|
|
|
use super::ErrorReport;
|
|
|
|
use neovim_lib::{Neovim, NeovimApi};
|
2017-10-15 11:34:48 +00:00
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq)]
|
2017-10-15 11:34:48 +00:00
|
|
|
enum NeovimClientState {
|
|
|
|
Uninitialized,
|
|
|
|
InitInProgress,
|
2017-11-10 15:36:54 +00:00
|
|
|
Initialized,
|
2017-10-15 11:34:48 +00:00
|
|
|
Error,
|
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub enum NeovimRef<'a> {
|
|
|
|
SingleThreaded(RefMut<'a, Neovim>),
|
2017-11-11 15:56:23 +00:00
|
|
|
MultiThreaded(MutexGuard<'a, Option<Neovim>>),
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> NeovimRef<'a> {
|
|
|
|
fn from_nvim(nvim: RefMut<'a, Neovim>) -> Self {
|
|
|
|
NeovimRef::SingleThreaded(nvim)
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
fn from_nvim_async(nvim_async: &'a NeovimClientAsync) -> Option<NeovimRef<'a>> {
|
|
|
|
let guard = nvim_async.nvim.lock().unwrap();
|
|
|
|
|
2017-11-11 15:56:23 +00:00
|
|
|
if guard.is_some() {
|
|
|
|
Some(NeovimRef::MultiThreaded(guard))
|
2017-11-10 15:36:54 +00:00
|
|
|
} else {
|
|
|
|
None
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
}
|
2017-12-11 20:15:17 +00:00
|
|
|
|
|
|
|
pub fn non_blocked(mut self) -> Option<Self> {
|
|
|
|
self.get_mode().ok_and_report().and_then(|mode| {
|
|
|
|
mode.iter()
|
|
|
|
.find(|kv| {
|
|
|
|
kv.0.as_str().map(|key| key == "blocking").unwrap_or(false)
|
|
|
|
})
|
|
|
|
.map(|kv| kv.1.as_bool().unwrap_or(false))
|
|
|
|
.and_then(|block| if block { None } else { Some(self) })
|
|
|
|
})
|
|
|
|
}
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
2017-10-15 11:34:48 +00:00
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
impl<'a> Deref for NeovimRef<'a> {
|
|
|
|
type Target = Neovim;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Neovim {
|
2017-10-15 11:34:48 +00:00
|
|
|
match *self {
|
2017-11-10 15:36:54 +00:00
|
|
|
NeovimRef::SingleThreaded(ref nvim) => &*nvim,
|
2017-11-11 15:56:23 +00:00
|
|
|
NeovimRef::MultiThreaded(ref nvim) => (&*nvim).as_ref().unwrap(),
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
}
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
2017-10-15 11:34:48 +00:00
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
impl<'a> DerefMut for NeovimRef<'a> {
|
|
|
|
fn deref_mut(&mut self) -> &mut Neovim {
|
2017-10-15 11:34:48 +00:00
|
|
|
match *self {
|
2017-11-10 15:36:54 +00:00
|
|
|
NeovimRef::SingleThreaded(ref mut nvim) => &mut *nvim,
|
2017-11-11 15:56:23 +00:00
|
|
|
NeovimRef::MultiThreaded(ref mut nvim) => (&mut *nvim).as_mut().unwrap(),
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub struct NeovimClientAsync {
|
2017-11-11 15:56:23 +00:00
|
|
|
nvim: Arc<Mutex<Option<Neovim>>>,
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
impl NeovimClientAsync {
|
2017-11-11 15:56:23 +00:00
|
|
|
fn new() -> Self {
|
|
|
|
NeovimClientAsync { nvim: Arc::new(Mutex::new(None)) }
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 15:56:23 +00:00
|
|
|
pub fn borrow(&self) -> Option<NeovimRef> {
|
|
|
|
NeovimRef::from_nvim_async(self)
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
2017-10-15 11:34:48 +00:00
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
impl Clone for NeovimClientAsync {
|
|
|
|
fn clone(&self) -> Self {
|
2017-11-13 09:15:13 +00:00
|
|
|
NeovimClientAsync { nvim: self.nvim.clone() }
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct NeovimClient {
|
|
|
|
state: Cell<NeovimClientState>,
|
|
|
|
nvim: RefCell<Option<Neovim>>,
|
2017-11-11 15:56:23 +00:00
|
|
|
nvim_async: NeovimClientAsync,
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
2017-10-15 11:34:48 +00:00
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
impl NeovimClient {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
NeovimClient {
|
|
|
|
state: Cell::new(NeovimClientState::Uninitialized),
|
|
|
|
nvim: RefCell::new(None),
|
2017-11-11 15:56:23 +00:00
|
|
|
nvim_async: NeovimClientAsync::new(),
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 09:15:13 +00:00
|
|
|
pub fn clear(&self) {
|
|
|
|
let mut nvim = self.nvim.borrow_mut();
|
|
|
|
if nvim.is_some() {
|
|
|
|
nvim.take();
|
|
|
|
} else {
|
|
|
|
self.nvim_async.nvim.lock().unwrap().take();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn async_to_sync(&self) {
|
2017-11-13 09:15:13 +00:00
|
|
|
let mut lock = self.nvim_async.nvim.lock().unwrap();
|
2017-11-11 15:56:23 +00:00
|
|
|
let nvim = lock.take().unwrap();
|
|
|
|
*self.nvim.borrow_mut() = Some(nvim);
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn set_nvim_async(&self, nvim: Neovim) -> NeovimClientAsync {
|
2017-11-11 15:56:23 +00:00
|
|
|
*self.nvim_async.nvim.lock().unwrap() = Some(nvim);
|
|
|
|
self.nvim_async.clone()
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn set_initialized(&self) {
|
|
|
|
self.state.set(NeovimClientState::Initialized);
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn set_error(&self) {
|
|
|
|
self.state.set(NeovimClientState::Error);
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn set_in_progress(&self) {
|
|
|
|
self.state.set(NeovimClientState::InitInProgress);
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn is_initialized(&self) -> bool {
|
|
|
|
self.state.get() == NeovimClientState::Initialized
|
|
|
|
}
|
2017-10-15 11:34:48 +00:00
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn is_uninitialized(&self) -> bool {
|
|
|
|
self.state.get() == NeovimClientState::Uninitialized
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 15:36:54 +00:00
|
|
|
pub fn is_initializing(&self) -> bool {
|
|
|
|
self.state.get() == NeovimClientState::InitInProgress
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn nvim(&self) -> Option<NeovimRef> {
|
|
|
|
let nvim = self.nvim.borrow_mut();
|
|
|
|
if nvim.is_some() {
|
|
|
|
Some(NeovimRef::from_nvim(
|
|
|
|
RefMut::map(nvim, |n| n.as_mut().unwrap()),
|
|
|
|
))
|
|
|
|
} else {
|
2017-11-11 15:56:23 +00:00
|
|
|
self.nvim_async.borrow()
|
2017-11-10 15:36:54 +00:00
|
|
|
}
|
2017-10-15 11:34:48 +00:00
|
|
|
}
|
|
|
|
}
|