diff --git a/src/color.rs b/src/color.rs index 8aa9d68..e57e0bd 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,6 +1,7 @@ use std; use gdk; use ui_model::Cell; +use theme::Theme; #[derive(Clone, PartialEq, Debug)] pub struct Color(pub f64, pub f64, pub f64); @@ -41,6 +42,7 @@ pub struct ColorModel { pub bg_color: Color, pub fg_color: Color, pub sp_color: Color, + pub theme: Theme, } impl ColorModel { @@ -49,6 +51,7 @@ impl ColorModel { bg_color: COLOR_BLACK, fg_color: COLOR_WHITE, sp_color: COLOR_RED, + theme: Theme::new(), } } @@ -102,4 +105,39 @@ impl ColorModel { pub fn actual_cell_sp<'a>(&'a self, cell: &'a Cell) -> &'a Color { cell.attrs.special.as_ref().unwrap_or(&self.sp_color) } + + pub fn pmenu_bg(&self) -> &Color { + if let Some(ref pmenu) = self.theme.pmenu { + pmenu.bg.as_ref().unwrap_or(&self.bg_color) + } else { + &self.bg_color + } + } + + + pub fn pmenu_fg(&self) -> &Color { + if let Some(ref pmenu) = self.theme.pmenu { + pmenu.fg.as_ref().unwrap_or(&self.fg_color) + } else { + &self.fg_color + } + } + + + pub fn pmenu_bg_sel(&self) -> &Color { + if let Some(ref pmenu) = self.theme.pmenu { + pmenu.bg_sel.as_ref().unwrap_or(&self.bg_color) + } else { + &self.bg_color + } + } + + + pub fn pmenu_fg_sel(&self) -> &Color { + if let Some(ref pmenu) = self.theme.pmenu { + pmenu.fg_sel.as_ref().unwrap_or(&self.fg_color) + } else { + &self.fg_color + } + } } diff --git a/src/main.rs b/src/main.rs index 81a8c2a..6dcf074 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ mod sys; mod nvim_config; mod dirs; +mod theme; mod color; mod value; mod mode; diff --git a/src/nvim/mod.rs b/src/nvim/mod.rs index 61e888a..030c544 100644 --- a/src/nvim/mod.rs +++ b/src/nvim/mod.rs @@ -159,7 +159,7 @@ pub fn post_start_init( pub trait ErrorReport { fn report_err(&self, nvim: &mut NeovimApi); - fn ok_and_report(&self, nvim: &mut NeovimApi) -> Option<&T>; + fn ok_and_report(self, nvim: &mut NeovimApi) -> Option; } impl ErrorReport for result::Result { @@ -170,9 +170,9 @@ impl ErrorReport for result::Result { } } - fn ok_and_report(&self, nvim: &mut NeovimApi) -> Option<&T> { + fn ok_and_report(self, nvim: &mut NeovimApi) -> Option { self.report_err(nvim); - self.as_ref().ok() + self.ok() } } diff --git a/src/nvim/redraw_handler.rs b/src/nvim/redraw_handler.rs index 89421bc..59f3390 100644 --- a/src/nvim/redraw_handler.rs +++ b/src/nvim/redraw_handler.rs @@ -201,7 +201,7 @@ pub fn call( ); let tab_attr = tab_attrs .get("tab") - .map(|tab_id| Tabpage::new(tab_id.clone())) + .map(|&tab_id| Tabpage::new(tab_id.clone())) .unwrap(); (tab_attr, name_attr) diff --git a/src/popup_menu.rs b/src/popup_menu.rs index cf9a3e1..00cf641 100644 --- a/src/popup_menu.rs +++ b/src/popup_menu.rs @@ -50,11 +50,13 @@ impl State { self.renderer.set_property_font( Some(&shell.get_font_desc().to_string()), ); + + let color_model = &shell.color_model; self.renderer.set_property_foreground_rgba( - Some(&shell.get_foreground().into()), + Some(&color_model.pmenu_fg().into()), ); self.renderer.set_property_background_rgba( - Some(&shell.get_background().into()), + Some(&color_model.pmenu_bg().into()), ); let col_count = menu[0].len(); diff --git a/src/shell.rs b/src/shell.rs index 8ba03f3..ba8fe75 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -57,7 +57,7 @@ enum ResizeState { pub struct State { pub model: UiModel, - color_model: ColorModel, + pub color_model: ColorModel, cur_attrs: Option, mouse_enabled: bool, nvim: Rc, @@ -117,14 +117,6 @@ impl State { } } - pub fn get_foreground(&self) -> &Color { - &self.color_model.fg_color - } - - pub fn get_background(&self) -> &Color { - &self.color_model.bg_color - } - pub fn nvim(&self) -> Option { self.nvim.nvim() } @@ -939,6 +931,10 @@ impl RedrawEvents for State { } } } + + if let Some(mut nvim) = self.nvim.nvim() { + self.color_model.theme.update(&mut *nvim); + } RepaintMode::Nothing } diff --git a/src/theme.rs b/src/theme.rs new file mode 100644 index 0000000..637a9f9 --- /dev/null +++ b/src/theme.rs @@ -0,0 +1,68 @@ +use std::collections::HashMap; + +use neovim_lib::{Value, Neovim, NeovimApi}; + +use nvim::ErrorReport; +use color::Color; +use value::ValueMapExt; + +pub struct Theme { + pub pmenu: Option, +} + +impl Theme { + pub fn new() -> Self { + Theme { pmenu: None } + } + + pub fn update(&mut self, nvim: &mut Neovim) { + self.pmenu = Some(Pmenu::new(nvim)); + } +} + +pub struct Pmenu { + pub bg: Option, + pub fg: Option, + pub bg_sel: Option, + pub fg_sel: Option, +} + +impl Pmenu { + pub fn new(nvim: &mut Neovim) -> Self { + let (bg, fg) = get_hl_colors(nvim, "Pmenu"); + let (bg_sel, fg_sel) = get_hl_colors(nvim, "PmenuSel"); + + Pmenu { + bg, + fg, + bg_sel, + fg_sel, + } + } +} + +fn get_hl_color(map: &HashMap<&str, &Value>, color_name: &str) -> Option { + if let Some(col) = map.get(color_name) { + if let Some(col) = col.as_u64() { + Some(Color::from_indexed_color(col)) + } else { + None + } + } else { + None + } +} + +fn get_hl_colors(nvim: &mut Neovim, hl: &str) -> (Option, Option) { + nvim.get_hl_by_name(hl, true) + .ok_and_report(nvim) + .and_then(|m| if let Some(m) = m.to_attrs_map_report() { + Some(( + get_hl_color(&m, "background"), + get_hl_color(&m, "foreground"), + )) + } else { + None + }) + .unwrap_or((None, None)) +} diff --git a/src/value.rs b/src/value.rs index 827dbcb..74a98c1 100644 --- a/src/value.rs +++ b/src/value.rs @@ -2,19 +2,31 @@ use std::collections::HashMap; use neovim_lib::Value; pub trait ValueMapExt { - fn to_attrs_map(&self) -> Result, String>; + fn to_attrs_map(&self) -> Result, String>; + + fn to_attrs_map_report(&self) -> Option>; } impl ValueMapExt for Vec<(Value, Value)> { - fn to_attrs_map(&self) -> Result, String> { + fn to_attrs_map(&self) -> Result, String> { self.iter() .map(|p| { p.0 .as_str() .ok_or_else(|| "Can't convert map key to string".to_owned()) - .map(|key| (key, p.1.clone())) + .map(|key| (key, &p.1)) }) - .collect::, String>>() + .collect::, String>>() } + + fn to_attrs_map_report(&self) -> Option> { + match self.to_attrs_map() { + Err(e) => { + error!("{}", e); + None + } + Ok(m) => Some(m), + } + } }