Skip to content

Commit

Permalink
feat(path): support file preview for path source
Browse files Browse the repository at this point in the history
  • Loading branch information
willothy committed Mar 2, 2024
1 parent 4eab577 commit 62ed697
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 9 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2139,6 +2139,7 @@ Declared and defined in [`lua/dropbar/menu.lua`](https://github.com/Bekaboo/drop
| `_win_configs` | `table?` | evaluated window configuration |
| `cursor` | `integer[]?` | initial cursor position |
| `prev_win` | `integer?` | previous window, assigned when calling new() or automatically determined in open() |
| `prev_buf` | `integer?` | previous buffer, assigned when calling new() or automatically determined in open() |
| `sub_menu` | `dropbar_menu_t?` | submenu, assigned when calling new() or automatically determined when a new menu opens |
| `prev_menu` | `dropbar_menu_t?` | previous menu, assigned when calling new() or automatically determined in open() |
| `clicked_at` | `integer[]?` | last position where the menu was clicked, 1,0-indexed |
Expand Down
8 changes: 8 additions & 0 deletions doc/dropbar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1881,6 +1881,14 @@ dropbar_menu_t.win *dropbar_menu_t.win*
Type ~
integer

dropbar_menu_t.prev_buf *dropbar_menu_t.prev_buf*

Previous buffer, assigned when calling `new()` or automatically
determined in `open()`

Type ~
integer?

dropbar_menu_t.is_opened *dropbar_menu_t.is_opened*

Whether the menu is currently opened
Expand Down
15 changes: 15 additions & 0 deletions lua/dropbar/menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ end
---@field _win_configs table evaluated window configuration
---@field cursor integer[]? initial cursor position
---@field prev_win integer? previous window, assigned when calling new() or automatically determined in open()
---@field prev_buf integer? previous buffer, assigned when calling new() or automatically determined in open()
---@field sub_menu dropbar_menu_t? submenu, assigned when calling new() or automatically determined when a new menu opens
---@field prev_menu dropbar_menu_t? previous menu, assigned when calling new() or automatically determined in open()
---@field clicked_at integer[]? last position where the menu was clicked, byte-indexed, 1,0-indexed
Expand Down Expand Up @@ -303,6 +304,20 @@ function dropbar_menu_t:click_at(pos, min_width, n_clicks, button, modifiers)
end
end

---Retrieves the root window of the menu.
---If `self.prev_menu` is nil then this `self.prev_win`.
---Otherwise, it is the root window of `self.prev_menu`.
---@return integer?
function dropbar_menu_t:root_win()
local current = self
local win = self.prev_win
while current and current.prev_menu do
win = current.prev_menu.prev_win
current = current.prev_menu
end
return win
end

---"Click" the component in the dropbar menu
---Side effects: update self.clicked_at
---@param symbol dropbar_symbol_t
Expand Down
98 changes: 89 additions & 9 deletions lua/dropbar/sources/path.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ local function get_icon_and_hl(path)
local icon = icon_kind_opts.symbols.File
local icon_hl = 'DropBarIconKindFile'
local name_hl = 'DropBarKindFile'
local stat = vim.loop.fs_stat(path)
local stat = vim.uv.fs_stat(path)
if not stat then
return icon, icon_hl
elseif stat.type == 'directory' then
Expand All @@ -34,6 +34,79 @@ local function get_icon_and_hl(path)
return icon, icon_hl, name_hl
end

---@param self dropbar_symbol_t
local function preview_prepare_buf(self, path)
local buf
if vim.uv.fs_stat(path).type == 'directory' then
self:preview_restore_view()
return
end
buf = vim.fn.bufnr(path, false)
if buf == nil or buf == -1 then
buf = vim.fn.bufadd(path)
if not buf then
self:preview_restore_view()
return
end
if not vim.api.nvim_buf_is_loaded(buf) then
vim.fn.bufload(buf)
end
end
if buf == nil or self.entry.menu == nil or self.entry.menu.win == nil then
self:preview_restore_view()
return
end
return buf
end

---@param self dropbar_symbol_t
local function preview_open(self, path)
local preview_buf = preview_prepare_buf(self, path)
if not preview_buf then
return
end
local buflisted = vim.bo[preview_buf].buflisted

local preview_win = self.entry.menu:root_win()
if not preview_win then
return
end
self.entry.menu.prev_buf = self.entry.menu.prev_buf
or vim.api.nvim_win_get_buf(preview_win)

vim.api.nvim_create_autocmd('BufLeave', {
buffer = self.entry.menu.buf,
callback = function()
self:preview_restore_view()
end,
})
vim.api.nvim_win_set_buf(preview_win, preview_buf)
-- set cursor to the last exited position in buf (:h '"), if available
local last_exit = vim.api.nvim_buf_get_mark(preview_buf, '"')
if last_exit[1] ~= 0 then
vim.api.nvim_win_set_cursor(preview_win, last_exit)
end

vim.bo[preview_buf].buflisted = buflisted

-- ensure dropbar still shows then the preview buffer is opened
vim.wo[preview_win].winbar = '%{%v:lua.dropbar.get_dropbar_str()%}'
end

---@param self dropbar_symbol_t
local function preview_close(self)
if self.win then
if self.entry.menu.prev_buf then
vim.api.nvim_win_set_buf(self.win, self.entry.menu.prev_buf)
end
if self.view then
vim.api.nvim_win_call(self.win, function()
vim.fn.winrestview(self.view)
end)
end
end
end

---Convert a path to a dropbar symbol
---@param path string full path
---@param buf integer buffer handler
Expand All @@ -42,6 +115,7 @@ end
local function convert(path, buf, win)
local path_opts = configs.opts.sources.path
local icon, icon_hl, name_hl = get_icon_and_hl(path)

return bar.dropbar_symbol_t:new(setmetatable({
buf = buf,
win = win,
Expand All @@ -53,6 +127,10 @@ local function convert(path, buf, win)
jump = function(_)
vim.cmd.edit(path)
end,
preview = vim.schedule_wrap(function(self)
preview_open(self, path)
end),
preview_restore_view = preview_close,
}, {
---@param self dropbar_symbol_t
__index = function(self, k)
Expand All @@ -69,14 +147,16 @@ local function convert(path, buf, win)
local parent_dir = vim.fs.dirname(path)
self.siblings = {}
self.sibling_idx = 1
for idx, name in vim.iter(vim.fs.dir(parent_dir)):enumerate() do
if path_opts.filter(name) then
table.insert(
self.siblings,
convert(parent_dir .. '/' .. name, buf, win)
)
if name == self.name then
self.sibling_idx = idx
if parent_dir then
for idx, name in vim.iter(vim.fs.dir(parent_dir)):enumerate() do
if path_opts.filter(name) then
table.insert(
self.siblings,
convert(parent_dir .. '/' .. name, buf, win)
)
if name == self.name then
self.sibling_idx = idx
end
end
end
end
Expand Down

0 comments on commit 62ed697

Please sign in to comment.