diff --git a/README.md b/README.md index b6b970e..8c0bdb3 100644 --- a/README.md +++ b/README.md @@ -220,9 +220,9 @@ require("oil").setup({ is_always_hidden = function(name, bufnr) return false end, - -- Sort file names in a more intuitive order for humans. Is less performant, - -- so you may want to set to false if you work with large directories. - natural_order = true, + -- Sort file names with numbers in a more intuitive order for humans. + -- Can be "fast", true, or false. "fast" will turn it off for large directories. + natural_order = "fast", -- Sort file and directory names case insensitive case_insensitive = false, sort = { diff --git a/doc/oil.txt b/doc/oil.txt index 44bdcfa..b655206 100644 --- a/doc/oil.txt +++ b/doc/oil.txt @@ -105,9 +105,9 @@ CONFIG *oil-confi is_always_hidden = function(name, bufnr) return false end, - -- Sort file names in a more intuitive order for humans. Is less performant, - -- so you may want to set to false if you work with large directories. - natural_order = true, + -- Sort file names with numbers in a more intuitive order for humans. + -- Can be "fast", true, or false. "fast" will turn it off for large directories. + natural_order = "fast", -- Sort file and directory names case insensitive case_insensitive = false, sort = { diff --git a/lua/oil/columns.lua b/lua/oil/columns.lua index 40b7d74..d882792 100644 --- a/lua/oil/columns.lua +++ b/lua/oil/columns.lua @@ -19,6 +19,7 @@ local all_columns = {} ---@field render_action? fun(action: oil.ChangeAction): string ---@field perform_action? fun(action: oil.ChangeAction, callback: fun(err: nil|string)) ---@field get_sort_value? fun(entry: oil.InternalEntry): number|string +---@field create_sort_value_factory? fun(num_entries: integer): fun(entry: oil.InternalEntry): number|string ---@param name string ---@param column oil.ColumnDefinition @@ -292,18 +293,31 @@ M.register("name", { error("Do not use the name column. It is for sorting only") end, - get_sort_value = function(entry) - local sort_value = entry[FIELD_NAME] - - if config.view_options.natural_order then - sort_value = sort_value:gsub("%d+", pad_number) + create_sort_value_factory = function(num_entries) + if + config.view_options.natural_order == false + or (config.view_options.natural_order == "fast" and num_entries > 5000) + then + if config.view_options.case_insensitive then + return function(entry) + return entry[FIELD_NAME]:lower() + end + else + return function(entry) + return entry[FIELD_NAME] + end + end + else + if config.view_options.case_insensitive then + return function(entry) + return entry[FIELD_NAME]:gsub("%d+", pad_number):lower() + end + else + return function(entry) + return entry[FIELD_NAME]:gsub("%d+", pad_number) + end + end end - - if config.view_options.case_insensitive then - sort_value = sort_value:lower() - end - - return sort_value end, }) diff --git a/lua/oil/config.lua b/lua/oil/config.lua index f203e87..5ced37d 100644 --- a/lua/oil/config.lua +++ b/lua/oil/config.lua @@ -90,9 +90,9 @@ local default_config = { is_always_hidden = function(name, bufnr) return false end, - -- Sort file names in a more intuitive order for humans. Is less performant, - -- so you may want to set to false if you work with large directories. - natural_order = true, + -- Sort file names with numbers in a more intuitive order for humans. + -- Can be "fast", true, or false. "fast" will turn it off for large directories. + natural_order = "fast", -- Sort file and directory names case insensitive case_insensitive = false, sort = { @@ -273,7 +273,7 @@ local M = {} ---@field show_hidden boolean ---@field is_hidden_file fun(name: string, bufnr: integer): boolean ---@field is_always_hidden fun(name: string, bufnr: integer): boolean ----@field natural_order boolean +---@field natural_order boolean|"fast" ---@field case_insensitive boolean ---@field sort oil.SortSpec[] @@ -281,7 +281,7 @@ local M = {} ---@field show_hidden? boolean Show files and directories that start with "." ---@field is_hidden_file? fun(name: string, bufnr: integer): boolean This function defines what is considered a "hidden" file ---@field is_always_hidden? fun(name: string, bufnr: integer): boolean This function defines what will never be shown, even when `show_hidden` is set ----@field natural_order? boolean Sort file names in a more intuitive order for humans. Is less performant, so you may want to set to false if you work with large directories. +---@field natural_order? boolean|"fast" Sort file names with numbers in a more intuitive order for humans. Can be slow for large directories. ---@field case_insensitive? boolean Sort file and directory names case insensitive ---@field sort? oil.SortSpec[] Sort order for the file list diff --git a/lua/oil/view.lua b/lua/oil/view.lua index ddc5db3..8aa8ed7 100644 --- a/lua/oil/view.lua +++ b/lua/oil/view.lua @@ -537,8 +537,9 @@ M.initialize = function(bufnr) end ---@param adapter oil.Adapter +---@param num_entries integer ---@return fun(a: oil.InternalEntry, b: oil.InternalEntry): boolean -local function get_sort_function(adapter) +local function get_sort_function(adapter, num_entries) local idx_funs = {} local sort_config = config.view_options.sort @@ -560,7 +561,9 @@ local function get_sort_function(adapter) ) end local col = columns.get_column(adapter, col_name) - if col and col.get_sort_value then + if col and col.create_sort_value_factory then + table.insert(idx_funs, { col.create_sort_value_factory(num_entries), order }) + elseif col and col.get_sort_value then table.insert(idx_funs, { col.get_sort_value, order }) else vim.notify_once( @@ -611,7 +614,7 @@ local function render_buffer(bufnr, opts) local entries = cache.list_url(bufname) local entry_list = vim.tbl_values(entries) - table.sort(entry_list, get_sort_function(adapter)) + table.sort(entry_list, get_sort_function(adapter, #entry_list)) local jump_idx if opts.jump_first then