From 53b5a2f34b68875898f0531032fbf090e3952ad7 Mon Sep 17 00:00:00 2001 From: Iron-E <36409591+Iron-E@users.noreply.github.com> Date: Wed, 17 Jul 2024 02:44:17 +0000 Subject: [PATCH] feat: case-insentive sorting (#598) * feat(config): `ignore_case` option * feat(api): provide configured sort case converter in `with_pin_order` This seems like the cleanest way to inject the conversion. We don't know what is applicable to be converted from within the function, and so we can't apply it automatically. On the other hand, if we make this a separate helper function, it will be cumbersome to call it in each sorting function that needs it. I would be open to hearing other ideas, though. * ref(api): use `to_sort_case` in sorting functions where applicable * docs: `sort.ignore_case` * perf(api): use function instead of closure SEE: https://github.com/romgrk/barbar.nvim/pull/598#discussion_r1678639195 --- README.md | 6 ++++++ doc/barbar.txt | 10 ++++++++++ lua/barbar/api.lua | 21 +++++++++++++-------- lua/barbar/config.lua | 5 +++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1bfa33ed..56e7d4a1 100644 --- a/README.md +++ b/README.md @@ -401,6 +401,12 @@ require'barbar'.setup { -- Sets the name of unnamed buffers. By default format is "[Buffer X]" -- where X is the buffer number. But only a static string is accepted here. no_name_title = nil, + + -- sorting options + sort = { + -- tells barbar to ignore case differences while sorting buffers + ignore_case = true, + }, } ``` diff --git a/doc/barbar.txt b/doc/barbar.txt index d1b5ec6f..b0c3b57a 100644 --- a/doc/barbar.txt +++ b/doc/barbar.txt @@ -535,6 +535,16 @@ sidebar_filetypes ~ }} < + *barbar-setup.sort* +sort ~ + Configures the `:BufferOrderBy*` commands. + + *barbar-setup.sort.ignore_case* + sort.ignore_case ~ + `boolean` (default `false`) + If `true`, comparisons of names in buffer orderings will not take into + account differences in case (e.g. 'a' will equal 'A'). + *barbar-setup.tabpages* tabpages ~ `boolean` (default: `true`) diff --git a/lua/barbar/api.lua b/lua/barbar/api.lua index 06f76eed..33ebc49d 100644 --- a/lua/barbar/api.lua +++ b/lua/barbar/api.lua @@ -13,6 +13,7 @@ local command = vim.api.nvim_command --- @type function local get_current_buf = vim.api.nvim_get_current_buf --- @type function local getchar = vim.fn.getchar --- @type function local set_current_buf = vim.api.nvim_set_current_buf --- @type function +local tolower = vim.fn.tolower -- TODO: remove `vim.fs and` after 0.8 release local normalize = vim.fs and vim.fs.normalize @@ -59,9 +60,13 @@ local function notify_buffer_not_found(buffer_number) end --- Forwards some `order_func` after ensuring that all buffers sorted in the order of pinned first. ---- @param order_func fun(bufnr_a: integer, bufnr_b: integer): boolean accepts `(integer, integer)` params. +--- @param order_func fun(bufnr_a: integer, bufnr_b: integer, to_sort_case: fun(s: string): string): boolean accepts `(integer, integer)` params. --- @return fun(bufnr_a: integer, bufnr_b: integer): boolean local function with_pin_order(order_func) + local to_sort_case = config.options.sort.ignore_case and tolower or function(s) + return s + end + return function(a, b) local a_pinned = state.is_pinned(a) local b_pinned = state.is_pinned(b) @@ -71,7 +76,7 @@ local function with_pin_order(order_func) elseif b_pinned and not a_pinned then return false else - return order_func(a, b) + return order_func(a, b, to_sort_case) end end end @@ -364,12 +369,12 @@ end --- Order the buffers by their name --- @return nil function api.order_by_name() - table_sort(state.buffers, with_pin_order(function(a, b) + table_sort(state.buffers, with_pin_order(function(a, b, to_sort_case) local parts_of_a = vim.split(buf_get_name(a), '/') local parts_of_b = vim.split(buf_get_name(b), '/') local name_of_a = parts_of_a[#parts_of_a] local name_of_b = parts_of_b[#parts_of_b] - return name_of_b > name_of_a + return to_sort_case(name_of_b) > to_sort_case(name_of_a) end)) render.update() @@ -378,10 +383,10 @@ end --- Order the buffers by their parent directory. --- @return nil function api.order_by_directory() - table_sort(state.buffers, with_pin_order(function(a, b) + table_sort(state.buffers, with_pin_order(function(a, b, to_sort_case) local name_of_a = buf_get_name(a) local name_of_b = buf_get_name(b) - local compare_a_b = name_of_b > name_of_a + local compare_a_b = to_sort_case(name_of_b) > to_sort_case(name_of_a) -- TODO: remove this block after 0.8 releases if not normalize then @@ -409,8 +414,8 @@ end --- Order the buffers by filetype. --- @return nil function api.order_by_language() - table_sort(state.buffers, with_pin_order(function(a, b) - return buf_get_option(a, 'filetype') < buf_get_option(b, 'filetype') + table_sort(state.buffers, with_pin_order(function(a, b, to_sort_case) + return to_sort_case(buf_get_option(a, 'filetype')) < to_sort_case(buf_get_option(b, 'filetype')) end)) render.update() diff --git a/lua/barbar/config.lua b/lua/barbar/config.lua index 5dffe2a6..c104033d 100644 --- a/lua/barbar/config.lua +++ b/lua/barbar/config.lua @@ -194,6 +194,9 @@ local DEPRECATED_OPTIONS = { --- @field event? string --- @field text? string +--- @class barbar.config.options.sort +--- @field ignore_case boolean + --- @class barbar.config.options --- @field animation boolean --- @field auto_hide integer @@ -216,6 +219,7 @@ local DEPRECATED_OPTIONS = { --- @field no_name_title? string --- @field semantic_letters boolean --- @field sidebar_filetypes {[string]: nil|barbar.config.options.sidebar_filetype} +--- @field sort barbar.config.options.sort --- @field tabpages boolean --- @class barbar.Config @@ -341,6 +345,7 @@ function config.setup(options) preset = 'default', semantic_letters = true, sidebar_filetypes = {}, + sort = { ignore_case = false }, tabpages = true, })