Skip to content

Commit

Permalink
feat: added pinned views
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Jun 2, 2023
1 parent 9322531 commit 07a1b6d
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 17 deletions.
26 changes: 18 additions & 8 deletions lua/edgy/sidebar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,34 @@ end
function M:on_win_enter()
vim.api.nvim_create_autocmd("WinEnter", {
callback = function()
local win = vim.api.nvim_get_current_win()
for _, w in ipairs(self.wins) do
if w.win == win then
if not w.visible then
w:show()
vim.schedule(function()
local win = vim.api.nvim_get_current_win()
for _, w in ipairs(self.wins) do
if w.win == win then
if not w.visible then
w:show()
end
break
end
break
end
end
end)
end,
})
end

---@param wins table<string, number[]>
function M:update(wins)
local visible = 0
for _, view in ipairs(self.views) do
visible = visible + view:update(wins[view.ft] or {})
end
self.wins = {}
for _, view in ipairs(self.views) do
view:update(wins[view.ft] or {})
if visible > 0 then
view:check_pinned()
else
view:hide_pinned()
end
vim.list_extend(self.wins, view.wins)
end
for w, win in ipairs(self.wins) do
Expand Down
45 changes: 44 additions & 1 deletion lua/edgy/view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ local Window = require("edgy.window")
---@field winbar? boolean
---@field pinned? boolean
---@field sidebar Edgy.Sidebar
---@field open? fun()
---@field open? fun()|string
---@field close? fun()

---@class Edgy.View: Edgy.View.Opts
---@field title string
---@field wins Edgy.Window[]
---@field size Edgy.Size
---@field pinned_win? Edgy.Window
local M = {}
M.__index = M

Expand All @@ -38,6 +39,48 @@ function M:update(wins)
for _, win in ipairs(wins) do
self.wins[#self.wins + 1] = index[win] or Window.new(win, self)
end
return #self.wins
end

function M:check_pinned()
if not self.pinned or #self.wins > 0 then
self:hide_pinned()
return
end
if not (self.pinned_win and vim.api.nvim_win_is_valid(self.pinned_win.win)) then
local buf = vim.api.nvim_create_buf(false, true)
vim.bo[buf].buftype = "nofile"
vim.bo[buf].bufhidden = "wipe"
vim.bo[buf].swapfile = false
vim.api.nvim_buf_set_name(buf, "edgy://" .. self.title)
local win = vim.api.nvim_open_win(buf, false, {
relative = "editor",
width = 1,
height = 1,
col = 0,
row = 0,
style = "minimal",
})
vim.api.nvim_create_autocmd("BufWinLeave", {
buffer = buf,
callback = function()
self:hide_pinned()
end,
})
self.pinned_win = Window.new(win, self)
end
self.wins[1] = self.pinned_win
self.wins[1].visible = false
end

function M:hide_pinned()
if self.pinned_win and vim.api.nvim_win_is_valid(self.pinned_win.win) then
if self.pinned_win.win == vim.api.nvim_get_current_win() then
self.pinned_win:goto_main()
end
vim.api.nvim_win_close(self.pinned_win.win, true)
self.pinned_win = nil
end
end

return M
66 changes: 58 additions & 8 deletions lua/edgy/window.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local Util = require("edgy.util")
local Config = require("edgy.config")

---@class Edgy.Window
Expand All @@ -8,6 +9,7 @@ local Config = require("edgy.config")
---@field height number
---@field next? Edgy.Window
---@field prev? Edgy.Window
---@field opening boolean
local M = {}
M.__index = M

Expand All @@ -23,10 +25,22 @@ function M.new(win, view)
win = win,
}, M)
M.cache[win] = self
self.opening = false
if self.view.winbar ~= false then
if vim.api.nvim_win_get_height(win) == 1 then
vim.api.nvim_win_set_height(win, 2)
end
vim.wo[self.win].winbar = "%!v:lua.edgy_winbar(" .. win .. ")"
end
vim.wo[self.win].winfixwidth = true
vim.api.nvim_create_autocmd("WinClosed", {
callback = function(event)
if tonumber(event.match) == self.win then
self:goto_main()
return true
end
end,
})
return self
end

Expand All @@ -37,34 +51,70 @@ end
---@param visibility? boolean
function M:show(visibility)
self.visible = visibility == nil and true or visibility or false
if self.visible and self:is_pinned() then
self.visible = false
return self:open()
end

if not self.visible and not self.prev and not self.next then
self.visible = true
return
end

if not self.visible and vim.api.nvim_get_current_win() == self.win then
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if not M.cache[w] then
vim.api.nvim_set_current_win(w)
break
end
end
self:goto_main()
end

if not self.visible then
self:ensure_one_visible()
end

vim.cmd([[redrawstatus!]])
require("edgy.layout").update()
end

function M:open()
if self.opening then
return
end
self.opening = true
vim.schedule(function()
self:goto_main()
if type(self.view.open) == "function" then
Util.try(self.view.open)
elseif type(self.view.open) == "string" then
Util.try(function()
vim.cmd(self.view.open)
end)
else
Util.error("View is pinned and has no open function")
end
self.opening = false
end)
end

function M:goto_main()
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if not M.cache[w] and w ~= self.win then
vim.api.nvim_set_current_win(w)
break
end
end
end

function M:is_pinned()
return self.view.pinned_win == self
end

function M:ensure_one_visible()
if self:sibling(function(w)
return w.visible
end) then
return
end
if self.prev then
if self.prev and not self.prev:is_pinned() then
self.prev:show()
elseif self.next then
elseif self.next and not self.next:is_pinned() then
self.next:show()
end
end
Expand Down

0 comments on commit 07a1b6d

Please sign in to comment.