diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-02 11:38:19 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-02 11:38:19 +0200 |
| commit | 04a5a938994ddb95cfaa9a74b180e457d3a2b5d0 (patch) | |
| tree | 31ce9525ed3f3423678397323b65c910d63eadb1 /src/sheet | |
| parent | fe0938b1de0c46fc2afcaa3dcd6a0f4ec870d21a (diff) | |
implement new lua interface
Diffstat (limited to 'src/sheet')
| -rw-r--r-- | src/sheet/eval.rs | 55 | ||||
| -rw-r--r-- | src/sheet/foreach.rs | 37 | ||||
| -rw-r--r-- | src/sheet/luaref.rs | 82 | ||||
| -rw-r--r-- | src/sheet/mod.rs | 65 | ||||
| -rw-r--r-- | src/sheet/register.rs | 2 |
5 files changed, 124 insertions, 117 deletions
diff --git a/src/sheet/eval.rs b/src/sheet/eval.rs deleted file mode 100644 index 2108e48..0000000 --- a/src/sheet/eval.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::{ - sync::{Arc, RwLock}, - thread::JoinHandle, -}; - -use mlua::prelude::*; - -use crate::lua; - -use super::{cell::Cell, Sheet}; - -pub trait EvalFunction { - fn eval_function( - &self, - func: String, - range: Vec<(usize, usize)>, - ) -> JoinHandle<Result<Sheet, String>>; -} - -impl EvalFunction for Arc<RwLock<Sheet>> { - fn eval_function( - &self, - func_text: String, - range: Vec<(usize, usize)>, - ) -> JoinHandle<Result<Sheet, String>> { - *self.read().unwrap().progress.lock().unwrap() = 0; - let this = Arc::clone(self); - std::thread::spawn(move || { - let lua = lua::get(); - let read_sheet = this.read().unwrap(); - let mut sheet = read_sheet.clone(); - let result = lua.load(func_text).eval::<LuaFunction>(); - - match result { - Ok(func) => { - let read_sheet = this.read().unwrap(); - - for (i, (row, column)) in range.iter().enumerate() { - *read_sheet.progress.lock().unwrap() = (i * 100 / range.len()) as u8; - - let cellref = read_sheet.get_ref(*row, *column); - - match func.call::<_, Cell>(cellref) { - Ok(cell) => sheet.set_cell(*row, *column, cell), - Err(error) => return Err(error.to_string()), - } - } - } - Err(error) => return Err(error.to_string()), - } - - Ok(sheet) - }) - } -} diff --git a/src/sheet/foreach.rs b/src/sheet/foreach.rs new file mode 100644 index 0000000..a2a3f90 --- /dev/null +++ b/src/sheet/foreach.rs @@ -0,0 +1,37 @@ +use std::sync::{Arc, RwLock}; + +use mlua::prelude::*; + +use super::{cell::Cell, Sheet}; + +pub trait LuaForEach { + fn lua_foreach<'lua>( + &self, + func: LuaFunction<'lua>, + range: Vec<(usize, usize)>, + ) -> Result<(), LuaError>; +} + +impl LuaForEach for Arc<RwLock<Sheet>> { + fn lua_foreach<'lua>( + &self, + func: LuaFunction<'lua>, + range: Vec<(usize, usize)>, + ) -> Result<(), LuaError> { + let mut this = self.write().unwrap(); + let mut sheet = this.clone(); + + for (row, column) in range.iter() { + let cellref = this.get_ref(*row, *column); + + match func.call::<_, Cell>(cellref) { + Ok(cell) => sheet.set_cell(*row, *column, cell), + Err(error) => return Err(error), + } + } + + this.apply(sheet); + + Ok(()) + } +} diff --git a/src/sheet/luaref.rs b/src/sheet/luaref.rs new file mode 100644 index 0000000..fa4b8f9 --- /dev/null +++ b/src/sheet/luaref.rs @@ -0,0 +1,82 @@ +use crate::state::GlobalState; + +use super::{ + foreach::LuaForEach, + register::{Register, SheetId}, +}; +use mlua::prelude::*; + +pub struct SheetLuaRef { + id: SheetId, +} + +impl SheetLuaRef { + pub fn new(id: SheetId) -> Self { + Self { id } + } + + pub fn id(&self) -> SheetId { + self.id + } +} + +impl LuaUserData for SheetLuaRef { + fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_method_get("width", |_, luaref| { + Ok(Register::get(luaref.id).unwrap().read().unwrap().width()) + }); + + fields.add_field_method_get("height", |_, luaref| { + Ok(Register::get(luaref.id).unwrap().read().unwrap().height()) + }); + } + + fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method_mut("cell", |lua, luaref, (row, column): (usize, usize)| { + if let Some(rw) = Register::get(luaref.id) { + let sheet = rw.read().unwrap(); + Ok(sheet.get_ref(row, column).into_lua(lua).unwrap()) + } else { + Ok(LuaValue::Nil) + } + }); + + methods.add_method_mut("foreach", |_, luaref, func: LuaFunction| { + let range: Vec<_> = { + let state = GlobalState::instance(); + let lock = state.sheetview.active_sheet().unwrap(); + let sheet = lock.read().unwrap(); + + if sheet.id() != luaref.id() { + return Ok(()); + } + + let (width, height) = (sheet.width(), sheet.height()); + + if state.sheetview.selection_anchor.is_some() { + state.sheetview.selection() + } else { + let mut cells = Vec::new(); + for row in 0..height { + for column in 0..width { + cells.push((row, column)); + } + } + cells + } + }; + + Register::get(luaref.id).unwrap().lua_foreach(func, range) + }) + } +} + +impl<'lua> FromLua<'lua> for SheetLuaRef { + fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> { + if let Some(ud) = value.as_userdata() { + ud.take() + } else { + Err(LuaError::runtime("failed to parse sheet")) + } + } +} diff --git a/src/sheet/mod.rs b/src/sheet/mod.rs index 501b71e..5f28e07 100644 --- a/src/sheet/mod.rs +++ b/src/sheet/mod.rs @@ -1,18 +1,14 @@ -use std::sync::Mutex; - use cell::{Cell, CellRef}; -use mlua::prelude::*; -use register::{Register, SheetId}; pub mod cell; -pub mod eval; +pub mod foreach; pub mod register; +pub mod luaref; #[derive(Debug, Default)] pub struct Sheet { id: register::SheetId, rows: Vec<Vec<Cell>>, - progress: Mutex<u8>, } impl Sheet { @@ -20,7 +16,6 @@ impl Sheet { Self { id, rows: vec![vec![Cell::new_empty(); width]; height], - progress: Mutex::new(0), } } @@ -41,9 +36,8 @@ impl Sheet { } pub fn get_ref(&self, row: usize, column: usize) -> Option<CellRef> { - self.get_cell(row, column).map(|cell| { - unsafe { CellRef::new(self.id, row, column, cell.clone()) } - }) + self.get_cell(row, column) + .map(|cell| unsafe { CellRef::new(self.id, row, column, cell.clone()) }) } pub fn height(&self) -> usize { @@ -74,10 +68,6 @@ impl Sheet { pub fn apply(&mut self, other: Sheet) { self.rows = other.rows; } - - pub fn progress(&self) -> u8 { - *self.progress.lock().unwrap() - } } impl Clone for Sheet { @@ -85,54 +75,7 @@ impl Clone for Sheet { Sheet { id: self.id, rows: self.rows.clone(), - progress: Mutex::new(0), } } } -pub struct SheetLuaRef { - id: SheetId, -} - -impl SheetLuaRef { - pub fn new(id: SheetId) -> Self { - Self { id } - } - - pub fn id(&self) -> SheetId { - self.id - } -} - -impl LuaUserData for SheetLuaRef { - fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("width", |_, luaref| { - Ok(Register::get(luaref.id).unwrap().read().unwrap().width()) - }); - - fields.add_field_method_get("height", |_, luaref| { - Ok(Register::get(luaref.id).unwrap().read().unwrap().height()) - }); - } - - fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_method_mut("cell", |lua, luaref, (row, column): (usize, usize)| { - if let Some(rw) = Register::get(luaref.id) { - let sheet = rw.read().unwrap(); - Ok(sheet.get_ref(row, column).into_lua(lua).unwrap()) - } else { - Ok(LuaValue::Nil) - } - }) - } -} - -impl<'lua> FromLua<'lua> for SheetLuaRef { - fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> { - if let Some(ud) = value.as_userdata() { - ud.take() - } else { - Err(LuaError::runtime("failed to parse sheet")) - } - } -} diff --git a/src/sheet/register.rs b/src/sheet/register.rs index 039c6f0..c43720d 100644 --- a/src/sheet/register.rs +++ b/src/sheet/register.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock}; use mlua::{Table, UserData, Value}; -use super::{cell::Cell, Sheet, SheetLuaRef}; +use super::{cell::Cell, Sheet, luaref::SheetLuaRef}; static REGISTER: RwLock<Vec<Arc<RwLock<Sheet>>>> = RwLock::new(Vec::new()); |