Skip to content

Commit

Permalink
Add optional behavior to flatten and clone
Browse files Browse the repository at this point in the history
Note: I haven't tested this code yet.
  • Loading branch information
Danielkonge committed Dec 2, 2023
1 parent aff4221 commit 358d8b9
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 12 deletions.
5 changes: 3 additions & 2 deletions docs/config/lua/wezterm.table/count.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

{{since('nightly')}}

This function returns the number of non-nil elements of a Lua table (or array) passed to it.
This function returns the number of non-nil elements of any Lua table passed to it.

Note: The Lua function `#` also returns the length of an array, but `#` only works for array-style
tables with contiguous integer keys starting with index `1`, and not sparse arrays (with gaps in
their integer keys), or object or other style of tables with non-integer keys.
their integer keys), or object or other style of tables with non-integer keys. `wezterm.table.count`
can instead be used for such tables.

```lua
local wezterm = require 'wezterm'
Expand Down
43 changes: 33 additions & 10 deletions lua-api-crates/table-funcs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use config::lua::get_or_create_sub_module;
use config::lua::mlua::{self, Lua, Table, Value as LuaValue};
use config::lua::mlua::{self, Lua, Table, Value as LuaValue, MultiValue as LuaMultiValue};
use luahelper::impl_lua_conversion_dynamic;
use wezterm_dynamic::{FromDynamic, ToDynamic};

Expand Down Expand Up @@ -29,6 +29,16 @@ enum ConflictMode {
}
impl_lua_conversion_dynamic!(ConflictMode);

#[derive(Default, Debug, FromDynamic, ToDynamic, Clone, PartialEq, Eq, Copy)]
enum DepthMode {
/// Take the latest value
#[default]
Top,
/// Raise an error
Deep,
}
impl_lua_conversion_dynamic!(DepthMode);

// merge tables
// (in case of overlap of the tables, we default to taking the key-value pair from the last table)
// Note that we don't use a HashMap since we want to keep the order of the tables, which
Expand Down Expand Up @@ -104,28 +114,41 @@ fn deep_extend<'lua>(
Ok(tbl)
}

fn clone<'lua>(lua: &'lua Lua, table: Table<'lua>) -> mlua::Result<Table<'lua>> {
fn clone<'lua>(lua: &'lua Lua, (table, behavior): (Table<'lua>, Option<DepthMode>)) -> mlua::Result<Table<'lua>> {
let res: Table<'lua> = lua.create_table()?;

let behavior = behavior.unwrap_or_default();
for pair in table.pairs::<LuaValue, LuaValue>() {
let (key, value) = pair?;
if let LuaValue::Table(tbl) = value {
res.set(key, clone(lua, tbl)?)?;
} else {
res.set(key, value)?;
match behavior {
DepthMode::Top => {
res.set(key, value)?
}
DepthMode::Deep => {
if let LuaValue::Table(tbl) = value {
res.set(key, clone(lua, (tbl, Some(behavior)))?)?
} else {
res.set(key, value)?;
}
}
}
}
Ok(res)
}

fn flatten<'lua>(lua: &'lua Lua, arrays: Vec<LuaValue<'lua>>) -> mlua::Result<Vec<LuaValue<'lua>>> {
fn flatten<'lua>(lua: &'lua Lua, (arrays, behavior): (Vec<LuaValue<'lua>>, Option<DepthMode>)) -> mlua::Result<Vec<LuaValue<'lua>>> {
let mut flat_vec: Vec<LuaValue> = vec![];
let behavior = behavior.unwrap_or_default();
for item in arrays {
match item {
LuaValue::Table(tbl) => {
let tbl_as_vec = tbl.sequence_values().filter_map(|x| x.ok()).collect();
let mut flat = flatten(lua, tbl_as_vec)?;
flat_vec.append(&mut flat);
if behavior == DepthMode::Deep {
let tbl_as_vec = tbl.sequence_values().filter_map(|x| x.ok()).collect();
let mut flat = flatten(lua, (tbl_as_vec, Some(behavior)))?;
flat_vec.append(&mut flat);
} else {
flat_vec.push(LuaValue::Table(tbl));
}
}
LuaValue::Nil => (),
other => {
Expand Down

0 comments on commit 358d8b9

Please sign in to comment.