Skip to content

BUG: Custom Sort always called with a {type="Dir", path="foo"} argument #1226

@FalcoGer

Description

@FalcoGer

Did you check docs and existing issues?

  • I have read all the docs.
  • I have searched the existing issues.
  • I have searched the existing discussions.

Neovim Version (nvim -v)

NVIM v0.10.0-dev-e59cf3b3a

Operating System / Version

Ubuntu Mate 22.04

Describe the Bug

When using a custom sorting function, it is always called at least once with an object that doesn't actually exist. The object looks like

local fooObj = {
  type = "Dir",
  path = "foo"
}

This is a problem because one needs to filter out this object from their search, because sorting by another field like name causes a lua error to occur, because the erroneous foo object doesn't have such other fields that one might want to sort by.

Screenshots, Traceback

No response

Steps to Reproduce

  1. Use this sort function
-- Sort function for files
local sortFunc = function(a, b)
    -- keys of a and b
    -- not documented anywhere
    --   parent_path:           full, absolute path of parent directory
    --   type:                  "directory" (even for links), or "file"
    --   path:                  full, absolute path, no trailing slash
    --   name:                  file name
    --   is_link                bool is a symlink
    --   is_reveal_target       bool ??
    --   link_to                full, absolute path to link target
    --   loaded                 bool if file is loaded in editor
    --   id                     seems to be same as path
    --   children               type of a/b table, directories only
    --   exts                   file extension  ??, files only
    --   ext                    file extension  ??, filey only
    --   name_lcase             name, but lowercase, files only?

    if a.name == nil then
        local s = ""
        if a ~= nil and type(a) == 'table' then
            for k, v in pairs(a) do
                s = s .. '[' .. k .. '] = ' .. tostring(v) .. ' , '
            end
        else
            s = s .. tostring(a)
        end
        print(s)
        return false
    end

    if b.name == nil then
        local s = ""
        if b ~= nil and type(b) == 'table' then
            for k, v in pairs(b) do
                s = s .. '[' .. k .. '] = ' .. tostring(v) .. ' , '
            end
        else
            s = s .. tostring(b)
        end
        print(s)
        return true
    end

    if a.type == "directory" and b.type ~= "directory" then
         -- directories first
        return true
    end
    if b.type == "directory" and a.type ~= "directory" then
        -- directories first
        return false
    end

    if a.name:sub(1, 1) == '.' and b.name:sub(1, 1) ~= '.' then
        -- dotfiles last
        return false
    end
    if b.name:sub(1, 1) == '.' and a.name:sub(1, 1) ~= '.' then
        -- dotfiles last
        return true
    end
    -- otherwise just sort by name, case insensitive
    return a.name:upper() < b.name:upper()
end
  1. Open :Neotree
  2. Observe output from print

Expected Behavior

Every item has a field "name"
Documentation on what the sort function's arguments are is available in :h neo-tree

Your Configuration

-

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentationhow-towontfixThis will not be worked on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions