Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(path): support floating and embedded preview for path source
Browse files Browse the repository at this point in the history
refactor: remove floating preview from path source

docs: update vimdoc
willothy authored and bekaboo committed Mar 2, 2024
1 parent a133a7d commit fa51f27
Showing 4 changed files with 124 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -2133,12 +2133,14 @@ Declared and defined in [`lua/dropbar/menu.lua`](https://github.com/Bekaboo/drop
| ------ | ------ | ------ |
| `buf` | `integer` | buffer number of the menu |
| `win` | `integer` | window id of the menu |
| `preview_win` | `integer` | window id being used for preview, if any |
| `is_opened` | `boolean?` | whether the menu is currently opened |
| `entries` | [`dropbar_menu_entry_t[]`](#dropbar_menu_entry_t) | entries in the menu |
| `win_configs` | `table` | window configuration, value can be a function, see [menu configuration options](#menu) |
| `_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 |
15 changes: 15 additions & 0 deletions doc/dropbar.txt
Original file line number Diff line number Diff line change
@@ -1881,6 +1881,21 @@ dropbar_menu_t.win *dropbar_menu_t.win*
Type ~
integer

dropbar_menu_t.preview_win *dropbar_menu_t.preview_win*

Window being used for preview, if any

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
16 changes: 16 additions & 0 deletions lua/dropbar/menu.lua
Original file line number Diff line number Diff line change
@@ -177,12 +177,14 @@ end
---@class dropbar_menu_t
---@field buf integer?
---@field win integer?
---@field preview_win integer? The open preview window, if any
---@field is_opened boolean?
---@field entries dropbar_menu_entry_t[]
---@field win_configs table window configuration, value can be a function
---@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
@@ -303,6 +305,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
100 changes: 91 additions & 9 deletions lua/dropbar/sources/path.lua
Original file line number Diff line number Diff line change
@@ -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
@@ -34,6 +34,81 @@ 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.preview_win = preview_win
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[self.entry.menu.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
@@ -42,6 +117,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,
@@ -53,6 +129,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)
@@ -69,14 +149,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

0 comments on commit fa51f27

Please sign in to comment.