Skip to content

Commit

Permalink
feat: use dropbar menu for ui.select (opt-in)
Browse files Browse the repository at this point in the history
  • Loading branch information
willothy committed Dec 12, 2023
1 parent 9405df5 commit 2cfe15d
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- [Utility Functions](#utility-functions)
- [Bar Utility Functions](#bar-utility-functions)
- [Menu Utility Functions](#menu-utility-functions)
- [Usage with `vim.ui.select`](#usage-with-vimuiselect)
- [Highlighting](#highlighting)
- [Developers](#developers)
- [Architecture](#architecture)
Expand All @@ -48,6 +49,7 @@
- [`dropbar_menu_entry_t`](#dropbar_menu_entry_t)
- [`dropbar_menu_hl_info_t`](#dropbar_menu_hl_info_t)
- [`dropbar_source_t`](#dropbar_source_t)
- [`dropbar_select_opts_t`](#dropbar_select_opts_t)
- [Making a New Source](#making-a-new-source)
- [Making a Source With Drop-Down Menus](#making-a-source-with-drop-down-menus)
- [Default `on_click()` Callback](#default-on_click-callback)
Expand Down Expand Up @@ -1602,6 +1604,19 @@ Defined in [`lua/dropbar/utils/menu.lua`](https://github.com/Bekaboo/dropbar.nvi
- If `opts.win` is not specified, return all opened dropbar menus
- `utils.menu.get_current(): dropbar_menu_t?`
- Get current dropbar menu
- utils.menu.select(items: any[], opts: table, on_choice: function(item, idx))
- Opt-in replacement for `vim.ui.select`
- Supports non-string items by formatting via the `opts.format_item` callback

### Usage with `vim.ui.select`

Dropbar can be used as a drop-in replacement for Neovim's builtin `vim.ui.select` menu.

To enable this functionality, simply replace `vim.ui.select` with `dropbar.utils.menu.select`:

```lua
vim.ui.select = require("dropbar.utils.menu").select
```

### Highlighting

Expand Down Expand Up @@ -2042,6 +2057,21 @@ Declared in [`lua/dropbar/sources/init.lua`](https://github.com/Bekaboo/dropbar.
| ------ | ------ | ------ |
| `get_symbols` | `function(buf: integer, win: integer, cursor: integer[]): dropbar_symbol_t[]` | returns the symbols<sub>[`dropbar_symbol_t[]`](#dropbar_symbol_t)</sub> to show in the winbar given buffer number `buf` and cursor position `cursor` |

#### `dropbar_select_opts_t`

Declared in [`lua/dropbar/utils/menu.lua`](https://github.com/Bekaboo/dropbar.nvim/blob/master/lua/dropbar/utils/menu.lua).

---

`dropbar_select_opts_t` is a class that represents the options passed to `utils.menu.select` (`vim.ui.select` with some extensions).

`dropbar_select_opts_t` has the following field:

| Field | Type | Description |
| ------ | ------ | ------ |
| `prompt` | `string?` | determines what will be shown at the top of the select menu. |
| `format_item` | `fun(item: any): string, string[][]?` | formats the list items for display in the menu, and optionally formats virtual text chunks to be shown below the item. |

### Making a New Source

A [`dropbar_source_t`](#dropbar_source_t) instance is just a table with
Expand Down
3 changes: 3 additions & 0 deletions lua/dropbar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ local function setup(opts)
desc = 'Update hover highlight on focus gained.',
})
end
if configs.opts.menu.ui_select then
vim.ui.select = utils.menu.select
end
vim.g.loaded_dropbar = true
end

Expand Down
83 changes: 83 additions & 0 deletions lua/dropbar/utils/menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,87 @@ function M.update_preview(mouse)
last_previewed_menu = menu
end

---@class dropbar_select_opts_t
---Text to be displayed at the top of the menu
---@field prompt? string
---Function to format each item in the menu.
---Required if `items` is not a list of strings.
---The second return value is a list of virtual text chunks to be displayed below the item. If
---nothing is returned for the second value, no virtual text will be displayed.
---@field format_item? fun(item: any): string, string[][]?

---@param items string[]|table[] list of items to be selected
---@param opts dropbar_select_opts_t
function M.select(items, opts, on_choice)
if not items then
return
end

opts = opts or {}

local entries = vim
.iter(items)
:enumerate()
:map(function(idx, item)
local text = item
local virt_text

-- support custom formats for items like some
-- other ui-select plugins do
if opts.format_item then
text, virt_text = opts.format_item(item)
end

return require('dropbar.menu').dropbar_menu_entry_t:new({
-- virt_text will only be shown if returned from `format_item`
virt_text = virt_text,
components = {
require('dropbar.bar').dropbar_symbol_t:new({
icon = '',
icon_hl = 'Special',
name = text,
on_click = function(self)
self.entry.menu:close()
if on_choice then
on_choice(item, idx)
end
end,
}),
},
})
end)
:totable()

local border, title_pos
if opts.prompt then
border = require('dropbar.configs').opts.menu.win_configs.border
title_pos = 'center'
end

local menu = require('dropbar.menu').dropbar_menu_t:new({
entries = entries,
prev_win = vim.api.nvim_get_current_win(),
win_configs = {
relative = 'cursor',
title = opts.prompt,
row = 1,
col = 1,
border = border,
title_pos = title_pos,
},
})

menu:open()

vim.api.nvim_create_autocmd('CursorMoved', {
buffer = menu.buf,
callback = function()
local cursor = { vim.api.nvim_win_get_cursor(menu.win)[1], 1 }
vim.api.nvim_win_set_cursor(menu.win, cursor)
menu:update_hover_hl(cursor)
end,
desc = 'Lock cursor to the first column of the menu',
})
end

return M

0 comments on commit 2cfe15d

Please sign in to comment.