Search code examples
luaneovim

How to get all files and directories within the current working directory of Neovim using Lua?


Given a file that is open for editing within Neovim, how can one return all files and directories within the current working directory (CWD) of that open file?

The intended use case is to have a key-mapping set that has a callback to a function that checks whether a current file or directory exists within the CWD. I am trying to write such a function. In the pseudo-code shown further below, I have called it existsInCWD.

Scenario

For example, the key-map in the mappings.lua file

vim.keymap.set({'n'}, '<A-f>', '',
    { 
        desc = "Check if 'figures' directory exists",
        callback = function()
            local figuresDirExists = existsInCWD("figures")
            if figuresDirExists then
                print("Figure directory exists.")
            else
                print("Figure directory does not exist.")
            end
        end
    }
)

is responsible for calling the existsInCWD function. This function then gets all the files and directories in the current working directory and checks whether the passed in name matches any of the files.

existsInCWD = function(nameToCheck)
    -- Get current working directory
    local cwDir = vim.fn.getcwd()

    -- Get all files and directories in CWD (pseudo-code)
    local cwdContent = get_all_files_and_dirs_in_cwd()

    -- Check if specified file or directory exists
    local fullNameToCheck = cwDir .. "/" .. nameToCheck
    print("Checking for: \"" .. fullNameToCheck .. "\"")
    for _, cwdItem in pairs(cwdContent) do
        if cwdItem == fullNameToCheck then
            return true
        end
    end
    return false
end

In the above pseudo-code, I am looking for a Lua/Neovim-compatible solution to the get_all_files_and_dirs_in_cwd() pseudo-function that makes use of the built-in functionality of Neovim.


Solution

  • To store all files and directories in the CWD, one can use:

    local cwDir = vim.fn.getcwd()
    local cwdContent = vim.split(vim.fn.glob(cwDir .. "/*"), '\n', {trimempty=true})
    -- Note 1: if cwDir contains a trailing "/" because the CWD was acquired
    -- by means other than getcwd() (e.g. Lua string matching/substitution),
    -- then remove the "/" preceding the "*" in the above line to avoid "//" issues
    -- Note 2: use {trimempty=true} to ensure that vim.split() drops 
    -- empty space preceding a separator instead of treating it as en entity to keep.
    

    The variable cwdContent can then be iterated over and used as desired. As a complete example function:

    existsInCWD = function(nameToCheck)
        local cwDir = vim.fn.getcwd()
    
        -- Get all files and directories in CWD
        local cwdContent = vim.split(vim.fn.glob(cwDir .. "/*"), '\n', {trimempty=true})
    
        -- Check if specified file or directory exists
        local fullNameToCheck = cwDir .. "/" .. nameToCheck
        print("Checking for: \"" .. fullNameToCheck .. "\"")
        for _, cwdItem in pairs(cwdContent) do
            if cwdItem == fullNameToCheck then
                return true
            end
        end
        return false
    end