Skip to content

Commit

Permalink
fix: inconsistent resizes on vsplits (#380)
Browse files Browse the repository at this point in the history
## 📃 Summary

should close #298

opening/closing a vsplit alters the ui, and since we resize side
buffers, it might shrink buffers that are on the side of those sides.

we now resize splits as well, but not integrations
  • Loading branch information
shortcuts authored Aug 29, 2024
1 parent 1797ffa commit af5c9bc
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 48 deletions.
24 changes: 21 additions & 3 deletions lua/no-neck-pain/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ function N.init(scope, goToCurr)

-- if we do not have side buffers, we must ensure we only trigger a focus if we re-create them
local hadSideBuffers = true
if S.checkSides(S, "and", false) then
if not S.is_side_win_valid(S, "left") or not S.is_side_win_valid(S, "right") then
hadSideBuffers = false
end

W.createSideBuffers()
W.create_side_buffers()

if S.consumeRedraw(S) then
if S.consume_redraw(S) then
W.reposition(string.format("%s:consumeRedraw", scope))
end

Expand All @@ -119,6 +119,24 @@ function N.init(scope, goToCurr)
vim.api.nvim_set_current_win(S.getSideID(S, "curr"))
end

-- if we still have side buffers open at this point, and we have vsplit opened,
-- there might be width issues so we the resize opened vsplits.
if S.checkSides(S, "or", true) and S.getColumns(S) > 1 then
D.log("wins_resize", "have %d columns", S.getColumns(S))

for _, win in pairs(S.getUnregisteredWins(S)) do
W.resize(win, _G.NoNeckPain.config.width, string.format("win:%d", win))
end

if not hadSideBuffers then
W.resize(
S.getSideID(S, "curr"),
_G.NoNeckPain.config.width,
string.format("win:%d", S.getSideID(S, "curr"))
)
end
end

S.save(S)
end

Expand Down
26 changes: 21 additions & 5 deletions lua/no-neck-pain/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ end
---
---@return boolean
---@private
function State:consumeRedraw()
function State:consume_redraw()
local redraw = self.tabs[self.activeTab].redraw

self.tabs[self.activeTab].redraw = false
Expand Down Expand Up @@ -184,16 +184,17 @@ function State:getIntegration(id)
return nil, nil
end

---Gets every unregistered wins (non main, non integrations).
---Gets wins that are not relative or main wins.
---
---@return table: the list of windows.
---@return table: the list of windows IDs.
---@private
function State:getUnregisteredWins()
return vim.tbl_filter(function(win)
return not A.isRelativeWindow(win)
and win ~= self.getSideID(self, "curr")
and win ~= self.getSideID(self, "left")
and win ~= self.getSideID(self, "right")
and not self.is_supported_integration(self, "_", win)
end, vim.api.nvim_tabpage_list_wins(self.activeTab))
end

Expand All @@ -205,7 +206,7 @@ end
---@return string?: the supported integration name.
---@return table?: the supported integration infos.
---@private
function State:isSupportedIntegration(scope, win)
function State:is_supported_integration(scope, win)
win = win or 0
local tab = self.getTabSafe(self)
local buffer = vim.api.nvim_win_get_buf(win)
Expand Down Expand Up @@ -245,6 +246,21 @@ function State:isActiveTabRegistered()
and vim.api.nvim_tabpage_is_valid(self.activeTab)
end

---Returns true if the win isn't registered, or if it is and valid, false otherwise.
---
---@param side "left"|"right": the side of the window.
---@return boolean
---@private
function State:is_side_win_valid(side)
if not self.isSideEnabled(self, side) then
return true
end

local id = self.getSideID(self, side)

return id ~= nil and vim.api.nvim_win_is_valid(id)
end

---Whether the side window is registered and a valid window.
---
---@param side "left"|"right"|"curr": the side of the window.
Expand Down Expand Up @@ -459,7 +475,7 @@ function State:setLayoutWindows(scope, wins)
for _, win in ipairs(wins) do
local id = win[2]
if win[1] == "leaf" and not A.isRelativeWindow(id) then
local supported, name, integration = self.isSupportedIntegration(self, scope, id)
local supported, name, integration = self.is_supported_integration(self, scope, id)
if supported and name and integration then
integration.width = vim.api.nvim_win_get_width(id) * 2
integration.id = id
Expand Down
2 changes: 1 addition & 1 deletion lua/no-neck-pain/util/event.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function E.skipEnable()
return true
end

return S.isSupportedIntegration(S, "E.skipEnable", nil)
return S.is_supported_integration(S, "E.skipEnable", nil)
end

return E
40 changes: 3 additions & 37 deletions lua/no-neck-pain/wins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ local W = {}
---@param width number: the width to apply to the window.
---@param side "left"|"right"|"curr"|"unregistered": the side of the window being resized, used for logging only.
---@private
local function resize(id, width, side)
function W.resize(id, width, side)
D.log(side, "resizing %d with padding %d", id, width)

if vim.api.nvim_win_is_valid(id) then
Expand Down Expand Up @@ -152,7 +152,7 @@ end
--- - If it already exists, we resize it.
---
---@private
function W.createSideBuffers()
function W.create_side_buffers()
local wins = {
left = { cmd = "topleft vnew", padding = 0 },
right = { cmd = "botright vnew", padding = 0 },
Expand Down Expand Up @@ -197,47 +197,13 @@ function W.createSideBuffers()
local padding = wins[side].padding or W.getPadding(side)

if padding > _G.NoNeckPain.config.minSideBufferWidth then
resize(S.getSideID(S, side), padding, side)
W.resize(S.getSideID(S, side), padding, side)
else
W.close("W.createSideBuffers", S.getSideID(S, side), side)
S.setSideID(S, nil, side)
end
end
end

local columns = S.getColumns(S)
local leftID = S.getSideID(S, "left")
local rightID = S.getSideID(S, "right")

-- if we still have side buffers open at this point, and we have vsplit opened,
-- there might be width issues so we the resize opened vsplits.
if (leftID or rightID) and columns > 1 then
local sWidth = wins.left.padding or wins.right.padding
local nbSide = leftID and rightID and 2 or 1

-- get the available usable width (screen size without side paddings)
sWidth = vim.o.columns - sWidth * nbSide
local remainingVSplits = columns - nbSide

if remainingVSplits < 1 then
remainingVSplits = 1
end

sWidth = math.floor(sWidth / remainingVSplits)

D.log(
"splitResize",
"%d/%d screen width remaining, %d columns including %d sides",
sWidth,
vim.o.columns,
columns,
nbSide
)

for _, win in pairs(S.getUnregisteredWins(S)) do
-- resize(win, sWidth, string.format("unregistered:%d", win))
end
end
end

---Determine the "padding" (width) of the buffer based on the `_G.NoNeckPain.config.width` and the width of the screen.
Expand Down
4 changes: 2 additions & 2 deletions tests/test_splits.lua
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ T["vsplit"]["correctly size splits when opening helper with side buffers open"]
Helpers.expect.equality(child.get_wins_in_tab(), { 1004, 1001, 1003, 1000, 1002 })

Helpers.expect.equality(child.lua_get("vim.api.nvim_win_get_width(1004)"), 80)
Helpers.expect.buf_width(child, "tabs[1].wins.main.curr", 18)
Helpers.expect.buf_width(child, "tabs[1].wins.main.curr", 17)
end

T["vsplit"]["correctly position side buffers when there's enough space"] = function()
Expand Down Expand Up @@ -348,7 +348,7 @@ T["vsplit/split"]["splits and vsplits keeps a correct size"] = function()
Helpers.expect.equality(child.get_current_win(), 1004)

Helpers.expect.buf_width(child, "tabs[1].wins.main.curr", 38)
Helpers.expect.equality(child.lua_get("vim.api.nvim_win_get_width(1003)"), 17)
Helpers.expect.equality(child.lua_get("vim.api.nvim_win_get_width(1003)"), 20)
end

return T

0 comments on commit af5c9bc

Please sign in to comment.