Files
nvim-config/lua/setup/init.lua

195 lines
5.3 KiB
Lua

local lock_path = vim.fs.joinpath(vim.fn.stdpath('config'), 'paq-lock.json')
local paq_removed_status = 3
local function clone_paq()
local path = vim.fn.stdpath('data') .. '/site/pack/paqs/opt/paq-nvim'
if not vim.uv.fs_stat(path) then
local repo = 'https://github.com/savq/paq-nvim.git'
local result = vim.system({ 'git', 'clone', '--depth=1', repo, path }):wait()
if result.code == 0 then
print('Package manager installed correctly')
end
end
end
local function load_paq()
vim.cmd.packadd('paq-nvim')
local paq = require('paq')
local packages = require('setup.packages').get()
paq:setup({ lock = lock_path })(packages)
return paq
end
local function run_paq(event, operation)
local done = false
vim.api.nvim_create_autocmd('User', {
pattern = event,
once = true,
callback = function()
done = true
end,
})
operation()
vim.wait(60000, function()
return done
end, 200)
return done
end
local function install_packages()
clone_paq()
local paq = load_paq()
if not run_paq('PaqDoneInstall', paq.install) then
print('Paq installation timeout or failed')
else
print('Paq installation completed')
end
end
local function assert_no_unlisted_package_dirs(paq)
local expected_dirs = {}
for _, filter in ipairs({ 'installed', 'to_install' }) do
for _, pkg in ipairs(paq.query(filter)) do
expected_dirs[pkg.dir] = true
end
end
local stale_dirs = {}
local paq_path = vim.fs.joinpath(vim.fn.stdpath('data'), 'site', 'pack', 'paqs')
for _, packdir in ipairs({ 'start', 'opt' }) do
local path = vim.fs.joinpath(paq_path, packdir)
if vim.uv.fs_stat(path) then
for name, type in vim.fs.dir(path) do
local dir = vim.fs.joinpath(path, name)
if type == 'directory' and not expected_dirs[dir] then
table.insert(stale_dirs, dir)
end
end
end
end
if #stale_dirs > 0 then
error('Paq cleanup left unlisted package directories:\n' .. table.concat(stale_dirs, '\n'))
end
end
local function prune_removed_lock_entries()
if vim.fn.filereadable(lock_path) == 0 then
return
end
local raw = table.concat(vim.fn.readfile(lock_path), '\n')
local lock = vim.json.decode(raw)
local changed = false
for name, pkg in pairs(lock) do
if pkg.status == paq_removed_status then
lock[name] = nil
changed = true
end
end
if changed then
vim.fn.writefile({ vim.json.encode(lock) }, lock_path)
end
end
local function reconcile_packages()
clone_paq()
local paq = load_paq()
if not run_paq('PaqDoneRemove', paq.clean) then
print('Paq cleanup timeout or failed')
return
end
assert_no_unlisted_package_dirs(paq)
prune_removed_lock_entries()
if not run_paq('PaqDoneInstall', paq.install) then
print('Paq installation timeout or failed')
else
print('Paq packages reconciled')
end
end
local function install_languages()
vim.cmd.packadd('mason.nvim')
require('mason').setup()
local lm = require('plugins.language-manager')
lm.invalidate_cache()
lm.load_specs()
lm.install()
end
local function sync_packages()
clone_paq()
local paq = load_paq()
if not run_paq('PaqDoneSync', function()
paq:sync()
end) then
print('Paq sync timeout or failed')
else
print('Paq sync completed')
end
end
local function fetch_lsp_configs()
local base_url = 'https://raw.githubusercontent.com/neovim/nvim-lspconfig/refs/heads/master/lsp/'
local lm = require('plugins.language-manager')
lm.invalidate_cache()
local general = lm.load_specs()
local lsp_dir = vim.fs.joinpath(vim.fn.stdpath('config'), 'lsp')
vim.fn.mkdir(lsp_dir, 'p')
for _, name in ipairs(general.language_servers or {}) do
local file = vim.fs.joinpath(lsp_dir, name .. '.lua')
if vim.fn.filereadable(file) == 0 then
local url = base_url .. name .. '.lua'
local cmd = string.format('curl -fsSL -o %q %q', file, url)
vim.fn.system(cmd)
if vim.v.shell_error ~= 0 then
vim.notify('Failed to fetch ' .. name .. '.lua', vim.log.levels.ERROR)
vim.fn.delete(file)
else
vim.notify('Fetched ' .. name .. '.lua', vim.log.levels.INFO)
end
else
vim.notify('Skipped existing ' .. name .. '.lua', vim.log.levels.INFO)
end
end
end
local function create_command(name, callback, desc)
vim.api.nvim_create_user_command(name, callback, { desc = desc })
end
create_command('Setup', function()
print('> Reconciling packages...')
reconcile_packages()
print('\n> Installing languages: treesitter parsers, language servers, linters, formatters...')
install_languages()
print('\n=== Setup Finished ===\n')
end, 'Install packages and language tooling (first-time setup)')
create_command('InstallPackages', function()
print('> Installing packages...')
install_packages()
print('\n=== Package Install Finished ===\n')
end, 'Install packages via Paq')
create_command('InstallLanguages', function()
print('> Installing languages: treesitter parsers, language servers, linters, formatters...')
install_languages()
print('\n=== Language Install Finished ===\n')
end, 'Install treesitter, LSP, linter, and formatter tooling')
create_command('Sync', sync_packages, 'Sync packages with Paq')
create_command('FetchLspConfigs', fetch_lsp_configs, 'Fetch default LSP configs into lsp/')