diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-02 15:51:45 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-02 15:51:45 +0200 |
| commit | d1492a10cdaf714074d29ad3366ab9c169d95b75 (patch) | |
| tree | 4192aa6825479f56332b3cd40d56913e48b95222 | |
| parent | c920f258f6c9b0623a841b7c27561fa1d09cef72 (diff) | |
add bartheme and barstate to sheetview
| -rw-r--r-- | src/config/theme/bar.rs | 62 | ||||
| -rw-r--r-- | src/config/theme/mod.rs | 1 | ||||
| -rw-r--r-- | src/config/theme/sheetview/bar.rs | 8 | ||||
| -rw-r--r-- | src/config/theme/sheetview/mod.rs (renamed from src/config/theme/sheetview.rs) | 10 | ||||
| -rw-r--r-- | src/config/theme/style.rs | 6 | ||||
| -rw-r--r-- | src/state/bar.rs | 60 | ||||
| -rw-r--r-- | src/state/mod.rs | 1 | ||||
| -rw-r--r-- | src/state/view/bar.rs | 7 | ||||
| -rw-r--r-- | src/state/view/mod.rs | 11 | ||||
| -rw-r--r-- | src/state/view/mode.rs | 12 | ||||
| -rw-r--r-- | src/widgets/logview.rs | 4 | ||||
| -rw-r--r-- | src/widgets/luaeditor/mod.rs | 6 | ||||
| -rw-r--r-- | src/widgets/sheetview/mod.rs | 169 | ||||
| -rw-r--r-- | src/widgets/statusbar.rs | 49 |
14 files changed, 250 insertions, 156 deletions
diff --git a/src/config/theme/bar.rs b/src/config/theme/bar.rs new file mode 100644 index 0000000..68a3b13 --- /dev/null +++ b/src/config/theme/bar.rs @@ -0,0 +1,62 @@ +macro_rules! BarTheme { + ($name:ident, $cfg:expr, $cfg_mut:expr) => { + use crate::config::theme::style::Style; + use crate::lua::evalsto::EvalTo; + use crate::state::view::mode::Mode; + use crate::widgets::statusbar::StatusBar; + use mlua::{Lua, UserData}; + + #[derive(Debug, Default, Clone)] + pub struct $name { + pub left: EvalTo<Style, Mode>, + pub middle: EvalTo<Style, Mode>, + pub right: EvalTo<Style, Mode>, + } + + impl $name { + pub const fn new() -> Self { + Self { + left: EvalTo::Value(Style::new()), + middle: EvalTo::Value(Style::new()), + right: EvalTo::Value(Style::new()), + } + } + + pub fn apply(bar: &mut StatusBar, mode: Mode, lua: &Lua) { + let (left, middle, right) = ( + $cfg.left.get(mode, lua).unwrap_or_default().style(), + $cfg.middle.get(mode, lua).unwrap_or_default().style(), + $cfg.right.get(mode, lua).unwrap_or_default().style(), + ); + + bar.set_left_style(left); + bar.set_middle_style(middle); + bar.set_right_style(right); + } + } + + impl UserData for $name { + fn add_fields<'lua, F: mlua::prelude::LuaUserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_function_get("left", |_, _| Ok($cfg.left.clone())); + fields.add_field_function_set("left", |_, _, style: EvalTo<Style, Mode>| { + $cfg_mut.left = style; + Ok(()) + }); + + fields.add_field_function_get("middle", |_, _| Ok($cfg.middle.clone())); + fields.add_field_function_set("middle", |_, _, style: EvalTo<Style, Mode>| { + $cfg_mut.middle = style; + Ok(()) + }); + + fields.add_field_function_get("right", |_, _| Ok($cfg.right.clone())); + fields.add_field_function_set("right", |_, _, style: EvalTo<Style, Mode>| { + $cfg_mut.right = style; + Ok(()) + }); + } + } + }; +} + +pub(super) use BarTheme; diff --git a/src/config/theme/mod.rs b/src/config/theme/mod.rs index 75f65a0..082cd17 100644 --- a/src/config/theme/mod.rs +++ b/src/config/theme/mod.rs @@ -7,6 +7,7 @@ use super::DUMMY_CONFIG; pub mod style; pub mod sheetview; +pub(self) mod bar; #[derive(Clone, Debug, Default)] pub struct Theme { diff --git a/src/config/theme/sheetview/bar.rs b/src/config/theme/sheetview/bar.rs new file mode 100644 index 0000000..c3d1d50 --- /dev/null +++ b/src/config/theme/sheetview/bar.rs @@ -0,0 +1,8 @@ +use super::super::bar::BarTheme; +use crate::config::GlobalConfig; + +BarTheme!( + SheetViewBarTheme, + GlobalConfig::instance().theme.sheetview.bar, + GlobalConfig::instance_mut().theme.sheetview.bar +); diff --git a/src/config/theme/sheetview.rs b/src/config/theme/sheetview/mod.rs index af0b585..fc999ca 100644 --- a/src/config/theme/sheetview.rs +++ b/src/config/theme/sheetview/mod.rs @@ -1,16 +1,21 @@ use mlua::UserData; use ratatui::style::Color; -use crate::{config::GlobalConfig, lua::evalsto::EvalTo, sheet::cell::CellRef}; +use crate::{config::{GlobalConfig, DUMMY_CONFIG}, lua::evalsto::EvalTo, sheet::cell::CellRef}; + +use self::bar::SheetViewBarTheme; use super::style::Style; +pub mod bar; + #[derive(Debug, Clone, Default)] pub struct SheetViewTheme { pub cursor: EvalTo<Style, CellRef>, pub selection: EvalTo<Style, CellRef>, pub cell: EvalTo<Style, CellRef>, pub background: EvalTo<Style, ()>, + pub bar: SheetViewBarTheme, } impl SheetViewTheme { @@ -20,6 +25,7 @@ impl SheetViewTheme { selection: EvalTo::Value(Style::new().fg(Color::White).bg(Color::DarkGray)), cell: EvalTo::Value(Style::new().fg(Color::White).bg(Color::Black)), background: EvalTo::Value(Style::new().bg(Color::Black)), + bar: SheetViewBarTheme::new(), } } } @@ -62,5 +68,7 @@ impl UserData for SheetViewTheme { cfg_mut!().background = background; Ok(()) }); + + fields.add_field_function_get("bar", |_, _| Ok(DUMMY_CONFIG.theme.sheetview.bar)) } } diff --git a/src/config/theme/style.rs b/src/config/theme/style.rs index 87cd068..aadd73b 100644 --- a/src/config/theme/style.rs +++ b/src/config/theme/style.rs @@ -38,6 +38,10 @@ impl Style { S: Styled<Item = I>, I: Styled, { + s.set_style(self.style()) + } + + pub fn style(&self) -> ratatui::style::Style { let mut style = ratatui::style::Style::default(); if let Some(fg) = self.fg { @@ -60,7 +64,7 @@ impl Style { style = style.underlined() } - s.set_style(style) + style } } diff --git a/src/state/bar.rs b/src/state/bar.rs new file mode 100644 index 0000000..6462449 --- /dev/null +++ b/src/state/bar.rs @@ -0,0 +1,60 @@ +macro_rules! BarState { + ($name:ident, $cfg:expr, $cfg_mut:expr) => { + use crate::lua::evalsto::EvalTo; + use crate::state::view::mode::Mode; + use crate::widgets::statusbar::StatusBar; + use mlua::{Lua, UserData}; + + #[derive(Debug, Default, Clone)] + pub struct $name { + pub left: EvalTo<String, Mode>, + pub middle: EvalTo<String, Mode>, + pub right: EvalTo<String, Mode>, + } + + impl $name { + pub const fn new() -> Self { + Self { + left: EvalTo::Value(String::new()), + middle: EvalTo::Value(String::new()), + right: EvalTo::Value(String::new()), + } + } + + pub fn apply(bar: &mut StatusBar, mode: Mode, lua: &Lua) { + let (left, middle, right) = ( + $cfg.left.get(mode, lua).unwrap_or_default(), + $cfg.middle.get(mode, lua).unwrap_or_default(), + $cfg.right.get(mode, lua).unwrap_or_default(), + ); + bar.set_left(left); + bar.set_middle(middle); + bar.set_right(right); + } + } + + impl UserData for $name { + fn add_fields<'lua, F: mlua::prelude::LuaUserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_function_get("left", |_, _| Ok($cfg.left.clone())); + fields.add_field_function_set("left", |_, _, style: EvalTo<String, Mode>| { + $cfg_mut.left = style; + Ok(()) + }); + + fields.add_field_function_get("middle", |_, _| Ok($cfg.middle.clone())); + fields.add_field_function_set("middle", |_, _, style: EvalTo<String, Mode>| { + $cfg_mut.middle = style; + Ok(()) + }); + + fields.add_field_function_get("right", |_, _| Ok($cfg.right.clone())); + fields.add_field_function_set("right", |_, _, style: EvalTo<String, Mode>| { + $cfg_mut.right = style; + Ok(()) + }); + } + } + }; +} + +pub(super) use BarState; diff --git a/src/state/mod.rs b/src/state/mod.rs index 5200da9..1f84716 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -8,6 +8,7 @@ pub mod editor; pub mod log; pub mod view; pub mod window; +pub(self) mod bar; #[derive(Debug, Default)] pub struct GlobalState { diff --git a/src/state/view/bar.rs b/src/state/view/bar.rs new file mode 100644 index 0000000..cc59e36 --- /dev/null +++ b/src/state/view/bar.rs @@ -0,0 +1,7 @@ +use crate::state::{bar::BarState, GlobalState}; + +BarState!( + SheetViewBarState, + GlobalState::instance().sheetview.bar, + GlobalState::instance_mut().sheetview.bar +); diff --git a/src/state/view/mod.rs b/src/state/view/mod.rs index 543644c..e45a3f4 100644 --- a/src/state/view/mod.rs +++ b/src/state/view/mod.rs @@ -2,9 +2,9 @@ use std::sync::{Arc, RwLock}; use mlua::{IntoLua, UserData, Value}; -use self::mode::Mode; +use self::{bar::SheetViewBarState, mode::Mode}; -use super::GlobalState; +use super::{GlobalState, DUMMY_STATE}; use crate::{ cursor::{Cursor, CursorMove}, sheet::{ @@ -15,6 +15,7 @@ use crate::{ }; pub mod mode; +pub mod bar; #[derive(Default, Debug)] pub struct SheetViewState { @@ -22,6 +23,7 @@ pub struct SheetViewState { active_sheet: Option<SheetId>, pub mode: Mode, pub selection_anchor: Option<(usize, usize)>, + pub bar: SheetViewBarState, } impl SheetViewState { @@ -31,6 +33,7 @@ impl SheetViewState { active_sheet: None, mode: Mode::Normal, selection_anchor: None, + bar: SheetViewBarState::new(), } } @@ -167,6 +170,10 @@ impl UserData for SheetViewState { } this.mode = mode; Ok(()) + }); + + fields.add_field_function_get("bar", |_, _| { + Ok(DUMMY_STATE.sheetview.bar) }) } diff --git a/src/state/view/mode.rs b/src/state/view/mode.rs index 3fa9c63..63e6e5b 100644 --- a/src/state/view/mode.rs +++ b/src/state/view/mode.rs @@ -18,15 +18,15 @@ impl<'lua> FromLua<'lua> for Mode { match value.as_str().unwrap().to_lowercase().as_ref() { "normal" => Ok(Mode::Normal), "visual" => Ok(Mode::Visual), - "insert" => Ok(Mode::Visual), - "command" => Ok(Mode::Visual), + "insert" => Ok(Mode::Insert), + "command" => Ok(Mode::Command), _ => Err(mlua::Error::runtime( - "mode needs to be 'normal', 'visual' or 'insert'", + "mode needs to be 'normal', 'visual', 'insert' or 'command'", )), } } else { Err(mlua::Error::runtime( - "mode needs to be 'normal', 'visual' or 'insert'", + "mode needs to be 'normal', 'visual' 'insert', or 'command'", )) } } @@ -39,8 +39,8 @@ impl<'lua> IntoLua<'lua> for Mode { ) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue<'lua>> { match self { Mode::Normal => "normal", - Mode::Visual => "insert", - Mode::Insert => "visual", + Mode::Visual => "visual", + Mode::Insert => "insert", Mode::Command => "command", } .into_lua(lua) diff --git a/src/widgets/logview.rs b/src/widgets/logview.rs index 5d30b17..4b80d7c 100644 --- a/src/widgets/logview.rs +++ b/src/widgets/logview.rs @@ -1,4 +1,4 @@ -use ratatui::{crossterm::event::KeyEvent, style::{Style, Stylize}, text::ToSpan, widgets::Widget}; +use ratatui::{crossterm::event::KeyEvent, text::ToSpan, widgets::Widget}; use crate::lua::iobuffer::iobuffer; @@ -12,7 +12,7 @@ pub struct LogView { impl LogView { pub fn new() -> Self { Self { - bar: StatusBar::new().left(" Log ").left_style(Style::default().on_magenta()), + bar: StatusBar::new(), } } diff --git a/src/widgets/luaeditor/mod.rs b/src/widgets/luaeditor/mod.rs index de35c3d..3ce9ab5 100644 --- a/src/widgets/luaeditor/mod.rs +++ b/src/widgets/luaeditor/mod.rs @@ -1,6 +1,6 @@ use ratatui::{ crossterm::event::{KeyCode, KeyEvent, KeyModifiers}, - style::{Style, Stylize}, + style::Stylize, text::{ToLine, ToSpan}, widgets::Widget, }; @@ -23,9 +23,7 @@ pub struct LuaEditor { impl LuaEditor { pub fn new() -> Self { Self { - bar: StatusBar::new() - .left(" [No Name] ") - .left_style(Style::default().on_magenta()), + bar: StatusBar::new(), scroll: 0, highlight_config: treesitter::new_highlight_configuration(), } diff --git a/src/widgets/sheetview/mod.rs b/src/widgets/sheetview/mod.rs index 96c4234..202bb70 100644 --- a/src/widgets/sheetview/mod.rs +++ b/src/widgets/sheetview/mod.rs @@ -1,17 +1,16 @@ use ratatui::{ crossterm::event::{KeyCode, KeyEvent}, prelude::*, - style::Stylize, text::ToLine, widgets::{Paragraph, Widget}, }; use crate::{ - config::GlobalConfig, + config::{theme::sheetview::bar::SheetViewBarTheme, GlobalConfig}, cursor::CursorMove, lua, sheet::cell::Cell, - state::{view::mode::Mode, window::Window, GlobalState}, + state::{view::{bar::SheetViewBarState, mode::Mode}, window::Window, GlobalState}, }; use super::statusbar::StatusBar; @@ -27,12 +26,7 @@ pub struct SheetView { impl SheetView { pub fn new() -> Self { Self { - bar: StatusBar::new() - .left(" NORMAL ") - .left_style(Style::default().on_magenta()) - .middle("Sheet") - .right("") - .right_style(Style::default().on_red()), + bar: StatusBar::new(), scroll: (0, 0), } } @@ -48,17 +42,18 @@ impl SheetView { .move_checked(cm) } - fn cursor(&self) -> (usize, usize) { - let state = GlobalState::instance(); - (state.sheetview.cursor.y(), state.sheetview.cursor.x()) - } - fn start_selection(&self) { let mut state = GlobalState::instance_mut(); - state.sheetview.selection_anchor = Some(self.cursor()); + state.sheetview.selection_anchor = Some((state.sheetview.cursor.y(), state.sheetview.cursor.x())); state.sheetview.mode = Mode::Visual; } + fn stop_selection(&self) { + let mut state = GlobalState::instance_mut(); + state.sheetview.selection_anchor = None; + state.sheetview.mode = Mode::Normal; + } + fn open_editor(&self) { let mut state = GlobalState::instance_mut(); state.editor.buffer.set_lines_from_string( @@ -126,7 +121,7 @@ end)"#, KeyCode::Char('k') => self.move_cursor(CursorMove::Up(1)), KeyCode::Char('h') => self.move_cursor(CursorMove::Left(1)), KeyCode::Char('l') => self.move_cursor(CursorMove::Right(1)), - KeyCode::Char('v') => self.start_selection(), + KeyCode::Char('v') | KeyCode::Esc => self.stop_selection(), KeyCode::Char('s') => self.open_editor(), KeyCode::Char(':') => { self.set_mode(Mode::Command); @@ -162,99 +157,85 @@ impl Widget for &mut SheetView { where Self: Sized, { - let theme = GlobalConfig::instance().theme.sheetview.clone(); + let mode = { + let theme = GlobalConfig::instance().theme.sheetview.clone(); - let state = GlobalState::instance(); - let lock = state.sheetview.active_sheet().unwrap(); - let sheet = lock.read().unwrap(); - let cursor = &state.sheetview.cursor; + let state = GlobalState::instance(); + let lock = state.sheetview.active_sheet().unwrap(); + let sheet = lock.read().unwrap(); + let cursor = &state.sheetview.cursor; - let sheet_area_inner = self.bar.area(area); + let sheet_area_inner = self.bar.area(area); - let viewport_rows = sheet.height().min(sheet_area_inner.height as usize); - let viewport_columns = sheet - .width() - .min((sheet_area_inner.width / DEFAULT_COLUMN_WIDTH) as usize); + let viewport_rows = sheet.height().min(sheet_area_inner.height as usize); + let viewport_columns = sheet + .width() + .min((sheet_area_inner.width / DEFAULT_COLUMN_WIDTH) as usize); - if cursor.y() >= viewport_rows + self.scroll.0 { - self.scroll.0 = (cursor.y() - viewport_rows) + 1; - } else if cursor.y() < self.scroll.0 { - self.scroll.0 = cursor.y(); - } + if cursor.y() >= viewport_rows + self.scroll.0 { + self.scroll.0 = (cursor.y() - viewport_rows) + 1; + } else if cursor.y() < self.scroll.0 { + self.scroll.0 = cursor.y(); + } - if cursor.x() >= viewport_columns + self.scroll.1 { - self.scroll.1 = (cursor.x() - viewport_columns) + 1; - } else if cursor.x() < self.scroll.1 { - self.scroll.1 = cursor.x(); - } + if cursor.x() >= viewport_columns + self.scroll.1 { + self.scroll.1 = (cursor.x() - viewport_columns) + 1; + } else if cursor.x() < self.scroll.1 { + self.scroll.1 = cursor.x(); + } - theme - .background - .get((), &lua::get()) - .unwrap_or_default() - .apply(Paragraph::default()) - .render(area, buf); + theme + .background + .get((), &lua::get()) + .unwrap_or_default() + .apply(Paragraph::default()) + .render(sheet_area_inner, buf); - for row in 0..viewport_rows { - for column in 0..(viewport_columns + 1) { - let (cell_pos_y, cell_pos_x) = (row + self.scroll.0, column + self.scroll.1); + for row in 0..viewport_rows { + for column in 0..(viewport_columns + 1) { + let (cell_pos_y, cell_pos_x) = (row + self.scroll.0, column + self.scroll.1); - if let Some(cell_ref) = sheet.get_ref(cell_pos_y, cell_pos_x) { - let cell = cell_ref.value().to_string() + " "; + if let Some(cell_ref) = sheet.get_ref(cell_pos_y, cell_pos_x) { + let cell = cell_ref.value().to_string() + " "; - let line = if (cell_pos_y, cell_pos_x) == (cursor.y(), cursor.x()) { - theme - .cursor - .get(cell_ref, &lua::get()) - .unwrap_or_default() - .apply(cell.to_line()) - } else if state.sheetview.selection_contains(cell_pos_y, cell_pos_x) { - theme - .selection - .get(cell_ref, &lua::get()) - .unwrap_or_default() - .apply(cell.to_line()) - } else { - theme - .cell - .get(cell_ref, &lua::get()) - .unwrap_or_default() - .apply(cell.to_line()) - }; + let line = if (cell_pos_y, cell_pos_x) == (cursor.y(), cursor.x()) { + theme + .cursor + .get(cell_ref, &lua::get()) + .unwrap_or_default() + .apply(cell.to_line()) + } else if state.sheetview.selection_contains(cell_pos_y, cell_pos_x) { + theme + .selection + .get(cell_ref, &lua::get()) + .unwrap_or_default() + .apply(cell.to_line()) + } else { + theme + .cell + .get(cell_ref, &lua::get()) + .unwrap_or_default() + .apply(cell.to_line()) + }; - let rect = Rect::new( - sheet_area_inner.x + (column as u16) * DEFAULT_COLUMN_WIDTH, - sheet_area_inner.y + (row as u16), - (sheet_area_inner.width - (column as u16) * DEFAULT_COLUMN_WIDTH) - .min(DEFAULT_COLUMN_WIDTH), - 1, - ); + let rect = Rect::new( + sheet_area_inner.x + (column as u16) * DEFAULT_COLUMN_WIDTH, + sheet_area_inner.y + (row as u16), + (sheet_area_inner.width - (column as u16) * DEFAULT_COLUMN_WIDTH) + .min(DEFAULT_COLUMN_WIDTH), + 1, + ); - line.render(rect, buf); + line.render(rect, buf); + } } } - } - match state.sheetview.mode { - Mode::Command => { - self.bar.set_left(" COMMAND "); - } - - Mode::Insert => { - self.bar.set_left(" INSERT "); - } - - _ => { - if state.sheetview.selection_anchor.is_some() { - self.bar.set_left(" VISUAL "); - } else { - self.bar.set_left(" NORMAL "); - self.bar.set_middle_alignment(Alignment::Center); - self.bar.set_middle("Sheet"); - } - } - } + state.sheetview.mode + }; + SheetViewBarState::apply(&mut self.bar, mode, &lua::get()); + SheetViewBarTheme::apply(&mut self.bar, mode, &lua::get()); self.bar.render(area, buf); } } diff --git a/src/widgets/statusbar.rs b/src/widgets/statusbar.rs index c8d52e5..61ce1a3 100644 --- a/src/widgets/statusbar.rs +++ b/src/widgets/statusbar.rs @@ -1,3 +1,4 @@ + use ratatui::{ crossterm::event::{KeyCode, KeyEvent}, layout::{Alignment, Rect}, @@ -6,7 +7,7 @@ use ratatui::{ widgets::Widget, }; -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub struct StatusBar { left: String, left_style: Style, @@ -34,50 +35,6 @@ impl StatusBar { } } - pub fn left<S>(mut self, text: S) -> Self - where - S: AsRef<str>, - { - self.left = text.as_ref().to_string(); - self - } - - pub fn middle<S>(mut self, text: S) -> Self - where - S: AsRef<str>, - { - self.middle = text.as_ref().to_string(); - self - } - - pub fn right<S>(mut self, text: S) -> Self - where - S: AsRef<str>, - { - self.right = text.as_ref().to_string(); - self - } - - pub fn left_style(mut self, style: Style) -> Self { - self.left_style = style; - self - } - - pub fn middle_style(mut self, style: Style) -> Self { - self.left_style = style; - self - } - - pub fn middle_alignment(mut self, alignment: Alignment) -> Self { - self.middle_alignment = alignment; - self - } - - pub fn right_style(mut self, style: Style) -> Self { - self.right_style = style; - self - } - pub fn set_left<S>(&mut self, text: S) where S: AsRef<str>, @@ -104,7 +61,7 @@ impl StatusBar { } pub fn set_middle_style(&mut self, style: Style) { - self.left_style = style; + self.middle_style = style; } pub fn set_right_style(&mut self, style: Style) { |