From 51909eff78b6e0e73a02fd520fc6b1edc7f54c41 Mon Sep 17 00:00:00 2001 From: Will Hopkins Date: Sat, 9 Dec 2023 04:41:35 -0800 Subject: [PATCH 1/3] feat: use dropbar menu for `ui.select` (opt-in) --- README.md | 30 ++++++++++++++ doc/dropbar.txt | 39 +++++++++++++++++- lua/dropbar.lua | 3 ++ lua/dropbar/utils/menu.lua | 83 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30be4703..731f3eee 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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) @@ -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 @@ -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[`dropbar_symbol_t[]`](#dropbar_symbol_t) 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 diff --git a/doc/dropbar.txt b/doc/dropbar.txt index 01c161e9..54c75cee 100644 --- a/doc/dropbar.txt +++ b/doc/dropbar.txt @@ -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| @@ -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| @@ -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* @@ -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* diff --git a/lua/dropbar.lua b/lua/dropbar.lua index 886f48cf..538d6b1d 100644 --- a/lua/dropbar.lua +++ b/lua/dropbar.lua @@ -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 diff --git a/lua/dropbar/utils/menu.lua b/lua/dropbar/utils/menu.lua index 2fde75a3..be3c7fe3 100644 --- a/lua/dropbar/utils/menu.lua +++ b/lua/dropbar/utils/menu.lua @@ -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 From 56ca5475758255269d8438722558624a5303224d Mon Sep 17 00:00:00 2001 From: bekaboo <18127878294@qq.com> Date: Thu, 14 Dec 2023 10:54:37 +0800 Subject: [PATCH 2/3] docs: fix docs format --- README.md | 2 +- doc/dropbar.txt | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 731f3eee..6eb026be 100644 --- a/README.md +++ b/README.md @@ -1615,7 +1615,7 @@ Dropbar can be used as a drop-in replacement for Neovim's builtin `vim.ui.select To enable this functionality, simply replace `vim.ui.select` with `dropbar.utils.menu.select`: ```lua -vim.ui.select = require("dropbar.utils.menu").select +vim.ui.select = require('dropbar.utils.menu').select ``` ### Highlighting diff --git a/doc/dropbar.txt b/doc/dropbar.txt index 54c75cee..cdf0f19e 100644 --- a/doc/dropbar.txt +++ b/doc/dropbar.txt @@ -30,7 +30,7 @@ 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 Usage with `vim.ui.select` |dropbar-configuration-usage-with-ui-select| + 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| @@ -1026,16 +1026,15 @@ utils.menu.get_current() *dropbar-utility-functions-utils.menu.get_current()* `dropbar_menu_t` or `nil` ------------------------------------------------------------------------------ -USAGE WITH `vim.ui.select` *dropbar-configuration-usage-with-ui-select* +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`: +`dropbar.utils.menu.select`: >lua ->lua -vim.ui.select = require("dropbar.utils.menu").select + vim.ui.select = require('dropbar.utils.menu').select < ------------------------------------------------------------------------------ From c6852fd7ae5d4423f49c69c734fbf5b0fecf25ed Mon Sep 17 00:00:00 2001 From: bekaboo <18127878294@qq.com> Date: Thu, 14 Dec 2023 10:59:26 +0800 Subject: [PATCH 3/3] refactor: remove unneeded options --- lua/dropbar.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/lua/dropbar.lua b/lua/dropbar.lua index 538d6b1d..886f48cf 100644 --- a/lua/dropbar.lua +++ b/lua/dropbar.lua @@ -151,9 +151,6 @@ 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