Skip to content

Custom Actions

TheBlob42 edited this page Nov 11, 2022 · 6 revisions

<CR> to toggle directories and open files

  • use <CR> on a closed directory to open it
  • use <CR> on an open directory to close it
  • use <CR> on a file to open it
local elements = require('drex.elements')

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            ['<CR>'] = function()
                local line = vim.api.nvim_get_current_line()

                if require('drex.utils').is_open_directory(line) then
                    elements.collapse_directory()
                else
                    elements.expand_element()
                end
            end
        }
    }
}

Trash element

This example uses trash-cli but you can use whatever command you prefer

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            ['t'] = function()
                local line = vim.api.nvim_get_current_line()
                local element = require('drex.utils').get_element(line)
                vim.fn.jobstart("trash-put '" .. element .. "' &", { detach = true })
            end
        }
    }
}

Open element with system default application

This example only works on Linux with xdg-open available on the PATH

Check out start for Windows and open for MacOS as an alternative

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            ['X'] = function()
                local line = vim.api.nvim_get_current_line()
                local element = require('drex.utils').get_element(line)
                vim.fn.jobstart("xdg-open '" .. element .. "' &", { detach = true })
            end
        }
    }
}

Expand/Collapse all directories

Expand or collapse (recursively) all directories of the current DREX buffer

local utils = require('drex.utils')
local elements = require('drex.elements')

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            -- expand every directory in the current buffer
            ['O'] = function()
                local row = 1
                while true do
                    local line = vim.api.nvim_buf_get_lines(0, row - 1, row, false)[1]
                    if utils.is_closed_directory(line) then
                        elements.expand_element(0, row)
                    end
                    row = row + 1

                    if row > vim.fn.line('$') then
                        break
                    end
                end
            end,
            -- collapse every directory in the current buffer
            ['C'] = function()
                local row = 1
                while true do
                    local line = vim.api.nvim_buf_get_lines(0, row - 1, row, false)[1]
                    if utils.is_open_directory(line) then
                        elements.collapse_directory(0, row)
                    end
                    row = row + 1

                    if row > vim.fn.line('$') then
                        break
                    end
                end
            end,
        },
    },
}

Quick file/folder creation

By default the require('drex.actions.files').create() function will take the path corresponding to the current cursor position to determine at which base path the new element should be created. In case the cursor is on a directory element you will be prompted with a choice of creating the element within that directory or on the same level as it

In order to quicken this process you can pass a base path into the create function, for example:

  • use a to create the new element on the same level as the cursor
  • use A to create the new element within the directory the cursor is on
    • in case it's not a directory create it on the same level instead
local utils = require('drex.utils')
local files = require('drex.actions.files')

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            ['a'] = function()
                local line = vim.api.nvim_get_current_line()
                files.create(utils.get_path(line))
            end,
            ['A'] = function()
                local line = vim.api.nvim_get_current_line()
                if utils.is_directory(line) then
                    files.create(utils.get_element(line) .. utils.path_separator)
                else
                    -- fallback to same level if element is not a directory
                    files.create(utils.get_path(line))
                end
            end,
        }
    }
}

Auto expand

Auto expand sub-directories if their only child is a single directory for quicker navigation

auto expand example

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            ['l'] = function()
                -- local start = vim.api.nvim_win_get_cursor(0) -- OPTIONAL

                while true do
                    elements.expand_element()

                    local row = vim.api.nvim_win_get_cursor(0)[1]
                    local lines = vim.api.nvim_buf_get_lines(0, row - 1, row + 2, false)

                    -- special case for files
                    if lines[1] and not utils.is_directory(lines[1]) then
                        return
                    end

                    -- check if a given line is a child element of the expanded element
                    local is_child = function(l)
                        if not l then
                            return false
                        end
                        return vim.startswith(utils.get_element(l), utils.get_element(lines[1]) .. utils.path_separator)
                    end

                    if is_child(lines[2]) and utils.is_directory(lines[2]) and not is_child(lines[3]) then
                        vim.api.nvim_win_set_cursor(0, { row + 1, 0 })
                    else
                        -- vim.api.nvim_win_set_cursor(0, start) -- OPTIONAL
                        return
                    end
                end
            end,
        }
    }
}

Uncomment the two OPTIONAL lines if you like the cursor to stay on the original directory (unlike the GIF)

"Better-Escape" for search

Use a quick two key combination to cancel the current DREX search similar to better-escape.vim, better-escape.nvim or houdini.nvim. If you're already using one of those plugins you might want to add the same functionality here.

Internally DREX search uses getchar so regular keybindings are not working here

The following example code implements the jk sequence to exit the search

local timer = vim.loop.new_timer()

require('drex.config').setup {
    keybindings = {
        ['n'] = {
            ['/'] = function()
                require('drex.actions.search').search {
                    keybindings = {
                        j = function(args)
                            timer:start(vim.opt.timeoutlen:get(), 0, function()
                                -- empty function
                            end)
                            return args.input .. 'j'
                        end,
                        k = function(args)
                            if timer:get_due_in() and vim.endswith(args.input, 'j') then
                                return true
                            end
                            return args.input .. 'k'
                        end,
                    }
                }
            end,
        }
    }
}