Telescope.nvim picker to choose different pyenv install for pylsp. - sh.itjust.works
# Preview
[https://sh.itjust.works/pictrs/image/78a73868-10c3-4e55-9a70-943f71305604.gif]
— # What So I really needed my pylsp
[https://github.com/python-lsp/python-lsp-server] to use a different pyenv
[https://github.com/pyenv/pyenv] install, and just want to share my basic
solution in hopes it’ll help someone else. The basic gist of it is that I use
vim.system() to get the version paths through pyenv: bash pyenv root pyenv
versions --bare --skip-aliases and create a telescope picker for selection. Then
I use vim.lsp.client.notify() with the workspace/didChangeConfiguration lsp
method to change pylsp’s settings (for which options can be found here
[https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md]).
# Code lua local pickers = require("telescope.pickers") local finders =
require("telescope.finders") local conf = require("telescope.config").values
local actions = require("telescope.actions") local action_state =
require("telescope.actions.state") local M = {} M.get_pyenv_root = function() if
not vim.fn.executable('pyenv') then vim.notify("pyenv executable not in path.",
vim.log.levels.WARN) return nil end local root_cmd = vim.system({ 'pyenv',
'root', }):wait() if root_cmd.code ~= 0 then vim.notify('"pyenv root" command
returned non zero exit status.', vim.log.levels.WARN) return nil end local
pyenv_root = string.gsub(root_cmd.stdout, '%s+', '') local pyenv_versions_path =
vim.fs.joinpath(pyenv_root, '/versions') if not
vim.fn.isdirectory(pyenv_versions_path) then vim.notify("Failed to find pyenv
versions directory, '" .. pyenv_versions_path .. "'.", vim.log.levels.WARN)
return nil end return pyenv_versions_path end M.get_pyenv_version_paths =
function() if not vim.fn.executable('pyenv') then vim.notify("pyenv executable
not in path.", vim.log.levels.WARN) return nil end local cmd = { 'pyenv',
'versions', '--bare', '--skip-aliases' } local versions_cmd =
vim.system(cmd):wait() if versions_cmd.code ~= 0 then vim.notify('command "' ..
vim.inspect(cmd) .. '" returned non zero exit status.', vim.log.levels.WARN)
return nil end local versions = vim.fn.split(versions_cmd.stdout, '\n') return
versions end M.get_pyenv_results = function() local pyenv_versions_root =
M.get_pyenv_root() local results = {} if pyenv_versions_root == nil then return
nil end local pyenv_versions = M.get_pyenv_version_paths() if pyenv_versions ==
nil then return nil end for _, version_path in ipairs(pyenv_versions) do
table.insert(results, { version_path, vim.fs.joinpath(pyenv_versions_root,
version_path), }) end return results end M.set_pylsp_environment =
function(python_env) local pylsp_clients = vim.lsp.get_clients({ name = "pylsp"
}) if pylsp_clients == nil or next(pylsp_clients) == nil then vim.notify("No
Pylsp clients found.", vim.log.levels.WARN) return end local clients = 0 for _,
client in ipairs(pylsp_clients) do
client.notify("workspace/didChangeConfiguration", { settings = { pylsp = {
plugins = { jedi = { environment = python_env } } } } }) clients = clients + 1
end vim.notify("Set python environment to '" .. python_env .. "' for " ..
clients .. " pylsp clients.") end M.pyenvs = function(opts) opts = opts or {}
local version_results = M.get_pyenv_results() if version_results == nil then
return end pickers.new(opts, { prompt_title = "pyenvs", finder =
finders.new_table({ results = version_results, entry_maker = function(entry)
return { value = entry, display = entry[1], ordinal = entry[1], } end, }),
attach_mappings = function(prompt_bufnr, _)
actions.select_default:replace(function() actions.close(prompt_bufnr) local
selection = action_state.get_selected_entry()
M.set_pylsp_environment(selection.value[2]) end) return true end, sorter =
conf.generic_sorter(opts) }):find() end return M And now you can easily open the
picker with the M.pyenvs() function. Also nice way to create the keymap for it
is to wait for the LspAttach autocmd (which fires when an LSP is attached to a
buffer) to fire and only create the keymap on the buffer that pylsp is attached
to like so: (don’t forget to change the ‘<module_name>’) lua
vim.api.nvim_create_autocmd("LspAttach", { callback = function(args) local
client = vim.lsp.get_client_by_id(args.data.client_id) if client and client.name
== "pylsp" then vim.keymap.set("n", "<leader>le", function() local pylsp_picker
= require("<module_name>") pylsp_picker.pyenvs() end, { desc = "[e]nvironment
(python)", buffer = args.buf }) end end })