Implement "add plugin", base code for vimawesome support
This commit is contained in:
@@ -23,6 +23,13 @@ extern crate serde;
|
||||
extern crate serde_derive;
|
||||
extern crate toml;
|
||||
|
||||
// http request library
|
||||
extern crate futures;
|
||||
extern crate hyper;
|
||||
extern crate tokio_core;
|
||||
extern crate serde_json;
|
||||
extern crate hyper_tls;
|
||||
|
||||
mod sys;
|
||||
|
||||
mod nvim_config;
|
||||
|
||||
@@ -2,34 +2,35 @@ use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use super::vim_plug;
|
||||
use super::store::Store;
|
||||
use super::store::{Store, PlugInfo};
|
||||
|
||||
use nvim::NeovimClient;
|
||||
|
||||
pub struct Manager {
|
||||
vim_plug: vim_plug::Manager,
|
||||
pub store: Store,
|
||||
pub plug_manage_state: PlugManageState,
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
pub fn new() -> Self {
|
||||
|
||||
let (plug_manage_state, store) = if Store::is_config_exists() {
|
||||
(PlugManageState::NvimGtk, Store::load())
|
||||
} else {
|
||||
(PlugManageState::Unknown, Store::empty())
|
||||
};
|
||||
|
||||
Manager {
|
||||
vim_plug: vim_plug::Manager::new(),
|
||||
plug_manage_state: PlugManageState::Unknown,
|
||||
plug_manage_state,
|
||||
store,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_config(&mut self) -> Option<PlugManagerConfigSource> {
|
||||
if Store::is_config_exists() {
|
||||
let store = Store::load();
|
||||
if store.is_enabled() {
|
||||
let config = PlugManagerConfigSource::new(&store);
|
||||
self.plug_manage_state = PlugManageState::NvimGtk(store);
|
||||
Some(config)
|
||||
} else {
|
||||
self.plug_manage_state = PlugManageState::NvimGtk(store);
|
||||
None
|
||||
}
|
||||
pub fn load_config(&self) -> Option<PlugManagerConfigSource> {
|
||||
if self.store.is_enabled() {
|
||||
Some(PlugManagerConfigSource::new(&self.store))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -40,42 +41,30 @@ impl Manager {
|
||||
}
|
||||
|
||||
pub fn update_state(&mut self) {
|
||||
if self.vim_plug.is_loaded() {
|
||||
if let PlugManageState::Unknown = self.plug_manage_state {
|
||||
self.plug_manage_state =
|
||||
PlugManageState::VimPlug(Store::load_from_plug(&self.vim_plug));
|
||||
if let PlugManageState::Unknown = self.plug_manage_state {
|
||||
if self.vim_plug.is_loaded() {
|
||||
self.store = Store::load_from_plug(&self.vim_plug);
|
||||
self.plug_manage_state = PlugManageState::VimPlug;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_mut(&mut self) -> Option<&mut Store> {
|
||||
match self.plug_manage_state {
|
||||
PlugManageState::NvimGtk(ref mut store) => Some(store),
|
||||
PlugManageState::VimPlug(ref mut store) => Some(store),
|
||||
PlugManageState::Unknown => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store(&self) -> Option<&Store> {
|
||||
match self.plug_manage_state {
|
||||
PlugManageState::NvimGtk(ref store) => Some(store),
|
||||
PlugManageState::VimPlug(ref store) => Some(store),
|
||||
PlugManageState::Unknown => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(&self) {
|
||||
self.store().map(|s| s.save());
|
||||
self.store.save();
|
||||
}
|
||||
|
||||
pub fn clear_removed(&mut self) {
|
||||
self.store_mut().map(|s| s.clear_removed());
|
||||
self.store.clear_removed();
|
||||
}
|
||||
|
||||
pub fn add_plug(&mut self, plug: PlugInfo) {
|
||||
self.store.add_plug(plug);
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PlugManageState {
|
||||
NvimGtk(Store),
|
||||
VimPlug(Store),
|
||||
NvimGtk,
|
||||
VimPlug,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ mod vim_plug;
|
||||
mod store;
|
||||
mod manager;
|
||||
mod plugin_settings_dlg;
|
||||
mod vimawesome;
|
||||
|
||||
pub use self::ui::Ui;
|
||||
pub use self::manager::{Manager, PlugManagerConfigSource};
|
||||
|
||||
@@ -4,10 +4,10 @@ use gtk::prelude::*;
|
||||
use super::store;
|
||||
|
||||
pub struct Builder<'a> {
|
||||
title: &'a str
|
||||
title: &'a str,
|
||||
}
|
||||
|
||||
impl <'a> Builder <'a> {
|
||||
impl<'a> Builder<'a> {
|
||||
pub fn new(title: &'a str) -> Self {
|
||||
Builder { title }
|
||||
}
|
||||
@@ -17,28 +17,40 @@ impl <'a> Builder <'a> {
|
||||
Some(self.title),
|
||||
Some(parent),
|
||||
gtk::DIALOG_USE_HEADER_BAR | gtk::DIALOG_DESTROY_WITH_PARENT,
|
||||
&[("Cancel", gtk::ResponseType::Cancel.into()),
|
||||
("Ok", gtk::ResponseType::Accept.into())],
|
||||
&[
|
||||
("Cancel", gtk::ResponseType::Cancel.into()),
|
||||
("Ok", gtk::ResponseType::Ok.into()),
|
||||
],
|
||||
);
|
||||
|
||||
let content = dlg.get_content_area();
|
||||
let grid = gtk::Grid::new();
|
||||
let list = gtk::ListBox::new();
|
||||
list.set_selection_mode(gtk::SelectionMode::None);
|
||||
|
||||
let label = gtk::Label::new("Path:");
|
||||
let path = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
||||
let label = gtk::Label::new("Repo");
|
||||
let entry = gtk::Entry::new();
|
||||
|
||||
grid.attach(&label, 0, 0, 1, 1);
|
||||
grid.attach(&entry, 1, 0, 1, 1);
|
||||
|
||||
content.add(&grid);
|
||||
path.pack_start(&label, true, true, 0);
|
||||
path.pack_end(&entry, false, true, 0);
|
||||
|
||||
list.add(&path);
|
||||
|
||||
|
||||
content.add(&list);
|
||||
content.show_all();
|
||||
|
||||
if dlg.run() == gtk::ResponseType::Ok.into() {
|
||||
}
|
||||
let ok: i32 = gtk::ResponseType::Ok.into();
|
||||
let res = if dlg.run() == ok {
|
||||
entry.get_text().map(|name| {
|
||||
store::PlugInfo::new(name.to_owned(), name.to_owned())
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
dlg.destroy();
|
||||
|
||||
None
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@ impl Store {
|
||||
Store { settings: Settings::load() }
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Store { settings: Settings::empty() }
|
||||
}
|
||||
|
||||
pub fn load_from_plug(vim_plug: &vim_plug::Manager) -> Self {
|
||||
let settings = match vim_plug.get_plugs() {
|
||||
Err(msg) => {
|
||||
@@ -61,6 +65,14 @@ impl Store {
|
||||
pub fn restore_plug(&mut self, idx: usize) {
|
||||
self.settings.plugs[idx].removed = false;
|
||||
}
|
||||
|
||||
pub fn add_plug(&mut self, plug: PlugInfo) {
|
||||
self.settings.plugs.push(plug);
|
||||
}
|
||||
|
||||
pub fn plugs_count(&self) -> usize {
|
||||
self.settings.plugs.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
||||
@@ -11,6 +11,7 @@ use gtk::prelude::*;
|
||||
use super::manager;
|
||||
use super::store::{Store, PlugInfo};
|
||||
use super::plugin_settings_dlg;
|
||||
use super::vimawesome::Vimawesome;
|
||||
|
||||
pub struct Ui<'a> {
|
||||
manager: &'a Arc<UiMutex<manager::Manager>>,
|
||||
@@ -39,70 +40,74 @@ impl<'a> Ui<'a> {
|
||||
let add_plug_btn = gtk::Button::new_with_label("Add..");
|
||||
header_bar.pack_end(&add_plug_btn);
|
||||
|
||||
let manager_ref = self.manager.clone();
|
||||
add_plug_btn.connect_clicked(clone!(dlg => move |_| {
|
||||
add_plugin(&dlg, &manager_ref);
|
||||
}));
|
||||
|
||||
let enable_swc = gtk::Switch::new();
|
||||
enable_swc.set_valign(gtk::Align::Center);
|
||||
enable_swc.show();
|
||||
|
||||
let manager_ref = self.manager.clone();
|
||||
header_bar.pack_end(&enable_swc);
|
||||
|
||||
header_bar.set_title("Plug");
|
||||
header_bar.set_show_close_button(true);
|
||||
header_bar.show_all();
|
||||
header_bar.show();
|
||||
|
||||
dlg.set_titlebar(&header_bar);
|
||||
|
||||
let pages = SettingsPages::new(move |row_name| if row_name == "plugins" {
|
||||
let pages = SettingsPages::new(
|
||||
clone!(add_plug_btn => move |row_name| if row_name == "plugins" {
|
||||
add_plug_btn.show();
|
||||
} else {
|
||||
add_plug_btn.hide();
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
match self.manager.borrow_mut().plug_manage_state {
|
||||
enable_swc.set_state(self.manager.borrow().store.is_enabled());
|
||||
|
||||
match self.manager.borrow().plug_manage_state {
|
||||
manager::PlugManageState::Unknown => {
|
||||
add_help_tab(
|
||||
&pages,
|
||||
"<span foreground=\"red\">Note:</span> NeovimGtk plugin manager <b>disabled</b>!",
|
||||
);
|
||||
}
|
||||
manager::PlugManageState::VimPlug(ref store) => {
|
||||
enable_swc.set_state(store.is_enabled());
|
||||
manager::PlugManageState::VimPlug => {
|
||||
add_help_tab(
|
||||
&pages,
|
||||
"<span foreground=\"red\">Note:</span> NeovimGtk plugin manager <b>disabled</b>!\n\
|
||||
NeovimGtk manages plugins use vim-plug as backend, so enable it disables vim-plug configuration.\n\
|
||||
Current configuration taken from your vim-plug",
|
||||
);
|
||||
self.add_plugin_list_tab(&pages, store);
|
||||
}
|
||||
manager::PlugManageState::NvimGtk(ref store) => {
|
||||
enable_swc.set_state(store.is_enabled());
|
||||
manager::PlugManageState::NvimGtk => {
|
||||
let get_plugins = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
// TODO:
|
||||
|
||||
Vimawesome::new().log();
|
||||
|
||||
let get_plugins_lbl = gtk::Label::new("Get Plugins");
|
||||
pages.add_page(&get_plugins_lbl, &get_plugins, "get_plugins");
|
||||
|
||||
self.add_plugin_list_tab(&pages, store);
|
||||
}
|
||||
}
|
||||
|
||||
let plugs_panel = self.add_plugin_list_tab(&pages, &self.manager.borrow().store);
|
||||
|
||||
let manager_ref = self.manager.clone();
|
||||
enable_swc.connect_state_set(move |_, state| {
|
||||
manager_ref.borrow_mut().store_mut().map(
|
||||
|s| s.set_enabled(state),
|
||||
);
|
||||
manager_ref.borrow_mut().store.set_enabled(state);
|
||||
Inhibit(false)
|
||||
});
|
||||
|
||||
let manager_ref = self.manager.clone();
|
||||
add_plug_btn.connect_clicked(clone!(dlg => move |_| {
|
||||
add_plugin(&dlg, &manager_ref, &plugs_panel);
|
||||
}));
|
||||
|
||||
content.pack_start(&*pages, true, true, 0);
|
||||
content.show_all();
|
||||
|
||||
|
||||
if dlg.run() == gtk::ResponseType::Ok.into() {
|
||||
let ok: i32 = gtk::ResponseType::Ok.into();
|
||||
if dlg.run() == ok {
|
||||
let mut manager = self.manager.borrow_mut();
|
||||
manager.clear_removed();
|
||||
manager.save();
|
||||
@@ -111,77 +116,99 @@ impl<'a> Ui<'a> {
|
||||
dlg.destroy();
|
||||
}
|
||||
|
||||
fn add_plugin_list_tab(&self, pages: &SettingsPages, store: &Store) {
|
||||
fn add_plugin_list_tab(&self, pages: &SettingsPages, store: &Store) -> gtk::ListBox {
|
||||
let plugins = gtk::Box::new(gtk::Orientation::Vertical, 3);
|
||||
self.fill_plugin_list(&plugins, store);
|
||||
let plugs_panel = self.fill_plugin_list(&plugins, store);
|
||||
|
||||
let plugins_lbl = gtk::Label::new("Plugins");
|
||||
pages.add_page(&plugins_lbl, &plugins, "plugins");
|
||||
plugs_panel
|
||||
}
|
||||
|
||||
fn fill_plugin_list(&self, panel: >k::Box, store: &Store) {
|
||||
fn fill_plugin_list(&self, panel: >k::Box, store: &Store) -> gtk::ListBox {
|
||||
let scroll = gtk::ScrolledWindow::new(None, None);
|
||||
scroll.get_style_context().map(|c| c.add_class("view"));
|
||||
let plugs_panel = gtk::ListBox::new();
|
||||
|
||||
for (idx, plug_info) in store.get_plugs().iter().enumerate() {
|
||||
let row = gtk::ListBoxRow::new();
|
||||
let row_container = gtk::Box::new(gtk::Orientation::Vertical, 5);
|
||||
row_container.set_border_width(5);
|
||||
let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5);
|
||||
let label_box = create_plug_label(plug_info);
|
||||
let row = create_plug_row(idx, plug_info, &self.manager);
|
||||
|
||||
|
||||
let button_box = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
||||
button_box.set_halign(gtk::Align::End);
|
||||
|
||||
let exists_button_box = gtk::Box::new(gtk::Orientation::Horizontal, 5);
|
||||
|
||||
let remove_btn = gtk::Button::new_with_label("Remove");
|
||||
exists_button_box.pack_start(&remove_btn, false, true, 0);
|
||||
|
||||
let undo_btn = gtk::Button::new_with_label("Undo");
|
||||
|
||||
|
||||
row_container.pack_start(&hbox, true, true, 0);
|
||||
hbox.pack_start(&label_box, true, true, 0);
|
||||
button_box.pack_start(&exists_button_box, false, true, 0);
|
||||
hbox.pack_start(&button_box, false, true, 0);
|
||||
|
||||
row.add(&row_container);
|
||||
plugs_panel.add(&row);
|
||||
|
||||
|
||||
let manager_ref = self.manager.clone();
|
||||
remove_btn.connect_clicked(
|
||||
clone!(label_box, button_box, exists_button_box, undo_btn => move |_| {
|
||||
label_box.set_sensitive(false);
|
||||
button_box.remove(&exists_button_box);
|
||||
button_box.pack_start(&undo_btn, false, true, 0);
|
||||
button_box.show_all();
|
||||
manager_ref.borrow_mut().store_mut().map(|s| s.remove_plug(idx));
|
||||
}),
|
||||
);
|
||||
|
||||
let manager_ref = self.manager.clone();
|
||||
undo_btn.connect_clicked(
|
||||
clone!(label_box, button_box, exists_button_box, undo_btn => move |_| {
|
||||
label_box.set_sensitive(true);
|
||||
button_box.remove(&undo_btn);
|
||||
button_box.pack_start(&exists_button_box, false, true, 0);
|
||||
button_box.show_all();
|
||||
manager_ref.borrow_mut().store_mut().map(|s| s.restore_plug(idx));
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
scroll.add(&plugs_panel);
|
||||
panel.pack_start(&scroll, true, true, 0);
|
||||
|
||||
plugs_panel
|
||||
}
|
||||
}
|
||||
|
||||
fn add_plugin<F: IsA<gtk::Window>>(parent: &F, manager: &Arc<UiMutex<manager::Manager>>) {
|
||||
plugin_settings_dlg::Builder::new("Add plugin").show(parent);
|
||||
fn create_plug_row(
|
||||
plug_idx: usize,
|
||||
plug_info: &PlugInfo,
|
||||
manager: &Arc<UiMutex<manager::Manager>>,
|
||||
) -> gtk::ListBoxRow {
|
||||
let row = gtk::ListBoxRow::new();
|
||||
let row_container = gtk::Box::new(gtk::Orientation::Vertical, 5);
|
||||
row_container.set_border_width(5);
|
||||
let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5);
|
||||
let label_box = create_plug_label(plug_info);
|
||||
|
||||
|
||||
let button_box = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
||||
button_box.set_halign(gtk::Align::End);
|
||||
|
||||
let exists_button_box = gtk::Box::new(gtk::Orientation::Horizontal, 5);
|
||||
|
||||
let remove_btn = gtk::Button::new_with_label("Remove");
|
||||
exists_button_box.pack_start(&remove_btn, false, true, 0);
|
||||
|
||||
let undo_btn = gtk::Button::new_with_label("Undo");
|
||||
|
||||
|
||||
row_container.pack_start(&hbox, true, true, 0);
|
||||
hbox.pack_start(&label_box, true, true, 0);
|
||||
button_box.pack_start(&exists_button_box, false, true, 0);
|
||||
hbox.pack_start(&button_box, false, true, 0);
|
||||
|
||||
row.add(&row_container);
|
||||
|
||||
|
||||
remove_btn.connect_clicked(
|
||||
clone!(manager, label_box, button_box, exists_button_box, undo_btn => move |_| {
|
||||
label_box.set_sensitive(false);
|
||||
button_box.remove(&exists_button_box);
|
||||
button_box.pack_start(&undo_btn, false, true, 0);
|
||||
button_box.show_all();
|
||||
manager.borrow_mut().store.remove_plug(plug_idx);
|
||||
}),
|
||||
);
|
||||
|
||||
undo_btn.connect_clicked(
|
||||
clone!(manager, label_box, button_box, exists_button_box, undo_btn => move |_| {
|
||||
label_box.set_sensitive(true);
|
||||
button_box.remove(&undo_btn);
|
||||
button_box.pack_start(&exists_button_box, false, true, 0);
|
||||
button_box.show_all();
|
||||
manager.borrow_mut().store.restore_plug(plug_idx);
|
||||
}),
|
||||
);
|
||||
|
||||
row
|
||||
}
|
||||
|
||||
fn add_plugin<F: IsA<gtk::Window>>(
|
||||
parent: &F,
|
||||
manager: &Arc<UiMutex<manager::Manager>>,
|
||||
plugs_panel: >k::ListBox,
|
||||
) {
|
||||
if let Some(new_plugin) = plugin_settings_dlg::Builder::new("Add plugin").show(parent) {
|
||||
let row = create_plug_row(manager.borrow().store.plugs_count(), &new_plugin, manager);
|
||||
row.show_all();
|
||||
plugs_panel.add(&row);
|
||||
|
||||
manager.borrow_mut().add_plug(new_plugin);
|
||||
}
|
||||
}
|
||||
|
||||
fn create_plug_label(plug_info: &PlugInfo) -> gtk::Box {
|
||||
@@ -214,11 +241,10 @@ struct SettingsPages {
|
||||
stack: gtk::Stack,
|
||||
content: gtk::Box,
|
||||
rows: Rc<RefCell<Vec<(gtk::ListBoxRow, &'static str)>>>,
|
||||
row_selected: Box<FnMut(&str)>,
|
||||
}
|
||||
|
||||
impl SettingsPages {
|
||||
pub fn new<F: FnMut(&str) + 'static>(row_selected: F) -> Self {
|
||||
pub fn new<F: Fn(&str) + 'static>(row_selected: F) -> Self {
|
||||
let content = gtk::Box::new(gtk::Orientation::Horizontal, 5);
|
||||
let categories = gtk::ListBox::new();
|
||||
categories.get_style_context().map(|c| c.add_class("view"));
|
||||
@@ -235,6 +261,7 @@ impl SettingsPages {
|
||||
if let Some(ref r) = rows.borrow().iter().find(|r| r.0 == *row) {
|
||||
if let Some(child) = stack.get_child_by_name(&r.1) {
|
||||
stack.set_visible_child(&child);
|
||||
row_selected(&r.1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -246,7 +273,6 @@ impl SettingsPages {
|
||||
stack,
|
||||
content,
|
||||
rows,
|
||||
row_selected: Box::new(row_selected),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
56
src/plug_manager/vimawesome.rs
Normal file
56
src/plug_manager/vimawesome.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use std::io;
|
||||
use futures::{Future, Stream};
|
||||
use hyper::{self, Client};
|
||||
use tokio_core::reactor::Core;
|
||||
use serde_json;
|
||||
use hyper_tls::HttpsConnector;
|
||||
|
||||
pub struct Vimawesome {}
|
||||
|
||||
impl Vimawesome {
|
||||
pub fn new() -> Self {
|
||||
Vimawesome {}
|
||||
}
|
||||
|
||||
pub fn log(&self) {
|
||||
match self.request() {
|
||||
Ok(list) => println!("list: {:?}", list),
|
||||
Err(e) => error!("{}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn request(&self) -> Result<DescriptionList, hyper::error::Error> {
|
||||
let mut core = Core::new()?;
|
||||
let handle = core.handle();
|
||||
let client = Client::configure()
|
||||
.connector(HttpsConnector::new(4, &handle).map_err(|e| {
|
||||
io::Error::new(io::ErrorKind::Other, e)
|
||||
})?)
|
||||
.build(&handle);
|
||||
let uri = "https://vimawesome.com/api/plugins?query=&page=1".parse()?;
|
||||
|
||||
let work = client.get(uri).and_then(|res| {
|
||||
res.body().concat2().and_then(move |body| {
|
||||
let description_list: DescriptionList =
|
||||
serde_json::from_slice(&body).map_err(|e| {
|
||||
io::Error::new(io::ErrorKind::Other, e)
|
||||
})?;
|
||||
Ok(description_list)
|
||||
})
|
||||
});
|
||||
core.run(work)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct DescriptionList {
|
||||
plugins: Box<[Description]>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Description {
|
||||
name: String,
|
||||
github_url: String,
|
||||
author: String,
|
||||
github_stars: i64,
|
||||
}
|
||||
@@ -53,7 +53,7 @@ impl Components {
|
||||
|
||||
impl Ui {
|
||||
pub fn new(options: ShellOptions) -> Ui {
|
||||
let mut plug_manager = plug_manager::Manager::new();
|
||||
let plug_manager = plug_manager::Manager::new();
|
||||
let plug_config = plug_manager.load_config();
|
||||
|
||||
let nvim_config = NvimConfig::new(plug_config);
|
||||
|
||||
Reference in New Issue
Block a user