TheBlob42 / drex.nvim

Another directory/file explorer for Neovim written in Lua
GNU General Public License v3.0
96 stars 8 forks source link

open drex in a buffer and find element #31

Closed rodolfoksveiga closed 2 years ago

rodolfoksveiga commented 2 years ago

First of all, thanks for developing Drex. The package is very nice and offers most of the features I'm looking for.

While using it though, I missed a function to open Drex in a buffer and locate the file in the file tree, similar to DrexDrawerFindFileAndFocus. Therefore, I decided to dig into the code and change it myself.

As you can see the changes are quite simple and it works properly on my side... I hope this is enough for now.

TheBlob42 commented 2 years ago

Thank you for the nice words and your PR :slightly_smiling_face:

Your custom command to me looks very similar to this example from the wiki (in particular the - command) (but opens the cwd instead of the direct file parent dir)

Therefore I am hesitant to merge this PR as it does not provide any "new" functionality, but rather combines existing features in a certain way. I guess you already have something similar to the DrexFindFile command in your own config? So I would rather think of enhancing the wiki with your example, so that other users with a similar use case can take it as inspiration. This way we keep the Lua codebase as small as possible and rather encourage people to combine and build the stuff they need like you did :thinking:

rodolfoksveiga commented 2 years ago

Sorry that I took so long, but I didn't find time to answer you before. Anyway, I share with you some improvements I've done on my Drex configuration. Of course these improvements solve my own needs, but I hope some of them can help the community and perhaps you can even publish them on README or related.

Here is the part of my Drex configuration that matters (the rest is pretty standard):

-- dir path: ~/.config/nvim/lua/user/drex.lua

local clearClipboard = '<cmd>lua require("drex.clipboard").clear_clipboard()<cr>'

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            ['<cr>'] = '<cmd>lua require("user.drex").open()<cr>j',
            ['<c-c>'] = clearClipboard,
            ['c'] = '<cmd>lua require("drex.actions.files").create()<cr>',
            ['d'] = '<cmd>lua require("user.drex").flexible_action(require("drex.actions.files").delete)<cr>',
            ['r'] = '<cmd>lua require("user.drex").flexible_action(require("drex.actions.files").multi_rename)<cr>3j$T/',
            ['p'] = '<cmd>lua require("drex.actions.files").copy_and_paste()<cr>' .. clearClipboard,
            ['P'] = '<cmd>lua require("drex.actions.files").cut_and_move()<cr>' .. clearClipboard
        }
    },
    on_leave = function ()
        require('drex.clipboard').clear_clipboard()
    end,
}

-- keymaps
vim.keymap.set('n', '<leader>p', '<cmd>lua require("user.drex").find_element("%")<cr>', { noremap = true, silent = true })

-- customized functions
local D = {}

local api = vim.api
local utils = require('drex.utils')
local elements = require('drex.elements')
local open_directory_buffer = require('drex').open_directory_buffer
local get_clipboard_entries = require('drex.clipboard').get_clipboard_entries

function D.find_element(path)
    path = utils.expand_path(path)
    open_directory_buffer('.')
    pcall(elements.focus_element, api.nvim_get_current_win(), path)
end

function D.flexible_action(action)
    local clipboard = get_clipboard_entries()

    local target = 'clipboard'
    if vim.tbl_isempty(clipboard) then
        target = 'line'
    end

    action(target)
end

function D.open()
    local clipboard = get_clipboard_entries()

    if vim.tbl_isempty(clipboard) then
        elements.expand_element()
    else
        vim.tbl_map(
            function(file)
                if vim.fn.isdirectory(file) == 0 then vim.cmd('e ' .. file)
                end
            end,
            clipboard
        )
    end
end

return D
TheBlob42 commented 2 years ago

That is indeed a very interesting configuration you have created there :slightly_smiling_face:

This is definitively worth sharing as an example for other users. I am thinking about a dedicated "user configuration" section in the wiki for such examples by other contributors. Unfortunately Github has no feature for pull requests on the connected wiki project of a repository...

However if you provide me with a small description about your configuration (what did you try to archive, special features, etc.) in a few sentences and a link to your Neovim configuration I would add your example and a link to your Github account and configuration (for credits).

rodolfoksveiga commented 2 years ago

I must confess that I've been enjoying a lot using Drex. It's very minimalist, but offers the features I expect to have in a file explorer/manager. The code is also quite straight forward, which gives the users room for easy improvements... Congrats for the plugin development.


Let me cut to the chase and explain what I was trying to achieve there.

-- file path: ~/.config/nvim/lua/user/drex.lua

local clearClipboard = '<cmd>lua require("drex.clipboard").clear_clipboard()<cr>'

require('drex.config').configure {
    keybindings = {
        ['n'] = {
            -- open single or multiple files (if drex clipboard is populated), or expand the line if drex clipboard is empty and it's a directory
            ['<cr>'] = '<cmd>lua require("user.drex").open()<cr>',
            -- just clear drex clipboard
            ['<c-c>'] = clearClipboard,
            -- use the user defined function "flexible_action" to delete single or multiple files (if drex clipboard is populated)
            ['d'] = '<cmd>lua require("user.drex").flexible_action(require("drex.actions.files").delete)<cr>',
            -- same concept of "delete" action, but for buffer renaming (i love using my vim keys for editing file name)
            --- since i use bulk renaming usually for changing file name, i appended "3j$T/" after the function call, because i want my cursor to skip drex comments on the first three lines and to be right at the beginning of the file name
            ---- example: /home/rodolfo/test.dir/<CURSOR>test_file.lua
            ['r'] = '<cmd>lua require("user.drex").flexible_action(require("drex.actions.files").multi_rename)<cr>3j$T/',
            -- i like to clear drex clipboard after copying or moving files
            ['p'] = '<cmd>lua require("drex.actions.files").copy_and_paste()<cr>' .. clearClipboard,
            ['P'] = '<cmd>lua require("drex.actions.files").cut_and_move()<cr>' .. clearClipboard
        }
    },
    -- also clear drex clipboard when closing the plugin
    on_leave = function ()
        require('drex.clipboard').clear_clipboard()
    end,
}

-- keymaps
vim.keymap.set('n', '<leader>p', '<cmd>lua require("user.drex").find_element("%")<cr>', { noremap = true, silent = true })

-- customized functions
local D = {}

local api = vim.api
local utils = require('drex.utils')
local elements = require('drex.elements')
local open_directory_buffer = require('drex').open_directory_buffer
local get_clipboard_entries = require('drex.clipboard').get_clipboard_entries

-- "find_element" opens drex "full screen" and find the buffer file, if the buffer is not empty, otherwise opens the root directory of the project
function D.find_element(path)
    path = utils.expand_path(path)
    open_directory_buffer('.')
    -- here i use pcall because drex always throws me an error if i try to call "focus_element" with an empty buffer
    pcall(elements.focus_element, api.nvim_get_current_win(), path)
end

-- "flexible_action" basically checks if drex clipboard is populated so "delete" and "multi_rename" actions can be called for a single file or for multiple files
--- perhaps this is a nice improvement for the plugin in general and doesn't cost that much.. just one extra if statement and a function call
function D.flexible_action(action)
    local clipboard = get_clipboard_entries()

    -- if there are entries on drex clipboard, use "clipboard" as a parameter of the callback function
    local target = 'clipboard'
    -- if drex clipboard is empty, use "line" as a parameter of the callback function
    if vim.tbl_isempty(clipboard) then
        target = 'line'
    end

    action(target)
end

-- "open" is the function i was missing the most on drex and it basically opens multiple files, or a single file, if the clipboard is empty
function D.open()
    local clipboard = get_clipboard_entries()

    -- if drex clipboard is empty, open the file or expand the directory on the line
    if vim.tbl_isempty(clipboard) then
        elements.expand_element()
    -- if drex clipboard is populated, open multiple files
    else
        -- map over the clipboard table
        vim.tbl_map(
            function(file)
                -- just open the file if it is not a directory, otherwise the directory would open as a drex buffer with root on that directory (this behavior is not desired)
                if vim.fn.isdirectory(file) == 0 then vim.cmd('e ' .. file)
                end
            end,
            clipboard
        )
    end
end

return D

I hope this clarifications help you and other users on the community. Let me know if I can help you further!

TheBlob42 commented 2 years ago

Thank you for the kind word :heart: it all started as a tool for my personal needs, so I am quite happy that other people find it "straight forward" and enables them to build their own custom configuration

I have added a new section to the wiki (see here) and added your example code
I really hope that others are also interested in sharing their unique configs :slightly_smiling_face:

rodolfoksveiga commented 2 years ago

Sounds cool! I'm happy to contribute a little to your project.

If I have more significant improvements in my configuration, I'll let you know.

Wish you all the best :)