aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/installers/pip3.lua
blob: 3dd44167ffba6f645c06d360cbec528960078c0d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
local path = require "nvim-lsp-installer.path"
local Data = require "nvim-lsp-installer.data"
local installers = require "nvim-lsp-installer.installers"
local std = require "nvim-lsp-installer.installers.std"
local platform = require "nvim-lsp-installer.platform"
local process = require "nvim-lsp-installer.process"
local settings = require "nvim-lsp-installer.settings"
local context = require "nvim-lsp-installer.installers.context"
local log = require "nvim-lsp-installer.log"

local M = {}

local REL_INSTALL_DIR = "venv"

---@param python_executable string
---@param packages string[]
local function create_installer(python_executable, packages)
    return installers.pipe {
        std.ensure_executables {
            {
                python_executable,
                ("%s was not found in path. Refer to https://www.python.org/downloads/."):format(python_executable),
            },
        },
        ---@type ServerInstallerFunction
        function(_, callback, ctx)
            local pkgs = Data.list_copy(packages or {})
            local c = process.chain {
                cwd = ctx.install_dir,
                stdio_sink = ctx.stdio_sink,
                env = process.graft_env(M.env(ctx.install_dir)),
            }

            c.run(python_executable, { "-m", "venv", REL_INSTALL_DIR })
            if ctx.requested_server_version then
                -- The "head" package is the recipient for the requested version. It's.. by design... don't ask.
                pkgs[1] = ("%s==%s"):format(pkgs[1], ctx.requested_server_version)
            end

            local install_command = { "-m", "pip", "install", "-U" }
            vim.list_extend(install_command, settings.current.pip.install_args)
            c.run("python", vim.list_extend(install_command, pkgs))

            c.spawn(callback)
        end,
    }
end

---@param packages string[] @The pip packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
function M.packages(packages)
    local py3 = create_installer("python3", packages)
    local py = create_installer("python", packages)
    -- see https://github.com/williamboman/nvim-lsp-installer/issues/128
    local installer_variants = platform.is_win and { py, py3 } or { py3, py }

    local py3_host_prog = vim.g.python3_host_prog
    if py3_host_prog then
        log.fmt_trace("Found python3_host_prog (%s)", py3_host_prog)
        table.insert(installer_variants, 1, create_installer(py3_host_prog, packages))
    end

    return installers.pipe {
        context.promote_install_dir(),
        installers.first_successful(installer_variants),
    }
end

---@param root_dir string @The directory to resolve the executable from.
function M.env(root_dir)
    return {
        PATH = process.extend_path {
            path.concat { root_dir, REL_INSTALL_DIR, platform.is_win and "Scripts" or "bin" },
        },
    }
end

return M