summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config/keymap/keymap_store.rs4
-rw-r--r--src/cursor.rs26
-rw-r--r--src/lua/runnable.rs4
-rw-r--r--src/lua/runtime.rs17
-rw-r--r--src/sheet/loader.rs55
-rw-r--r--src/sheet/mod.rs2
-rw-r--r--src/sheet/register.rs10
-rw-r--r--src/sheet/tablized.rs60
-rw-r--r--src/state/editor/cursorshape.rs6
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,