diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-10 15:41:31 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-08-10 15:41:31 +0200 |
| commit | b747ca8af52129876b577a4f20f7105a05c6b002 (patch) | |
| tree | d976a5c3cd135dfecb1014246936bb7a8b525c4b | |
| parent | 4763d8ce3b833df1e7321a407b08666f69657fdb (diff) | |
add global fileloader registry
| -rw-r--r-- | src/config/keymap/keymap_store.rs | 4 | ||||
| -rw-r--r-- | src/cursor.rs | 26 | ||||
| -rw-r--r-- | src/lua/runnable.rs | 4 | ||||
| -rw-r--r-- | src/lua/runtime.rs | 17 | ||||
| -rw-r--r-- | src/sheet/loader.rs | 55 | ||||
| -rw-r--r-- | src/sheet/mod.rs | 2 | ||||
| -rw-r--r-- | src/sheet/register.rs | 10 | ||||
| -rw-r--r-- | src/sheet/tablized.rs | 60 | ||||
| -rw-r--r-- | src/state/editor/cursorshape.rs | 6 |
9 files changed, 160 insertions, 24 deletions
diff --git a/src/config/keymap/keymap_store.rs b/src/config/keymap/keymap_store.rs index e5e32e5..e4da9da 100644 --- a/src/config/keymap/keymap_store.rs +++ b/src/config/keymap/keymap_store.rs @@ -8,9 +8,11 @@ use ratatui::crossterm::event::KeyEvent; use crate::lua::runnable::Runnable; +type KeyMapHandler = Arc<Mutex<dyn Runnable<(), bool>>>; + #[derive(Default, Clone)] pub struct KeyMapStore { - store: Option<HashMap<KeyEvent, Arc<Mutex<dyn Runnable<(), bool>>>>>, + store: Option<HashMap<KeyEvent, KeyMapHandler>>, } impl KeyMapStore { diff --git a/src/cursor.rs b/src/cursor.rs index 5027e80..6e49cf7 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -23,24 +23,22 @@ impl<'lua> FromLuaMulti<'lua> for CursorMove { .filter(|v| v.is_integer() || v.is_number()) .map(|v| { if v.is_number() { - v.as_number().unwrap_or(0.0) + v.as_number().unwrap() as usize } else { - v.as_number().unwrap_or(0.0) + v.as_integer().unwrap() as usize } - }) - .map(|n| n as usize); + }); let second = values .get(2) .filter(|v| v.is_integer() || v.is_number()) .map(|v| { if v.is_number() { - v.as_number().unwrap() + v.as_number().unwrap() as usize } else { - v.as_number().unwrap() + v.as_integer().unwrap() as usize } - }) - .map(|n| n as usize); + }); if let Some(value) = values.get(0) { if value.is_string() { @@ -54,15 +52,19 @@ impl<'lua> FromLuaMulti<'lua> for CursorMove { "begin" => return Ok(CursorMove::Begin), "end" => return Ok(CursorMove::End), "jump" => { - if first.is_some() && second.is_some() { - return Ok(CursorMove::Jump((first.unwrap(), second.unwrap()))); + if let Some(first) = first { + if let Some(second) = second { + return Ok(CursorMove::Jump((first.max(0), second.max(0)))); + } } return Err(mlua::Error::runtime("invalid row, column values")); } "relative" => { - if first.is_some() && second.is_some() { - return Ok(CursorMove::Jump((first.unwrap(), second.unwrap()))); + if let Some(first) = first { + if let Some(second) = second { + return Ok(CursorMove::Relative((first as isize, second as isize))); + } } return Err(mlua::Error::runtime("invalid row, column values")); diff --git a/src/lua/runnable.rs b/src/lua/runnable.rs index adda512..683d191 100644 --- a/src/lua/runnable.rs +++ b/src/lua/runnable.rs @@ -5,6 +5,7 @@ use super::ownedfunction::OwnedFunction; pub trait Runnable<A, R> where Self: Send, + R: ?Sized { fn run<'lua>(&self, arg: A, lua: &'lua Lua) -> Result<R> where @@ -16,6 +17,7 @@ impl<A, R, T> Runnable<A, R> for T where T: Fn(A) -> R, Self: Send, + R: ?Sized { fn run<'lua>(&self, arg: A, _: &'lua Lua) -> Result<R> where @@ -29,6 +31,7 @@ where impl<A, R> Runnable<A, R> for OwnedFunction where Self: Send, + R: ?Sized { fn run<'lua>(&self, arg: A, lua: &'lua Lua) -> Result<R> where @@ -39,4 +42,3 @@ where func.call::<A, R>(arg) } } - diff --git a/src/lua/runtime.rs b/src/lua/runtime.rs index ce34827..6a0a230 100644 --- a/src/lua/runtime.rs +++ b/src/lua/runtime.rs @@ -3,14 +3,15 @@ use std::time::{SystemTime, UNIX_EPOCH}; use crate::{ config::{self, GlobalConfig}, - sheet::register::Register, state::GlobalState, + sheet::{loader::Loader, register::Register}, + state::GlobalState, }; pub fn neosheet(lua: &Lua) -> Result<()> { let exports = lua.create_table()?; exports - .set("sheets", lua.create_userdata(Register)?) + .set("sheet", lua.create_userdata(Register)?) .unwrap(); exports .set("config", lua.create_userdata(GlobalConfig::default())?) @@ -18,6 +19,9 @@ pub fn neosheet(lua: &Lua) -> Result<()> { exports .set("state", lua.create_userdata(GlobalState::default())?) .unwrap(); + exports + .set("loader", lua.create_proxy::<Loader>()?) + .unwrap(); lua.globals() .get::<_, Table>("package")? @@ -45,10 +49,15 @@ pub fn package(lua: &Lua) -> Result<()> { package.set( "path", format!( - "{}/?.lua;{}/?/init.lua;{};./?.lua", + "{}/?.lua;{}/?/init.lua;{}/lib/?.lua;{}/lib/?/init.lua;{};./?.lua", + config::constants::USER_CONFIG_DIR.as_str(), + config::constants::USER_CONFIG_DIR.as_str(), config::constants::USER_CONFIG_DIR.as_str(), config::constants::USER_CONFIG_DIR.as_str(), - path.split(';').filter(|s| s.starts_with('/')).collect::<Vec<&str>>().join(";"), + path.split(';') + .filter(|s| s.starts_with('/')) + .collect::<Vec<&str>>() + .join(";"), ), )?; Ok(()) diff --git a/src/sheet/loader.rs b/src/sheet/loader.rs new file mode 100644 index 0000000..613d2a5 --- /dev/null +++ b/src/sheet/loader.rs @@ -0,0 +1,55 @@ +use std::{ + collections::HashMap, + path::Path, + sync::{Mutex, MutexGuard}, +}; + +use lazy_static::lazy_static; +use mlua::{Lua, UserData}; + +use crate::lua::{ownedfunction::OwnedFunction, runnable::Runnable}; + +use super::{register::SheetId, tablized::Tablized}; + +lazy_static! { + static ref GLOBAL_LOADER: Mutex<Loader> = Mutex::new(Loader::new()); +} + +#[derive(Default)] +pub struct Loader { + loaders: HashMap<String, Box<dyn Runnable<String, Tablized>>>, +} + +impl Loader { + pub fn new() -> Self { + Self { + loaders: HashMap::new(), + } + } + + pub fn load_sheet(&self, path: String, lua: &Lua) -> Option<SheetId> { + let p = Path::new(&path); + let loader = self.loaders.get(p.extension()?.to_str()?)?; + match loader.run(path, lua) { + Ok(table) => table.to_sheet(lua).ok(), + Err(_) => None, + } + } + + pub fn add(&mut self, extension: String, func: Box<dyn Runnable<String, Tablized>>) { + self.loaders.insert(extension, func); + } + + pub fn get() -> MutexGuard<'static, Loader> { + GLOBAL_LOADER.lock().unwrap() + } +} + +impl UserData for Loader { + fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_function("add", |_, (extension, func): (String, OwnedFunction)| { + GLOBAL_LOADER.lock().unwrap().add(extension, Box::new(func)); + Ok(()) + }); + } +} diff --git a/src/sheet/mod.rs b/src/sheet/mod.rs index ffaec94..118e2ca 100644 --- a/src/sheet/mod.rs +++ b/src/sheet/mod.rs @@ -4,6 +4,8 @@ pub mod cell; pub mod map; pub mod register; pub mod luaref; +pub mod loader; +pub mod tablized; #[derive(Debug, Default)] pub struct Sheet { diff --git a/src/sheet/register.rs b/src/sheet/register.rs index c43720d..aaf9c35 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, luaref::SheetLuaRef}; +use super::{cell::Cell, loader::Loader, luaref::SheetLuaRef, Sheet}; static REGISTER: RwLock<Vec<Arc<RwLock<Sheet>>>> = RwLock::new(Vec::new()); @@ -59,7 +59,7 @@ impl Register { impl UserData for Register { fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_function_mut("create", |lua, table: Table| { + methods.add_function("create", |lua, table: Table| { let id = Register::create_from_table(table)?; let luaref = SheetLuaRef::new(id); if let Ok(ud) = lua.create_userdata(luaref) { @@ -69,7 +69,11 @@ impl UserData for Register { } }); - methods.add_function_mut("get", |lua, id: SheetId| { + methods.add_function("open", |lua, path: String| { + Ok(Loader::get().load_sheet(path, lua)) + }); + + methods.add_function("get", |lua, id: SheetId| { if Register::get(id).is_some() { let luaref = SheetLuaRef::new(id); if let Ok(ud) = lua.create_userdata(luaref) { diff --git a/src/sheet/tablized.rs b/src/sheet/tablized.rs new file mode 100644 index 0000000..a40af0d --- /dev/null +++ b/src/sheet/tablized.rs @@ -0,0 +1,60 @@ +use mlua::{FromLuaMulti, Lua, RegistryKey}; + +use super::{ + cell::Cell, + register::{Register, SheetId}, +}; + +pub enum Tablized { + Vector(Vec<Vec<Cell>>), + Table(RegistryKey), +} + +impl Tablized { + pub fn to_sheet(&self, lua: &Lua) -> mlua::Result<SheetId> { + match self { + Tablized::Vector(v) => { + let rows = v.len(); + let columns = v + .iter() + .max_by_key(|v| v.len()) + .unwrap_or(&Vec::new()) + .len(); + + let id = Register::create(columns, rows); + let lock = Register::get(id).unwrap(); + let mut sheet = lock.write().unwrap(); + + for row in 0..rows { + for column in 0..columns { + if let Some(value) = v.get(row).and_then(|c| c.get(column)) { + sheet.set_cell(row, column, value.clone()) + } + } + } + + Ok(id) + } + Tablized::Table(key) => { + let table = lua.registry_value(key)?; + Register::create_from_table(table) + }, + } + } +} + +impl<'lua> FromLuaMulti<'lua> for Tablized { + fn from_lua_multi( + values: mlua::prelude::LuaMultiValue<'lua>, + lua: &'lua mlua::prelude::Lua, + ) -> mlua::prelude::LuaResult<Self> { + if let Some(value) = values.get(0) { + if value.is_table() { + let key = lua.create_registry_value(value)?; + return Ok(Self::Table(key)); + } + } + + Err(mlua::Error::runtime("table needed")) + } +} diff --git a/src/state/editor/cursorshape.rs b/src/state/editor/cursorshape.rs index b9b45bd..b2eddc5 100644 --- a/src/state/editor/cursorshape.rs +++ b/src/state/editor/cursorshape.rs @@ -37,9 +37,9 @@ impl<'lua> IntoLua<'lua> for CursorShape { } } -impl Into<SetCursorStyle> for CursorShape { - fn into(self) -> SetCursorStyle { - match self { +impl From<CursorShape> for SetCursorStyle { + fn from(shape: CursorShape) -> SetCursorStyle { + match shape { CursorShape::Block => SetCursorStyle::SteadyBlock, CursorShape::Bar => SetCursorStyle::SteadyBar, CursorShape::Underscore => SetCursorStyle::SteadyUnderScore, |