mikavilpas / yazi.nvim

A Neovim Plugin for the yazi terminal file manager
MIT License
441 stars 14 forks source link

Lsp rename refactoring doesn't work #372

Closed gipo355 closed 1 month ago

gipo355 commented 1 month ago

Hey!

Thanks for this amazing plugin, i'm using it alot.

Unfortunately, i have to resolve to nvimtree, telescope-file-project or oil for renaming, moving files because refactoring doesn't work on yazi out of the box.

Am i supposed to do something for it to work?

I'm working on a typescript project with typescript-tools (tsserver)

If i rename or mvoe a file with nvimtree or one of the others mentioned above, all imports get renamed correctly.

Doing it in yazi instead does not.

I have lsp-file-operations plugin installed

mikavilpas commented 1 month ago

Hi! That's strange - it does work for me. See here

https://github.com/user-attachments/assets/0fa10360-7d8a-4a4e-af17-ca5b9d4badb9

Can you try it out on this project https://github.com/GregRos/parjs/ ?

mikavilpas commented 1 month ago

I'm guessing here, but could it be that after you have e.g. renamed a typescript file, you have unsaved changes to the buffers? Maybe they're not shown like they are for me in your configuration?

I'm using typescript-tools myself, btw.

gipo355 commented 1 month ago

Hi Mika, thanks for the swift reply!

Will try it out asap and let you know.

Let me know if I can give you some more info too

P.s. I have my whole config on https://github.com/gipo355/nvim

gipo355 commented 1 month ago

hey @mikavilpas, i tried doing the exact same thing in the gif in the repo you linked and it only renames the file

Posting a gif for it too: yazi-nvim-not-working-lsp-refacotr

mikavilpas commented 1 month ago

Ok, it looks like you are doing everything correctly. I have a couple of ideas to try, but can you try out one thing before that:

Try to upgrade to the latest version of yazi (0.3 or nightly) and enable these settings in your config: https://github.com/mikavilpas/dotfiles/blob/main/.config/nvim/lua/plugins/my-file-manager.lua#L15-L19

gipo355 commented 1 month ago

tested with the config options you posted, yazi version was already 0.3.0, tried installing nightly too but no luck :disappointed:

mikavilpas commented 1 month ago

Okay, thanks for trying it out. I will try to build a reproduction script for you to try as it may be something else in your configuration for example. 👍🏻

gipo355 commented 1 month ago

It could be for sure, I could try debugging and removing stuff to check but it really isn't a blocker for me at the moment.

For now I'm fine refactoring with oil, happy to know it works and it's probably a config on my side.

Please feel free to close the issue, I will try to pinpoint what it could be some time in the future and report back here!

mikavilpas commented 1 month ago

One thought just popped into my mind. Can you run :checkhealth yazi and post the output here?

Mine is


==============================================================================
yazi: require("yazi.health").check()

yazi ~
- Running yazi.nvim version 5.5.1
- Found `yazi` version `Yazi 0.3.0 (22a4be1 2024-08-11)` 👍
- yazi.nvim log file is at /Users/mikavilpas/.local/state/nvim/yazi.log
-     hint: use `gf` to open the file path under the cursor
- Found `ya` version `Ya 0.3.0 (22a4be1 2024-08-11)` 👍
- You have enabled `open_for_directories` in your config. Because of this, please make sure you are loading yazi when Neovim starts.
- OK yazi
gipo355 commented 1 month ago
==============================================================================
yazi: require("yazi.health").check()

yazi ~
- yazi.nvim log file is at /home/wolf/.local/state/nvim/yazi.log
-     hint: use `gf` to open the file path under the cursor
- OK yazi

this is my config for yazi

return {
    'mikavilpas/yazi.nvim',
    dependencies = {
        'nvim-lua/plenary.nvim',
    },
    event = 'VeryLazy',
    keys = {
        -- 👇 in this section, choose your own keymappings!
        {
            -- '<leader>-',
            '-',
            function()
                require('yazi').yazi()
            end,
            desc = 'Open the file manager',
        },
        {
            -- Open in the current working directory
            -- '<leader>cw',
            '<leader>-',
            function()
                require('yazi').yazi(nil, vim.fn.getcwd())
            end,
            desc = "Open the file manager in nvim's working directory",
        },
    },
    ---@type YaziConfig
    opts = {
        -- open_for_directories = false,
        use_ya_for_events_reading = true,
        use_yazi_client_id_flag = true,
        open_multiple_tabs = true,
        open_for_directories = true,
    },
    config = function(opts)
        require('yazi').setup(opts)
    end,
}

I just noticed we are passing opts directly into the setup. This may not work correcly

mikavilpas commented 1 month ago

Oh, nice catch! I think the correct signature for the function is config = function(self, opts).

gipo355 commented 1 month ago

I'm not sure, i tried direcly calling the setup without passing opts but nothing really changed

             require('yazi').setup({
            {
                -- open_for_directories = false,
                use_ya_for_events_reading = true,
                use_yazi_client_id_flag = true,
                open_multiple_tabs = true,
                open_for_directories = true,
            },
        })
mikavilpas commented 1 month ago

Can you see a change in the health check now that the config should be passed correctly?

gipo355 commented 1 month ago

nope, it stays the same as above.

For reference i tried all these variants:

return {
    'mikavilpas/yazi.nvim',
    dependencies = {
        'nvim-lua/plenary.nvim',
    },
    event = 'VeryLazy',
    keys = {
        -- 👇 in this section, choose your own keymappings!
        {
            -- '<leader>-',
            '-',
            function()
                require('yazi').yazi()
            end,
            desc = 'Open the file manager',
        },
        {
            -- Open in the current working directory
            -- '<leader>cw',
            '<leader>-',
            function()
                require('yazi').yazi(nil, vim.fn.getcwd())
            end,
            desc = "Open the file manager in nvim's working directory",
        },
    },
    ---@type YaziConfig
    opts = {
        -- open_for_directories = false,
        use_ya_for_events_reading = true,
        use_yazi_client_id_flag = true,
        open_multiple_tabs = true,
        open_for_directories = true,
    },
    -- config = function(opts)
    --     -- require('yazi').setup(opts)
    --
    --     require('yazi').setup(self, opts)
    --
    --     -- require('yazi').setup({
    --     --     {
    --     --         -- open_for_directories = false,
    --     --         use_ya_for_events_reading = true,
    --     --         use_yazi_client_id_flag = true,
    --     --         open_multiple_tabs = true,
    --     --         open_for_directories = true,
    --     --     },
    --     -- })
    -- end,
}
gipo355 commented 1 month ago

this is my lazy init:

require('lazy').setup({
    spec = {
        -- This is the easiest way to modularize your config.

        -- NOTE: it doesn't need to be init.lua, it loads every file with return {} [ or return {{}} and lazy flats it ]
        -- WARN: it loads folders with init.lua (e.g. ../others/utils/init.lua loads ../others/utils.lua)

        -- i prefer this method so i can just add files without manually requiring all of them
        -- this imports the folders and loads all files with return {} in them (also subfolders with init.lua)

        { import = 'user.plugins.others' },
        { import = 'user.plugins.singles' },

        -- { import = 'user.plugins.notes' },
        { import = 'user.plugins.mini' },
        { import = 'user.plugins.file-browsers' },
        { import = 'user.plugins.sessions-welcome' },
        { import = 'user.plugins.themes' },
        { import = 'user.plugins.telescope' },

        { import = 'user.plugins.toggleterm' },

        { import = 'user.plugins.http' },

        { import = 'user.plugins.cmp' },
        { import = 'user.plugins.ai' },
        { import = 'user.plugins.git' },

        { import = 'user.plugins.dap' },
        { import = 'user.plugins.lsp.langs' },
        { import = 'user.plugins.lsp.formatters' },
        { import = 'user.plugins.lsp.lspconfig' },

        -- other ways
        -- 'tpope/vim-sleuth', -- Detect tabstop and shiftwidth automatically

        -- Use `opts = {}` to force a plugin to be loaded.
        -- "gc" to comment visual regions/lines
        -- { 'numToStr/Comment.nvim', opts = {} },

        -- modular approach: using `require 'path/name'` will
        -- include a plugin definition from file lua/path/name.lua
        -- require('plugins.indent_line'),
    },
    defaults = {
        -- from lazyvim repo
        -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup.
        -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default.
        lazy = true,
        -- It's recommended to leave version=false for now, since a lot the plugin that support versioning,
        -- have outdated releases, which may break your Neovim install.
        version = false, -- always use the latest git commit
        -- version = "*", -- try installing the latest stable version for plugins that support semver

        ui = {
            -- If you have a Nerd Font, set icons to an empty table which will use the
            -- default lazy.nvim defined Nerd Font icons otherwise define a unicode icons table
            icons = _G.user.have_nerd_font and {} or {
                cmd = '⌘',
                config = '🛠',
                event = '📅',
                ft = '📂',
                init = '⚙',
                keys = '🗝',
                plugin = '🔌',
                runtime = '💻',
                require = '🌙',
                source = '📄',
                start = '🚀',
                task = '📌',
                lazy = '💤 ',
            },
        },
    },
    change_detection = {
        -- automatically check for config file changes and reload the ui
        enabled = false,
        notify = false, -- get a notification when changes are found
    },
    checker = { enabled = false }, -- automatically check for plugin updates
    performance = {
        cache = {
            enabled = true,
        },
        reset_packpath = true, -- reset the package path to improve startup time,
        rtp = {
            -- disable some rtp plugins
            -- those are builtins
            disabled_plugins = {
                'gzip',
                'matchit',
                -- "matchparen",
                'netrwPlugin',
                'tarPlugin', -- disable editing tar files
                'tohtml',
                'tutor',
                'zipPlugin', -- disable editing zip files
            },
        },
    },
})
mikavilpas commented 1 month ago

Okay, I think we're making good progress. Here's a reproduction script, can you save this as repro.lua in a temporary directory?

-- You can use this file to reproduce an issue with your configuration.

---@module "yazi"
---@module "lazy"

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)
vim.g.mapleader = " "

-- install the following plugins
---@type LazySpec
local plugins = {
  { "catppuccin/nvim", name = "catppuccin", opts = { flavour = "macchiato" } },
  {
    "mikavilpas/yazi.nvim",
    event = "VeryLazy",
    keys = {
      -- 👇 in this section, choose your own keymappings!
      {
        -- '<leader>-',
        "-",
        "<cmd>Yazi<cr>",
        desc = "Open the file manager",
      },
    },
    ---@type YaziConfig
    opts = {
      -- open_for_directories = false,
      use_ya_for_events_reading = true,
      use_yazi_client_id_flag = true,
      open_multiple_tabs = true,
      open_for_directories = true,
    },
    -- config = function(opts)
    --     -- require('yazi').setup(opts)
    --
    --     require('yazi').setup(self, opts)
    --
    --     -- require('yazi').setup({
    --     --     {
    --     --         -- open_for_directories = false,
    --     --         use_ya_for_events_reading = true,
    --     --         use_yazi_client_id_flag = true,
    --     --         open_multiple_tabs = true,
    --     --         open_for_directories = true,
    --     --     },
    --     -- })
    -- end,
  },
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
  install = { colorscheme = { "catppuccin" } },
})

vim.cmd.colorscheme("catppuccin")
-- add anything else here

Then try to run that with nvim -u repro.lua. Finally, run :checkhealth yazi and see if the output changes. For me, the output is the following


==============================================================================
yazi: require("yazi.health").check()

yazi ~
- Running yazi.nvim version 5.1.1
- Found `yazi` version `Yazi 0.3.0 (22a4be1 2024-08-11)` 👍
- yazi.nvim log file is at /Users/mikavilpas/git/yazi.nvim/.repro//state/nvim/yazi.log
-     hint: use `gf` to open the file path under the cursor
- Found `ya` version `Ya 0.3.0 (22a4be1 2024-08-11)` 👍
- You have enabled `open_for_directories` in your config. Because of this, please make sure you are loading yazi when Neovim starts.
- OK yazi
gipo355 commented 1 month ago

indeed, it changed.

==============================================================================
yazi: require("yazi.health").check()

yazi ~
- Running yazi.nvim version 5.5.1
- Found `yazi` version `Yazi 0.3.0 (Arch Linux 2024-08-07)` 👍
- yazi.nvim log file is at /home/wolf/Programming/tests/tmp/.repro//state/nvim/yazi.log
-     hint: use `gf` to open the file path under the cursor
- Found `ya` version `Ya 0.3.0 (VERGEN_IDEMPOTENT_OUTPUT 2024-08-07)` 👍
- You have enabled `open_for_directories` in your config. Because of this, please make sure you are loading yazi when Neovim starts.
- OK yazi
mikavilpas commented 1 month ago

It looks like this reproduction setup can read the config correctly. I'll write a validator for the config structure and maybe you can run that on your real setup to pinpoint any issues.

mikavilpas commented 1 month ago

It's not required right now but if you are interested and want to experiment with your setup, you can open yazi with logging using this

:lua require('yazi').yazi({log_level = vim.log.levels.DEBUG})

The health check contains the path to the log file, and it may show something useful. Not sure because I have never hit this particular case before 🙂

gipo355 commented 1 month ago

i noticed you omitted the stable branch from lazy.

I tried to change the config of the lazy bootstrap in my config (copying from docs) and removed the branch stable:

-- [[ Install `lazy.nvim` plugin manager ]]
--    See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
-- if not vim.loop.fs_stat(lazypath) then
--     local lazyrepo = 'https://github.com/folke/lazy.nvim.git'
--     vim.fn.system({
--         'git',
--         'clone',
--         '--filter=blob:none',
--         '--branch=stable',
--         lazyrepo,
--         lazypath,
--     })
-- end ---@diagnostic disable-next-line: undefined-field
-- vim.opt.rtp:prepend(lazypath)
if not (vim.uv or vim.loop).fs_stat(lazypath) then
    local lazyrepo = 'https://github.com/folke/lazy.nvim.git'
    local out = vim.fn.system({
        'git',
        'clone',
        '--filter=blob:none',
        -- '--branch=stable',
        lazyrepo,
        lazypath,
    })
    if vim.v.shell_error ~= 0 then
        vim.api.nvim_echo({
            { 'Failed to clone lazy.nvim:\n', 'ErrorMsg' },
            { out, 'WarningMsg' },
            { '\nPress any key to exit...' },
        }, true, {})
        vim.fn.getchar()
        os.exit(1)
    end
end
vim.opt.rtp:prepend(lazypath)

and run a Lazy sync.

Now the checkhealth shows the correct output

mikavilpas commented 1 month ago

Hmm, interesting. With these changes, do you still experience the same behaviour (no lsp renaming stuff)?

gipo355 commented 1 month ago

tested: can now successfully refactor with yazi

edit: also readded the stable branch and retested. works good.

I am now convinced something like caching was messed up with my config although I did :Lazy sync before

mikavilpas commented 1 month ago

Oh, nice work! 😄

By the way, I have a question for lsp feedback if you don't mind: when you rename with the other tools (I think you said oil and nvimtree), does it work the same way in yazi.nvim, or are there some things that are different/troublesome?

gipo355 commented 1 month ago

got the error btw:

-  "yazi.nvim": { "branch": "master", "commit": "a2f7832af7462c79d57777dd8c36ad0edfb84b39" },
+  "yazi.nvim": { "branch": "main", "commit": "065685bf0e3acd2393f42f788f46e12c4b9732f5" },

running sync upped yazi to branch main. No idea why it was stuck there? (I swear i did run lazy sync)

I'm not really sure about the difference, I'm not noticing any at the moment.

My saves are synchronous and slower than your gif because conform and lsps are formatting each of the changed buffer before save. (this happens for all of them)

If i notice anything i will add something here then.

Thanks alot for your help @mikavilpas , it really helped me figure out the problem

gipo355 commented 1 month ago

logging here the opts table received in the setup call inside the config fn:

{
  _ = {
    cache = {
      cmd_list = { "Yazi", "Yazi cwd", "Yazi toggle" },
      keys_list = { <1>{ "-", <function 1>,
          desc = "Open the file manager",
          mode = "n"
        }, <2>{ "<leader>-", <function 2>,
          desc = "Open the file manager in nvim's working directory",
          mode = "n"
        } },
      opts = {
        open_for_directories = true,
        open_multiple_tabs = true,
        use_ya_for_events_reading = true,
        use_yazi_client_id_flag = true
      }
    },
    frags = { 11, 9, 132 },
    handlers = {
      cmd = {
        Yazi = "Yazi",
        ["Yazi cwd"] = "Yazi cwd",
        ["Yazi toggle"] = "Yazi toggle"
      },
      keys = {
        [" -"] = {
          desc = "Open the file manager in nvim's working directory",
          id = " -",
          lhs = "<leader>-",
          mode = "n",
          rhs = <function 2>
        },
        ["-"] = {
          desc = "Open the file manager",
          id = "-",
          lhs = "-",
          mode = "n",
          rhs = <function 1>
        }
      }
    },
    installed = true,
    loaded = {
      start = "start"
    },
    pkg = {
      dir = "/home/wolf/.local/share/nvim/lazy/yazi.nvim",
      file = "lazy.lua",
      name = "yazi.nvim",
      source = "lazy",
      spec = <3>{ "yazi.nvim",
        optional = true,
        specs = { { "nvim-lua/plenary.nvim",
            lazy = true,
            <metatable> = {
              __index = { "nvim-lua/plenary.nvim",
                lazy = true,
                <metatable> = {
                  __index = { "plenary.nvim",
                    optional = true,
                    specs = <4>{ "nvim-lua/plenary.nvim",
                      lazy = true,
                      optional = true
                    },
                    <metatable> = {
                      __index = <table 4>
                    }
                  }
                }
              }
            }
          }, <5>{ "mikavilpas/yazi.nvim",
            cmd = { "Yazi", "Yazi cwd", "Yazi toggle" },
            optional = true,
            opts = {}
          } },
        <metatable> = {
          __index = <table 5>
        }
      }
    }
  },
  dependencies = { "plenary.nvim" },
  dir = "/home/wolf/.local/share/nvim/lazy/yazi.nvim",
  name = "yazi.nvim",
  optional = false,
  url = "https://github.com/mikavilpas/yazi.nvim.git",
  <metatable> = {
    __index = { "mikavilpas/yazi.nvim",
      config = <function 3>,
      dependencies = { "nvim-lua/plenary.nvim" },
      keys = { <table 1>, <table 2> },
      lazy = false,
      opts = {
        open_for_directories = true,
        open_multiple_tabs = true,
        use_ya_for_events_reading = true,
        use_yazi_client_id_flag = true
      },
      <metatable> = {
        __index = <table 3>
      }
    }
  }
}
gipo355 commented 1 month ago

@mikavilpas since you asked for feedback, I will gladly report back after I used a bit all of them!

Is there any more specific thing you are more interested about?

mikavilpas commented 1 month ago

Yes, actually. Do the other plugins you have used save all files synchronously (faster)? I use prettierd in my config which is probably faster when many files need to be saved.

I could see if a performance improvement can be made if this is the case.

gipo355 commented 1 month ago

That's an interesting question, I will take a look at this a bit since big monorepos may cause a bad UX.

Until now i experienced always the same behavior, synch format on save.

If i recall right, i specifically made it this way since async saves were causing conflicts.

For reference, my auto formats configs are here:

https://github.com/gipo355/nvim/blob/main/lua/user/plugins/lsp/formatters/none-ls.lua

https://github.com/gipo355/nvim/blob/main/lua/user/plugins/lsp/formatters/conform.lua

(Code is a bit messy since i prefer leaving old comments for now)

You can see i was using prettierd but i switched back to prettier since it wasn't working properly in my last project, some strange behaviors in a monorepo.

Conform (like builtin buf format) has the ability to format asynch but it was overriding multiple lsps autoformats which were facing race conditions.

Overall, auto format on save and lsp formattings (commands, priorities, selections) are still a tad behind other editors IMHO

Will take a closer look soon

Edit: brainstorming a bit

Lsp and autoformatting is an argument i wanted to get back into since it's quite a bit messy.

There are multiple sources, some come from lsp, some from conform, some from nonels.

for ts files, i usually have tsserver, prettier and eslint active.

It would be cool, if i have 10 open buffers, to format asynchronously but in order.

First, everything asynch with tsserver, then with eslint and at last with prettier for example.

The problem i see is that the eslint lsp exposes a command to be run manually, tsserver requires vim.buf.format and prettier requires conform (or none-ls).

So it's a mix of everything and for now i hacked up a solution patching everything together running command synchronously while i look for a better solution to standardize and omogenize everything.

One option could be stuffing everything in conform if possible, giving up lsps provided by lspconfig but that doesn't sound that great tbh

(you can see in the formatting folder i posted above some things i was looking for, like efm)

gipo355 commented 1 month ago

hey @mikavilpas good afternoon!

I've refactored a bit my autosave on format, experimenting with some different approaches.

https://github.com/gipo355/nvim/blob/main/lua/user/plugins/lsp/formatters/none-ls.lua

https://github.com/gipo355/nvim/blob/main/lua/user/plugins/lsp/formatters/conform.lua

I've also been trying oil nvimtree and yazi for refactoring.

While overall everything is quite faster since i removed some duplicate aucmds, It feels like yazi is actually faster than the others for now and more fluid too. (the main reason i love your plugin)

P.S. if you have suggestions on the autosaves approaches I'm happy to receive them!

mikavilpas commented 1 month ago

That's really interesting. I think the experience of setting up lsps+formatting in neovim is maybe its weakest part. I'm hoping things will improve in the future.

Although I remember using vim about 12 years ago and back then it was not possible to run any build commands asynchronously - everything was sync and if you had a long build script/compilation, it would block vim for that time. So things are insanely better nowadays 😄

mikavilpas commented 1 month ago

Btw, do you happen to use a single window workflow in neovim, or do you prefer splits? Or something else?

I like to use splits and bufferline.nvim so currently everything in this plugin only supports this approach. But perhaps other types of workflows could be supported too.

gipo355 commented 1 month ago

I actually disabled bufferline and moved to tabs after reading interesting discussions on it.

I feel like workflow is much stronger now.

I can use tabs simply to replace bufferline, or as different splits layouts or even different projects and pwds

The way I set it up allows me to cwd each tab separately very quickly with root patterns mainly because 90% of my work is nx monorepos usage.

This way in a monorepo I switfy change subproject and filter out files from telescope for example while retaining the ability to grep globally in the monorepo if needed.

Each tab is independent and I often use splits both hor and vert