diff --git a/README.md b/README.md index 5f8615c1..94b353ad 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ - [Treesitter](#treesitter) - [LSP](#lsp) - [Markdown](#markdown) + - [Terminal](#terminal) - [API](#api) - [Utility Functions](#utility-functions) - [Bar Utility Functions](#bar-utility-functions) @@ -69,7 +70,7 @@ https://github.com/Bekaboo/dropbar.nvim/assets/76579810/e8c1ac26-0321-4762-9975- - [x] Multiple backends that support fall-backs - `dropbar.nvim` comes with four builtin sources: + `dropbar.nvim` comes with five builtin sources: - [x] [lsp](https://github.com/Bekaboo/dropbar.nvim/blob/master/lua/dropbar/sources/lsp.lua): gets symbols from language servers using nvim's builtin LSP framework @@ -79,6 +80,8 @@ https://github.com/Bekaboo/dropbar.nvim/assets/76579810/e8c1ac26-0321-4762-9975- - [x] [treesitter](https://github.com/Bekaboo/dropbar.nvim/blob/master/lua/dropbar/sources/treesitter.lua): gets symbols from treesitter parsers using nvim's builtin treesitter integration + - [x] [terminal](https://github.com/Bekaboo/dropbar.nvim/blob/master/lua/dropbar/sources/terminal.lua): easily switch terminal buffers using the dropdown menu + To make a new source yourself, see [making a new source](#making-a-new-source). For source fall-backs support, see [bar options](#bar). @@ -310,6 +313,7 @@ https://github.com/Bekaboo/dropbar.nvim/assets/76579810/e8c1ac26-0321-4762-9975- Value = '󰎠 ', Variable = '󰀫 ', WhileStatement = '󰑖 ', + Terminal = '' }, }, ui = { @@ -612,6 +616,23 @@ https://github.com/Bekaboo/dropbar.nvim/assets/76579810/e8c1ac26-0321-4762-9975- look_ahead = 200, }, }, + terminal = { + ---@type string|fun(buf: integer): string + icon = function(buf) + local icon = M.opts.icons.kinds.symbols.Terminal + if M.opts.icons.kinds.use_devicons then + icon = require('nvim-web-devicons').get_icon_by_filetype( + vim.bo[buf].filetype + ) or icon + end + return icon + end, + ---@type string|fun(buf: integer): string + name = vim.api.nvim_buf_get_name, + ---@type boolean + ---Show the current terminal buffer in the menu + show_current = true, + } }, } ``` @@ -831,7 +852,7 @@ the symbols: view.topline = topline vim.fn.winrestview(view) end - end, + end ``` #### Bar @@ -851,7 +872,6 @@ winbar: ```lua function(buf, _) local sources = require('dropbar.sources') - local utils = require('dropbar.utils') if vim.bo[buf].ft == 'markdown' then return { sources.path, @@ -862,6 +882,11 @@ winbar: }), } end + if vim.bo[buf].buftype == 'terminal' then + return { + sources.terminal, + } + end return { sources.path, utils.source.fallback({ @@ -869,7 +894,7 @@ winbar: sources.treesitter, }), } - end, + end ``` - For more information about sources, see [`dropbar_source_t`](#dropbar_source_t). - `opts.bar.padding`: `{ left: number, right: number }` @@ -1164,6 +1189,43 @@ each sources. - Number of lines to update when cursor moves out of the parsed range - Default: `200` +##### Terminal + +- `opts.sources.terminal.icon`: `string` or `fun(buf: integer): string` + - Icon to show before terminal names + - Default: + ```lua + icon = function(buf) + local icon = M.opts.icons.kinds.symbols.Terminal + if M.opts.icons.kinds.use_devicons then + icon = require('nvim-web-devicons').get_icon_by_filetype( + vim.bo[buf].filetype + ) or icon + end + return icon + end + ``` + +- `opts.sources.terminal.name`: `string` or `fun(buf: integer): string` + - Easy to integrate with other plugins (for example, [toggleterm.nvim](https://github.com/akinsho/toggleterm.nvim)): + ```lua + name = function(buf) + local name = vim.api.nvim_buf_get_name(buf) + -- the second result val is the terminal object + local term = select(2, require("toggleterm.terminal").indentify(name)) + if term then + return term.display_name or term.name + else + return name + end + end + ``` + - Default: `vim.api.nvim_buf_get_name` + +- `opts.sources.terminal.show_current: boolean` + - Show the current terminal buffer in the menu + - Default: `true` + ### API `dropbar.nvim` exposes a few functions in `lua/dropbar/api.lua` that can be @@ -1305,6 +1367,7 @@ should be self-explanatory: | DropBarIconKindValue | `{ link = 'Number' }` | | DropBarIconKindVariable | `{ link = 'CmpItemKindVariable' }` | | DropBarIconKindWhileStatement | `{ link = 'Repeat' }` | + | DropBarIconKindTerminal | `{ link = 'Number' }` | | DropBarIconUIIndicator | `{ link = 'SpecialChar' }` | | DropBarIconUIPickPivot | `{ link = 'Error' }` | | DropBarIconUISeparator | `{ link = 'SpecialChar' }` | diff --git a/lua/dropbar/configs.lua b/lua/dropbar/configs.lua index c10cef91..3bea501b 100644 --- a/lua/dropbar/configs.lua +++ b/lua/dropbar/configs.lua @@ -7,7 +7,7 @@ M.opts = { ---@type boolean|fun(buf: integer, win: integer, info: table?): boolean enable = function(buf, win, _) return not vim.api.nvim_win_get_config(win).zindex - and vim.bo[buf].buftype == '' + and (vim.bo[buf].buftype == '' or vim.bo[buf].buftype == 'terminal') and vim.api.nvim_buf_get_name(buf) ~= '' and not vim.wo[win].diff end, @@ -176,6 +176,11 @@ M.opts = { }), } end + if vim.bo[buf].buftype == 'terminal' then + return { + sources.terminal, + } + end return { sources.path, utils.source.fallback({ @@ -419,6 +424,23 @@ M.opts = { look_ahead = 200, }, }, + terminal = { + ---@type string|fun(buf: integer): string + icon = function(buf) + local icon = M.opts.icons.kinds.symbols.Terminal + if M.opts.icons.kinds.use_devicons then + icon = require('nvim-web-devicons').get_icon_by_filetype( + vim.bo[buf].filetype + ) or icon + end + return icon + end, + ---@type string|fun(buf: integer): string + name = vim.api.nvim_buf_get_name, + ---@type boolean + ---Show the current terminal buffer in the menu + show_current = true, + }, }, } diff --git a/lua/dropbar/hlgroups.lua b/lua/dropbar/hlgroups.lua index 740fc38c..33b8c07f 100644 --- a/lua/dropbar/hlgroups.lua +++ b/lua/dropbar/hlgroups.lua @@ -65,6 +65,7 @@ local hlgroups = { DropBarIconKindValue = { link = 'Number' }, DropBarIconKindVariable = { link = 'CmpItemKindVariable' }, DropBarIconKindWhileStatement = { link = 'Repeat' }, + DropBarIconKindTerminal = { link = 'Number' }, DropBarIconUIIndicator = { link = 'SpecialChar' }, DropBarIconUIPickPivot = { link = 'Error' }, DropBarIconUISeparator = { link = 'SpecialChar' }, diff --git a/lua/dropbar/sources/terminal.lua b/lua/dropbar/sources/terminal.lua new file mode 100644 index 00000000..4055cfcf --- /dev/null +++ b/lua/dropbar/sources/terminal.lua @@ -0,0 +1,91 @@ +local initialized +local configs + +local function init() + initialized = true + configs = require('dropbar.configs') +end + +local function buf_info(buf) + local icon = configs.opts.sources.terminal.icon + if type(icon) == 'function' then + icon = icon(buf) + end + local name = configs.opts.sources.terminal.name + if type(name) == 'function' then + name = name(buf) + end + return { + icon = icon, + name = name, + icon_hl = 'DropBarIconKindTerminal', + } +end + +---@param sym dropbar_symbol_t +---@return dropbar_menu_entry_t[] +local function get_menu_entries(sym) + return vim + .iter(vim.api.nvim_list_bufs()) + :filter(function(buf) + return vim.bo[buf].buftype == 'terminal' + and (buf ~= sym.bar.buf or configs.opts.sources.terminal.show_current) + end) + :map(function(buf) + local entry = buf_info(buf) + entry.on_click = function() + vim.api.nvim_win_set_buf(sym.bar.win, buf) + sym.menu:close(true) + end + return require('dropbar.menu').dropbar_menu_entry_t:new({ + components = { + require('dropbar.bar').dropbar_symbol_t:new(entry), + }, + }) + end) + :totable() +end + +local function get_symbols(buf, win) + if not initialized then + init() + end + + local symbol = buf_info(buf) + symbol.on_click = function(self) + local entries = get_menu_entries(self) + if #entries > 0 then + self.menu = require('dropbar.menu').dropbar_menu_t:new({ + entries = entries, + prev_win = self.bar.win, + }) + self.menu:open({ + win_configs = { + win = win, + col = function(menu) + if menu.prev_menu then + return menu.prev_menu._win_configs.width + end + local mouse = vim.fn.getmousepos() + local bar = require('dropbar.api').get_dropbar( + vim.api.nvim_win_get_buf(menu.prev_win), + menu.prev_win + ) + if not bar then + return 0 + end + local _, range = + bar:get_component_at(math.max(0, mouse.wincol - 1)) + return range and range.start or 0 + end, + }, + }) + end + end + + return { + require('dropbar.bar').dropbar_symbol_t:new(symbol), + } +end + +return { get_symbols = get_symbols }