1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 21:32:13 +03:00

add __len and __pairs metamethods to wezterm.GLOBALS

Fixes this:

```
> wezterm.GLOBAL.foo = {"bar", "baz"}
> wezterm.GLOBAL.foo
[
    "bar",
    "baz",
]
> #wezterm.GLOBAL.foo
runtime error: [string "repl"]:1: attempt to get length of a userdata value (field 'foo')
stack traceback:
        [string "repl"]:1: in main chunk
>
```

and allows this:

```
> for k, v in pairs(wezterm.GLOBAL.foo) do print(k, v) ; end
```
This commit is contained in:
Wez Furlong 2023-03-21 21:04:52 -07:00
parent 00ada33fe2
commit 8755e731d3
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
2 changed files with 70 additions and 0 deletions

View File

@ -23,6 +23,7 @@ As features stabilize some brief notes about them will accumulate here.
#### Fixed
* ssh ProxyCommand didn't parse command lines containing `=` correctly. #3307
* `wezterm.GLOBALS.foo` now supports `__len` and `__pairs` metamethods
### 20230320-124340-559cb7b0

View File

@ -271,6 +271,75 @@ impl UserData for Value {
mlua::MetaMethod::Custom("__wezterm_to_dynamic".to_string()),
|lua: &Lua, this, _: ()| -> mlua::Result<mlua::Value> { gvalue_to_lua(lua, this) },
);
methods.add_meta_method(
mlua::MetaMethod::Len,
|lua: &Lua, this, _: ()| -> mlua::Result<mlua::Value> {
match this {
Value::Array(arr) => arr.inner.lock().unwrap().len().to_lua(lua),
Value::Object(obj) => obj.inner.lock().unwrap().len().to_lua(lua),
Value::String(s) => s.to_string().to_lua(lua),
_ => Err(mlua::Error::external(
"invalid type for len operator".to_string(),
)),
}
},
);
methods.add_meta_method(mlua::MetaMethod::Pairs, |lua, this, ()| match this {
Value::Array(_) => {
let stateless_iter =
lua.create_function(|lua, (this, i): (Value, usize)| match this {
Value::Array(arr) => {
let arr = arr.inner.lock().unwrap();
let i = i + 1;
if i <= arr.len() {
return Ok(mlua::Variadic::from_iter(vec![
i.to_lua(lua)?,
arr[i - 1].clone().to_lua(lua)?,
]));
}
return Ok(mlua::Variadic::new());
}
_ => unreachable!(),
})?;
Ok((stateless_iter, this.clone(), 0.to_lua(lua)?))
}
Value::Object(_) => {
let stateless_iter =
lua.create_function(|lua, (this, key): (Value, Option<String>)| match this {
Value::Object(obj) => {
let obj = obj.inner.lock().unwrap();
let mut iter = obj.iter();
let mut this_is_key = false;
if key.is_none() {
this_is_key = true;
}
while let Some((this_key, value)) = iter.next() {
if this_is_key {
return Ok(mlua::MultiValue::from_vec(vec![
this_key.clone().to_lua(lua)?,
value.clone().to_lua(lua)?,
]));
}
if Some(this_key.as_str()) == key.as_deref() {
this_is_key = true;
}
}
return Ok(mlua::MultiValue::new());
}
_ => unreachable!(),
})?;
Ok((stateless_iter, this.clone(), LuaValue::Nil))
}
_ => Err(mlua::Error::external(
"invalid type for __ipairs metamethod".to_string(),
)),
});
methods.add_meta_method(
mlua::MetaMethod::Index,
|lua: &Lua, this, key: LuaValue| -> mlua::Result<mlua::Value> {