feat: Snacks.nvim
This commit is contained in:
parent
cebc683566
commit
e62575407d
7 changed files with 390 additions and 1 deletions
|
@ -28,11 +28,14 @@ with final.pkgs.lib; let
|
||||||
all-plugins = with pkgs.vimPlugins; [
|
all-plugins = with pkgs.vimPlugins; [
|
||||||
# bleeding-edge plugins from flake inputs
|
# bleeding-edge plugins from flake inputs
|
||||||
# (mkNvimPlugin inputs.wf-nvim "wf.nvim") # (example) keymap hints
|
# (mkNvimPlugin inputs.wf-nvim "wf.nvim") # (example) keymap hints
|
||||||
|
lz-n
|
||||||
|
snacks-nvim
|
||||||
];
|
];
|
||||||
|
|
||||||
extraPackages = with pkgs; [
|
extraPackages = with pkgs; [
|
||||||
ripgrep
|
ripgrep
|
||||||
# language servers, etc.
|
lazygit
|
||||||
|
# language servers
|
||||||
lua-language-server
|
lua-language-server
|
||||||
nixd
|
nixd
|
||||||
];
|
];
|
||||||
|
|
|
@ -6,3 +6,7 @@ vim.g.sqlite_clib_path = require('luv').os_getenv('LIBSQLITE')
|
||||||
|
|
||||||
require('options')
|
require('options')
|
||||||
require('keymaps')
|
require('keymaps')
|
||||||
|
|
||||||
|
require('snacks-nvim')
|
||||||
|
|
||||||
|
-- require('lz.n').load('plugins')
|
||||||
|
|
21
nvim/lua/lib/lazy/util.lua
Normal file
21
nvim/lua/lib/lazy/util.lua
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# https://github.com/folke/lazy.nvim/blob/main/lua/lazy/core/util.lua
|
||||||
|
|
||||||
|
---@class lib.lazy.util
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
---@return string
|
||||||
|
function M.norm(path)
|
||||||
|
if path:sub(1, 1) == "~" then
|
||||||
|
local home = vim.uv.os_homedir() or ""
|
||||||
|
|
||||||
|
if home:sub(-1) == "\\" or home:sub(-1) == '/' then
|
||||||
|
home = home:sub(1, -2)
|
||||||
|
end
|
||||||
|
|
||||||
|
path = home .. path:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
path = path:gsub("\\", "/"):gsub("/+", "/")
|
||||||
|
|
||||||
|
return path:sub(-1) == "/" and path:sub(1, -2) or path
|
||||||
|
end
|
53
nvim/lua/lib/lazyvim/format.lua
Normal file
53
nvim/lua/lib/lazyvim/format.lua
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
-- https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/util/format.lua
|
||||||
|
|
||||||
|
---@class lib.lazyvim.format
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
---@param buf? number The buffer to enable for
|
||||||
|
function M.enabled(buf)
|
||||||
|
buf = (buf == nil or buf == 0) and vim.api.nvim_get_current_buf() or buf
|
||||||
|
local gaf = vim.g.autoformat
|
||||||
|
local baf = vim.b[buf].autoformat
|
||||||
|
|
||||||
|
-- If the buffer has a local value, use that.
|
||||||
|
if baf ~= nil then
|
||||||
|
return baf
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Otherwise use the global value if set, or true by default.
|
||||||
|
return gaf == nil or gaf
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param enable? boolean Whether to enable or disable
|
||||||
|
---@param buf? boolean Whether to enable for current buffer only
|
||||||
|
function M.enable(enable, buf)
|
||||||
|
if enable == nil then
|
||||||
|
enable = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if buf then
|
||||||
|
vim.b.autoformat = enable
|
||||||
|
else
|
||||||
|
vim.g.autoformat = enable
|
||||||
|
vim.b.autoformat = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param buf? boolean Whether to toggle for current buffer only
|
||||||
|
function M.snacks_toggle(buf)
|
||||||
|
return Snacks.toggle({
|
||||||
|
name = 'auto format (' .. (buf and 'buffer' or 'global') .. ')',
|
||||||
|
get = function()
|
||||||
|
if not buf then
|
||||||
|
return vim.g.autoformat == nil or vim.g.autoformat
|
||||||
|
end
|
||||||
|
|
||||||
|
return M.enabled()
|
||||||
|
end,
|
||||||
|
set = function(state)
|
||||||
|
M.enable(state, buf)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
27
nvim/lua/lib/lazyvim/lsp.lua
Normal file
27
nvim/lua/lib/lazyvim/lsp.lua
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
-- https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/util/lsp.lua
|
||||||
|
|
||||||
|
---@class lib.lazyvim.lsp
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
---@alias lsp.Client.filter {id?:number, bufnr?:number, name?:string, method?:string, filter?:fun(client:lsp.Client):boolean}
|
||||||
|
|
||||||
|
---@param opts? lsp.Client.filter
|
||||||
|
function M.get_clients(opts)
|
||||||
|
local ret = {} ---@type vim.lsp.Client[]
|
||||||
|
|
||||||
|
if vim.lsp.get_clients then
|
||||||
|
ret = vim.lsp.get_clients(opts)
|
||||||
|
else
|
||||||
|
---@diagnostic disable-next-line: deprecated
|
||||||
|
ret = vim.lsp.get_active_clients(opts)
|
||||||
|
|
||||||
|
if opts and opts.method then
|
||||||
|
---@param client vim.lsp.Client
|
||||||
|
ret = vim.tbl_filter(function(client)
|
||||||
|
return client.supports_method(opts.method, { bufnr = opts.bufnr })
|
||||||
|
end, ret)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return opts and opts.filter and vim.tbl_filter(opts.filter, ret) or ret
|
||||||
|
end
|
193
nvim/lua/lib/lazyvim/root.lua
Normal file
193
nvim/lua/lib/lazyvim/root.lua
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
-- https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/util/root.lua
|
||||||
|
|
||||||
|
local lazy_util = require('lib.lazy.util')
|
||||||
|
local lazyvim_lsp = require('lib.lazyvim.lsp')
|
||||||
|
|
||||||
|
---@class lib.lazyvim.root
|
||||||
|
---@overload fun(): string
|
||||||
|
local M = setmetatable({}, {
|
||||||
|
__call = function(m)
|
||||||
|
return m.get()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
---@class LazyRoot
|
||||||
|
---@field paths string[]
|
||||||
|
---@field spec LazyRootSpec
|
||||||
|
|
||||||
|
---@alias LazyRootFn fun(buf:number): (string|string[])
|
||||||
|
---@alias LazyRootSpec string|string[]|LazyRootFn
|
||||||
|
|
||||||
|
---@type LazyRootSpec[]
|
||||||
|
M.spec = { 'lsp', { '.git', 'lua' }, 'cwd' }
|
||||||
|
|
||||||
|
M.detectors = {}
|
||||||
|
|
||||||
|
function M.detectors.cwd()
|
||||||
|
return { vim.uv.cwd() }
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.realpath(path)
|
||||||
|
if path == '' or path == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
path = vim.uv.fs_realpath(path) or path
|
||||||
|
|
||||||
|
return lazy_util.norm(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.bufpath(buf)
|
||||||
|
return M.realpath(vim.api.nvim_buf_get_name(assert(buf)))
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.detectors.lsp(buf)
|
||||||
|
local bufpath = M.bufpath(buf)
|
||||||
|
|
||||||
|
if not bufpath then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local roots = {} ---@type string[]
|
||||||
|
local clients = lazyvim_lsp.get_clients({ bufnr = buf })
|
||||||
|
|
||||||
|
clients = vim.tbl_filter(function(client)
|
||||||
|
return not vim.tbl_contains(vim.g.root_lsp_ignore or {}, client.name)
|
||||||
|
end, clients)
|
||||||
|
|
||||||
|
for _, client in pairs(clients) do
|
||||||
|
local workspace = client.config.workspace_folders
|
||||||
|
|
||||||
|
for _, ws in pairs(workspace or {}) do
|
||||||
|
roots[#roots + 1] = vim.uri_to_fname(ws.uri)
|
||||||
|
end
|
||||||
|
|
||||||
|
if client.root_dir then
|
||||||
|
roots[#roots + 1] = client.root_dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return vim.tbl_filter(function(path)
|
||||||
|
path = lazy_util.norm(path)
|
||||||
|
|
||||||
|
return path and bufpath:find(path, 1, true) == 1
|
||||||
|
end, roots)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param patterns string[]|string
|
||||||
|
function M.detectors.pattern(buf, patterns)
|
||||||
|
if type(patterns) == 'string' then
|
||||||
|
patterns = { patterns }
|
||||||
|
end
|
||||||
|
|
||||||
|
local path = M.bufpath(buf) or vim.uv.cwd()
|
||||||
|
local pattern = vim.fs.find(function(name)
|
||||||
|
for _, p in ipairs(patterns) do
|
||||||
|
if name == p then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if p:sub(1, 1) == '*' and name:find(vim.pesc(p:sub(2)) .. '$') then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end, { path = path, upward = true })[1]
|
||||||
|
|
||||||
|
return pattern and { vim.fs.dirname(pattern) } or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param spec LazyRootSpec
|
||||||
|
---@return LazyRootFn
|
||||||
|
function M.resolve(spec)
|
||||||
|
if M.detectors[spec] then
|
||||||
|
return M.detectors[spec]
|
||||||
|
elseif type(spec) == 'function' then
|
||||||
|
return spec
|
||||||
|
end
|
||||||
|
|
||||||
|
return function(buf)
|
||||||
|
return M.detectors.pattern(buf, spec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param opts? {buf?:number, spec?:LazyRootSpec[], all?:boolean}
|
||||||
|
function M.detect(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
opts.spec = opts.spec
|
||||||
|
or type(vim.g.root_spec) == 'table' and vim.g.root_spec
|
||||||
|
or M.spec
|
||||||
|
opts.buf = (opts.buf == nil or opts.buf == 0)
|
||||||
|
and vim.api.nvim_get_current_buf()
|
||||||
|
or opts.buf
|
||||||
|
|
||||||
|
local ret = {} ---@type LazyRoot[]
|
||||||
|
|
||||||
|
for _, spec in ipairs(opts.spec) do
|
||||||
|
local paths = M.resolve(spec)(opts.buf)
|
||||||
|
|
||||||
|
paths = paths or {}
|
||||||
|
paths = type(paths) == 'table' and paths or { paths }
|
||||||
|
|
||||||
|
local roots = {} ---@type string[]
|
||||||
|
|
||||||
|
for _, p in ipairs(paths) do
|
||||||
|
local pp = M.realpath(p)
|
||||||
|
|
||||||
|
if pp and not vim.tbl_contains(roots, pp) then
|
||||||
|
roots[#roots + 1] = pp
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(roots, function(a, b)
|
||||||
|
return #a > #b
|
||||||
|
end)
|
||||||
|
|
||||||
|
if #roots > 0 then
|
||||||
|
ret[#ret + 1] = { spec = spec, paths = roots }
|
||||||
|
|
||||||
|
if opts.all == false then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type table<number, string>
|
||||||
|
M.cache = {}
|
||||||
|
|
||||||
|
-- Returns the root directory based on:
|
||||||
|
-- * lsp workspace folders
|
||||||
|
-- * lsp root_dir
|
||||||
|
-- * root pattern of filename of the current buffer
|
||||||
|
-- * root pattern of cwd
|
||||||
|
---@param opts? {normalize?:boolean, buf?:number}
|
||||||
|
function M.get(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
|
||||||
|
local buf = opts.buf or vim.api.nvim_get_current_buf()
|
||||||
|
local ret = M.cache[buf]
|
||||||
|
|
||||||
|
if not ret then
|
||||||
|
local roots = M.detect({ all = false, buf = buf })
|
||||||
|
|
||||||
|
ret = roots[1] and roots[1].paths[1] or vim.uv.cwd()
|
||||||
|
|
||||||
|
M.cache[buf] = ret
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.git()
|
||||||
|
local root = M.get()
|
||||||
|
local git_root = vim.fs.find('.git', { path = root, upward = true })[1]
|
||||||
|
local ret = git_root and vim.fn.fnamemodify(git_root, ':h') or root
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
88
nvim/lua/snacks-nvim.lua
Normal file
88
nvim/lua/snacks-nvim.lua
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
-- Snacks needs to be loaded very early, so it gets its own special file.
|
||||||
|
local set = vim.keymap.set
|
||||||
|
local lazyvim_format = require('lib.lazyvim.format')
|
||||||
|
local lazyvim_root = require('lib.lazyvim.root')
|
||||||
|
|
||||||
|
require('snacks').setup({
|
||||||
|
bigfile = { enabled = true },
|
||||||
|
dashboard = { enabled = true },
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Buffers -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||||
|
set({ 'n' }, '<LEADER>bd', function()
|
||||||
|
Snacks.bufdelete()
|
||||||
|
end, { desc = 'Delete buffer' })
|
||||||
|
|
||||||
|
set({ 'n' }, '<LEADER>bo', function()
|
||||||
|
Snacks.bufdelete.other()
|
||||||
|
end, { desc = 'Delete other buffers' })
|
||||||
|
|
||||||
|
-- Toggles -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||||
|
|
||||||
|
local toggle = Snacks.toggle
|
||||||
|
|
||||||
|
lazyvim_format.snacks_toggle():map('<LEADER>uf')
|
||||||
|
lazyvim_format.snacks_toggle(true):map('<LEADER>uF') -- current buffer only
|
||||||
|
|
||||||
|
toggle.option('spell', { name = 'spelling' }):map('<LEADER>us')
|
||||||
|
toggle.option('wrap', { name = 'wrap' }):map('<LEADER>uw')
|
||||||
|
|
||||||
|
toggle.option('relativenumber', { name = 'relative number' }):map('<LEADER>uL')
|
||||||
|
toggle.line_number():map('<LEADER>ul')
|
||||||
|
|
||||||
|
toggle.diagnostics():map('<LEADER>ud')
|
||||||
|
|
||||||
|
toggle
|
||||||
|
.option(
|
||||||
|
'conceallevel',
|
||||||
|
{ off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2 }
|
||||||
|
)
|
||||||
|
:map('<LEADER>uc')
|
||||||
|
|
||||||
|
toggle.treesitter():map('<LEADER>uT')
|
||||||
|
|
||||||
|
if vim.lsp.inlay_hint then
|
||||||
|
toggle.inlay_hints():map('<LEADER>uh')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Git -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||||
|
|
||||||
|
set({ 'n' }, '<LEADER>gb', function()
|
||||||
|
Snacks.git.blame_line()
|
||||||
|
end, { desc = 'Git blame line' })
|
||||||
|
|
||||||
|
set({ 'n' }, '<LEADER>gB', function()
|
||||||
|
Snacks.gitbrowse()
|
||||||
|
end, { desc = 'Git browse (open)' })
|
||||||
|
|
||||||
|
set({ 'n' }, '<LEADER>gY', function()
|
||||||
|
Snacks.gitbrowse({
|
||||||
|
open = function(url)
|
||||||
|
vim.fn.setreg('+', url)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end, { desc = 'Git browse (copy)' })
|
||||||
|
|
||||||
|
-- LazyGit -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||||
|
|
||||||
|
if vim.fn.executable('lazygit') == 1 then
|
||||||
|
set({ 'n' }, '<LEADER>gg', function()
|
||||||
|
Snacks.lazygit({ cwd = lazyvim_root.git() })
|
||||||
|
end, { desc = 'Lazygit (root dir)' })
|
||||||
|
|
||||||
|
-- set({ 'n' }, '<LEADER>gG', function()
|
||||||
|
-- Snacks.lazygit()
|
||||||
|
-- end, { desc = 'Lazygit (cwd)' })
|
||||||
|
|
||||||
|
set({ 'n' }, '<LEADER>gf', function()
|
||||||
|
Snacks.lazygit.log_file()
|
||||||
|
end, { desc = 'Lazygit current file history' })
|
||||||
|
|
||||||
|
set({ 'n' }, '<LEADER>gl', function()
|
||||||
|
Snacks.lazygit.log({ cwd = lazyvim_root.git() })
|
||||||
|
end, { desc = 'Lazygit log' })
|
||||||
|
|
||||||
|
-- set({ 'n' }, '<LEADER>gL', function()
|
||||||
|
-- Snacks.lazygit.log()
|
||||||
|
-- end, { desc = 'Lazygit log (cwd)' })
|
||||||
|
end
|
Loading…
Reference in a new issue