Skip to content

Commit

Permalink
udpate
Browse files Browse the repository at this point in the history
  • Loading branch information
glepnir committed Sep 29, 2024
1 parent 4ed7575 commit 294adec
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 100 deletions.
39 changes: 39 additions & 0 deletions lua/minpm/async.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
local function wrap_async(func)
return function(...)
local args = { ... }
return function(callback)
table.insert(args, callback)
func(unpack(args))
end
end
end

local function await(promise)
local co = coroutine.running()
promise(function(...)
local args = { ... }
vim.schedule(function()
assert(coroutine.resume(co, unpack(args)))
end)
end)
return coroutine.yield()
end

local function async(func)
return function(...)
local co = coroutine.create(func)
local function step(...)
local ok, err = coroutine.resume(co, ...)
if not ok then
error(err)
end
end
step(...)
end
end

return {
async_fs_fstat = wrap_async(vim.uv.fs_fstat),
async = async,
await = await,
}
6 changes: 6 additions & 0 deletions lua/minpm/event.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
local api = vim.api
local au = api.nvim_create_autocmd

local M = {}

return M
146 changes: 46 additions & 100 deletions lua/minpm/init.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local api, stdpath, uv = vim.api, vim.fn.stdpath, vim.uv
local api, stdpath, uv, if_nil = vim.api, vim.fn.stdpath, vim.uv, vim.F.if_nil
local repos, INSTALL = {}, 0
local buf_set_lines, create_autocmd = api.nvim_buf_set_lines, api.nvim_create_autocmd
local create_autocmd = api.nvim_create_autocmd
local packadd = vim.cmd.packadd
local exec_autocmds = api.nvim_exec_autocmds
local data_dir = stdpath('data')
Expand All @@ -10,7 +10,7 @@ local STARTDIR = vim.fs.joinpath(data_dir, 'site', 'pack', 'minpm', 'start')
local OPTDIR = vim.fs.joinpath(data_dir, 'site', 'pack', 'minpm', 'opt')
---@diagnostic disable-next-line: param-type-mismatch
vim.opt.packpath:prepend(vim.fs.joinpath(data_dir, 'site'))
local if_nil = vim.F.if_nil
local window, TaskQueue = require('minpm.win'), require('minpm.task')

local function as_table(data)
return type(data) ~= 'table' and { data } or data
Expand All @@ -19,132 +19,77 @@ end
local use_meta = {}
use_meta.__index = use_meta

function use_meta:when(e)
self.event = as_table(e)
self.islazy = true
local id
id = create_autocmd(e, {
function use_meta:handle_event()
self.auid = create_autocmd(self.event, {
pattern = self.ft or nil,
callback = function(args)
if self.remote then
api.nvim_del_autocmd(id)
packadd(self.tail)
exec_autocmds(e, {
modeline = false,
data = args.data,
})
if self.setup_config then
local module = self.tail:gsub('%.nvim', ''):gsub('-nvim', '')
require(module).setup(self.setup_config)
end
if not self.remote then
return
end

api.nvim_del_autocmd(self.auid)
packadd(self.tail)
local module = self.tail:gsub('%.nvim$', ''):gsub('-nvim$', ''):gsub('^nvim%-', '')
local m_setup = vim.tbl_get(require(module), 'setup')
if type(m_setup) == 'function' then
m_setup(self.setup_config)
end

if self.after_config then
self.after_config()
end

exec_autocmds(self.event, {
modeline = false,
data = args.data,
})
end,
})
end

function use_meta:when(e)
self.event = as_table(e)
self.islazy = true
self:handle_event()
return self
end

function use_meta:lang(ft)
self.ft = as_table(ft)
self.event = 'FileType'
self:handle_event()
self.islazy = true
return self
end

function use_meta:setup(config)
self.setup_config = config
function use_meta:dev()
self.isdev = true
self.remote = false
return self
end

function use_meta:config(config)
assert(type(config) == 'function')
self.config = config
function use_meta:setup(setup_config)
self.setup_config = setup_config
return self
end

local window = {}
function window:new()
local o = {}
setmetatable(o, self)
self.__index = self
self.content = {}
self.last_row = -1
return o
end

function window:create_window()
self.bufnr = api.nvim_create_buf(false, false)
self.winid = api.nvim_open_win(self.bufnr, true, {
relative = 'editor',
height = math.floor(vim.o.lines * 0.5),
width = math.floor(vim.o.columns * 0.8),
row = 3,
col = 10,
border = 'rounded',
noautocmd = true,
style = 'minimal',
})
vim.wo[self.winid].wrap = false
vim.bo[self.bufnr].buftype = 'nofile'
vim.bo[self.bufnr].bufhidden = 'wipe'
vim.keymap.set('n', 'q', function()
if self.winid and api.nvim_win_is_valid(self.winid) then
api.nvim_win_close(self.winid, true)
self.bufnr, self.winid = nil, nil
end
end, { buffer = self.bufnr, desc = 'quit window' })
end

function window:get_row(repo_name)
if not vim.list_contains(self.content, repo_name) then
self.content[#self.content + 1] = repo_name
return #self.content
end
for k, v in ipairs(self.content) do
if v == repo_name then
return k
end
end
end

function window:write_output(name, data)
local row = self:get_row(name) - 1
vim.schedule(function()
if not self.bufnr then
self:create_window()
end
vim.bo[self.bufnr].modifiable = true
buf_set_lines(self.bufnr, row, row + 1, false, { ('%s: %s'):format(name, data) })
vim.bo[self.bufnr].modifiable = false
end)
function use_meta:config(config)
assert(type(config) == 'function')
self.after_config = config
return self
end

local MAX_CONCURRENT_TASKS = if_nil(vim.g.minpm_max_concurrent_tasks, 2)
local active_tasks = 0
local task_queue = {}

local function process_queue()
while active_tasks < MAX_CONCURRENT_TASKS and #task_queue > 0 do
local task = table.remove(task_queue, 1)
active_tasks = active_tasks + 1
task(function()
active_tasks = active_tasks - 1
process_queue()
end)
end
end

local function queue_task(fn)
table.insert(task_queue, fn)
process_queue()
end
local tsq = TaskQueue:new(MAX_CONCURRENT_TASKS)

function use_meta:do_action(action, winobj)
queue_task(function(task_done)
tsq:queue_task(function(task_done)
local path = vim.fs.joinpath(self.islazy and OPTDIR or STARTDIR, self.tail)
local url = ('https://github.com/%s'):format(self.name)
local cmd = action == INSTALL and { 'git', 'clone', '--progress', url, path }
or { 'git', '-C', path, 'pull', '--progress' }
uv.fs_stat(path, function(_, stat)
if stat and stat.type == 'directory' then
winobj:write_output(self.name, 'Directory already exists skipped')
task_done()
return
end
Expand Down Expand Up @@ -173,10 +118,11 @@ function use_meta:do_action(action, winobj)
end

local function action_wrapper(act)
act = act or INSTALL
return function()
local winobj = window:new()
vim.iter(repos):map(function(repo)
if not repo.remote then
if not repo.remote or repo.isdev then
return
end
repo:do_action(act, winobj)
Expand Down
32 changes: 32 additions & 0 deletions lua/minpm/task.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
local TaskQueue = {}
TaskQueue.__index = TaskQueue

function TaskQueue:new(max_concurrent)
return setmetatable({
active_tasks = 0,
max_concurrent_tasks = max_concurrent or 2,
task_queue = {},
}, TaskQueue)
end

function TaskQueue:process_queue()
while self.active_tasks < self.max_concurrent_tasks and #self.task_queue > 0 do
local task = table.remove(self.task_queue, 1)
self.active_tasks = self.active_tasks + 1

task(function()
self.active_tasks = self.active_tasks - 1
self:process_queue() -- Continue processing the queue
end)
end
end

--- @class ActionFn function
---
--- @param fn ActionFn
function TaskQueue:queue_task(fn)
table.insert(self.task_queue, fn)
self:process_queue()
end

return TaskQueue
67 changes: 67 additions & 0 deletions lua/minpm/win.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
local api = vim.api

local window = {}
function window:new()
local o = {}
setmetatable(o, self)
self.__index = self
self.content = {}
self.last_row = -1
return o
end
function window:create_buffer()
self.bufnr = api.nvim_create_buf(false, false)
vim.bo[self.bufnr].buftype = 'nofile'
vim.bo[self.bufnr].bufhidden = 'wipe'
end

function window:set_mappings()
vim.keymap.set('n', 'q', function()
if self.winid and api.nvim_win_is_valid(self.winid) then
api.nvim_win_close(self.winid, true)
self.bufnr, self.winid = nil, nil
end
end, { buffer = self.bufnr, desc = 'quit window' })
end

function window:create_window()
self:create_buffer()
self.winid = api.nvim_open_win(self.bufnr, true, {
relative = 'editor',
height = math.floor(vim.o.lines * 0.5),
width = math.floor(vim.o.columns * 0.8),
row = 3,
col = 10,
border = 'rounded',
noautocmd = true,
style = 'minimal',
})
vim.wo[self.winid].wrap = false
self:set_mappings()
end

function window:get_row(repo_name)
if not vim.list_contains(self.content, repo_name) then
self.content[#self.content + 1] = repo_name
return #self.content
end
for k, v in ipairs(self.content) do
if v == repo_name then
return k
end
end
end

function window:write_output(name, data)
local row = self:get_row(name) - 1
vim.schedule(function()
if not self.bufnr then
self:create_window()
end
vim.bo[self.bufnr].modifiable = true
api.nvim_buf_set_lines(self.bufnr, row, row + 1, false, { ('%s: %s'):format(name, data) })
vim.bo[self.bufnr].modifiable = false
end)
end

return window

0 comments on commit 294adec

Please sign in to comment.