Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Per package dependency versioning via vim.dep #3

Open
tjdevries opened this issue Feb 7, 2022 · 1 comment
Open

Per package dependency versioning via vim.dep #3

tjdevries opened this issue Feb 7, 2022 · 1 comment

Comments

@tjdevries
Copy link

-- Usage:
local path = vim.dep "plenary.path"

Implementation:

-- instead of deps, we can call it `lua_modules` :cry:
--
-- TODO: Add `deps` stuff to `package.path` so then you could drop all of this in deps/
-- deps/
--  myplugin__plenary__commit

-- Could also add:
-- $ROOT/deps/
-- $ROOT/lua/deps/...
-- For now this works with $ROOT/lua/deps since then `require` bits get to work for free.
-- if we add a new searcher, then it would probably work fine either way.

local uv = vim.loop

-- YOU CAN ONLY CALL THIS FUNCTION FROM THE APPROPRIATE LEVEL OF NESTEDNESS
-- OTHERWISE YOU GET THE WRONG PATH. CAREFUL OF THIS ONE!
local function get_script_path()
  local path = debug.getinfo(3, "S").source:sub(2):match "(.*/)"
  return uv.fs_realpath(path)
end

local function find_plugin_root(path)
  -- TODO: Windows Sadge
  local parts = vim.split(path, "/")
  while #parts > 0 do
    local subpath = table.concat(parts, "/")
    if uv.fs_stat(subpath .. "/plugin.lua") then
      return subpath
    end

    table.remove(parts, #parts)
  end

  return nil
end

local function get_dep_name(name)
  name = string.gsub(name, "/", ".")
  return vim.split(name, "%.")[1]
end

local function make_dep_path(plug_name, dep_name, version, name)
  return string.format("deps.%s__%s__%s.lua.%s", plug_name, dep_name, version, name)
end

local dep = function(name)
  local plugin_script = get_script_path()
  local dep_name = get_dep_name(name)

  local plugin_root = find_plugin_root(plugin_script)
  if plugin_root then
    local plugin_config = loadfile(plugin_root .. "/plugin.lua")()
    local plugin_deps = plugin_config.dependencies
    if not plugin_deps[dep_name] then
      error(string.format("Could not find dependency: %s // %s", dep_name, name))
    end

    -- TODO: This is a bit goofy, but it makes it so that we can
    -- still use require easily.
    local dep_version = string.gsub(plugin_deps[dep_name], "%.", "-")
    local dep_path = make_dep_path(plugin_config.name, dep_name, dep_version, name)

    NESTED_REQUIRE = true
    local ok, mod = pcall(require, dep_path)
    NESTED_REQUIRE = false

    if not ok then
      error(mod)
    end

    return mod
    -- return setfenv(require, {
    --   require = function(req_name)
    --     error(req_name)
    --   end,
    -- })(dep_path)
  end

  error(string.format("Unable to find plugin root: %s // %s", name, plugin_script))
end


vim.dep = dep
@ii14
Copy link
Member

ii14 commented Feb 8, 2022

The idea is to have multiple versions of the same package? I think in order for that to be a thing, dependencies would have to explicitly declare that they promise not to modify the global state in any way, so you don't have multiple versions fighting over the same global variable or something like that.

@mjlbach mjlbach changed the title vim.dep Per package dependency versioning via vim.dep Mar 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants