From 3bd02437447a835a619306bb509d96839bc63749 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sat, 27 Apr 2024 02:25:55 +0300 Subject: [PATCH 1/2] tabline/bufferline: convert to setupOpts this is pretty much WIP and contains a bunch of bugs that I haven't tackled yet. --- .../tabline/nvim-bufferline/config.nix | 107 +----- .../nvim-bufferline/nvim-bufferline.nix | 318 +++++++++++++++++- 2 files changed, 335 insertions(+), 90 deletions(-) diff --git a/modules/plugins/tabline/nvim-bufferline/config.nix b/modules/plugins/tabline/nvim-bufferline/config.nix index 93b0f58..c52fb49 100644 --- a/modules/plugins/tabline/nvim-bufferline/config.nix +++ b/modules/plugins/tabline/nvim-bufferline/config.nix @@ -6,101 +6,30 @@ inherit (lib.modules) mkIf mkMerge; inherit (lib.nvim.binds) mkLuaBinding mkBinding pushDownDefault; inherit (lib.nvim.dag) entryAnywhere; + inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.tabline.nvimBufferline; self = import ./nvim-bufferline.nix {inherit lib;}; inherit (self.options.vim.tabline.nvimBufferline) mappings; in { - config = mkIf cfg.enable ( - let - mouse = { - right = "'vertical sbuffer %d'"; - close = '' - function(bufnum) - require("bufdelete").bufdelete(bufnum, false) - end - ''; + config = mkIf cfg.enable { + vim = { + startPlugins = [ + (assert config.vim.visuals.nvimWebDevicons.enable; "nvim-bufferline-lua") + "bufdelete-nvim" + ]; + + binds.whichKey.register = pushDownDefault { + "b" = "+Buffer"; + "bm" = "BufferLineMove"; + "bs" = "BufferLineSort"; + "bsi" = "BufferLineSortById"; }; - in { - vim = { - startPlugins = [ - (assert config.vim.visuals.nvimWebDevicons.enable; "nvim-bufferline-lua") - "bufdelete-nvim" - ]; - maps.normal = mkMerge [ - (mkLuaBinding cfg.mappings.closeCurrent "require(\"bufdelete\").bufdelete" mappings.closeCurrent.description) - (mkBinding cfg.mappings.cycleNext ":BufferLineCycleNext" mappings.cycleNext.description) - (mkBinding cfg.mappings.cycleNext ":BufferLineCycleNext" mappings.cycleNext.description) - (mkBinding cfg.mappings.cyclePrevious ":BufferLineCyclePrev" mappings.cyclePrevious.description) - (mkBinding cfg.mappings.pick ":BufferLinePick" mappings.pick.description) - (mkBinding cfg.mappings.sortByExtension ":BufferLineSortByExtension" mappings.sortByExtension.description) - (mkBinding cfg.mappings.sortByDirectory ":BufferLineSortByDirectory" mappings.sortByDirectory.description) - (mkLuaBinding cfg.mappings.sortById "function() require(\"bufferline\").sort_buffers_by(function (buf_a, buf_b) return buf_a.id < buf_b.id end) end" mappings.sortById.description) - (mkBinding cfg.mappings.moveNext ":BufferLineMoveNext" mappings.moveNext.description) - (mkBinding cfg.mappings.movePrevious ":BufferLineMovePrev" mappings.movePrevious.description) - ]; - - binds.whichKey.register = pushDownDefault { - "b" = "+Buffer"; - "bm" = "BufferLineMove"; - "bs" = "BufferLineSort"; - "bsi" = "BufferLineSortById"; - }; - - luaConfigRC.nvimBufferline = entryAnywhere '' - require("bufferline").setup{ - options = { - mode = "buffers", - numbers = "both", - close_command = ${mouse.close}, - right_mouse_command = ${mouse.right}, - indicator = { - style = 'icon', - indicator_icon = '▎', - }, - buffer_close_icon = '󰅖', - modified_icon = '●', - close_icon = '', - left_trunc_marker = '', - right_trunc_marker = '', - max_name_length = 18, - max_prefix_length = 15, - tab_size = 18, - show_buffer_icons = true, - show_buffer_close_icons = true, - show_close_icon = true, - show_tab_indicators = true, - persist_buffer_sort = true, - --separator_style = "thin", - separator_style = { " ", " " }, - enforce_regular_tabs = true, - always_show_bufferline = true, - offsets = { - {filetype = "NvimTree", text = "File Explorer", text_align = "center"} - }, - sort_by = 'extension', - diagnostics = "nvim_lsp", -- TODO: use coc if it's enabled - diagnostics_update_in_insert = true, - diagnostics_indicator = function(count, level, diagnostics_dict, context) - local s = "" - for e, n in pairs(diagnostics_dict) do - local sym = e == "error" and "" - or (e == "warning" and "" or "" ) - if(sym ~= "") then - s = s .. " " .. n .. sym - end - end - return s - end, - numbers = function(opts) - return string.format('%s·%s', opts.raise(opts.id), opts.lower(opts.ordinal)) - end, - } - } - ''; - }; - } - ); + luaConfigRC.nvimBufferline = entryAnywhere '' + require("bufferline").setup({options = ${toLuaObject cfg.setupOpts}}) + ''; + }; + }; } diff --git a/modules/plugins/tabline/nvim-bufferline/nvim-bufferline.nix b/modules/plugins/tabline/nvim-bufferline/nvim-bufferline.nix index 6e2b87e..cc3f90f 100644 --- a/modules/plugins/tabline/nvim-bufferline/nvim-bufferline.nix +++ b/modules/plugins/tabline/nvim-bufferline/nvim-bufferline.nix @@ -1,6 +1,8 @@ {lib, ...}: let - inherit (lib.options) mkEnableOption; + inherit (lib.options) mkOption mkEnableOption literalExpression; + inherit (lib.types) enum bool either nullOr str int listOf; inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; in { options.vim.tabline.nvimBufferline = { enable = mkEnableOption "neovim bufferline"; @@ -16,5 +18,319 @@ in { moveNext = mkMappingOption "Move next buffer" "bmn"; movePrevious = mkMappingOption "Move previous buffer" "bmp"; }; + + setupOpts = mkPluginSetupOption "Bufferline-nvim" { + mode = mkOption { + type = enum ["tabs" "buffers"]; + default = "tabs"; + description = "Mode to use for bufferline"; + }; + + themable = mkOption { + type = bool; + default = true; + description = '' + Whether or not highlight groups to be overriden. + + While false, bufferline.nvim sets highlights as default + ''; + }; + + numbers = mkOption { + type = either (enum ["none" "ordinal" "buffer_id" "both"]) luaInline; + default = lib.generators.mkLuaInline '' + function(opts) + return string.format('%s·%s', opts.raise(opts.id), opts.lower(opts.ordinal)) + end + ''; + description = "Whether or not to show buffer numbers"; + }; + + close_command = mkOption { + type = either str luaInline; + default = lib.generators.mkLuaInline '' + function(bufnum) + require("bufdelete").bufdelete(bufnum, false) + end + ''; + description = "Command to run when closing a buffer"; + }; + + right_mouse_command = mkOption { + type = nullOr (either str luaInline); + default = "vertical sbuffer %d"; + description = "Command to run when right clicking a buffer"; + }; + + middle_mouse_command = mkOption { + type = nullOr (either str luaInline); + default = null; + description = "Command to run when middle clicking a buffer"; + }; + + indicator = { + icon = mkOption { + type = nullOr str; + default = null; + description = '' + The indicatotor icon to use for current buffer. + + ::: {.warning} + This **must** be ommitted while style is not `icon` + ::: + ''; + }; + + style = mkOption { + type = enum ["icon" "underline" "none"]; + default = "underline"; + description = "Style for indicator"; + }; + }; + + buffer_close_icon = mkOption { + type = str; + default = " 󰅖 "; + description = "Icon for close button"; + }; + + modified_icon = mkOption { + type = str; + default = "● "; + description = "Icon for modified buffer"; + }; + + close_icon = mkOption { + type = str; + default = "  "; + description = "Icon for close button"; + }; + + left_trunc_marker = mkOption { + type = str; + default = ""; + description = "Icon for left truncation"; + }; + + right_trunc_marker = mkOption { + type = str; + default = ""; + description = "Icon for right truncation"; + }; + + name_formatter = mkOption { + type = nullOr luaInline; + default = null; + description = '' + `name_formatter` can be used to change the buffer's label in the + bufferline. + + ::: {.note} + Some names can/will break the bufferline so use this at your + discretion knowing that it has some limitations that will + **NOT** be fixed. + ::: + ''; + }; + + max_name_length = mkOption { + type = int; + default = 18; + description = "Max name length"; + }; + + max_prefix_length = mkOption { + type = int; + default = 15; + description = "Length of prefix used when a buffer is de-duplicated"; + }; + + truncate_names = mkOption { + type = bool; + default = true; + description = "Truncate names"; + }; + + diagnostics = mkOption { + type = enum [false "nvim_lsp" "coc"]; + default = "nvim_lsp"; + description = "Diagnostics provider to be used in buffer LSP indicators"; + }; + + diagnostics_update_in_insert = mkOption { + type = bool; + default = false; + description = '' + Whether to update diagnostics while in insert mode. + + Setting this to true has performance implications, but they may be + negligible depending on your setup. Set it to true if you know what + you are doing. + ''; + }; + + diagnostics_indicator = mkOption { + type = nullOr luaInline; + default = lib.generators.mkLuaInline '' + function(count, level, diagnostics_dict, context) + local s = " " + for e, n in pairs(diagnostics_dict) do + local sym = e == "error" and "  " + or (e == "warning" and "  " or "  " ) + s = s .. n .. sym + end + return s + end + ''; + + description = '' + Function to get the diagnostics indicator. + The function should return a string to be used as the indicator. + + Can be set to nil to keep the buffer name highlight, but delete the + highlighting. + ''; + }; + + custom_filter = mkOption { + type = nullOr luaInline; + default = null; + example = literalExpression lib.generators.mkLuaInline '' + custom_filter = function(buf_number, buf_numbers) + -- filter out filetypes you don't want to see + if vim.bo[buf_number].filetype ~= "" then + return true + end + -- filter out by buffer name + if vim.fn.bufname(buf_number) ~= "" then + return true + end + -- filter out based on arbitrary rules + -- e.g. filter out vim wiki buffer from tabline in your work repo + if vim.fn.getcwd() == "" and vim.bo[buf_number].filetype ~= "wiki" then + return true + end + -- filter out by it's index number in list (don't show first buffer) + if buf_numbers[1] ~= buf_number then + return true + end + end + ''; + + description = '' + Custom filter function for filtering out buffers. + + ::: {.note} + This will be called a lot, so you are encouraged to keep it as + short and lightweight as possible unless you are fully aware + of the performance implications. + ::: + ''; + }; + + color_icons = mkOption { + type = bool; + default = true; + description = "Whether or not to add filetype icon highlights"; + }; + + show_buffer_icons = mkOption { + type = bool; + default = true; + description = "Whether or not to show buffer icons"; + }; + + show_buffer_close_icons = mkOption { + type = bool; + default = true; + description = "Whether or not to show buffer close icons"; + }; + + show_close_icon = mkOption { + type = bool; + default = true; + description = "Whether or not to show close icon"; + }; + + show_tab_indicators = mkOption { + type = bool; + default = true; + description = "Whether or not to show tab indicators"; + }; + + show_duplicate_prefix = mkOption { + type = bool; + default = true; + description = "Whether or not to show duplicate prefix"; + }; + + duplicates_across_groups = mkOption { + type = bool; + default = true; + description = "Whether to consider duplicate paths in different groups as duplicates"; + }; + + persist_buffer_sort = mkOption { + type = bool; + default = true; + description = "Whether or not custom sorted buffers should persist"; + }; + + move_wraps_at_ends = mkOption { + type = bool; + default = false; + description = "Whether or not the move command \"wraps\" at the first or last position"; + }; + + seperator_style = mkOption { + type = either (enum ["thick" "thin" "slope" "slant"]) (listOf str); + default = [" " " "]; + description = '' + Style of the buffer separator. + + Can be either one of the suspported values, or a list containing + **at most** two elements for `focused` and `unfocused` respectively. + ''; + }; + + enforce_regular_tabs = mkOption { + type = bool; + default = false; + description = "Whether to enforce regular tabs"; + }; + + always_show_bufferline = mkOption { + type = bool; + default = true; + description = "Whether to always show bufferline"; + }; + + auto_toggle_bufferline = mkOption { + type = bool; + default = false; + description = "Whether to auto toggle bufferline"; + }; + + hover = { + enabled = mkEnableOption "hover" // {default = true;}; + delay = mkOption { + type = int; + default = 200; + description = "Delay for hover, in ms"; + }; + + reveal = mkOption { + type = listOf str; + default = ["close"]; + description = "Reveal hover window"; + }; + }; + + sort_by = mkOption { + type = either (enum ["insert_after_current" "insert_at_end" "id" "extension" "relative_directory" "directory" "tabs"]) luaInline; + default = "extension"; + description = "Method to sort buffers by. Must be one of the supported valuees, or an inline Lua value."; + }; + }; }; } From 852c862f050bc84c3cace444216c22cd48d972c6 Mon Sep 17 00:00:00 2001 From: Frothy <76622149+FrothyMarrow@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:25:44 -0400 Subject: [PATCH 2/2] lib: avoid filtering null values to be used as nil --- lib/lua.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/lua.nix b/lib/lua.nix index 0ed2505..9f081e8 100644 --- a/lib/lua.nix +++ b/lib/lua.nix @@ -77,8 +77,7 @@ in rec { else "[${toLuaObject n}] = " + (toLuaObject v)) (filterAttrs ( - _: v: - (v != null) && (toLuaObject v != "{}") + _: v: (toLuaObject v != "{}") ) args))) + "}"