diff options
Diffstat (limited to 'src/config')
| -rw-r--r-- | src/config/constants.rs | 23 | ||||
| -rw-r--r-- | src/config/mod.rs | 37 | ||||
| -rw-r--r-- | src/config/theme/colorpair.rs | 106 | ||||
| -rw-r--r-- | src/config/theme/mod.rs | 30 | ||||
| -rw-r--r-- | src/config/theme/sheetview.rs | 69 |
5 files changed, 265 insertions, 0 deletions
diff --git a/src/config/constants.rs b/src/config/constants.rs new file mode 100644 index 0000000..5a8283a --- /dev/null +++ b/src/config/constants.rs @@ -0,0 +1,23 @@ +use lazy_static::lazy_static; + +lazy_static! { + pub static ref USER_CONFIG_DIR: String = { + match dirs::config_local_dir() { + Some(mut d) => { + d.push("neosheet"); + d.as_path().to_str().unwrap_or("").to_string() + } + None => String::new(), + } + }; + pub static ref USER_RC_PATH: String = { + match dirs::config_local_dir() { + Some(mut d) => { + d.push("neosheet"); + d.push("init.lua"); + d.as_path().to_str().unwrap_or("").to_string() + } + None => String::new(), + } + }; +} diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 0000000..e6c4952 --- /dev/null +++ b/src/config/mod.rs @@ -0,0 +1,37 @@ +use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; + +use mlua::{UserData, UserDataFields}; + +use self::theme::Theme; + +pub mod theme; +pub mod constants; + +pub struct GlobalConfig { + pub theme: Theme, +} + +static GLOBAL_CONFIG: RwLock<GlobalConfig> = RwLock::new(GlobalConfig::new()); +const DUMMY_CONFIG: GlobalConfig = GlobalConfig::new(); + +impl GlobalConfig { + pub const fn new() -> Self { + Self { + theme: Theme::new(), + } + } + + pub fn instance() -> RwLockReadGuard<'static, Self> { + GLOBAL_CONFIG.read().unwrap() + } + + pub fn instance_mut() -> RwLockWriteGuard<'static, Self> { + GLOBAL_CONFIG.write().unwrap() + } +} + +impl UserData for GlobalConfig { + fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_function_get("theme", |_, _| Ok(DUMMY_CONFIG.theme)) + } +} diff --git a/src/config/theme/colorpair.rs b/src/config/theme/colorpair.rs new file mode 100644 index 0000000..77e6af4 --- /dev/null +++ b/src/config/theme/colorpair.rs @@ -0,0 +1,106 @@ +use std::str::FromStr; + +use mlua::{FromLua, IntoLua}; +use ratatui::style::{Color, Styled, Stylize}; + +#[derive(Clone)] +pub struct ColorPair { + pub fg: Color, + pub bg: Color, +} + +impl ColorPair { + pub const fn new(fg: Color, bg: Color) -> Self { + ColorPair { bg, fg } + } + + pub fn apply<S, I>(&self, s: S) -> <I as Styled>::Item + where + S: Styled<Item = I>, + I: Styled, + { + s.bg(self.bg).fg(self.fg) + } +} + +impl<'lua> FromLua<'lua> for ColorPair { + fn from_lua( + value: mlua::prelude::LuaValue<'lua>, + _lua: &'lua mlua::prelude::Lua, + ) -> mlua::prelude::LuaResult<Self> { + if value.is_table() { + let table = value.as_table().unwrap(); + if let Ok(fg) = table.get::<_, LuaColor>(1) { + if let Ok(bg) = table.get::<_, LuaColor>(2) { + return Ok(ColorPair::new(fg.into(), bg.into())); + } + } else if let Ok(fg) = table.get::<_, LuaColor>("fg") { + if let Ok(bg) = table.get::<_, LuaColor>("bg") { + return Ok(ColorPair::new(fg.into(), bg.into())); + } + } + } + + return Err(mlua::Error::runtime("could not parse colorpair")); + } +} + +impl<'lua> IntoLua<'lua> for ColorPair { + fn into_lua( + self, + lua: &'lua mlua::prelude::Lua, + ) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue<'lua>> { + let table = lua.create_table()?; + table.set("fg", LuaColor::from(self.fg))?; + table.set("bg", LuaColor::from(self.bg))?; + Ok(table.into_lua(lua)?) + } +} + +struct LuaColor { + color: Color, +} + +impl LuaColor { + fn new(color: Color) -> Self { + Self { color } + } +} + +impl From<Color> for LuaColor { + fn from(value: Color) -> Self { + LuaColor::new(value) + } +} + +impl Into<Color> for LuaColor { + fn into(self) -> Color { + self.color + } +} + +impl<'lua> FromLua<'lua> for LuaColor { + fn from_lua( + value: mlua::prelude::LuaValue<'lua>, + _lua: &'lua mlua::prelude::Lua, + ) -> mlua::prelude::LuaResult<Self> { + if value.is_string() { + let str = value.as_str().unwrap(); + match Color::from_str(str) { + Ok(color) => Ok(color.into()), + Err(_) => Err(mlua::Error::runtime("color has wrong format")), + } + } else { + Err(mlua::Error::runtime("color has wrong format")) + } + } +} + +impl<'lua> IntoLua<'lua> for LuaColor { + fn into_lua( + self, + lua: &'lua mlua::prelude::Lua, + ) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue<'lua>> { + Ok(self.color.to_string().to_lowercase().into_lua(lua)?) + } +} diff --git a/src/config/theme/mod.rs b/src/config/theme/mod.rs new file mode 100644 index 0000000..b7baf3a --- /dev/null +++ b/src/config/theme/mod.rs @@ -0,0 +1,30 @@ + +use mlua::UserData; + +use self::sheetview::SheetViewTheme; + +use super::DUMMY_CONFIG; + +pub mod colorpair; +pub mod sheetview; + +#[derive(Clone)] +pub struct Theme { + pub sheetview: SheetViewTheme, +} + +impl Theme { + pub const fn new() -> Self { + Self { + sheetview: SheetViewTheme::new(), + } + } +} + +impl UserData for Theme { + fn add_fields<'lua, F: mlua::prelude::LuaUserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_function_get("sheetview", |_, _| { + Ok(DUMMY_CONFIG.theme.sheetview) + }) + } +} diff --git a/src/config/theme/sheetview.rs b/src/config/theme/sheetview.rs new file mode 100644 index 0000000..de5751a --- /dev/null +++ b/src/config/theme/sheetview.rs @@ -0,0 +1,69 @@ +use mlua::{IntoLua, Table, UserData}; +use ratatui::style::Color; + +use crate::config::GlobalConfig; + +use super::colorpair::ColorPair; + +#[derive(Clone)] +pub struct SheetViewTheme { + pub cursor: ColorPair, + pub selection: ColorPair, + pub cell: (ColorPair, ColorPair), +} + +impl SheetViewTheme { + pub const fn new() -> Self { + Self { + cursor: ColorPair::new(Color::Black, Color::White), + selection: ColorPair::new(Color::White, Color::DarkGray), + cell: ( + ColorPair::new(Color::White, Color::Black), + ColorPair::new(Color::White, Color::DarkGray), + ), + } + } +} + +macro_rules! cfg { + () => { + GlobalConfig::instance().theme.sheetview + }; +} + +macro_rules! cfg_mut { + () => { + GlobalConfig::instance_mut().theme.sheetview + }; +} + +impl UserData for SheetViewTheme { + fn add_fields<'lua, F: mlua::prelude::LuaUserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_function_get("cursor", |_, _| Ok(cfg!().cursor.clone())); + + fields.add_field_function_set("cursor", |_, _, pair: ColorPair| { + cfg_mut!().cursor = pair; + Ok(()) + }); + + fields.add_field_function_get("selection", |_, _| Ok(cfg!().selection.clone())); + + fields.add_field_function_set("selection", |_, _, pair: ColorPair| { + cfg_mut!().selection = pair; + Ok(()) + }); + + fields.add_field_function_get("cell", |lua, _| { + let table = lua.create_table()?; + let sel = cfg!().cell.clone(); + table.set(1, sel.0)?; + table.set(2, sel.1)?; + Ok(table.into_lua(lua)?) + }); + + fields.add_field_function_set("cell", |_, _, pair: Table| { + cfg_mut!().cell = (pair.get(1)?, pair.get(2)?); + Ok(()) + }); + } +} |