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 14, 2023
1 parent 9405df5 commit 6f3edd2
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 1 deletion.
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 fields:

| 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
39 changes: 38 additions & 1 deletion doc/dropbar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ CONTENTS *dropbar-table-of-contents*
5.3 Utility Functions |dropbar-configuration-utility-functions|
5.3.1 Bar Utility Functions |dropbar-configuration-utility-functions-bar|
5.3.2 Menu Utility Functions |dropbar-configuration-utility-functions-menu|
5.4 Highlighting |dropbar-configuration-highlighting|
5.4 Usage with `vim.ui.select` |dropbar-configuration-usage-with-ui-select|
5.5 Highlighting |dropbar-configuration-highlighting|
6. Developers |dropbar-developers|
6.1 Architecture |dropbar-developers-architecture|
6.2 Classes |dropbar-developers-classes|
Expand All @@ -40,6 +41,7 @@ CONTENTS *dropbar-table-of-contents*
6.2.5 `dropbar_menu_entry_t` |dropbar-developers-classes-dropbar_menu_entry_t|
6.2.6 `dropbar_menu_hl_info_t` |dropbar-developers-classes-dropbar_menu_hl_info_t|
6.2.7 `dropbar_source_t` |dropbar-developers-classes-dropbar_source_t|
6.2.8 `dropbar_select_opts_t` |dropbar-developers-classes-dropbar_select_opts_t|
6.3 Making a new source |dropbar-developers-making-a-new-source|
6.3.1 Making a source with drop-down menus |dropbar-developers-making-a-source-with-drop-down-menus|
6.3.2 Default `on_click()` callback |dropbar-developers-default-on_click-callback|
Expand Down Expand Up @@ -1023,6 +1025,19 @@ utils.menu.get_current() *dropbar-utility-functions-utils.menu.get_current()*
Returns ~
`dropbar_menu_t` or `nil`

------------------------------------------------------------------------------
USAGE WITH `vim.ui.select` *dropbar-configuration-usage-with-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 *dropbar-configuration-highlighting*

Expand Down Expand Up @@ -2190,6 +2205,28 @@ dropbar_source_t.get_symbols({buf}, {win}, {cursor})
Returns ~
(`dropbar_symbol_t`[]): the symbols to show in the winbar

..............................................................................
DROPBAR_SELECT_OPTS_T *dropbar_select_opts_t*

Declared in `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:

*dropbar_select_opts_t.format_item*
dropbar_select_opts_t.format_item({item})

Format an item in the list of items passed to `utils.menu.select` into a
string.

Parameters ~
{item} (any): item in the list of items passed to `utils.menu.select`

Returns ~
(`string`): the text to display for the item
(`string`[][]?): optional virtual text to display below the item

------------------------------------------------------------------------------
MAKING A NEW SOURCE *dropbar-developers-making-a-source*

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 6f3edd2

Please sign in to comment.