2017-11-14 15:38:24 +00:00
|
|
|
use std::collections::HashMap;
|
2018-04-07 18:18:06 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
use std::cell::Ref;
|
2017-11-14 15:38:24 +00:00
|
|
|
|
2018-04-07 18:18:06 +00:00
|
|
|
use glib;
|
2017-11-14 15:38:24 +00:00
|
|
|
|
2018-04-07 18:18:06 +00:00
|
|
|
use neovim_lib::{CallError, Neovim, NeovimApiAsync, Value};
|
|
|
|
|
|
|
|
use ui::UiMutex;
|
2017-11-14 15:38:24 +00:00
|
|
|
use nvim::ErrorReport;
|
|
|
|
use color::Color;
|
|
|
|
use value::ValueMapExt;
|
|
|
|
|
2018-04-07 18:18:06 +00:00
|
|
|
struct State {
|
|
|
|
pmenu: Pmenu,
|
2018-05-05 19:41:38 +00:00
|
|
|
cursor: Cursor,
|
2018-04-07 18:18:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl State {
|
|
|
|
fn new() -> Self {
|
|
|
|
State {
|
|
|
|
pmenu: Pmenu::new(),
|
2018-05-05 19:41:38 +00:00
|
|
|
cursor: Cursor::new(),
|
2018-04-07 18:18:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-14 15:38:24 +00:00
|
|
|
pub struct Theme {
|
2018-04-07 18:18:06 +00:00
|
|
|
state: Arc<UiMutex<State>>,
|
2017-11-14 15:38:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Theme {
|
|
|
|
pub fn new() -> Self {
|
2018-04-07 18:18:06 +00:00
|
|
|
Theme {
|
|
|
|
state: Arc::new(UiMutex::new(State::new())),
|
|
|
|
}
|
2017-11-14 15:38:24 +00:00
|
|
|
}
|
|
|
|
|
2018-04-07 18:18:06 +00:00
|
|
|
pub fn pmenu(&self) -> Ref<Pmenu> {
|
|
|
|
Ref::map(self.state.borrow(), |s| &s.pmenu)
|
|
|
|
}
|
|
|
|
|
2018-05-05 19:41:38 +00:00
|
|
|
pub fn cursor(&self) -> Ref<Cursor> {
|
|
|
|
Ref::map(self.state.borrow(), |s| &s.cursor)
|
|
|
|
}
|
|
|
|
|
2018-04-07 18:18:06 +00:00
|
|
|
pub fn queue_update(&self, nvim: &mut Neovim) {
|
2018-05-05 19:41:38 +00:00
|
|
|
self.get_hl(nvim, "Cursor", |state, bg, _fg| {
|
|
|
|
state.cursor.bg = bg;
|
|
|
|
});
|
|
|
|
|
2018-04-07 18:18:06 +00:00
|
|
|
self.get_hl(nvim, "Pmenu", |state, bg, fg| {
|
|
|
|
state.pmenu.bg = bg;
|
|
|
|
state.pmenu.fg = fg;
|
|
|
|
});
|
|
|
|
|
|
|
|
self.get_hl(nvim, "PmenuSel", |state, bg_sel, fg_sel| {
|
|
|
|
state.pmenu.bg_sel = bg_sel;
|
|
|
|
state.pmenu.fg_sel = fg_sel;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_hl<CB>(&self, nvim: &mut Neovim, hl_name: &str, mut cb: CB)
|
|
|
|
where
|
|
|
|
CB: FnMut(&mut State, Option<Color>, Option<Color>) + Send + 'static,
|
|
|
|
{
|
|
|
|
let state = self.state.clone();
|
|
|
|
|
|
|
|
nvim.get_hl_by_name_async(hl_name, true)
|
|
|
|
.cb(move |v| {
|
|
|
|
let mut hl = Some(hl_colors(v));
|
|
|
|
glib::idle_add(move || {
|
|
|
|
let (bg, fg) = hl.take().unwrap();
|
|
|
|
let mut state = state.borrow_mut();
|
|
|
|
cb(&mut *state, bg, fg);
|
|
|
|
glib::Continue(false)
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.call();
|
2017-11-14 15:38:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-05 19:41:38 +00:00
|
|
|
pub struct Cursor {
|
|
|
|
pub bg: Option<Color>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Cursor {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Cursor {
|
|
|
|
bg: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-14 15:38:24 +00:00
|
|
|
pub struct Pmenu {
|
|
|
|
pub bg: Option<Color>,
|
|
|
|
pub fg: Option<Color>,
|
|
|
|
pub bg_sel: Option<Color>,
|
|
|
|
pub fg_sel: Option<Color>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Pmenu {
|
2018-04-07 18:18:06 +00:00
|
|
|
pub fn new() -> Self {
|
2017-11-14 15:38:24 +00:00
|
|
|
Pmenu {
|
2018-04-07 18:18:06 +00:00
|
|
|
bg: None,
|
|
|
|
fg: None,
|
|
|
|
bg_sel: None,
|
|
|
|
fg_sel: None,
|
2017-11-14 15:38:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_hl_color(map: &HashMap<&str, &Value>, color_name: &str) -> Option<Color> {
|
2018-04-07 18:18:06 +00:00
|
|
|
map.get(color_name)
|
|
|
|
.and_then(|col| col.as_u64())
|
|
|
|
.map(Color::from_indexed_color)
|
2017-11-14 15:38:24 +00:00
|
|
|
}
|
|
|
|
|
2018-04-07 18:18:06 +00:00
|
|
|
fn hl_colors(hl: Result<Vec<(Value, Value)>, CallError>) -> (Option<Color>, Option<Color>) {
|
|
|
|
hl.ok_and_report()
|
|
|
|
.and_then(|m| {
|
|
|
|
if let Some(m) = m.to_attrs_map_report() {
|
|
|
|
let reverse = m.get("reverse").and_then(|v| v.as_bool()).unwrap_or(false);
|
|
|
|
let bg = get_hl_color(&m, "background");
|
|
|
|
let fg = get_hl_color(&m, "foreground");
|
|
|
|
if reverse {
|
|
|
|
Some((fg, bg))
|
|
|
|
} else {
|
|
|
|
Some((bg, fg))
|
|
|
|
}
|
2017-12-24 14:11:37 +00:00
|
|
|
} else {
|
2018-04-07 18:18:06 +00:00
|
|
|
None
|
2017-12-24 14:11:37 +00:00
|
|
|
}
|
2017-11-14 15:38:24 +00:00
|
|
|
})
|
|
|
|
.unwrap_or((None, None))
|
|
|
|
}
|
2018-04-07 18:18:06 +00:00
|
|
|
|