Add xplr.util.layout_replaced (#574)

Closes: https://github.com/sayanarijit/xplr/issues/573
This commit is contained in:
Arijit Basu 2023-01-28 23:07:06 +05:30 committed by GitHub
parent f64835609c
commit 628d2cfc26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 112 additions and 0 deletions

View File

@ -5,6 +5,7 @@ use crate::msg::in_::external::ExplorerConfig;
use crate::path;
use crate::path::RelativityConfig;
use crate::ui;
use crate::ui::Layout;
use crate::ui::Style;
use crate::ui::WrapOptions;
use anyhow::Result;
@ -42,6 +43,7 @@ pub(crate) fn create_table(lua: &Lua) -> Result<Table> {
util = relative_to(util, lua)?;
util = shortened(util, lua)?;
util = textwrap(util, lua)?;
util = layout_replaced(util, lua)?;
Ok(util)
}
@ -511,3 +513,49 @@ pub fn textwrap<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
util.set("textwrap", func)?;
Ok(util)
}
/// Find the target layout in the given layout and replace it with the replacement layout,
/// returning a new layout.
///
/// Type: function( layout:[Layout][4], target:[Layout][4], replacement:[Layout][4] ) -> layout:[Layout][4]
///
/// Example:
///
/// ```lua
/// local layout = {
/// Horizontal = {
/// splits = {
/// "Table", -- Target
/// "HelpMenu",
/// },
/// config = ...,
/// }
/// }
///
/// xplr.util.layout_replaced(layout, "Table", "Selection")
/// -- {
/// -- Horizontal = {
/// -- splits = {
/// -- "Selection", -- Replaced
/// -- "HelpMenu",
/// -- },
/// -- config = ...
/// -- }
/// -- }
/// ```
pub fn layout_replaced<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
let func = lua.create_function(
move |lua, (layout, target, replacement): (Table, Table, Table)| {
let layout: Layout = lua.from_value(Value::Table(layout))?;
let target: Layout = lua.from_value(Value::Table(target))?;
let replacement: Layout = lua.from_value(Value::Table(replacement))?;
let res = layout.replace(&target, &replacement);
let res = lua.to_value(&res)?;
Ok(res)
},
)?;
util.set("layout_replaced", func)?;
Ok(util)
}

View File

@ -168,6 +168,32 @@ impl Layout {
(_, other) => other.to_owned(),
}
}
pub fn replace(self, target: &Self, replacement: &Self) -> Self {
match self {
Self::Horizontal { splits, config } => Self::Horizontal {
splits: splits
.into_iter()
.map(|s| s.replace(target, replacement))
.collect(),
config,
},
Self::Vertical { splits, config } => Self::Vertical {
splits: splits
.into_iter()
.map(|s| s.replace(target, replacement))
.collect(),
config,
},
other => {
if other == *target {
replacement.to_owned()
} else {
other
}
}
}
}
}
#[derive(
@ -1540,4 +1566,42 @@ mod tests {
}
);
}
#[test]
fn test_layout_replace() {
let layout = Layout::Horizontal {
config: LayoutOptions {
margin: Some(2),
horizontal_margin: Some(3),
vertical_margin: Some(4),
constraints: Some(vec![
Constraint::Percentage(80),
Constraint::Percentage(20),
]),
},
splits: vec![Layout::Table, Layout::HelpMenu],
};
let res = layout.clone().replace(&Layout::Table, &Layout::Selection);
match (res, layout) {
(
Layout::Horizontal {
config: res_config,
splits: res_splits,
},
Layout::Horizontal {
config: layout_config,
splits: layout_splits,
},
) => {
assert_eq!(res_config, layout_config);
assert_eq!(res_splits.len(), layout_splits.len());
assert_eq!(res_splits[0], Layout::Selection);
assert_ne!(res_splits[0], layout_splits[0]);
assert_eq!(res_splits[1], layout_splits[1]);
}
_ => panic!("Unexpected layout"),
}
}
}