1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-22 12:51:31 +03:00

cut more things over to dynamic

This commit is contained in:
Wez Furlong 2022-05-17 09:48:50 -07:00
parent f587cac145
commit 862dbc604a
9 changed files with 13 additions and 1558 deletions

5
Cargo.lock generated
View File

@ -2021,10 +2021,7 @@ dependencies = [
"bstr 0.2.17", "bstr 0.2.17",
"log", "log",
"mlua", "mlua",
"serde",
"serde_json",
"strsim 0.10.0", "strsim 0.10.0",
"thiserror",
"wezterm-dynamic", "wezterm-dynamic",
] ]
@ -3057,7 +3054,7 @@ dependencies = [
"log", "log",
"luahelper", "luahelper",
"ntapi", "ntapi",
"serde", "wezterm-dynamic",
"winapi 0.3.9", "winapi 0.3.9",
] ]

View File

@ -133,7 +133,7 @@ pub fn make_lua_context(config_file: &Path) -> anyhow::Result<Lua> {
} }
}, },
item @ _ => { item @ _ => {
let item = format!("{:?}", ValueWrapper(item)); let item = format!("{:?}", item);
output.push_str(&item); output.push_str(&item);
} }
} }

View File

@ -10,8 +10,5 @@ edition = "2018"
bstr = "0.2" bstr = "0.2"
log = "0.4" log = "0.4"
mlua = "0.7" mlua = "0.7"
serde = {version="1.0", features = ["rc", "derive"]}
serde_json = "1.0"
strsim = "0.10" strsim = "0.10"
thiserror = "1.0"
wezterm-dynamic = { path = "../wezterm-dynamic" } wezterm-dynamic = { path = "../wezterm-dynamic" }

View File

@ -1,43 +1,16 @@
#![macro_use] #![macro_use]
pub use mlua;
use mlua::{ToLua, Value as LuaValue};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use wezterm_dynamic::{FromDynamic, ToDynamic, Value as DynValue}; use wezterm_dynamic::{FromDynamic, ToDynamic, Value as DynValue};
mod serde_lua;
pub use mlua;
use mlua::{ToLua, Value as LuaValue};
pub use serde_lua::from_lua_value;
pub use serde_lua::ser::to_lua_value;
/// Implement lua conversion traits for a type. /// Implement lua conversion traits for a type.
/// This implementation requires that the type implement /// This implementation requires that the type implement
/// serde Serialize and Deserialize. /// FromDynamic and ToDynamic.
/// Why do we need these traits? They allow `create_function` to /// Why do we need these traits? They allow `create_function` to
/// operate in terms of our internal types rather than forcing /// operate in terms of our internal types rather than forcing
/// the implementer to use generic Value parameter or return values. /// the implementer to use generic Value parameter or return values.
#[macro_export]
macro_rules! impl_lua_conversion {
($struct:ident) => {
impl<'lua> $crate::mlua::ToLua<'lua> for $struct {
fn to_lua(
self,
lua: &'lua $crate::mlua::Lua,
) -> Result<$crate::mlua::Value<'lua>, $crate::mlua::Error> {
Ok($crate::to_lua_value(lua, self)?)
}
}
impl<'lua> $crate::mlua::FromLua<'lua> for $struct {
fn from_lua(
value: $crate::mlua::Value<'lua>,
_lua: &'lua $crate::mlua::Lua,
) -> Result<Self, $crate::mlua::Error> {
Ok($crate::from_lua_value(value)?)
}
}
};
}
#[macro_export] #[macro_export]
macro_rules! impl_lua_conversion_dynamic { macro_rules! impl_lua_conversion_dynamic {
($struct:ident) => { ($struct:ident) => {
@ -103,6 +76,7 @@ pub fn dynamic_to_lua_value<'lua>(
}) })
} }
/// FIXME: lua_value_to_dynamic should detect and avoid cycles in the underlying lua object
pub fn lua_value_to_dynamic(value: LuaValue) -> mlua::Result<DynValue> { pub fn lua_value_to_dynamic(value: LuaValue) -> mlua::Result<DynValue> {
Ok(match value { Ok(match value {
LuaValue::Nil => DynValue::Null, LuaValue::Nil => DynValue::Null,
@ -166,5 +140,3 @@ pub struct ValueLua {
pub value: wezterm_dynamic::Value, pub value: wezterm_dynamic::Value,
} }
impl_lua_conversion_dynamic!(ValueLua); impl_lua_conversion_dynamic!(ValueLua);
pub use serde_lua::ValueWrapper;

File diff suppressed because it is too large Load Diff

View File

@ -1,466 +0,0 @@
use super::ValueWrapper;
use mlua::{Lua, Table, ToLua, Value};
use serde::ser::Error as SerError;
use serde::{serde_if_integer128, Serialize, Serializer};
use thiserror::*;
pub fn to_lua_value<'lua, T>(lua: &'lua Lua, input: T) -> Result<Value<'lua>, Error>
where
T: Serialize,
{
let serializer = LuaSerializer { lua };
input.serialize(serializer)
}
#[derive(Debug, Error)]
pub enum Error {
#[error("{}", msg)]
Custom { msg: String },
}
impl Error {
fn lua(e: mlua::Error) -> Error {
Error::custom(e)
}
}
impl From<Error> for mlua::Error {
fn from(e: Error) -> mlua::Error {
mlua::Error::external(e)
}
}
impl SerError for Error {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
Error::Custom {
msg: msg.to_string(),
}
}
}
struct LuaSerializer<'lua> {
lua: &'lua Lua,
}
struct LuaSeqSerializer<'lua> {
lua: &'lua Lua,
table: Table<'lua>,
index: usize,
}
impl<'lua> serde::ser::SerializeSeq for LuaSeqSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
let value = value.serialize(LuaSerializer { lua: self.lua })?;
self.table.set(self.index, value).map_err(Error::lua)?;
self.index += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Table(self.table))
}
}
impl<'lua> serde::ser::SerializeTuple for LuaSeqSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
serde::ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
serde::ser::SerializeSeq::end(self)
}
}
impl<'lua> serde::ser::SerializeTupleStruct for LuaSeqSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
serde::ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Value<'lua>, Error> {
serde::ser::SerializeSeq::end(self)
}
}
struct LuaTupleVariantSerializer<'lua> {
lua: &'lua Lua,
table: Table<'lua>,
index: usize,
name: String,
}
impl<'lua> serde::ser::SerializeTupleVariant for LuaTupleVariantSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
let value = value.serialize(LuaSerializer { lua: self.lua })?;
self.table.set(self.index, value).map_err(Error::lua)?;
self.index += 1;
Ok(())
}
fn end(self) -> Result<Value<'lua>, Error> {
let map = self.lua.create_table().map_err(Error::lua)?;
map.set(self.name, self.table).map_err(Error::lua)?;
Ok(Value::Table(map))
}
}
struct LuaMapSerializer<'lua> {
lua: &'lua Lua,
table: Table<'lua>,
key: Option<Value<'lua>>,
}
impl<'lua> serde::ser::SerializeMap for LuaMapSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<(), Error> {
let key = key.serialize(LuaSerializer { lua: self.lua })?;
self.key.replace(key);
Ok(())
}
fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
let value = value.serialize(LuaSerializer { lua: self.lua })?;
let key = self
.key
.take()
.expect("serialize_key must be called before serialize_value");
self.table.set(key, value).map_err(Error::lua)?;
Ok(())
}
fn serialize_entry<K: Serialize + ?Sized, V: Serialize + ?Sized>(
&mut self,
key: &K,
value: &V,
) -> Result<(), Error> {
let key = key.serialize(LuaSerializer { lua: self.lua })?;
let value = value.serialize(LuaSerializer { lua: self.lua })?;
self.table.set(key, value).map_err(Error::lua)?;
Ok(())
}
fn end(self) -> Result<Value<'lua>, Error> {
Ok(Value::Table(self.table))
}
}
impl<'lua> serde::ser::SerializeStruct for LuaMapSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(
&mut self,
key: &str,
value: &T,
) -> Result<(), Error> {
serde::ser::SerializeMap::serialize_entry(self, key, value)
}
fn end(self) -> Result<Value<'lua>, Error> {
serde::ser::SerializeMap::end(self)
}
}
struct LuaStructVariantSerializer<'lua> {
lua: &'lua Lua,
name: String,
table: Table<'lua>,
}
impl<'lua> serde::ser::SerializeStructVariant for LuaStructVariantSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(
&mut self,
key: &str,
value: &T,
) -> Result<(), Error> {
let key = key.serialize(LuaSerializer { lua: self.lua })?;
let value = value.serialize(LuaSerializer { lua: self.lua })?;
self.table.set(key, value).map_err(Error::lua)?;
Ok(())
}
fn end(self) -> Result<Value<'lua>, Error> {
let map = self.lua.create_table().map_err(Error::lua)?;
map.set(self.name, self.table).map_err(Error::lua)?;
Ok(Value::Table(map))
}
}
impl<'lua> serde::Serializer for LuaSerializer<'lua> {
type Ok = Value<'lua>;
type Error = Error;
type SerializeSeq = LuaSeqSerializer<'lua>;
type SerializeTuple = LuaSeqSerializer<'lua>;
type SerializeTupleStruct = LuaSeqSerializer<'lua>;
type SerializeTupleVariant = LuaTupleVariantSerializer<'lua>;
type SerializeMap = LuaMapSerializer<'lua>;
type SerializeStruct = LuaMapSerializer<'lua>;
type SerializeStructVariant = LuaStructVariantSerializer<'lua>;
fn serialize_bool(self, b: bool) -> Result<Value<'lua>, Error> {
b.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_i8(self, i: i8) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_i16(self, i: i16) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_i32(self, i: i32) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_i64(self, i: i64) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_u8(self, i: u8) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_u16(self, i: u16) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_u32(self, i: u32) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_u64(self, i: u64) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
serde_if_integer128! {
fn serialize_u128(self, i: u128) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_i128(self, i: i128) -> Result<Value<'lua>, Error> {
i.to_lua(self.lua).map_err(Error::lua)
}
}
fn serialize_f32(self, f: f32) -> Result<Value<'lua>, Error> {
f.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_f64(self, f: f64) -> Result<Value<'lua>, Error> {
f.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_char(self, c: char) -> Result<Value<'lua>, Error> {
let mut s = String::new();
s.push(c);
self.serialize_str(&s)
}
fn serialize_str(self, s: &str) -> Result<Value<'lua>, Error> {
s.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_bytes(self, b: &[u8]) -> Result<Value<'lua>, Error> {
let b: &bstr::BStr = b.into();
b.to_lua(self.lua).map_err(Error::lua)
}
fn serialize_none(self) -> Result<Value<'lua>, Error> {
Ok(Value::Nil)
}
fn serialize_some<T: Serialize + ?Sized>(self, v: &T) -> Result<Value<'lua>, Error> {
v.serialize(self)
}
fn serialize_unit(self) -> Result<Value<'lua>, Error> {
Ok(Value::Nil)
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Value<'lua>, Error> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Value<'lua>, Error> {
self.serialize_str(variant)
}
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_name: &'static str,
value: &T,
) -> Result<Value<'lua>, Error> {
value.serialize(self)
}
fn serialize_newtype_variant<T: Serialize + ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Value<'lua>, Error> {
let value = value.serialize(LuaSerializer { lua: self.lua })?;
let table = self.lua.create_table().map_err(Error::lua)?;
table.set(variant, value).map_err(Error::lua)?;
Ok(Value::Table(table))
}
fn serialize_seq(self, len: Option<usize>) -> Result<LuaSeqSerializer<'lua>, Error> {
self.serialize_tuple(len.unwrap_or(0))
}
fn serialize_tuple(self, _len: usize) -> Result<LuaSeqSerializer<'lua>, Error> {
let table = self.lua.create_table().map_err(Error::lua)?;
Ok(LuaSeqSerializer {
lua: self.lua,
table,
index: 1,
})
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<LuaSeqSerializer<'lua>, Error> {
self.serialize_tuple(len)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<LuaTupleVariantSerializer<'lua>, Error> {
let table = self.lua.create_table().map_err(Error::lua)?;
Ok(LuaTupleVariantSerializer {
lua: self.lua,
table,
index: 1,
name: variant.to_string(),
})
}
fn serialize_map(
self,
_len: std::option::Option<usize>,
) -> Result<LuaMapSerializer<'lua>, Error> {
let table = self.lua.create_table().map_err(Error::lua)?;
Ok(LuaMapSerializer {
lua: self.lua,
table,
key: None,
})
}
fn serialize_struct(
self,
_name: &'static str,
len: usize,
) -> Result<LuaMapSerializer<'lua>, Error> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<LuaStructVariantSerializer<'lua>, Error> {
let table = self.lua.create_table().map_err(Error::lua)?;
Ok(LuaStructVariantSerializer {
lua: self.lua,
table,
name: variant.to_owned(),
})
}
}
impl<'lua> Serialize for ValueWrapper<'lua> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match &self.0 {
Value::Nil => serializer.serialize_unit(),
Value::Boolean(b) => serializer.serialize_bool(*b),
Value::Integer(i) => serializer.serialize_i64(*i),
Value::Number(n) => serializer.serialize_f64(*n),
Value::String(s) => match s.to_str() {
Ok(s) => serializer.serialize_str(s),
Err(_) => serializer.serialize_bytes(s.as_bytes()),
},
Value::Table(table) => {
if let Ok(true) = table.contains_key(1) {
let mut values = vec![];
for value in table.clone().sequence_values() {
match value {
Ok(value) => values.push(ValueWrapper(value)),
Err(err) => {
return Err(S::Error::custom(format!(
"while retrieving an array element: {}",
err
)))
}
}
}
values.serialize(serializer)
} else {
use serde::ser::SerializeMap;
let mut pairs = vec![];
for pair in table.clone().pairs::<Value, Value>() {
match pair {
Ok(pair) => pairs.push((ValueWrapper(pair.0), ValueWrapper(pair.1))),
Err(err) => {
return Err(S::Error::custom(format!(
"while retrieving map element: {}",
err
)))
}
}
}
let mut map = serializer.serialize_map(Some(pairs.len()))?;
for (k, v) in pairs.into_iter() {
map.serialize_entry(&k, &v)?;
}
map.end()
}
}
Value::UserData(_) | Value::LightUserData(_) => Err(S::Error::custom(
"cannot represent userdata in the serde data model",
)),
Value::Thread(_) => Err(S::Error::custom(
"cannot represent thread in the serde data model",
)),
Value::Function(_) => Err(S::Error::custom(
"cannot represent lua function in the serde data model",
)),
Value::Error(e) => Err(S::Error::custom(format!(
"cannot represent lua error {} in the serde data model",
e
))),
}
}
}

View File

@ -9,7 +9,7 @@ edition = "2021"
libc = "0.2" libc = "0.2"
log = "0.4" log = "0.4"
luahelper = { path = "../luahelper" } luahelper = { path = "../luahelper" }
serde = {version="1.0", features = ["derive"]} wezterm-dynamic = { path = "../wezterm-dynamic" }
[target."cfg(windows)".dependencies] [target."cfg(windows)".dependencies]
ntapi = "0.3" ntapi = "0.3"

View File

@ -1,12 +1,12 @@
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::path::PathBuf; use std::path::PathBuf;
use wezterm_dynamic::{FromDynamic, ToDynamic};
mod linux; mod linux;
mod macos; mod macos;
mod windows; mod windows;
#[derive(Debug, Serialize, Deserialize, Copy, Clone)] #[derive(Debug, Copy, Clone, FromDynamic, ToDynamic)]
pub enum LocalProcessStatus { pub enum LocalProcessStatus {
Idle, Idle,
Run, Run,
@ -22,7 +22,7 @@ pub enum LocalProcessStatus {
Unknown, Unknown,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Clone, FromDynamic, ToDynamic)]
pub struct LocalProcessInfo { pub struct LocalProcessInfo {
/// The process identifier /// The process identifier
pub pid: u32, pub pid: u32,
@ -55,7 +55,7 @@ pub struct LocalProcessInfo {
/// Child processes, keyed by pid /// Child processes, keyed by pid
pub children: HashMap<u32, LocalProcessInfo>, pub children: HashMap<u32, LocalProcessInfo>,
} }
luahelper::impl_lua_conversion!(LocalProcessInfo); luahelper::impl_lua_conversion_dynamic!(LocalProcessInfo);
impl LocalProcessInfo { impl LocalProcessInfo {
/// Walk this sub-tree of processes and return a unique set /// Walk this sub-tree of processes and return a unique set

View File

@ -1,7 +1,6 @@
use crate::scripting::guiwin::GuiWin; use crate::scripting::guiwin::GuiWin;
use chrono::prelude::*; use chrono::prelude::*;
use log::Level; use log::Level;
use luahelper::ValueWrapper;
use mlua::Value; use mlua::Value;
use mux::termwiztermtab::TermWizTerminal; use mux::termwiztermtab::TermWizTerminal;
use termwiz::cell::{AttributeChange, CellAttributes, Intensity}; use termwiz::cell::{AttributeChange, CellAttributes, Intensity};
@ -134,7 +133,8 @@ pub fn show_debug_overlay(mut term: TermWizTerminal, gui_win: GuiWin) -> anyhow:
let chunk = host.lua.load(&expr); let chunk = host.lua.load(&expr);
match smol::block_on(chunk.eval_async::<Value>()) { match smol::block_on(chunk.eval_async::<Value>()) {
Ok(result) => { Ok(result) => {
let text = format!("{:#?}", ValueWrapper(result)); let value = luahelper::lua_value_to_dynamic(result);
let text = format!("{:#?}", value);
term.render(&[Change::Text(format!("{}\r\n", text.replace("\n", "\r\n")))])?; term.render(&[Change::Text(format!("{}\r\n", text.replace("\n", "\r\n")))])?;
} }
Err(err) => { Err(err) => {