diff options
-rw-r--r-- | nvim/.config/nvim/lua/plugins/conform.lua | 5 | ||||
-rw-r--r-- | nvim/.config/nvim/lua/tobyvin/autocmds.lua | 73 | ||||
-rw-r--r-- | nvim/.config/nvim/lua/tobyvin/utils.lua | 60 | ||||
-rw-r--r-- | nvim/.config/nvim/lua/tobyvin/utils/buf.lua | 41 | ||||
-rw-r--r-- | nvim/.config/nvim/lua/tobyvin/utils/dashboard.lua | 88 | ||||
-rw-r--r-- | nvim/.config/nvim/lua/tobyvin/utils/fs.lua | 60 | ||||
-rw-r--r-- | nvim/.config/nvim/lua/tobyvin/utils/session.lua | 32 |
7 files changed, 192 insertions, 167 deletions
diff --git a/nvim/.config/nvim/lua/plugins/conform.lua b/nvim/.config/nvim/lua/plugins/conform.lua index 5c630e1..0e544e3 100644 --- a/nvim/.config/nvim/lua/plugins/conform.lua +++ b/nvim/.config/nvim/lua/plugins/conform.lua @@ -6,7 +6,6 @@ local M = { opts = { format_on_save = false, format_after_save = false, - log_level = vim.log.levels.DEBUG, formatters_by_ft = { lua = { "stylua" }, css = { "prettier" }, @@ -14,8 +13,7 @@ local M = { htmldjango = { "djlint" }, tex = { "latexindent" }, plaintex = { "latexindent" }, - -- FIX: Move "injected" back to "*" if/when https://github.com/stevearc/conform.nvim/issues/200 is fixed. - markdown = { "prettier", "markdownlint", "injected" }, + markdown = { "prettier", "markdownlint" }, nginx = { "nginxbeautifier" }, python = { "black" }, -- FIX: Remove if/when https://github.com/stevearc/conform.nvim/issues/127 gets fixed. @@ -24,6 +22,7 @@ local M = { scss = { "prettier" }, sh = { "shfmt" }, PKGBUILD = { "shfmt" }, + ["*"] = { "injected", "trim_whitespace", "trim_newlines" }, }, formatters = { latexindent = { diff --git a/nvim/.config/nvim/lua/tobyvin/autocmds.lua b/nvim/.config/nvim/lua/tobyvin/autocmds.lua index eee8923..cbb55b9 100644 --- a/nvim/.config/nvim/lua/tobyvin/autocmds.lua +++ b/nvim/.config/nvim/lua/tobyvin/autocmds.lua @@ -4,37 +4,21 @@ vim.api.nvim_create_autocmd("TextYankPost", { group = augroup, pattern = "*", callback = function() - vim.highlight.on_yank({ macro = true }) + vim.highlight.on_yank() end, desc = "Highlight yank", }) -vim.api.nvim_create_autocmd("VimLeavePre", { - group = vim.api.nvim_create_augroup("session", { clear = true }), - callback = function() - -- HACK: Workaround for bug preventing restoration of current/alt buffers. - -- See: https://github.com/stevearc/oil.nvim/issues/29 - if vim.bo.filetype == "oil" then - require("oil").close() - end - - if vim.fn.argc() == 0 and #vim.fn.getbufinfo({ buflisted = 1, bufloaded = 1 }) > 0 then - pcall(U.session.write) - end - end, - desc = "write session on vim exit", +vim.api.nvim_create_autocmd("VimEnter", { + group = augroup, + callback = U.buf.on_enter, + desc = "setup initial buffer", }) -vim.api.nvim_create_autocmd("VimEnter", { +vim.api.nvim_create_autocmd("VimLeavePre", { group = augroup, - callback = function() - if vim.fn.argc() == 0 then - local curr_buf = vim.api.nvim_get_current_buf() - U.dashboard.setup() - vim.api.nvim_buf_delete(curr_buf, {}) - end - end, - desc = "show dashboard on startup", + callback = U.session.on_exit, + desc = "write session on vim exit", }) vim.api.nvim_create_autocmd({ "WinEnter", "TermOpen" }, { @@ -50,44 +34,3 @@ vim.api.nvim_create_autocmd("TermOpen", { command = "normal G", desc = "move to bottom of terminal", }) - -vim.api.nvim_create_autocmd("BufWritePre", { - group = augroup, - callback = function(args) - -- HACK: Workaround for writing oil.nvim buffers - if not vim.bo[args.buf].buflisted or vim.bo.filetype == "oil" then - return - end - - local file = vim.loop.fs_realpath(args.match) or args.match - local parent = vim.fn.fnamemodify(file, ":h") - - if not parent then - return - end - - local stat = vim.loop.fs_stat(parent) - - if not stat then - local prompt = string.format("'%s' does not exist. Create it?", parent) - if vim.fn.confirm(prompt, "&Yes\n&No") == 1 then - vim.fn.mkdir(vim.fn.fnamemodify(parent, ":p"), "p") - end - elseif stat.type ~= "directory" then - local msg = string.format("cannot create directory ā%sā: Not a directory", parent) - vim.notify(msg, vim.log.levels.ERROR) - end - end, - desc = "Check for missing directory on write", -}) - -vim.api.nvim_create_autocmd("BufWritePre", { - group = augroup, - pattern = "*", - callback = function() - local cursor = vim.api.nvim_win_get_cursor(0) - vim.cmd("%s/\\s\\+$//e") - vim.api.nvim_win_set_cursor(0, cursor) - end, - desc = "Trim whitespace on write", -}) diff --git a/nvim/.config/nvim/lua/tobyvin/utils.lua b/nvim/.config/nvim/lua/tobyvin/utils.lua index 73d271e..0acbc32 100644 --- a/nvim/.config/nvim/lua/tobyvin/utils.lua +++ b/nvim/.config/nvim/lua/tobyvin/utils.lua @@ -1,15 +1,11 @@ local M = { + fs = require("tobyvin.utils.fs"), + buf = require("tobyvin.utils.buf"), dashboard = require("tobyvin.utils.dashboard"), session = require("tobyvin.utils.session"), dap = require("tobyvin.utils.dap"), - sep = vim.uv.os_uname().version:match("Windows") and "\\" or "/", } ----@param ... string -M.join = function(...) - return table.concat({ ... }, M.sep) -end - function M.inspect(v) print(vim.inspect(v)) return v @@ -96,56 +92,4 @@ function M.extend_hl(ns, name, ...) vim.api.nvim_set_hl(ns, name, hl) end ----@class stdpath ----@field cache fun(...: string): string ----@field config fun(...: string): string ----@field config_dirs fun(...: string): string ----@field data fun(...: string): string ----@field data_dirs fun(...: string): string ----@field log fun(...: string): string ----@field run fun(...: string): string ----@field state fun(...: string): string -M.stdpath = setmetatable({}, { - __call = function(t, dir, ...) - return t[dir](...) - end, - __index = function(t, dir) - local value = vim.fn.stdpath(dir) - if not value or type(value) == "table" then - t[dir] = value - else - t[dir] = function(...) - return table.concat({ vim.fs.dirname(value), ... }, M.sep) - end - end - - return t[dir] - end, -}) - ----Searches upward from <bufnr>'s name for <filename>. If not found, returns the first existing ----fallback or nil if none exist ----@param bufnr integer ----@param filename string ----@param ... string? fallback paths -function M.find(bufnr, filename, ...) - local results = vim.fs.find(filename, { - upward = true, - stop = vim.uv.os_homedir(), - path = vim.fs.dirname(vim.api.nvim_buf_get_name(bufnr)), - }) - vim.list_extend(results, { ... }) - - return vim.iter(results) - :map(function(f) - if not f:starts("/") then - f = M.join(vim.fn.stdpath("config") --[[@as string]], f) - end - return f - end) - :find(function(f) - return vim.fn.filereadable(f) == 1 - end) -end - return M diff --git a/nvim/.config/nvim/lua/tobyvin/utils/buf.lua b/nvim/.config/nvim/lua/tobyvin/utils/buf.lua new file mode 100644 index 0000000..19d62a7 --- /dev/null +++ b/nvim/.config/nvim/lua/tobyvin/utils/buf.lua @@ -0,0 +1,41 @@ +local M = {} + +---@return Iter +function M.iter() + return vim.iter(vim.api.nvim_list_bufs()) +end + +---@param bufnr integer +---@return boolean +function M.is_valid(bufnr) + return vim.api.nvim_buf_is_valid(bufnr) + and vim.api.nvim_buf_is_loaded(bufnr) + and vim.bo[bufnr].buflisted + and vim.bo[bufnr].buftype ~= "nofile" +end + +---@param bufnr integer +---@return boolean +function M.is_invalid(bufnr) + return not M.is_valid(bufnr) +end + +---@param bufnr integer +function M.delete(bufnr, opts) + vim.api.nvim_buf_delete(bufnr, opts or {}) +end + +function M.on_enter() + if vim.fn.argc() == 0 then + vim.bo.buftype = "nofile" + vim.bo.bufhidden = "wipe" + + vim.keymap.set("n", "<leader>sr", U.session.read, { + buffer = 0, + desc = "read session", + }) + end + return true +end + +return M diff --git a/nvim/.config/nvim/lua/tobyvin/utils/dashboard.lua b/nvim/.config/nvim/lua/tobyvin/utils/dashboard.lua index 951dcf5..679666d 100644 --- a/nvim/.config/nvim/lua/tobyvin/utils/dashboard.lua +++ b/nvim/.config/nvim/lua/tobyvin/utils/dashboard.lua @@ -27,7 +27,6 @@ end ---@field augroup integer? ---@field win integer? ---@field buf integer? ----@field setup function local M = { rendered = {}, sections = { @@ -71,11 +70,20 @@ local M = { }, } +function M.next_fortune(bufnr) + M.render(bufnr, 1) +end + +function M.refresh_stats(bufnr) + M.render(bufnr, 3) +end + function M.render(bufnr, index) bufnr = bufnr or 0 - local width = vim.api.nvim_win_get_width(0) - local height = vim.api.nvim_win_get_height(0) + local opts = vim.b[bufnr].dashboard_opts + local width = vim.api.nvim_win_get_width(opts.winid) + local height = vim.api.nvim_win_get_height(opts.winid) local rendered = {} local dashboard = vim.b[bufnr].dashboard or {} @@ -112,10 +120,17 @@ function M.render(bufnr, index) vim.b[bufnr].dashboard = dashboard end -function M.initialize() +function M.initialize(opts) local bufnr = vim.api.nvim_create_buf(false, true) - vim.api.nvim_set_current_buf(bufnr) - local winid = vim.api.nvim_get_current_win() + + if not opts.winid then + if opts.float then + opts.winid = vim.api.nvim_open_win(bufnr, opts.float_enter, opts.float_opts) + else + opts.winid = vim.api.nvim_get_current_win() + vim.api.nvim_win_set_buf(opts.winid, bufnr) + end + end vim.bo[bufnr].textwidth = 0 vim.bo[bufnr].bufhidden = "wipe" @@ -125,36 +140,53 @@ function M.initialize() vim.bo[bufnr].buftype = "nofile" vim.bo[bufnr].filetype = "dashboard" vim.bo[bufnr].synmaxcol = 0 - vim.wo[winid][0].wrap = false - vim.wo[winid][0].colorcolumn = "" - vim.wo[winid][0].foldlevel = 999 - vim.wo[winid][0].foldcolumn = "0" - vim.wo[winid][0].cursorcolumn = false - vim.wo[winid][0].cursorline = false - vim.wo[winid][0].number = false - vim.wo[winid][0].relativenumber = false - vim.wo[winid][0].list = false - vim.wo[winid][0].spell = false - vim.wo[winid][0].signcolumn = "no" - - vim.b[bufnr].dashboard = {} - vim.b[bufnr].dashboard.augroup = vim.api.nvim_create_augroup("dashboard", { clear = true }) + + vim.iter(opts.win_opts):each(function(k, v) + vim.wo[opts.winid][0][k] = v + end) + + vim.b[bufnr].dashboard_opts = opts return bufnr end -function M.next_fortune(bufnr) - M.render(bufnr, 1) +function M.on_enter() + if vim.fn.argc() == 0 then + M.setup() + end + return true end -function M.refresh_stats(bufnr) - M.render(bufnr, 3) -end +function M.setup(opts) + opts = vim.tbl_extend("keep", opts or {}, { + float = false, + float_enter = false, + float_opts = { + relative = "editor", + width = 80, + height = 50, + col = (vim.o.columns - (opts and opts.width or 80)) / 2, + row = (vim.o.lines - (opts and opts.height or 50)) / 2, + style = "minimal", + }, + win_opts = { + wrap = false, + colorcolumn = "", + foldlevel = 999, + foldcolumn = "0", + cursorcolumn = false, + cursorline = false, + number = false, + relativenumber = false, + list = false, + spell = false, + signcolumn = "no", + }, + }) -function M.setup() - local augroup = vim.api.nvim_create_augroup("dashboard", { clear = true }) - local bufnr = M.initialize() + local bufnr = M.initialize(opts) + local augroup = vim.api.nvim_create_augroup("dashboard", { clear = true }) vim.api.nvim_create_autocmd("User", { group = augroup, pattern = { "LazyVimStarted", "LazyLoad", "LazyCheck" }, diff --git a/nvim/.config/nvim/lua/tobyvin/utils/fs.lua b/nvim/.config/nvim/lua/tobyvin/utils/fs.lua new file mode 100644 index 0000000..a02c351 --- /dev/null +++ b/nvim/.config/nvim/lua/tobyvin/utils/fs.lua @@ -0,0 +1,60 @@ +---@class tobyvin.utils.fs +---@field sep string path seperator used by os +local M = { + sep = vim.uv.os_uname().version:match("Windows") and "\\" or "/", +} + +---Wrapper around `vim.fs.find` with sane default options. +---@param names string +---@param opts table +function M.find(names, opts) + return vim.fs.find( + names, + vim.tbl_extend("keep", opts or {}, { + path = vim.fs.dirname(vim.api.nvim_buf_get_name(opts.bufnr or 0)), + upward = true, + }) + ) +end + +---Wrapper around `vim.fn.stdpath` providing functionality similar to `vim.cmd` +---@class tobyvin.utils.fs.xdg +---@field cache fun(...: string): string +---@field config fun(...: string): string +---@field config_dirs fun(...: string): string[] +---@field data fun(...: string): string +---@field data_dirs fun(...: string): string[] +---@field log fun(...: string): string +---@field run fun(...: string): string +---@field state fun(...: string): string +M.xdg = setmetatable({}, { + __call = function(t, dir, ...) + return t[dir](...) + end, + __index = function(t, k) + local stdpath = vim.fn.stdpath(k) + + if not stdpath then + return + elseif type(stdpath) == "string" then + local xdg_dir = vim.fs.dirname(stdpath) + t[k] = function(...) + return vim.fs.joinpath(xdg_dir, ...) + end + elseif type(stdpath) == "table" then + t[k] = function(...) + local paths = ... + return vim.iter(stdpath) + :map(vim.fs.dirname) + :map(function(p) + return vim.fs.joinpath(p, paths) + end) + :totable() + end + end + + return t[k] + end, +}) + +return M diff --git a/nvim/.config/nvim/lua/tobyvin/utils/session.lua b/nvim/.config/nvim/lua/tobyvin/utils/session.lua index 7246e23..737757c 100644 --- a/nvim/.config/nvim/lua/tobyvin/utils/session.lua +++ b/nvim/.config/nvim/lua/tobyvin/utils/session.lua @@ -1,23 +1,22 @@ local M = {} ---@return string session_path -function M.path() +function M.session_path() if vim.v.this_session and vim.v.this_session ~= "" then return vim.v.this_session end - local session_dir = table.concat({ vim.fn.stdpath("data"), "session" }, U.sep) - local name = vim.loop.cwd():gsub(":", "++"):gsub(U.sep, "%%"):gsub("$", ".vim") + local name = vim.loop.cwd():gsub(":", "++"):gsub(U.fs.sep, "%%"):gsub("$", ".vim") - if not name or name == "" then + if name == nil or name == "" then error(("Invalid session name: '%s'"):format(name)) end - return table.concat({ session_dir, name }, U.sep) + return U.fs.xdg.data("nvim", "session", name) end function M.write() - local is_ok, res = pcall(M.path) + local is_ok, res = pcall(M.session_path) if not is_ok then return vim.notify(res, vim.log.levels.ERROR) end @@ -30,20 +29,27 @@ function M.write() end function M.read() - local is_ok, res = pcall(M.path) + local is_ok, session_file = pcall(M.session_path) if not is_ok then - return vim.notify(res, vim.log.levels.ERROR) + return vim.notify(session_file, vim.log.levels.ERROR) end - if vim.fn.filereadable(res) ~= 1 then - return vim.notify("No session found", vim.log.levels.WARN) + if vim.fn.filereadable(session_file) ~= 1 then + return vim.notify(("No session found\nsession path: %s"):format(session_file), vim.log.levels.WARN) end if - #vim.fn.getbufinfo({ buflisted = 1, bufloaded = 1 }) == 0 - or vim.fn.confirm("Reading session will overwrite buffers. Continue?", "&Yes\n&No") == 1 + not U.buf.iter():any(U.buf.is_valid) + or vim.fn.confirm("Reading session will overwrite existing buffers. Continue?", "&Yes\n&No") == 1 then - vim.cmd.source(vim.fn.fnameescape(res)) + U.buf.iter():filter(U.buf.is_invalid):map(U.buf.delete) + vim.cmd.source(vim.fn.fnameescape(session_file)) + end +end + +function M.on_exit() + if vim.fn.argc() == 0 and U.buf.iter():any(U.buf.is_valid) then + pcall(M.write) end end |