nvim_gtk/plug_manager/
plugin_settings_dlg.rs

1use gtk;
2use gtk::prelude::*;
3
4use super::store;
5
6pub struct Builder<'a> {
7    title: &'a str,
8}
9
10impl<'a> Builder<'a> {
11    pub fn new(title: &'a str) -> Self {
12        Builder { title }
13    }
14
15    pub fn show<F: IsA<gtk::Window>>(&self, parent: &F) -> Option<store::PlugInfo> {
16        let dlg = gtk::Dialog::new_with_buttons(
17            Some(self.title),
18            Some(parent),
19            gtk::DialogFlags::USE_HEADER_BAR | gtk::DialogFlags::DESTROY_WITH_PARENT,
20            &[
21                ("Cancel", gtk::ResponseType::Cancel),
22                ("Ok", gtk::ResponseType::Ok),
23            ],
24        );
25
26        let content = dlg.get_content_area();
27        let border = gtk::Box::new(gtk::Orientation::Horizontal, 0);
28        border.set_border_width(12);
29
30        let list = gtk::ListBox::new();
31        list.set_selection_mode(gtk::SelectionMode::None);
32
33        let path = gtk::Box::new(gtk::Orientation::Horizontal, 5);
34        path.set_border_width(5);
35        let path_lbl = gtk::Label::new(Some("Repo"));
36        let path_e = gtk::Entry::new();
37        path_e.set_placeholder_text(Some("user_name/repo_name"));
38
39        path.pack_start(&path_lbl, true, true, 0);
40        path.pack_end(&path_e, false, true, 0);
41
42        list.add(&path);
43
44        let name = gtk::Box::new(gtk::Orientation::Horizontal, 5);
45        name.set_border_width(5);
46        let name_lbl = gtk::Label::new(Some("Name"));
47        let name_e = gtk::Entry::new();
48
49        name.pack_start(&name_lbl, true, true, 0);
50        name.pack_end(&name_e, false, true, 0);
51
52        list.add(&name);
53
54        border.pack_start(&list, true, true, 0);
55        content.add(&border);
56        content.show_all();
57
58        path_e.connect_changed(clone!(name_e => move |p| {
59            if let Some(name) = p.get_text().and_then(|t| extract_name(&t)) {
60                name_e.set_text(&name);
61            }
62        }));
63
64        let res = if dlg.run() == gtk::ResponseType::Ok {
65            path_e.get_text().map(|path| {
66                let name = name_e
67                    .get_text()
68                    .map(String::from)
69                    .and_then(|name| {
70                        if name.trim().is_empty() {
71                            None
72                        } else {
73                            Some(name.to_owned())
74                        }
75                    })
76                    .or_else(|| extract_name(path.as_str()))
77                    .unwrap_or_else(|| path.as_str().to_owned());
78
79                store::PlugInfo::new(name, path.to_owned())
80            })
81        } else {
82            None
83        };
84
85        dlg.destroy();
86
87        res
88    }
89}
90
91fn extract_name(path: &str) -> Option<String> {
92    if let Some(idx) = path.rfind(|c| c == '/' || c == '\\') {
93        if idx < path.len() - 1 {
94            let path = path.trim_end_matches(".git");
95            Some(path[idx + 1..].to_owned())
96        } else {
97            None
98        }
99    } else {
100        None
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn test_extract_name() {
110        assert_eq!(
111            Some("plugin_name".to_owned()),
112            extract_name("http://github.com/somebody/plugin_name.git")
113        );
114    }
115}