feat(plugins): replace scooter find‑replace with grug‑far and add Python interpreter resolution
This commit is contained in:
1 parent
28bd9b89f5
commit
77b718c77f
7 files changed
+203
-337
No files matched your search
@@ -0,0 +1,88 @@
|
||||
--- Python: interpreter resolution for basedpyright.
|
||||
---
|
||||
--- The astrocommunity basedpyright subpack pins `python.pythonPath` to
|
||||
--- `exepath "python"`, i.e. the system interpreter. Builtins and the stdlib
|
||||
--- (`enumerate`, `collections.Counter`, ...) come from basedpyright's bundled
|
||||
--- typeshed either way, but third-party imports only resolve — and only
|
||||
--- complete — when the server points at the environment that has them, which
|
||||
--- for a uv/poetry/venv project is the project's own virtualenv.
|
||||
---
|
||||
--- Resolution order: activated environment ($VIRTUAL_ENV / $CONDA_PREFIX) ->
|
||||
--- a virtualenv inside the LSP root -> system python3.
|
||||
--- `<Leader>lv` (venv-selector, from the base pack) still overrides at runtime.
|
||||
--- @module plugins.python
|
||||
|
||||
local VENV_DIRS = { ".venv", "venv", "env" }
|
||||
local ROOT_MARKERS = { "pyproject.toml", "uv.lock", "setup.py", "setup.cfg", "requirements.txt", ".git" }
|
||||
|
||||
--- @param path string? candidate interpreter
|
||||
--- @return string? path when it is an executable file
|
||||
local function executable(path)
|
||||
if not path or path == "" then return nil end
|
||||
local stat = vim.uv.fs_stat(path)
|
||||
if stat and stat.type == "file" and vim.fn.executable(path) == 1 then return path end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- @param root string? project root
|
||||
--- @return string interpreter absolute path or bare name
|
||||
local function python_path(root)
|
||||
local activated = vim.env.VIRTUAL_ENV or vim.env.CONDA_PREFIX
|
||||
local found = activated and executable(activated .. "/bin/python")
|
||||
if found then return found end
|
||||
|
||||
if root then
|
||||
for _, dir in ipairs(VENV_DIRS) do
|
||||
found = executable(root .. "/" .. dir .. "/bin/python")
|
||||
if found then return found end
|
||||
end
|
||||
end
|
||||
|
||||
return executable(vim.fn.exepath "python3") or "python3"
|
||||
end
|
||||
|
||||
local warned = {} ---@type table<string, true> roots already warned about
|
||||
|
||||
--- A locked project with no virtualenv checked out resolves against the system
|
||||
--- interpreter, where its dependencies are missing. That reads as "the LSP is
|
||||
--- broken" rather than "nothing is installed", so say it out loud once.
|
||||
--- @param root string?
|
||||
--- @param interpreter string
|
||||
local function warn_unsynced_project(root, interpreter)
|
||||
if not root or warned[root] or interpreter:find(root, 1, true) then return end
|
||||
local lock = vim.uv.fs_stat(root .. "/uv.lock") or vim.uv.fs_stat(root .. "/poetry.lock")
|
||||
if not lock then return end
|
||||
warned[root] = true
|
||||
vim.schedule(
|
||||
function()
|
||||
vim.notify(
|
||||
("basedpyright: no virtualenv in %s, using %s.\nRun `uv sync` for third-party completions.")
|
||||
:format(vim.fn.fnamemodify(root, ":~"), interpreter),
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
---@type LazySpec
|
||||
return {
|
||||
"AstroNvim/astrolsp",
|
||||
optional = true,
|
||||
---@type AstroLSPOpts
|
||||
opts = {
|
||||
config = {
|
||||
basedpyright = {
|
||||
before_init = function(_, config)
|
||||
local root = config.root_dir or vim.fs.root(0, ROOT_MARKERS)
|
||||
local interpreter = python_path(root)
|
||||
warn_unsynced_project(root, interpreter)
|
||||
config.settings = vim.tbl_deep_extend(
|
||||
"force",
|
||||
config.settings or {},
|
||||
{ python = { pythonPath = interpreter } }
|
||||
)
|
||||
end,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in new issue
Block a user