mirror of
https://github.com/wez/wezterm.git
synced 2024-09-20 03:09:06 +03:00
lua-api-crates/mux: refactor
split out multiple multiples
This commit is contained in:
parent
295677ed52
commit
a99920da0b
@ -14,6 +14,14 @@ use std::rc::Rc;
|
||||
use wezterm_dynamic::{FromDynamic, ToDynamic};
|
||||
use wezterm_term::TerminalSize;
|
||||
|
||||
mod pane;
|
||||
mod tab;
|
||||
mod window;
|
||||
|
||||
pub use pane::MuxPane;
|
||||
pub use tab::MuxTab;
|
||||
pub use window::MuxWindow;
|
||||
|
||||
fn get_mux() -> mlua::Result<Rc<Mux>> {
|
||||
Mux::get()
|
||||
.ok_or_else(|| mlua::Error::external("cannot get Mux: not running on the mux thread?"))
|
||||
@ -144,66 +152,6 @@ impl Default for HandySplitDirection {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, FromDynamic, ToDynamic)]
|
||||
struct SplitPane {
|
||||
#[dynamic(flatten)]
|
||||
cmd_builder: CommandBuilderFrag,
|
||||
#[dynamic(default = "spawn_tab_default_domain")]
|
||||
domain: SpawnTabDomain,
|
||||
#[dynamic(default)]
|
||||
direction: HandySplitDirection,
|
||||
#[dynamic(default)]
|
||||
top_level: bool,
|
||||
#[dynamic(default = "default_split_size")]
|
||||
size: f32,
|
||||
}
|
||||
impl_lua_conversion_dynamic!(SplitPane);
|
||||
|
||||
fn default_split_size() -> f32 {
|
||||
0.5
|
||||
}
|
||||
|
||||
impl SplitPane {
|
||||
async fn run(self, pane: MuxPane) -> mlua::Result<MuxPane> {
|
||||
let (command, command_dir) = self.cmd_builder.to_command_builder();
|
||||
let source = SplitSource::Spawn {
|
||||
command,
|
||||
command_dir,
|
||||
};
|
||||
|
||||
let size = if self.size == 0.0 {
|
||||
SplitSize::Percent(50)
|
||||
} else if self.size < 1.0 {
|
||||
SplitSize::Percent((self.size * 100.).floor() as u8)
|
||||
} else {
|
||||
SplitSize::Cells(self.size as usize)
|
||||
};
|
||||
|
||||
let direction = match self.direction {
|
||||
HandySplitDirection::Right | HandySplitDirection::Left => SplitDirection::Horizontal,
|
||||
HandySplitDirection::Top | HandySplitDirection::Bottom => SplitDirection::Vertical,
|
||||
};
|
||||
|
||||
let request = SplitRequest {
|
||||
direction,
|
||||
target_is_second: match self.direction {
|
||||
HandySplitDirection::Top | HandySplitDirection::Left => false,
|
||||
HandySplitDirection::Bottom | HandySplitDirection::Right => true,
|
||||
},
|
||||
top_level: self.top_level,
|
||||
size,
|
||||
};
|
||||
|
||||
let mux = get_mux()?;
|
||||
let (pane, _size) = mux
|
||||
.split_pane(pane.0, request, source, self.domain)
|
||||
.await
|
||||
.map_err(|e| mlua::Error::external(format!("{:#?}", e)))?;
|
||||
|
||||
Ok(MuxPane(pane.pane_id()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromDynamic, ToDynamic)]
|
||||
struct SpawnWindow {
|
||||
#[dynamic(default = "spawn_tab_default_domain")]
|
||||
@ -255,25 +203,6 @@ impl SpawnWindow {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MuxWindow(pub WindowId);
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MuxTab(pub TabId);
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MuxPane(pub PaneId);
|
||||
|
||||
impl MuxWindow {
|
||||
fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Ref<'a, Window>> {
|
||||
mux.get_window(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("window id {} not found in mux", self.0)))
|
||||
}
|
||||
|
||||
fn resolve_mut<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<RefMut<'a, Window>> {
|
||||
mux.get_window_mut(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("window id {} not found in mux", self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromDynamic, ToDynamic)]
|
||||
struct SpawnTab {
|
||||
#[dynamic(default)]
|
||||
@ -331,136 +260,6 @@ struct MuxTabInfo {
|
||||
}
|
||||
impl_lua_conversion_dynamic!(MuxTabInfo);
|
||||
|
||||
impl UserData for MuxWindow {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, _: ()| {
|
||||
Ok(format!(
|
||||
"MuxWindow(mux_window_id:{}, pid:{})",
|
||||
this.0,
|
||||
unsafe { libc::getpid() }
|
||||
))
|
||||
});
|
||||
methods.add_method("window_id", |_, this, _: ()| Ok(this.0));
|
||||
methods.add_async_method("gui_window", |lua, this, _: ()| async move {
|
||||
// Weakly bound to the gui module; mux cannot hard-depend
|
||||
// on wezterm-gui, but we can runtime resolve the appropriate module
|
||||
let wezterm_mod = get_or_create_module(lua, "wezterm")
|
||||
.map_err(|err| mlua::Error::external(format!("{err:#}")))?;
|
||||
let gui: mlua::Table = wezterm_mod.get("gui")?;
|
||||
let func: mlua::Function = gui.get("gui_window_for_mux_window")?;
|
||||
func.call_async::<_, mlua::Value>(this.0).await
|
||||
});
|
||||
methods.add_method("get_workspace", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
Ok(window.get_workspace().to_string())
|
||||
});
|
||||
methods.add_method("set_workspace", |_, this, new_name: String| {
|
||||
let mux = get_mux()?;
|
||||
let mut window = this.resolve_mut(&mux)?;
|
||||
Ok(window.set_workspace(&new_name))
|
||||
});
|
||||
methods.add_async_method("spawn_tab", |_, this, spawn: SpawnTab| async move {
|
||||
spawn.spawn(this).await
|
||||
});
|
||||
methods.add_method("get_title", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
Ok(window.get_title().to_string())
|
||||
});
|
||||
methods.add_method("set_title", |_, this, title: String| {
|
||||
let mux = get_mux()?;
|
||||
let mut window = this.resolve_mut(&mux)?;
|
||||
Ok(window.set_title(&title))
|
||||
});
|
||||
methods.add_method("tabs", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
Ok(window
|
||||
.iter()
|
||||
.map(|tab| MuxTab(tab.tab_id()))
|
||||
.collect::<Vec<MuxTab>>())
|
||||
});
|
||||
methods.add_method("tabs_with_info", |lua, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
let result = lua.create_table()?;
|
||||
let active_idx = window.get_active_idx();
|
||||
for (index, tab) in window.iter().enumerate() {
|
||||
let info = MuxTabInfo {
|
||||
index,
|
||||
is_active: index == active_idx,
|
||||
};
|
||||
let info = luahelper::dynamic_to_lua_value(lua, info.to_dynamic())?;
|
||||
match &info {
|
||||
LuaValue::Table(t) => {
|
||||
t.set("tab", MuxTab(tab.tab_id()))?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
result.set(index + 1, info)?;
|
||||
}
|
||||
Ok(result)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl MuxPane {
|
||||
fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Rc<dyn Pane>> {
|
||||
mux.get_pane(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("pane id {} not found in mux", self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for MuxPane {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, _: ()| {
|
||||
Ok(format!("MuxPane(pane_id:{}, pid:{})", this.0, unsafe {
|
||||
libc::getpid()
|
||||
}))
|
||||
});
|
||||
methods.add_method("pane_id", |_, this, _: ()| Ok(this.0));
|
||||
methods.add_async_method("split", |_, this, args: Option<SplitPane>| async move {
|
||||
let args = args.unwrap_or_default();
|
||||
args.run(this).await
|
||||
});
|
||||
methods.add_method("send_paste", |_, this, text: String| {
|
||||
let mux = get_mux()?;
|
||||
let pane = this.resolve(&mux)?;
|
||||
pane.send_paste(&text)
|
||||
.map_err(|e| mlua::Error::external(format!("{:#}", e)))?;
|
||||
Ok(())
|
||||
});
|
||||
methods.add_method("send_text", |_, this, text: String| {
|
||||
let mux = get_mux()?;
|
||||
let pane = this.resolve(&mux)?;
|
||||
pane.writer()
|
||||
.write_all(text.as_bytes())
|
||||
.map_err(|e| mlua::Error::external(format!("{:#}", e)))?;
|
||||
Ok(())
|
||||
});
|
||||
methods.add_method("window", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
Ok(mux
|
||||
.resolve_pane_id(this.0)
|
||||
.map(|(_domain_id, window_id, _tab_id)| MuxWindow(window_id)))
|
||||
});
|
||||
methods.add_method("tab", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
Ok(mux
|
||||
.resolve_pane_id(this.0)
|
||||
.map(|(_domain_id, _window_id, tab_id)| MuxTab(tab_id)))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl MuxTab {
|
||||
fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Rc<Tab>> {
|
||||
mux.get_tab(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("tab id {} not found in mux", self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, FromDynamic, ToDynamic)]
|
||||
struct MuxPaneInfo {
|
||||
/// The topological pane index that can be used to reference this pane
|
||||
@ -483,83 +282,3 @@ struct MuxPaneInfo {
|
||||
pub pixel_height: usize,
|
||||
}
|
||||
impl_lua_conversion_dynamic!(MuxPaneInfo);
|
||||
|
||||
impl UserData for MuxTab {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, _: ()| {
|
||||
Ok(format!("MuxTab(tab_id:{}, pid:{})", this.0, unsafe {
|
||||
libc::getpid()
|
||||
}))
|
||||
});
|
||||
methods.add_method("tab_id", |_, this, _: ()| Ok(this.0));
|
||||
methods.add_method("window", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
for window_id in mux.iter_windows() {
|
||||
if let Some(window) = mux.get_window(window_id) {
|
||||
for tab in window.iter() {
|
||||
if tab.tab_id() == this.0 {
|
||||
return Ok(Some(MuxWindow(window_id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
});
|
||||
methods.add_method("get_title", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
Ok(tab.get_title().to_string())
|
||||
});
|
||||
methods.add_method("set_title", |_, this, title: String| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
Ok(tab.set_title(&title))
|
||||
});
|
||||
methods.add_method("panes", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
Ok(tab
|
||||
.iter_panes()
|
||||
.into_iter()
|
||||
.map(|info| MuxPane(info.pane.pane_id()))
|
||||
.collect::<Vec<MuxPane>>())
|
||||
});
|
||||
|
||||
methods.add_method("set_zoomed", |_, this, zoomed: bool| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
let was_zoomed = tab.set_zoomed(zoomed);
|
||||
Ok(was_zoomed)
|
||||
});
|
||||
|
||||
methods.add_method("panes_with_info", |lua, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
|
||||
let result = lua.create_table()?;
|
||||
for (idx, pos) in tab.iter_panes().into_iter().enumerate() {
|
||||
let info = MuxPaneInfo {
|
||||
index: pos.index,
|
||||
is_active: pos.is_active,
|
||||
is_zoomed: pos.is_zoomed,
|
||||
left: pos.left,
|
||||
top: pos.top,
|
||||
width: pos.width,
|
||||
pixel_width: pos.pixel_width,
|
||||
height: pos.height,
|
||||
pixel_height: pos.pixel_height,
|
||||
};
|
||||
let info = luahelper::dynamic_to_lua_value(lua, info.to_dynamic())?;
|
||||
match &info {
|
||||
LuaValue::Table(t) => {
|
||||
t.set("pane", MuxPane(pos.pane.pane_id()))?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
result.set(idx + 1, info)?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
113
lua-api-crates/mux/src/pane.rs
Normal file
113
lua-api-crates/mux/src/pane.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MuxPane(pub PaneId);
|
||||
|
||||
impl MuxPane {
|
||||
pub fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Rc<dyn Pane>> {
|
||||
mux.get_pane(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("pane id {} not found in mux", self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for MuxPane {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, _: ()| {
|
||||
Ok(format!("MuxPane(pane_id:{}, pid:{})", this.0, unsafe {
|
||||
libc::getpid()
|
||||
}))
|
||||
});
|
||||
methods.add_method("pane_id", |_, this, _: ()| Ok(this.0));
|
||||
methods.add_async_method("split", |_, this, args: Option<SplitPane>| async move {
|
||||
let args = args.unwrap_or_default();
|
||||
args.run(this).await
|
||||
});
|
||||
methods.add_method("send_paste", |_, this, text: String| {
|
||||
let mux = get_mux()?;
|
||||
let pane = this.resolve(&mux)?;
|
||||
pane.send_paste(&text)
|
||||
.map_err(|e| mlua::Error::external(format!("{:#}", e)))?;
|
||||
Ok(())
|
||||
});
|
||||
methods.add_method("send_text", |_, this, text: String| {
|
||||
let mux = get_mux()?;
|
||||
let pane = this.resolve(&mux)?;
|
||||
pane.writer()
|
||||
.write_all(text.as_bytes())
|
||||
.map_err(|e| mlua::Error::external(format!("{:#}", e)))?;
|
||||
Ok(())
|
||||
});
|
||||
methods.add_method("window", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
Ok(mux
|
||||
.resolve_pane_id(this.0)
|
||||
.map(|(_domain_id, window_id, _tab_id)| MuxWindow(window_id)))
|
||||
});
|
||||
methods.add_method("tab", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
Ok(mux
|
||||
.resolve_pane_id(this.0)
|
||||
.map(|(_domain_id, _window_id, tab_id)| MuxTab(tab_id)))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, FromDynamic, ToDynamic)]
|
||||
struct SplitPane {
|
||||
#[dynamic(flatten)]
|
||||
cmd_builder: CommandBuilderFrag,
|
||||
#[dynamic(default = "spawn_tab_default_domain")]
|
||||
domain: SpawnTabDomain,
|
||||
#[dynamic(default)]
|
||||
direction: HandySplitDirection,
|
||||
#[dynamic(default)]
|
||||
top_level: bool,
|
||||
#[dynamic(default = "default_split_size")]
|
||||
size: f32,
|
||||
}
|
||||
impl_lua_conversion_dynamic!(SplitPane);
|
||||
|
||||
fn default_split_size() -> f32 {
|
||||
0.5
|
||||
}
|
||||
|
||||
impl SplitPane {
|
||||
async fn run(self, pane: MuxPane) -> mlua::Result<MuxPane> {
|
||||
let (command, command_dir) = self.cmd_builder.to_command_builder();
|
||||
let source = SplitSource::Spawn {
|
||||
command,
|
||||
command_dir,
|
||||
};
|
||||
|
||||
let size = if self.size == 0.0 {
|
||||
SplitSize::Percent(50)
|
||||
} else if self.size < 1.0 {
|
||||
SplitSize::Percent((self.size * 100.).floor() as u8)
|
||||
} else {
|
||||
SplitSize::Cells(self.size as usize)
|
||||
};
|
||||
|
||||
let direction = match self.direction {
|
||||
HandySplitDirection::Right | HandySplitDirection::Left => SplitDirection::Horizontal,
|
||||
HandySplitDirection::Top | HandySplitDirection::Bottom => SplitDirection::Vertical,
|
||||
};
|
||||
|
||||
let request = SplitRequest {
|
||||
direction,
|
||||
target_is_second: match self.direction {
|
||||
HandySplitDirection::Top | HandySplitDirection::Left => false,
|
||||
HandySplitDirection::Bottom | HandySplitDirection::Right => true,
|
||||
},
|
||||
top_level: self.top_level,
|
||||
size,
|
||||
};
|
||||
|
||||
let mux = get_mux()?;
|
||||
let (pane, _size) = mux
|
||||
.split_pane(pane.0, request, source, self.domain)
|
||||
.await
|
||||
.map_err(|e| mlua::Error::external(format!("{:#?}", e)))?;
|
||||
|
||||
Ok(MuxPane(pane.pane_id()))
|
||||
}
|
||||
}
|
91
lua-api-crates/mux/src/tab.rs
Normal file
91
lua-api-crates/mux/src/tab.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MuxTab(pub TabId);
|
||||
|
||||
impl MuxTab {
|
||||
pub fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Rc<Tab>> {
|
||||
mux.get_tab(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("tab id {} not found in mux", self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for MuxTab {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, _: ()| {
|
||||
Ok(format!("MuxTab(tab_id:{}, pid:{})", this.0, unsafe {
|
||||
libc::getpid()
|
||||
}))
|
||||
});
|
||||
methods.add_method("tab_id", |_, this, _: ()| Ok(this.0));
|
||||
methods.add_method("window", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
for window_id in mux.iter_windows() {
|
||||
if let Some(window) = mux.get_window(window_id) {
|
||||
for tab in window.iter() {
|
||||
if tab.tab_id() == this.0 {
|
||||
return Ok(Some(MuxWindow(window_id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
});
|
||||
methods.add_method("get_title", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
Ok(tab.get_title().to_string())
|
||||
});
|
||||
methods.add_method("set_title", |_, this, title: String| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
Ok(tab.set_title(&title))
|
||||
});
|
||||
methods.add_method("panes", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
Ok(tab
|
||||
.iter_panes()
|
||||
.into_iter()
|
||||
.map(|info| MuxPane(info.pane.pane_id()))
|
||||
.collect::<Vec<MuxPane>>())
|
||||
});
|
||||
|
||||
methods.add_method("set_zoomed", |_, this, zoomed: bool| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
let was_zoomed = tab.set_zoomed(zoomed);
|
||||
Ok(was_zoomed)
|
||||
});
|
||||
|
||||
methods.add_method("panes_with_info", |lua, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let tab = this.resolve(&mux)?;
|
||||
|
||||
let result = lua.create_table()?;
|
||||
for (idx, pos) in tab.iter_panes().into_iter().enumerate() {
|
||||
let info = MuxPaneInfo {
|
||||
index: pos.index,
|
||||
is_active: pos.is_active,
|
||||
is_zoomed: pos.is_zoomed,
|
||||
left: pos.left,
|
||||
top: pos.top,
|
||||
width: pos.width,
|
||||
pixel_width: pos.pixel_width,
|
||||
height: pos.height,
|
||||
pixel_height: pos.pixel_height,
|
||||
};
|
||||
let info = luahelper::dynamic_to_lua_value(lua, info.to_dynamic())?;
|
||||
match &info {
|
||||
LuaValue::Table(t) => {
|
||||
t.set("pane", MuxPane(pos.pane.pane_id()))?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
result.set(idx + 1, info)?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
});
|
||||
}
|
||||
}
|
90
lua-api-crates/mux/src/window.rs
Normal file
90
lua-api-crates/mux/src/window.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MuxWindow(pub WindowId);
|
||||
|
||||
impl MuxWindow {
|
||||
pub fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Ref<'a, Window>> {
|
||||
mux.get_window(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("window id {} not found in mux", self.0)))
|
||||
}
|
||||
|
||||
pub fn resolve_mut<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<RefMut<'a, Window>> {
|
||||
mux.get_window_mut(self.0)
|
||||
.ok_or_else(|| mlua::Error::external(format!("window id {} not found in mux", self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for MuxWindow {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, _: ()| {
|
||||
Ok(format!(
|
||||
"MuxWindow(mux_window_id:{}, pid:{})",
|
||||
this.0,
|
||||
unsafe { libc::getpid() }
|
||||
))
|
||||
});
|
||||
methods.add_method("window_id", |_, this, _: ()| Ok(this.0));
|
||||
methods.add_async_method("gui_window", |lua, this, _: ()| async move {
|
||||
// Weakly bound to the gui module; mux cannot hard-depend
|
||||
// on wezterm-gui, but we can runtime resolve the appropriate module
|
||||
let wezterm_mod = get_or_create_module(lua, "wezterm")
|
||||
.map_err(|err| mlua::Error::external(format!("{err:#}")))?;
|
||||
let gui: mlua::Table = wezterm_mod.get("gui")?;
|
||||
let func: mlua::Function = gui.get("gui_window_for_mux_window")?;
|
||||
func.call_async::<_, mlua::Value>(this.0).await
|
||||
});
|
||||
methods.add_method("get_workspace", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
Ok(window.get_workspace().to_string())
|
||||
});
|
||||
methods.add_method("set_workspace", |_, this, new_name: String| {
|
||||
let mux = get_mux()?;
|
||||
let mut window = this.resolve_mut(&mux)?;
|
||||
Ok(window.set_workspace(&new_name))
|
||||
});
|
||||
methods.add_async_method("spawn_tab", |_, this, spawn: SpawnTab| async move {
|
||||
spawn.spawn(this).await
|
||||
});
|
||||
methods.add_method("get_title", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
Ok(window.get_title().to_string())
|
||||
});
|
||||
methods.add_method("set_title", |_, this, title: String| {
|
||||
let mux = get_mux()?;
|
||||
let mut window = this.resolve_mut(&mux)?;
|
||||
Ok(window.set_title(&title))
|
||||
});
|
||||
methods.add_method("tabs", |_, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
Ok(window
|
||||
.iter()
|
||||
.map(|tab| MuxTab(tab.tab_id()))
|
||||
.collect::<Vec<MuxTab>>())
|
||||
});
|
||||
methods.add_method("tabs_with_info", |lua, this, _: ()| {
|
||||
let mux = get_mux()?;
|
||||
let window = this.resolve(&mux)?;
|
||||
let result = lua.create_table()?;
|
||||
let active_idx = window.get_active_idx();
|
||||
for (index, tab) in window.iter().enumerate() {
|
||||
let info = MuxTabInfo {
|
||||
index,
|
||||
is_active: index == active_idx,
|
||||
};
|
||||
let info = luahelper::dynamic_to_lua_value(lua, info.to_dynamic())?;
|
||||
match &info {
|
||||
LuaValue::Table(t) => {
|
||||
t.set("tab", MuxTab(tab.tab_id()))?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
result.set(index + 1, info)?;
|
||||
}
|
||||
Ok(result)
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user