1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
use std::rc::Rc;

use neovim_lib::{NeovimApi, NeovimApiAsync};

use crate::nvim::{NeovimClient, ErrorReport, NeovimRef};
use crate::value::ValueMapExt;

pub struct Manager {
    nvim: Option<Rc<NeovimClient>>,
}

impl Manager {
    pub fn new() -> Self {
        Manager { nvim: None }
    }

    pub fn initialize(&mut self, nvim: Rc<NeovimClient>) {
        self.nvim = Some(nvim);
    }

    fn nvim(&self) -> Option<NeovimRef> {
        self.nvim.as_ref().unwrap().nvim()
    }

    pub fn get_plugs(&self) -> Result<Box<[VimPlugInfo]>, String> {
        if let Some(mut nvim) = self.nvim() {
            let g_plugs = nvim.eval("g:plugs").map_err(|e| {
                format!("Can't retrive g:plugs map: {}", e)
            })?;

            let plugs_map = g_plugs
                .as_map()
                .ok_or("Can't retrive g:plugs map".to_owned())?
                .to_attrs_map()?;

            let g_plugs_order = nvim.eval("g:plugs_order").map_err(|e| format!("{}", e))?;

            let order_arr = g_plugs_order.as_array().ok_or(
                "Can't find g:plugs_order array"
                    .to_owned(),
            )?;

            let plugs_info: Vec<VimPlugInfo> = order_arr
                .iter()
                .map(|n| n.as_str())
                .filter_map(|name| if let Some(name) = name {
                    plugs_map
                        .get(name)
                        .and_then(|desc| desc.as_map())
                        .and_then(|desc| desc.to_attrs_map().ok())
                        .and_then(|desc| {
                            let uri = desc.get("uri").and_then(|uri| uri.as_str());
                            if let Some(uri) = uri {
                                Some(VimPlugInfo::new(name.to_owned(), uri.to_owned()))
                            } else {
                                None
                            }
                        })
                } else {
                    None
                })
                .collect();
            Ok(plugs_info.into_boxed_slice())
        } else {
            Err("Nvim not initialized".to_owned())
        }
    }

    pub fn is_loaded(&self) -> bool {
        if let Some(mut nvim) = self.nvim() {
            let loaded_plug = nvim.eval("exists('g:loaded_plug')");
            loaded_plug
                .ok_and_report()
                .and_then(|loaded_plug| loaded_plug.as_i64())
                .map_or(false, |loaded_plug| if loaded_plug > 0 {
                    true
                } else {
                    false
                })
        } else {
            false
        }
    }

    pub fn reload(&self, path: &str) {
        if let Some(mut nvim) = self.nvim() {
            nvim.command_async(&format!("source {}", path))
                .cb(|r| r.report_err())
                .call()
        }
    }
}

#[derive(Debug)]
pub struct VimPlugInfo {
    pub name: String,
    pub uri: String,
}

impl VimPlugInfo {
    pub fn new(name: String, uri: String) -> Self {
        VimPlugInfo { name, uri }
    }
}