diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-01 20:13:55 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-01 20:13:55 +0200 |
| commit | a807d4e6fb96c4d8b8585b7dbb862e53486562ec (patch) | |
| tree | 92481d73423fd925f4dd034d68cbfd2e30e216d5 /src/config | |
| parent | 417cee4eeeaf7516dfeb59cdbe34fed18f30e0f7 (diff) | |
add evalsto
Diffstat (limited to 'src/config')
| -rw-r--r-- | src/config/evalsto.rs | 64 | ||||
| -rw-r--r-- | src/config/mod.rs | 2 | ||||
| -rw-r--r-- | src/config/theme/colorpair.rs | 106 | ||||
| -rw-r--r-- | src/config/theme/mod.rs | 4 | ||||
| -rw-r--r-- | src/config/theme/sheetview.rs | 39 | ||||
| -rw-r--r-- | src/config/theme/style.rs | 119 |
6 files changed, 203 insertions, 131 deletions
diff --git a/src/config/evalsto.rs b/src/config/evalsto.rs new file mode 100644 index 0000000..10b2dd1 --- /dev/null +++ b/src/config/evalsto.rs @@ -0,0 +1,64 @@ +use std::{marker::PhantomData, sync::Arc}; + +use mlua::{FromLua, IntoLua, Lua, Result, Value}; + +use crate::lua::ownedfunction::OwnedFunction; + +#[derive(Clone, Debug)] +pub enum EvalTo<T, A> { + Function(Arc<OwnedFunction>, PhantomData<A>), + Value(T), +} + +impl<T, A> EvalTo<T, A> { + pub fn get<'lua>(&'lua self, args: A, lua: &'lua Lua) -> Result<T> + where + T: FromLua<'lua> + Clone, + A: IntoLua<'lua>, + { + match self { + EvalTo::Function(value, _) => { + let func = value.get(lua); + T::from_lua(func.call(args)?, lua) + } + EvalTo::Value(value) => Ok(value.clone()), + } + } + + pub const fn new(value: T) -> Self { + Self::Value(value) + } +} + +impl<'lua, T, A> FromLua<'lua> for EvalTo<T, A> +where + T: FromLua<'lua> + Clone, + A: IntoLua<'lua>, +{ + fn from_lua( + value: mlua::prelude::LuaValue<'lua>, + lua: &'lua mlua::prelude::Lua, + ) -> Result<Self> { + if value.is_function() { + Ok(Self::Function( + Arc::new(OwnedFunction::new(value, lua)), + PhantomData, + )) + } else { + Ok(Self::Value(T::from_lua(value, lua)?)) + } + } +} + +impl<'lua, T, A> IntoLua<'lua> for EvalTo<T, A> +where + T: FromLua<'lua> + Clone + IntoLua<'lua>, + A: IntoLua<'lua>, +{ + fn into_lua(self, lua: &'lua mlua::prelude::Lua) -> Result<Value<'lua>> { + match self { + EvalTo::Function(value, _) => Ok(value.get(lua).into_lua(lua)?), + EvalTo::Value(value) => value.into_lua(lua), + } + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index e6c4952..6e88306 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -6,7 +6,9 @@ use self::theme::Theme; pub mod theme; pub mod constants; +pub mod evalsto; +#[derive(Debug)] pub struct GlobalConfig { pub theme: Theme, } diff --git a/src/config/theme/colorpair.rs b/src/config/theme/colorpair.rs deleted file mode 100644 index 77e6af4..0000000 --- a/src/config/theme/colorpair.rs +++ /dev/null @@ -1,106 +0,0 @@ -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 index b7baf3a..35101c5 100644 --- a/src/config/theme/mod.rs +++ b/src/config/theme/mod.rs @@ -5,10 +5,10 @@ use self::sheetview::SheetViewTheme; use super::DUMMY_CONFIG; -pub mod colorpair; +pub mod style; pub mod sheetview; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Theme { pub sheetview: SheetViewTheme, } diff --git a/src/config/theme/sheetview.rs b/src/config/theme/sheetview.rs index de5751a..5590349 100644 --- a/src/config/theme/sheetview.rs +++ b/src/config/theme/sheetview.rs @@ -1,26 +1,23 @@ -use mlua::{IntoLua, Table, UserData}; +use mlua::{IntoLua, UserData}; use ratatui::style::Color; -use crate::config::GlobalConfig; +use crate::{config::{evalsto::EvalTo, GlobalConfig}, sheet::cell::CellRef}; -use super::colorpair::ColorPair; +use super::style::Style; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct SheetViewTheme { - pub cursor: ColorPair, - pub selection: ColorPair, - pub cell: (ColorPair, ColorPair), + pub cursor: Style, + pub selection: Style, + pub cell: EvalTo<Style, CellRef>, } 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), - ), + cursor: Style::new().fg(Color::Black).bg(Color::White), + selection: Style::new().fg(Color::White).bg(Color::DarkGray), + cell: EvalTo::Value(Style::new().fg(Color::White).bg(Color::Black)), } } } @@ -38,31 +35,27 @@ macro_rules! cfg_mut { } impl UserData for SheetViewTheme { - fn add_fields<'lua, F: mlua::prelude::LuaUserDataFields<'lua, Self>>(fields: &mut F) { + 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| { + fields.add_field_function_set("cursor", |_, _, pair: Style| { cfg_mut!().cursor = pair; Ok(()) }); fields.add_field_function_get("selection", |_, _| Ok(cfg!().selection.clone())); - fields.add_field_function_set("selection", |_, _, pair: ColorPair| { + fields.add_field_function_set("selection", |_, _, pair: Style| { 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)?) + Ok(cfg!().cell.clone().into_lua(lua)?) }); - fields.add_field_function_set("cell", |_, _, pair: Table| { - cfg_mut!().cell = (pair.get(1)?, pair.get(2)?); + fields.add_field_function_set("cell", |_, _, cell: EvalTo<Style, CellRef>| { + cfg_mut!().cell = cell; Ok(()) }); } diff --git a/src/config/theme/style.rs b/src/config/theme/style.rs new file mode 100644 index 0000000..6e8d161 --- /dev/null +++ b/src/config/theme/style.rs @@ -0,0 +1,119 @@ +use std::str::FromStr; + +use mlua::{FromLua, IntoLua}; +use ratatui::style::{Color, Styled, Stylize}; + +#[derive(Clone, Copy, Debug)] +pub struct Style { + pub fg: Option<Color>, + pub bg: Option<Color>, + pub italic: bool, + pub bold: bool, + pub underlined: bool +} + +impl Style { + pub const fn new() -> Self { + Self { + fg: None, + bg: None, + italic: false, + bold: false, + underlined: false, + } + } + + pub const fn fg(mut self, color: Color) -> Self { + self.fg = Some(color); + self + } + + pub const fn bg(mut self, color: Color) -> Self { + self.bg = Some(color); + self + } + + pub fn apply<S, I>(&self, s: S) -> <S as Styled>::Item + where + S: Styled<Item = I>, + I: Styled, + { + let mut style = ratatui::style::Style::default(); + + if let Some(fg) = self.fg { + style = style.fg(fg) + } + + if let Some(bg) = self.bg { + style = style.bg(bg) + } + + if self.italic { + style = style.italic() + } + + if self.bold { + style = style.bold() + } + + if self.underlined { + style = style.underlined() + } + + s.set_style(style) + } +} + +impl<'lua> FromLua<'lua> for Style { + 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(); + let mut style = Style::new(); + + if let Ok(fg) = table.get::<_, String>("fg").or_else(|_| table.get(1)) { + match Color::from_str(&fg) { + Ok(fg) => style.fg = Some(fg), + Err(_) => return Err(mlua::Error::runtime("could not parse fg")) + } + } + + if let Ok(bg) = table.get::<_, String>("bg").or_else(|_| table.get(2)) { + match Color::from_str(&bg) { + Ok(bg) => style.bg = Some(bg), + Err(_) => return Err(mlua::Error::runtime("could not parse bg")) + } + } + + if let Ok(italic) = table.get::<_, bool>("italic") { + style.italic = italic + } + + if let Ok(bold) = table.get::<_, bool>("bold") { + style.bold = bold + } + + if let Ok(underlined) = table.get::<_, bool>("underlined") { + style.underlined = underlined + } + + return Ok(style) + } + + return Err(mlua::Error::runtime("could not parse style")); + } +} + +impl<'lua> IntoLua<'lua> for Style { + fn into_lua( + self, + lua: &'lua mlua::prelude::Lua, + ) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue<'lua>> { + let table = lua.create_table()?; + table.set("fg", self.fg.map(|s| s.to_string()).into_lua(lua)?)?; + table.set("bg", self.bg.map(|s| s.to_string()).into_lua(lua)?)?; + Ok(table.into_lua(lua)?) + } +} |