commit 9185229a793f622aa1174523956e625c2ff22106
parent 068096dbfc5939c1f9194dbac06184e1a64c364e
Author: Oscar Benedito <oscar@oscarbenedito.com>
Date:   Sat, 11 Feb 2023 14:23:28 +0100

Minor changes and paq-nvim update

Diffstat:
M.config/nvim/lua/paq.lua | 197++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
M.config/xinitrc | 2+-
M.config/zsh/zshenv | 1+
3 files changed, 111 insertions(+), 89 deletions(-)

diff --git a/.config/nvim/lua/paq.lua b/.config/nvim/lua/paq.lua @@ -1,6 +1,6 @@ -- This file is a modified version of paq-nvim (https://github.com/savq/paq-nvim), -- which has the following notice. --- Last update: 2022-08-31 (commit bc5950b990729464f2493b1eaab5a7721bd40bf5) +-- Last update: 2023-02-11 (commit 31556e9451300eb0fdc3ba45994ea83eea9f4bb2) -- MIT License -- @@ -28,40 +28,45 @@ local uv = vim.loop local cfg = { path = vim.fn.stdpath("data") .. "/site/pack/paqs/", + opt = false, verbose = false, + url_format = "https://github.com/%s.git", } local logpath = vim.fn.has("nvim-0.8") == 1 and vim.fn.stdpath("log") or vim.fn.stdpath("cache") local logfile = logpath .. "/paq.log" -local packages = {} -- 'name' = {options...} pairs -local messages = { - install = { ok = "Installed", err = "Failed to install" }, - update = { ok = "Updated", err = "Failed to update", nop = "(up-to-date)" }, - remove = { ok = "Removed", err = "Failed to remove" }, - hook = { ok = "Ran hook for", err = "Failed to run hook for" }, -} +local packages = {} -- "name" = {options...} pairs -- This is done only once. Doing it for every process seems overkill local env = {} -local envfn = vim.fn.has('nvim-0.6') == 1 and uv.os_environ or vim.fn.environ -- compat +local envfn = vim.fn.has("nvim-0.6") == 1 and uv.os_environ or vim.fn.environ for var, val in pairs(envfn()) do - table.insert(env, ("%s=%s"):format(var, val)) + table.insert(env, string.format("%s=%s", var, val)) end table.insert(env, "GIT_TERMINAL_PROMPT=0") vim.cmd([[ - command! PaqInstall lua require('paq'):install() - command! PaqUpdate lua require('paq'):update() - command! PaqClean lua require('paq'):clean() - command! PaqSync lua require('paq'):sync() - command! PaqList lua require('paq').list() - command! PaqLogOpen lua require('paq').log_open() - command! PaqLogClean lua require('paq').log_clean() - command! -nargs=1 -complete=customlist,v:lua.require'paq'._get_hooks PaqRunHook lua require('paq')._run_hook(<f-args>) + command! -bar PaqInstall lua require('paq'):install() + command! -bar PaqUpdate lua require('paq'):update() + command! -bar PaqClean lua require('paq'):clean() + command! -bar PaqSync lua require('paq'):sync() + command! -bar PaqList lua require('paq').list() + command! -bar PaqLogOpen lua require('paq').log_open() + command! -bar PaqLogClean lua require('paq').log_clean() + command! -bar -nargs=1 -complete=customlist,v:lua.require'paq'._get_hooks PaqRunHook lua require('paq')._run_hook(<f-args>) ]]) local function report(op, name, res, n, total) - local count = n and (" [%d/%d]"):format(n, total) or "" - vim.notify((" Paq:%s %s %s"):format(count, messages[op][res], name), res == "err" and vim.log.levels.ERROR) + local messages = { + install = { ok = "Installed", err = "Failed to install" }, + update = { ok = "Updated", err = "Failed to update", nop = "(up-to-date)" }, + remove = { ok = "Removed", err = "Failed to remove" }, + hook = { ok = "Ran hook for", err = "Failed to run hook for" }, + } + local count = n and string.format(" [%d/%d]", n, total) or "" + vim.notify( + string.format(" Paq:%s %s %s", count, messages[op][res], name), + res == "err" and vim.log.levels.ERROR + ) end local function new_counter() @@ -74,8 +79,8 @@ local function new_counter() report(over_op or op, name, res, c.ok + c.nop, total) end end - local summary = (" Paq: %s complete. %d ok; %d errors;" .. (c.nop > 0 and " %d no-ops" or "")) - vim.notify(summary:format(op, c.ok, c.err, c.nop)) + local summary = " Paq: %s complete. %d ok; %d errors;" .. (c.nop > 0 and " %d no-ops" or "") + vim.notify(string.format(summary, op, c.ok, c.err, c.nop)) vim.cmd("packloadall! | silent! helptags ALL") vim.cmd("doautocmd User PaqDone" .. op:gsub("^%l", string.upper)) return true @@ -102,12 +107,6 @@ local function call_proc(process, args, cwd, cb, print_stdout) end end -local function log(message) - local log = uv.fs_open(logfile, "a+", 0x1A4) - uv.fs_write(log, message .. '\n') - uv.fs_close(log) -end - local function run_hook(pkg, counter, sync) local t = type(pkg.run) if t == "function" then @@ -164,6 +163,27 @@ local function get_git_hash(dir) return head_ref and first_line(dir .. "/.git/" .. head_ref:gsub("ref: ", "")) end +local function log_update_changes(pkg, prev_hash, cur_hash) + local output = {"\n\n" .. pkg.name .. " updated:\n"} + local stdout = uv.new_pipe() + local options = { + args = {"log", "--pretty=format:* %s", prev_hash .. ".." .. cur_hash}, + cwd = pkg.dir, stdio = {nil, stdout, nil}, + } + local handle + handle, _ = uv.spawn('git', options, function(code) + assert(code == 0, "Exited(" .. code .. ")") + handle:close() + local log = uv.fs_open(logfile, "a+", 0x1A4) + uv.fs_write(log, output, nil, nil) + uv.fs_close(log) + end) + stdout:read_start(function(err, data) + assert(not err, err) + table.insert(output, data) + end) +end + local function pull(pkg, counter, sync) local prev_hash = get_git_hash(pkg.dir) call_proc("git", { "pull", "--recurse-submodules", "--update-shallow" }, pkg.dir, function(ok) @@ -172,8 +192,7 @@ local function pull(pkg, counter, sync) else local cur_hash = get_git_hash(pkg.dir) if cur_hash ~= prev_hash then - log(pkg.name .. " updating...") - call_proc("git", { "log", "--pretty=format:* %s", prev_hash .. ".." .. cur_hash }, pkg.dir, function(ok) end, true) + log_update_changes(pkg, prev_hash, cur_hash) pkg.status = "updated" return pkg.run and run_hook(pkg, counter, sync) or counter(pkg.name, "ok", sync) else @@ -191,49 +210,59 @@ local function clone_or_pull(pkg, counter) end end -local function walk_dir(path, fn) - local handle = uv.fs_scandir(path) - while handle do - local name, t = uv.fs_scandir_next(handle) - if not name then - break - end - if not fn(path .. "/" .. name, name, t) then - return +-- Return an interator that walks `dir` in post-order. +local function walkdir(dir) + return coroutine.wrap(function() + local handle = uv.fs_scandir(dir) + while handle do + local name, t = uv.fs_scandir_next(handle) + if not name then + return + elseif t == "directory" then + for child, t in walkdir(dir .. "/" .. name) do + coroutine.yield(child, t) + end + end + coroutine.yield(dir .. "/" .. name, t) end - end - return true + end) end -local function check_rm() - local to_remove = {} - for _, packdir in pairs({ "start", "opt" }) do - walk_dir(cfg.path .. packdir, function(dir, name) - if name == "paq-nvim" then - return true - end - local pkg = packages[name] - if not (pkg and pkg.dir == dir) then - table.insert(to_remove, { name = name, dir = dir }) - end - return true - end) +local function rmdir(dir) + for name, t in walkdir(dir) do + local ok = (t == "directory") and uv.fs_rmdir(name) or uv.fs_unlink(name) + if not ok then + return ok + end end - return to_remove + return uv.fs_rmdir(dir) end -local function rmdir(dir, name, t) - if t == "directory" then - return walk_dir(dir, rmdir) and uv.fs_rmdir(dir) - else - return uv.fs_unlink(dir) +local function find_unlisted() + local unlisted = {} + -- TODO(breaking): Replace with `vim.fs.dir` + for _, packdir in pairs { "start", "opt" } do + local path = cfg.path .. packdir + local handle = uv.fs_scandir(path) + while handle do + local name, t = uv.fs_scandir_next(handle) + if t == "directory" and name ~= "paq-nvim" then + local dir = path .. "/" .. name + local pkg = packages[name] + if not pkg or pkg.dir ~= dir then + table.insert(unlisted, { name = name, dir = dir }) + end + elseif not name then + break + end + end end + return unlisted end local function remove(p, counter) - local ok = walk_dir(p.dir, rmdir) and uv.fs_rmdir(p.dir) + local ok = rmdir(p.dir) counter(p.name, ok and "ok" or "err") - if ok then packages[p.name] = { name = p.name, status = "removed" } end @@ -255,43 +284,35 @@ end -- stylua: ignore local function list() local installed = vim.tbl_filter(function(pkg) return pkg.exists end, packages) - table.sort(installed, function(a, b) return a.name < b.name end) - local removed = vim.tbl_filter(function(pkg) return pkg.status == "removed" end, packages) - table.sort(removed, function(a, b) return a.name < b.name end) - - local sym_tbl = { installed = "+", updated = "*", removed = " " } - for header, pkgs in pairs({ ["Installed packages:"] = installed, ["Recently removed:"] = removed }) do + local sort_by_name = function(a, b) return a.name < b.name end + table.sort(installed, sort_by_name) + table.sort(removed, sort_by_name) + local markers = { installed = "+", updated = "*" } + for header, pkgs in pairs { ["Installed packages:"] = installed, ["Recently removed:"] = removed } do if #pkgs ~= 0 then print(header) for _, pkg in ipairs(pkgs) do - print(" ", sym_tbl[pkg.status] or " ", pkg.name) + print(" ", markers[pkg.status] or " ", pkg.name) end end end end -local function parse_name(args) - if args.as then - return args.as - elseif args.url then - return args.url:gsub("%.git$", ""):match("/([%w-_.]+)$"), args.url - else - return args[1]:match("^[%w-]+/([%w-_.]+)$"), args[1] - end -end - local function register(args) if type(args) == "string" then args = { args } end - local name, src = parse_name(args) + local url = args.url + or (args[1]:match("^https?://") and args[1]) -- [1] is a URL + or string.format(cfg.url_format, args[1]) -- [1] is a repository name + local name = args.as + or url:gsub("%.git$", ""):match("/([%w-_.]+)$") -- Infer name from `url` if not name then - return vim.notify(" Paq: Failed to parse " .. src, vim.log.levels.ERROR) - elseif packages[name] then - return + return vim.notify(" Paq: Failed to parse " .. vim.inspect(args), vim.log.levels.ERROR) end - local dir = cfg.path .. (args.opt and "opt/" or "start/") .. name + local opt = args.opt or cfg.opt and args.opt == nil + local dir = cfg.path .. (opt and "opt/" or "start/") .. name packages[name] = { name = name, branch = args.branch, @@ -299,8 +320,8 @@ local function register(args) exists = vim.fn.isdirectory(dir) ~= 0, status = "listed", -- TODO: should probably merge this with `exists` in the future... pin = args.pin, - run = args.run, - url = args.url or "https://github.com/" .. args[1] .. ".git", + run = args.run, -- TODO(breaking): Rename + url = url, -- Oscar: add this line shallow = args.shallow == nil or args.shallow, -- end @@ -311,7 +332,7 @@ end return setmetatable({ install = function() exe_op("install", clone, vim.tbl_filter(function(pkg) return not pkg.exists and pkg.status ~= "removed" end, packages)) end, update = function() exe_op("update", pull, vim.tbl_filter(function(pkg) return pkg.exists and not pkg.pin end, packages)) end, - clean = function() exe_op("remove", remove, check_rm()) end, + clean = function() exe_op("remove", remove, find_unlisted()) end, sync = function(self) self:clean() exe_op("sync", clone_or_pull, vim.tbl_filter(function(pkg) return pkg.status ~= "removed" end, packages)) end, setup = function(self, args) for k, v in pairs(args) do cfg[k] = v end return self end, _run_hook = function(name) return run_hook(packages[name]) end, @@ -319,7 +340,7 @@ return setmetatable({ list = list, log_open = function() vim.cmd("sp " .. logfile) end, log_clean = function() return assert(uv.fs_unlink(logfile)) and vim.notify(" Paq: log file deleted") end, - register = function(pkg) register(pkg) end, + register = register, paq = register, -- TODO: deprecate. not urgent }, {__call = function(self, tbl) packages = {} vim.tbl_map(register, tbl) return self end, }) diff --git a/.config/xinitrc b/.config/xinitrc @@ -1,6 +1,6 @@ /home/oscar/.local/bin/configure-monitors xrdb ~/.config/Xresources -feh --bg-scale "${XDG_DATA_HOME:-$HOME/.local/share}/dwm/wallpaper.png" & +feh --no-fehbg --bg-scale "${XDG_DATA_HOME:-$HOME/.local/share}/dwm/wallpaper.png" & xautolock -detectsleep -corners 0-00 -time 5 \ -locker "slock" \ -notify 30 \ diff --git a/.config/zsh/zshenv b/.config/zsh/zshenv @@ -21,6 +21,7 @@ export ICEAUTHORITY="$XDG_CACHE_HOME/ICEauthority" export RXVT_SOCKET="$XDG_RUNTIME_DIR/urxvtd" export LESSHISTFILE="-" export XINITRC="$XDG_CONFIG_HOME/xinitrc" +export CARGO_HOME="$XDG_DATA_HOME/cargo" # Environment variables export VISUAL="nvim"