From 17d0760e4363775cd22546b494d6bcfee1c948a2 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Sat, 16 Mar 2024 16:40:47 -0500 Subject: [PATCH] Add deep copy to copy Lua layouts This is probably not going to be in the final iteration; I think I might convert all Lua layouts to classes instead of having users deep copy them to change settings --- api/lua/examples/default/default_config.lua | 13 ++++++++ api/lua/pinnacle/layout.lua | 23 ++++++++++--- api/lua/pinnacle/util.lua | 37 +++++++++++++++++++++ api/rust/src/layout.rs | 2 +- src/layout.rs | 2 -- 5 files changed, 69 insertions(+), 8 deletions(-) diff --git a/api/lua/examples/default/default_config.lua b/api/lua/examples/default/default_config.lua index 5a27b95..ef4745b 100644 --- a/api/lua/examples/default/default_config.lua +++ b/api/lua/examples/default/default_config.lua @@ -5,6 +5,7 @@ require("pinnacle").setup(function(Pinnacle) local Tag = Pinnacle.tag local Window = Pinnacle.window local Layout = Pinnacle.layout + local Util = Pinnacle.util local key = Input.key @@ -88,8 +89,20 @@ require("pinnacle").setup(function(Pinnacle) -- Layouts -- -------------------- + -- TODO: convert layouts into objs, deep_copy doesn't work on fns + + local master_stack_right = Util.deep_copy(Layout.builtins.master_stack) + master_stack_right.master_side = "right" + local master_stack_top = Util.deep_copy(Layout.builtins.master_stack) + master_stack_top.master_side = "top" + local master_stack_bottom = Util.deep_copy(Layout.builtins.master_stack) + master_stack_bottom.master_side = "bottom" + local layout_manager = Layout.new_cycling_manager({ Layout.builtins.master_stack, + master_stack_right, + master_stack_top, + master_stack_bottom, Layout.builtins.dwindle, Layout.builtins.spiral, Layout.builtins.corner, diff --git a/api/lua/pinnacle/layout.lua b/api/lua/pinnacle/layout.lua index dcfbc74..b1d2d30 100644 --- a/api/lua/pinnacle/layout.lua +++ b/api/lua/pinnacle/layout.lua @@ -42,29 +42,41 @@ end ---@class LayoutGenerator ---Generate an array of geometries from the given `LayoutArgs`. ---@field layout fun(self: self, args: LayoutArgs): { x: integer, y: integer, width: integer, height: integer }[] ----Gaps between windows. ---- ----Generators are free to ignore this, but it is recommended to implement gaps if ----it makes sense for the layout. ----@field gaps integer | { inner: integer, outer: integer } +---A `LayoutGenerator` that has one master area to one side +---and a stack of windows next to it. ---@class Builtin.MasterStack : LayoutGenerator +---@field gaps integer | { inner: integer, outer: integer } ---@field master_factor number ---@field master_side "left"|"right"|"top"|"bottom" ---@field master_count integer +---A `LayoutGenerator` that lays out windows in a shrinking fashion +---towards the bottom right corner. ---@class Builtin.Dwindle : LayoutGenerator +---@field gaps integer | { inner: integer, outer: integer } ---@field split_factors table +---A `LayoutGenerator` that has one main corner window and a +---horizontal and vertical stack flanking it on the other two sides. ---@class Builtin.Corner : LayoutGenerator +---@field gaps integer | { inner: integer, outer: integer } ---@field corner_width_factor number ---@field corner_height_factor number ---@field corner_loc "top_left"|"top_right"|"bottom_left"|"bottom_right" +---A `LayoutGenerator` that lays out windows in a spiral. +--- +---This is similar to the dwindle layout but in a spiral instead of +---towards the borrom right corner. ---@class Builtin.Spiral : LayoutGenerator +---@field gaps integer | { inner: integer, outer: integer } ---@field split_factors table +---A `LayoutGenerator` that attempts to layout windows such that +---they are the same size. ---@class Builtin.Fair : LayoutGenerator +---@field gaps integer | { inner: integer, outer: integer } ---@field direction "horizontal"|"vertical" local builtins = { @@ -401,6 +413,7 @@ function builtins.dwindle:layout(args) local to_push + ---@diagnostic disable-next-line: cast-local-type to_push, rest = rest:split_at(axis, split_coord, gaps) if not rest then diff --git a/api/lua/pinnacle/util.lua b/api/lua/pinnacle/util.lua index c7f04d6..a1c0411 100644 --- a/api/lua/pinnacle/util.lua +++ b/api/lua/pinnacle/util.lua @@ -77,6 +77,43 @@ function util.batch(requests) return responses end +-- Taken from the following stackoverflow answer: +-- https://stackoverflow.com/a/16077650 +local function deep_copy_rec(obj, seen) + seen = seen or {} + if obj == nil then + return nil + end + if seen[obj] then + return seen[obj] + end + + local no + if type(obj) == "table" then + no = {} + seen[obj] = no + + for k, v in next, obj, nil do + no[deep_copy_rec(k, seen)] = deep_copy_rec(v, seen) + end + setmetatable(no, deep_copy_rec(getmetatable(obj), seen)) + else -- number, string, boolean, etc + no = obj + end + return no +end + +---Create a deep copy of an object. +--- +---@generic T +--- +---@param obj T The object to deep copy. +--- +---@return T deep_copy A deep copy of `obj` +function util.deep_copy(obj) + return deep_copy_rec(obj, nil) +end + -- Geometry stuff ---@class RectangleModule diff --git a/api/rust/src/layout.rs b/api/rust/src/layout.rs index fc90239..407a836 100644 --- a/api/rust/src/layout.rs +++ b/api/rust/src/layout.rs @@ -744,7 +744,7 @@ pub enum CornerLocation { } /// A [`LayoutGenerator`] that has one main corner window and a -/// horizontal and vertical stack flanking on the other two sides. +/// horizontal and vertical stack flanking it on the other two sides. #[derive(Debug, Clone, Copy, PartialEq)] pub struct CornerLayout { /// Gaps between windows. diff --git a/src/layout.rs b/src/layout.rs index 68e3537..dcbffb2 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -222,8 +222,6 @@ impl State { } pub fn apply_layout(&mut self, geometries: Geometries) -> anyhow::Result<()> { - tracing::info!("Applying layout"); - let Geometries { request_id: Some(request_id), output_name: Some(output_name),