From 504d2ff50017764e8bb1bc31faa092cdeacab013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ot=C3=A1vio=20Schwanck=20dos=20Santos?= Date: Thu, 16 Feb 2023 16:24:00 +0000 Subject: [PATCH 1/7] fix(groups): refresh the UI when a group is closed (#682) --- .github/workflows/formatting.yaml | 2 +- .github/workflows/test.yaml | 12 ++++-------- lua/bufferline.lua | 1 + tests/init.lua | 9 +++++++++ tests/minimal_init.vim | 8 -------- 5 files changed, 15 insertions(+), 17 deletions(-) create mode 100644 tests/init.lua delete mode 100644 tests/minimal_init.vim diff --git a/.github/workflows/formatting.yaml b/.github/workflows/formatting.yaml index c06ee5ad..843fda76 100644 --- a/.github/workflows/formatting.yaml +++ b/.github/workflows/formatting.yaml @@ -1,4 +1,4 @@ -name: stylua +name: Formatting on: push: branches: ["main"] diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d3a4fbb6..47a33a27 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,10 +1,9 @@ --- -name: Run tests +name: Tests on: pull_request: ~ push: paths-ignore: - - ".github/**" - "*.md" branches: - main @@ -30,9 +29,6 @@ jobs: - name: Run tests run: | - test -d build/neovim/v0.7.0 || { - mkdir -p build/neovim/v0.7.0 - curl -Lo build/neovim/v0.7.0/nvim https://github.com/neovim/neovim/releases/download/v0.7.0/nvim.appimage - chmod +x build/neovim/v0.7.0/nvim - } - build/neovim/v0.7.0/nvim --headless --noplugin -u tests/minimal_init.vim -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/minimal_init.vim'}" + nvim --version + [ ! -d tests ] && exit 0 + nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua', sequential = true}" diff --git a/lua/bufferline.lua b/lua/bufferline.lua index 0be6bb02..e251b597 100644 --- a/lua/bufferline.lua +++ b/lua/bufferline.lua @@ -133,6 +133,7 @@ function M.group_action(name, action) assert(name, "A name must be passed to execute a group action") if action == "close" then groups.command(name, function(b) api.nvim_buf_delete(b.id, { force = true }) end) + ui.refresh() elseif action == "toggle" then groups.toggle_hidden(nil, name) ui.refresh() diff --git a/tests/init.lua b/tests/init.lua new file mode 100644 index 00000000..166a7d01 --- /dev/null +++ b/tests/init.lua @@ -0,0 +1,9 @@ +vim.opt.rtp:append({ + ".", + "../plenary.nvim", + "../nvim-web-devicons", +}) + +vim.cmd([[runtime! plugin/plenary.vim]]) +vim.o.swapfile = false +_G.__TEST = true diff --git a/tests/minimal_init.vim b/tests/minimal_init.vim deleted file mode 100644 index 853361e8..00000000 --- a/tests/minimal_init.vim +++ /dev/null @@ -1,8 +0,0 @@ -set rtp+=. -set rtp+=../plenary.nvim -set rtp+=../nvim-web-devicons -runtime! plugin/plenary.vim -set noswapfile -lua << EOF -_G.__TEST = true -EOF From f9239e4dce203256a0e7416d54ca606f7481ac07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ot=C3=A1vio=20Schwanck=20dos=20Santos?= Date: Thu, 16 Feb 2023 16:30:33 +0000 Subject: [PATCH 2/7] fix(group): check that group exists before operating on it (#681) --- lua/bufferline/groups.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lua/bufferline/groups.lua b/lua/bufferline/groups.lua index 2dc62783..c95cfae4 100644 --- a/lua/bufferline/groups.lua +++ b/lua/bufferline/groups.lua @@ -301,6 +301,11 @@ function M.command(group_name, callback) function(list) return list.name == group_name end, state.components_by_group ) + + if not group then + return + end + utils.for_each(callback, group) end From e0aa1fd8323609d9c7617b3d54e27236dea43741 Mon Sep 17 00:00:00 2001 From: FISH UP <68397336+MisterFISHUP@users.noreply.github.com> Date: Fri, 17 Feb 2023 15:41:41 +0100 Subject: [PATCH 3/7] feat: allow moving buffers to arbitrary positions (#675) --- doc/bufferline.txt | 4 ++++ lua/bufferline.lua | 1 + lua/bufferline/commands.lua | 17 +++++++++++++---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/doc/bufferline.txt b/doc/bufferline.txt index af975244..255b4a32 100644 --- a/doc/bufferline.txt +++ b/doc/bufferline.txt @@ -697,6 +697,10 @@ A few of this plugins commands can be mapped for ease of use. > nnoremap :BufferLineMoveNext nnoremap :BufferLineMovePrev + " These commands will move the current buffer to the first or the last position in the bufferline + nnoremap :lua require'bufferline'.move_to(1) + nnoremap :lua require'bufferline'.move_to(-1) + " These commands will sort buffers by directory, language, or a custom criteria nnoremap be :BufferLineSortByExtension nnoremap bd :BufferLineSortByDirectory diff --git a/lua/bufferline.lua b/lua/bufferline.lua index e251b597..e1b7973d 100644 --- a/lua/bufferline.lua +++ b/lua/bufferline.lua @@ -35,6 +35,7 @@ local BUFFERLINE_GROUP = "BufferlineCmds" local M = { move = commands.move, + move_to = commands.move_to, exec = commands.exec, go_to = commands.go_to, cycle = commands.cycle, diff --git a/lua/bufferline/commands.lua b/lua/bufferline/commands.lua index 0f1cfafc..3bed2e8c 100644 --- a/lua/bufferline/commands.lua +++ b/lua/bufferline/commands.lua @@ -149,11 +149,14 @@ function M.get_current_element_index(current_state, opts) end end ---- @param direction number -function M.move(direction) - local index = M.get_current_element_index(state) +--- Move the buffer at index `from_index` (or current index if not specified) to position `to_index` +--- @param to_index number negative indices are accepted (counting from the right instead of the left, e.g. -1 for the last position, -2 for the second-last, etc.) +--- @param from_index number? +function M.move_to(to_index, from_index) + local index = from_index or M.get_current_element_index(state) if not index then return utils.notify("Unable to find buffer to move, sorry", "warn") end - local next_index = index + direction + -- Calculate next index depending on the sign of `to_index` + local next_index = to_index > 0 and to_index or #state.components + 1 + to_index if next_index >= 1 and next_index <= #state.components then local item = state.components[index] local destination_buf = state.components[next_index] @@ -166,6 +169,12 @@ function M.move(direction) end end +--- @param direction number +function M.move(direction) + local index = M.get_current_element_index(state) + M.move_to(index + direction, index) +end + function M.cycle(direction) if vim.opt.showtabline == 0 then if direction > 0 then vim.cmd("bnext") end From dea64b9ed5b709bbf75b5e952badab78fe697bf1 Mon Sep 17 00:00:00 2001 From: Akin Sowemimo <22454918+akinsho@users.noreply.github.com> Date: Mon, 20 Feb 2023 09:36:05 +0000 Subject: [PATCH 4/7] refactor(tests)!: load dependencies in init.lua This moves away from adding dependencies in the ci workflow and instead adds and loads them locally, this allows these to be loaded locally in testing using lazy.nvim --- .github/workflows/test.yaml | 6 ------ .gitignore | 3 ++- tests/bufferline_spec.lua | 12 ++++------- tests/init.lua | 43 +++++++++++++++++++++++++++++++------ 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 47a33a27..0281fd8a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,12 +21,6 @@ jobs: wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.deb -O /tmp/nvim.deb sudo dpkg -i /tmp/nvim.deb - - name: Fetch dependencies - run: | - git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim - git clone --depth 1 https://github.com/kyazdani42/nvim-web-devicons ~/.local/share/nvim/site/pack/vendor/start/nvim-web-devicons - ln -s $(pwd) ~/.local/share/nvim/site/pack/vendor/start - - name: Run tests run: | nvim --version diff --git a/.gitignore b/.gitignore index 7c8b5ac4..5e4727e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .luacheckcache -/screenshots/ +screenshots/ +.tests/ diff --git a/tests/bufferline_spec.lua b/tests/bufferline_spec.lua index ff5664ad..9f5ea4e7 100644 --- a/tests/bufferline_spec.lua +++ b/tests/bufferline_spec.lua @@ -196,10 +196,8 @@ describe("Bufferline tests:", function() it("should close buffers to the right of the current buffer", function() bufferline.setup({ options = { - close_command = function(bufid) - vim.api.nvim_buf_delete(bufid, { force = true }) - end - } + close_command = function(bufid) vim.api.nvim_buf_delete(bufid, { force = true }) end, + }, }) vim.cmd("file! a.txt") vim.cmd("edit b.txt") @@ -217,10 +215,8 @@ describe("Bufferline tests:", function() it("should close buffers to the left of the current buffer", function() bufferline.setup({ options = { - close_command = function(bufid) - vim.api.nvim_buf_delete(bufid, { force = true }) - end - } + close_command = function(bufid) vim.api.nvim_buf_delete(bufid, { force = true }) end, + }, }) vim.cmd("edit! a.txt") vim.cmd("edit b.txt") diff --git a/tests/init.lua b/tests/init.lua index 166a7d01..f65787c5 100644 --- a/tests/init.lua +++ b/tests/init.lua @@ -1,9 +1,40 @@ -vim.opt.rtp:append({ - ".", - "../plenary.nvim", - "../nvim-web-devicons", -}) +local M = {} + +function M.root(root) + local f = debug.getinfo(1, "S").source:sub(2) + return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "") +end + +---@param plugin string +function M.load(plugin) + local name = plugin:match(".*/(.*)") + local package_root = M.root(".tests/site/pack/deps/start/") + if not vim.loop.fs_stat(package_root .. name) then + print("Installing " .. plugin) + vim.fn.mkdir(package_root, "p") + vim.fn.system({ + "git", + "clone", + "--depth=1", + "https://github.com/" .. plugin .. ".git", + package_root .. "/" .. name, + }) + end +end + +function M.setup() + vim.cmd([[set runtimepath=$VIMRUNTIME]]) + vim.opt.runtimepath:append(M.root()) + vim.opt.packpath = { M.root(".tests/site") } + M.load("nvim-lua/plenary.nvim") + M.load("nvim-tree/nvim-web-devicons") + vim.env.XDG_CONFIG_HOME = M.root(".tests/config") + vim.env.XDG_DATA_HOME = M.root(".tests/data") + vim.env.XDG_STATE_HOME = M.root(".tests/state") + vim.env.XDG_CACHE_HOME = M.root(".tests/cache") +end -vim.cmd([[runtime! plugin/plenary.vim]]) vim.o.swapfile = false _G.__TEST = true + +M.setup() From 9d95a6de91d83a7dd8559d2897082e89a85d5814 Mon Sep 17 00:00:00 2001 From: Akin <22454918+akinsho@users.noreply.github.com> Date: Mon, 20 Feb 2023 10:15:56 +0000 Subject: [PATCH 5/7] feat(icons): add `get_element_icon` option (#686) Co-authored-by: Camilo Romero --- doc/bufferline.txt | 11 +++++++++++ lua/bufferline/config.lua | 9 +++++---- lua/bufferline/utils/init.lua | 28 +++++++++++----------------- tests/bufferline_spec.lua | 13 +++++++++++++ 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/doc/bufferline.txt b/doc/bufferline.txt index 255b4a32..1b101c33 100644 --- a/doc/bufferline.txt +++ b/doc/bufferline.txt @@ -130,6 +130,17 @@ The available configuration are: } }, color_icons = true | false, -- whether or not to add the filetype icon highlights + get_element_icon = function(element) + -- element consists of {filetype: string, path: string, extension: string, directory: string} + -- This can be used to change how bufferline fetches the icon + -- for an element e.g. a buffer or a tab. + -- e.g. + local icon, hl = require('nvim-web-devicons').get_icon_by_filetype(opts.filetype, { default = false }) + return icon, hl + -- or + local custom_map = {my_thing_ft: {icon = "my_thing_icon", hl}} + return custom_map[element.filetype] + end, show_buffer_icons = true | false, -- disable filetype icons for buffers show_buffer_close_icons = true | false, show_buffer_default_icon = true | false, -- whether or not an unrecognised filetype should show a default icon diff --git a/lua/bufferline/config.lua b/lua/bufferline/config.lua index fb6780c8..41b5b9a6 100644 --- a/lua/bufferline/config.lua +++ b/lua/bufferline/config.lua @@ -32,10 +32,8 @@ local constants = lazy.require("bufferline.constants") ---@alias DiagnosticIndicator fun(count: number, level: number, errors: table, ctx: table): string ----@class HoverOptions ----@field reveal string[] ----@field delay integer ----@field enabled boolean +---@alias HoverOptions {reveal: string[], delay: integer, enabled: boolean} +---@alias IconFetcherOpts {directory: boolean, path: string, extension: string, filetype: string?} ---@class BufferlineOptions ---@field public mode BufferlineMode @@ -62,6 +60,7 @@ local constants = lazy.require("bufferline.constants") ---@field public show_buffer_icons boolean ---@field public show_buffer_close_icons boolean ---@field public show_buffer_default_icon boolean +---@field public get_element_icon fun(opts: IconFetcherOpts): string?, string? ---@field public show_close_icon boolean ---@field public show_tab_indicators boolean ---@field public show_duplicate_prefix boolean @@ -729,6 +728,8 @@ local function get_defaults() color_icons = true, show_buffer_icons = true, show_buffer_close_icons = true, + get_element_icon = nil, + ---@deprecated show_buffer_default_icon = true, show_close_icon = true, show_tab_indicators = true, diff --git a/lua/bufferline/utils/init.lua b/lua/bufferline/utils/init.lua index b34b92af..6e44e8bc 100644 --- a/lua/bufferline/utils/init.lua +++ b/lua/bufferline/utils/init.lua @@ -159,17 +159,17 @@ function M.notify(msg, level, opts) vim.schedule(function() vim.notify(msg, level, nopts) end) end ----@class GetIconOpts ----@field directory boolean ----@field path string ----@field extension string ----@field filetype string? - ---Get an icon for a filetype using either nvim-web-devicons or vim-devicons ---if using the lua plugin this also returns the icon's highlights ----@param opts GetIconOpts +---@param opts IconFetcherOpts ---@return string, string? function M.get_icon(opts) + local user_func = config.options.get_element_icon + if user_func and vim.is_callable(user_func) then + local icon, hl = user_func(opts) + if icon then return icon, hl end + end + local loaded, webdev_icons = pcall(require, "nvim-web-devicons") if opts.directory then local hl = loaded and "DevIconDefault" or nil @@ -184,18 +184,12 @@ function M.get_icon(opts) end if type == "terminal" then return webdev_icons.get_icon(type) end + --- TODO: Deprecate this option local use_default = config.options.show_buffer_default_icon - local icon, hl - if M.is_truthy(opts.filetype) then - -- Don't use a default here so that we fall through to the next case if no icon is found - icon, hl = webdev_icons.get_icon_by_filetype(opts.filetype, { default = false }) - end - if not icon then - icon, hl = webdev_icons.get_icon(fn.fnamemodify(opts.path, ":t"), opts.extension, { - default = use_default, - }) - end + local icon, hl = webdev_icons.get_icon(fn.fnamemodify(opts.path, ":t"), opts.extension, { + default = use_default, + }) if not icon then return "", "" end return icon, hl diff --git a/tests/bufferline_spec.lua b/tests/bufferline_spec.lua index 9f5ea4e7..e421621c 100644 --- a/tests/bufferline_spec.lua +++ b/tests/bufferline_spec.lua @@ -53,6 +53,19 @@ describe("Bufferline tests:", function() assert.is_truthy(tabline:match(icon)) end) + it("should allow specifying how icons are fetched", function() + local icon = "Q" + bufferline.setup({ + options = { + get_element_icon = function() return icon end, + }, + }) + vim.cmd("edit test.txt") + local tabline = nvim_bufferline() + assert.truthy(tabline) + assert.is_truthy(tabline:match(icon)) + end) + it("should allow formatting names", function() bufferline.setup({ options = { From 6837ad30bdae5dfb812d5d6114f33d273fd4a66f Mon Sep 17 00:00:00 2001 From: "Taaqif Peck (Tye)" Date: Mon, 20 Feb 2023 20:58:26 +0800 Subject: [PATCH 6/7] Feature: add slope separator (#659) --- doc/bufferline.txt | 3 ++- lua/bufferline/constants.lua | 2 ++ lua/bufferline/ui.lua | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/bufferline.txt b/doc/bufferline.txt index 1b101c33..9157d236 100644 --- a/doc/bufferline.txt +++ b/doc/bufferline.txt @@ -150,7 +150,7 @@ The available configuration are: persist_buffer_sort = true, -- whether or not custom sorted buffers should persist -- can also be a table containing 2 custom separators -- [focused and unfocused]. eg: { '|', '|' } - separator_style = "slant" | "thick" | "thin" | { 'any', 'any' }, + separator_style = "slant" | "slope" | "thick" | "thin" | { 'any', 'any' }, enforce_regular_tabs = false | true, always_show_bufferline = true | false, hover = { @@ -194,6 +194,7 @@ You can change the appearance of the bufferline separators by setting the * `slant` - Use slanted/triangular separators * `padded_slant` - Same as `slant` but with extra padding which some terminals require. If `slant` does not render correctly for you try padded this instead. +* `slope` - Use slanted/triangular separators but slopped to the right * `thick` - Increase the thickness of the separator characters * `thin` - (default) Use thin separator characters * finally you can pass in a custom list containing 2 characters which will be diff --git a/lua/bufferline/constants.lua b/lua/bufferline/constants.lua index be5ccf58..49a94a88 100644 --- a/lua/bufferline/constants.lua +++ b/lua/bufferline/constants.lua @@ -10,6 +10,7 @@ M.sep_names = { thin = "thin", thick = "thick", slant = "slant", + slope = "slope", padded_slant = "padded_slant", } @@ -18,6 +19,7 @@ M.sep_chars = { [M.sep_names.thin] = { "▏", "▕" }, [M.sep_names.thick] = { "▌", "▐" }, [M.sep_names.slant] = { "", "" }, + [M.sep_names.slope] = { "", "" }, [M.sep_names.padded_slant] = { "" .. M.padding, "" .. M.padding }, } diff --git a/lua/bufferline/ui.lua b/lua/bufferline/ui.lua index 9d48b97d..b3d86aad 100644 --- a/lua/bufferline/ui.lua +++ b/lua/bufferline/ui.lua @@ -271,7 +271,7 @@ end ---@param style string ---@return boolean local function is_slant(style) - return vim.tbl_contains({ sep_names.slant, sep_names.padded_slant }, style) + return vim.tbl_contains({ sep_names.slant, sep_names.padded_slant, sep_names.slope}, style) end --- "▍" "░" From 7d19acf40506cec66020e6285fb81d3440af0c18 Mon Sep 17 00:00:00 2001 From: Akin Sowemimo <22454918+akinsho@users.noreply.github.com> Date: Mon, 20 Feb 2023 13:03:28 +0000 Subject: [PATCH 7/7] docs(README): add image of slope styling --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 96f77235..9dc81d0a 100644 --- a/README.md +++ b/README.md @@ -104,11 +104,17 @@ for more details on how to configure this plugin in details please see `:h buffe #### Alternate styling +##### Slanted tabs + ![slanted tabs](https://user-images.githubusercontent.com/22454918/111992989-fec39b80-8b0d-11eb-851b-010641196a04.png) **NOTE**: some terminals require special characters to be padded so set the style to `padded_slant` if the appearance isn't right in your terminal emulator. Please keep in mind though that results may vary depending on your terminal emulator of choice and this style might will not work for all terminals +##### Sloped tabs + +![sloped tabs](https://user-images.githubusercontent.com/22454918/220115787-0ba2264f-1cf5-4f18-a322-7c7cfa3d8f42.png) + see: `:h bufferline-styling` ---