diff --git a/lua/oil/columns.lua b/lua/oil/columns.lua index 7e217afa..97d5e3c9 100644 --- a/lua/oil/columns.lua +++ b/lua/oil/columns.lua @@ -279,6 +279,10 @@ M.register("type", { end, }) +local function pad_number(int) + return string.format("%012d", int) +end + M.register("name", { render = function(entry, conf) error("Do not use the name column. It is for sorting only") @@ -289,7 +293,11 @@ M.register("name", { end, get_sort_value = function(entry) - return entry[FIELD_NAME] + if config.view_options.natural_order then + return entry[FIELD_NAME]:gsub("%d+", pad_number) + else + return entry[FIELD_NAME] + end end, }) diff --git a/lua/oil/config.lua b/lua/oil/config.lua index 8753903f..b3683873 100644 --- a/lua/oil/config.lua +++ b/lua/oil/config.lua @@ -90,6 +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 = { -- sort order can be "asc" or "desc" -- see :help oil-columns to see which columns are sortable diff --git a/lua/oil/view.lua b/lua/oil/view.lua index 72d5e947..a5032eed 100644 --- a/lua/oil/view.lua +++ b/lua/oil/view.lua @@ -515,37 +515,18 @@ M.initialize = function(bufnr) keymap_util.set_keymaps(config.keymaps, bufnr) end ---- Compare two strings while also treating multi-digit integers atomically ----@param a_val string ----@param b_val string ----@param order string ----@return boolean -local function natural_sort_compare(a_val, b_val, order) - ---This method pads integers with zeroes so that they are always 12 digits long. - ---As a result, comparing strings that have integers of different sizes work - ---as if we were comparing integers (instead of strings of integers) - --- - ---Note: if the file name has integers of more than 12 digits, this padding does not work - ---@param int integer - local function pad_to_compare(int) - return string.format("%012d", int) - end - - local a_val_padded = string.gsub(a_val, "%d+", pad_to_compare) - local b_val_padded = string.gsub(b_val, "%d+", pad_to_compare) - - if order == "desc" then - return a_val_padded > b_val_padded - else - return a_val_padded < b_val_padded - end -end - ---@param adapter oil.Adapter ---@return fun(a: oil.InternalEntry, b: oil.InternalEntry): boolean local function get_sort_function(adapter) local idx_funs = {} - for _, sort_pair in ipairs(config.view_options.sort) do + local sort_config = config.view_options.sort + + -- If empty, default to type + name sorting + if vim.tbl_isempty(sort_config) then + sort_config = { { "type", "asc" }, { "name", "asc" } } + end + + for _, sort_pair in ipairs(sort_config) do local col_name, order = unpack(sort_pair) if order ~= "asc" and order ~= "desc" then vim.notify_once( @@ -573,7 +554,11 @@ local function get_sort_function(adapter) local a_val = get_sort_value(a) local b_val = get_sort_value(b) if a_val ~= b_val then - return natural_sort_compare(a_val, b_val, order) + if order == "desc" then + return a_val > b_val + else + return a_val < b_val + end end end return a[FIELD_NAME] < b[FIELD_NAME]