linux-cultist / venv-selector.nvim

Allows selection of python virtual environment from within neovim
MIT License
379 stars 40 forks source link

venv does not activate automatically #96

Closed steakhutzeee closed 1 month ago

steakhutzeee commented 4 months ago

Hi, i configured the plugin this way:

return {
  -- https://github.com/linux-cultist/venv-selector.nvim

  'linux-cultist/venv-selector.nvim',
  dependencies = { 
    'neovim/nvim-lspconfig',
    'nvim-telescope/telescope.nvim', 
    'mfussenegger/nvim-dap', 
    'mfussenegger/nvim-dap-python'
  },
  config = function()
    require('venv-selector').setup {
      search = false,
      search_workspace = false,
      search_venv_managers = true,
      dap_enabled = false,
      notify_user_on_activate = true,
      pyenv_path = '/home/xxx/.pyenv/versions',
    }

    vim.api.nvim_create_autocmd('VimEnter', {
      desc = 'Auto select virtualenv Nvim open',
      pattern = '*',
      callback = function()
        local venv = vim.fn.findfile('pyproject.toml', vim.fn.getcwd() .. ';')
        if venv ~= '' then
          require('venv-selector').retrieve_from_cache()
        end
      end,
      once = true,
    })

  end,
  event = 'VeryLazy', -- Optional: needed only if you want to type `:VenvSelect` without a keymapping
  keys = {
    -- Keymap to open VenvSelector to pick a venv.
    { '<leader>vs', '<cmd>VenvSelect<cr>' },
    -- Keymap to retrieve the venv from a cache (the one previously used for the same project directory).
    { '<leader>vc', '<cmd>VenvSelectCached<cr>' },
  },
}

but when i open a Python file the venv is not automatically activated and i've to manually select it. Something is wrong with my config?

Thanks!

neolooong commented 4 months ago

require('venv-selector').retrieve_from_cache() can only be executed after LSP client started.

steakhutzeee commented 4 months ago

require('venv-selector').retrieve_from_cache() can only be executed after LSP client started.

Thanks, is there something I can do to set this or I only have to move this config to the LSP configuration?

Mr-Bojangles commented 3 months ago

I'm facing a similar issue. I use Pyright as my LSP and pylint as my linter. Both activate on opening any Python file. However, my virtual environments don't activate automatically. I am able to manually select a venv using :VenvSelect and I can reactivate from cache with :VenvSelectCached. Below is my config:

return {
. "linux-cultist/venv-selector.nvim",
. dependencies = {
. . "neovim/nvim-lspconfig",
. . "nvim-telescope/telescope.nvim",
. . "mfussenegger/nvim-dap-python",
. },
.
. config = function()
. . require("venv-selector").setup(
. . . {
. . . . pyenv_path = "/xx/xx/.pyenv/versions",
. . . },
. . .
. . . vim.api.nvim_create_autocmd("VimEnter", {
. . . . desc = "Auto select virtualenv Nvim open",
. . . . pattern = "*",
. . . . callback = function()
. . . . . local venv = vim.fn.findfile(".python-version", vim.fn.getcwd() .. ";")
. . . . . if venv ~= "" then
. . . . . . require("venv-selector").retrieve_from_cache()
. . . . . end
. . . . end,
. . . . once = true,
. . . })
. . )
. end,
.
. event = "VeryLazy",
. keys = {
. . { "<leader>vs", "<cmd>VenvSelect<CR>" },
. . { "<leader>vc", "<cmd>VenvSelectCached<CR>" },
. . { "<leader>vb", "<cmd>VenvSelectCurrent<CR>" },
. },
}

The only difference in my autocmd from the venv-selector example is that I tell it to look for a .python-version file as I use pyenv-virtualenv. Doing that or leaving in pyproject.toml produce no effect. I've even tried removing the conditional to just have it always retrieve the venv from cache, but that doesn't work, either.

Clearly I'm missing something. I'd appreciate any insight. Thanks in advance!

linux-cultist commented 3 months ago

The plugin doesn't automatically activate a venv for you. It was always necessary to select it in the list of venvs, or run the VenvSelectCached command.

I see that you are running it using a callback function but if I remember the code for VenvSelectCached correctly, it depends on knowing the current directory. Could be some issue with that or something else if it doesn't work. This scenario of calling it in a callback function was never tested I think.

Does VenvSelectCached work when running it manually?

neolooong commented 3 months ago

I use the following code. Just put it below setup function.

local augroup = vim.api.nvim_create_augroup("VenvSelectorRetrieve", { clear = true })
vim.api.nvim_create_autocmd({ "LspAttach" }, {
  pattern = { "*.py" },
  group = augroup,
  callback = function(args)
    if vim.lsp.get_client_by_id(args["data"]["client_id"])["name"] == "pyright" then
      require("venv-selector").retrieve_from_cache()
      vim.api.nvim_del_augroup_by_id(augroup)
    end
  end,
})

The snippet may not work well if you use many lsp at the same time. But I think it could work with some modification.

Mr-Bojangles commented 3 months ago

The plugin doesn't automatically activate a venv for you. It was always necessary to select it in the list of venvs, or run the VenvSelectCached command.

I see that you are running it using a callback function but if I remember the code for VenvSelectCached correctly, it depends on knowing the current directory. Could be some issue with that or something else if it doesn't work. This scenario of calling it in a callback function was never tested I think.

Does VenvSelectCached work when running it manually?

Yes, VenvSelectCached does work when running it manually. I'm new to Neovim and Lua, so I could be misinterpreting how things work. When I was going through the README I got the impression that retrieve_from_cache() is what VenvSelectCached is actually calling. So, that's what I thought the automate example would do.

-- UPDATE -- neolooong's suggested snippet worked - upon opening a Python file in a workspace with a venv, that venv was activated. I was then able to manually trigger linting. Thank you, linux-cultist and neolooong!

linux-cultist commented 2 months ago

Very good. I'm working on a new version of the plugin that has this feature as well (automatic activation of a venv in the current working directory if it has been activated once before).

It's still early days but it's available in the regexp branch. It works very different and uses none of the old configuration options. But it's much more flexible and won't require code changes in the plugin to support more venv managers or different types of searches.

linux-cultist commented 1 month ago

The new version of the plugin in the regexp branch will automatically activate your python interpreter if you have selected it at least once before in the current directory.

The next time you open neovim in the same directory and open a python file, it will activate the venv. And if you pick some other venv, it will be remembered the next time as well.

So if you want, you can try the new version:

Configuration for lazy.nvim:

return {
  "linux-cultist/venv-selector.nvim",
    dependencies = {
      "neovim/nvim-lspconfig", 
      "mfussenegger/nvim-dap", "mfussenegger/nvim-dap-python", --optional
      { "nvim-telescope/telescope.nvim", branch = "0.1.x", dependencies = { "nvim-lua/plenary.nvim" } },
    },
  lazy = false,
  branch = "regexp", -- This is the regexp branch, use this until its merged with the main branch later
  config = function()
      require("venv-selector").setup()
    end,
    keys = {
      { ",v", "<cmd>VenvSelect<cr>" },
    },
},

Dont need any options for this usecase either, it should work automatically. You run the ordinary VenvSelect command. I think there wont be a need for the VenvSelectCached command anymore.

linux-cultist commented 1 month ago

Please try the new version in the regexp branch where this should work automatically. I'm closing this but reopen if you still have issues with it or have questions etc. Happy to help.

steakhutzeee commented 1 month ago

Hi, thank you! The new branch looks amazing. Just tried and works flawlessy.

Just a couple of questions tho. Let's say we use your configuration snippet above. In that case all the default searches will be automatically enabled?

And also, where are defined $WORKSPACE_PATH/$FILE_PATH? I tried accessing them but looks like they're empty.

Thanks again!

linux-cultist commented 1 month ago

I'm very happy to hear that. :) It's always effort to rewrite something and rarely a good idea but in this case, I knew the foundations needed to change for the plugin to become much better. I hope everyone likes the new version.

Yes, with default config like above, all default searches are enabled. It searches for all the venv managers and also looks in your lsp workspace directory and your current working directory as well.

The variables that look like environment variables are actually just placeholders that gets replaced by the plugin when you run it. So you can use them in your own defined searches as well (if you write your own) and the plugin will put the real values in their place.

But they are not environment variables, they just look like it. Maybe another syntax would be better to avoid confusion.

steakhutzeee commented 1 month ago

I'm very happy to hear that. :) It's always effort to rewrite something and rarely a good idea but in this case, I knew the foundations needed to change for the plugin to become much better. I hope everyone likes the new version.

Yes, with default config like above, all default searches are enabled. It searches for all the venv managers and also looks in your lsp workspace directory and your current working directory as well.

The variables that look like environment variables are actually just placeholders that gets replaced by the plugin when you run it. So you can use them in your own defined searches as well (if you write your own) and the plugin will put the real values in their place.

But they are not environment variables, they just look like it. Maybe another syntax would be better to avoid confusion.

I see, thank you.

I tried with default settings but found no venv.

Tried opening a file with the venv stored directly in the project.

Like:

project/
project/.venv
project/src/file.py

But default search found nothing. I had to implement a custom regex.

So what are the values of $WORKSPACE_PATH/$FILE_PATH? Can i check them somehow?

linux-cultist commented 1 month ago

Yeah it's probably because the venv is hidden and I didn't want the default search to look through all hidden files. But it's really nice that you managed to put your own regexp in there. I guess the Readme was understandable then. :)

The values are filled in by the plugin but are not really exported anywhere. But that's a good idea actually, I could add functions for exporting what they are. Will look at that this weekend then!

linux-cultist commented 1 month ago

I added some functions you can call to see what the values are, and added it to the README as well:

`require("venv-selector").workspace_paths()`  -- Gives back the workspace paths your LSP is using
`require("venv-selector").cwd()`              -- Gives back the current working directory
`require("venv-selector").file_dir()`         -- Gives back the directory of the currently opened file

So if you want to see values from inside neovim, you can do this:

:lua =require("venv-selector").cwd()

Its a way to print the value easier.

For workspace paths / file dir, they will have values only when your LSP has found a workspace dir / you have a file opened in the editor.

I renamed $FILE_PATH to $FILE_DIR also since its a much better name. It is the directory of your opened file. It can be useful in searches sometimes when your venv is in the same directory as your opened file, but you opened neovim in a completely different directory than the file you opened.

steakhutzeee commented 1 month ago

This is great! Thank you!

This way I made these searches, in order to look both in a centralized location and the project workspace dir!

      search = {
        find_in_project = {
          command = "fd --full-path --hidden --color=never --absolute-path --follow --no-ignore '/bin/python$' $WORKSPACE_PATH"
        },
        find_in_home = {
          command = "fd --full-path --hidden --color=never --absolute-path --follow --no-ignore '/bin/python$' $HOME/.venv"
        },
      },
linux-cultist commented 1 month ago

Perfect. :) Makes me really happy to see users use the plugin and be happy with it. Thank you!

linux-cultist commented 1 month ago

Also I wanted to tell you, if the searches you wrote are enough to find all your venvs, you can disable the default ones to make the plugin slightly faster. :)

There is a enable_default_searches option that you can set to false if you like.