-- TODO: review if I want this for some buffers
vim.g.autoformat = false
--- bootstrap lazy.nvim, LazyVim and your plugins
-package.loaded["lazyvim.config.options"] = true
-require("config.lazy")
+_G.rmz = require("rmz.util")
+
+require("config")
--- Autocmds are automatically loaded on the VeryLazy event
+-- Autocmds are automatically loaded by config.init
local function augroup(name)
- return vim.api.nvim_create_augroup("lazyvim_" .. name, { clear = true })
+ return vim.api.nvim_create_augroup("rmz_" .. name, { clear = true })
end
+-- Check if we need to reload the file when it changed
+vim.api.nvim_create_autocmd({ "FocusGained", "TermClose", "TermLeave" }, {
+ group = augroup("checktime"),
+ callback = function()
+ if vim.o.buftype ~= "nofile" then
+ vim.cmd("checktime")
+ end
+ end,
+})
+
-- Highlight on yank
vim.api.nvim_create_autocmd("TextYankPost", {
group = augroup("highlight_yank"),
callback = function()
- vim.highlight.on_yank()
+ (vim.hl or vim.highlight).on_yank()
+ end,
+})
+
+-- resize splits if window got resized
+vim.api.nvim_create_autocmd({ "VimResized" }, {
+ group = augroup("resize_splits"),
+ callback = function()
+ local current_tab = vim.fn.tabpagenr()
+ vim.cmd("tabdo wincmd =")
+ vim.cmd("tabnext " .. current_tab)
+ end,
+})
+
+-- go to last loc when opening a buffer
+vim.api.nvim_create_autocmd("BufReadPost", {
+ group = augroup("last_loc"),
+ callback = function(event)
+ local exclude = { "gitcommit" }
+ local buf = event.buf
+ if vim.tbl_contains(exclude, vim.bo[buf].filetype) or vim.b[buf].rmz_last_loc then
+ return
+ end
+ vim.b[buf].rmz_last_loc = true
+ local mark = vim.api.nvim_buf_get_mark(buf, '"')
+ local lcount = vim.api.nvim_buf_line_count(buf)
+ if mark[1] > 0 and mark[1] <= lcount then
+ pcall(vim.api.nvim_win_set_cursor, 0, mark)
+ end
end,
})
vim.api.nvim_create_autocmd("FileType", {
group = augroup("close_with_q"),
pattern = {
- "PlenaryTestPopup",
+ "checkhealth",
+ "dbout",
+ "gitsigns-blame",
"help",
"lspinfo",
- "man",
"notify",
"qf",
"spectre_panel",
},
callback = function(event)
vim.bo[event.buf].buflisted = false
- vim.keymap.set("n", "q", "<cmd>close<cr>", { buffer = event.buf, silent = true })
+ vim.schedule(function()
+ vim.keymap.set("n", "q", function()
+ vim.cmd("close")
+ pcall(vim.api.nvim_buf_delete, event.buf, { force = true })
+ end, {
+ buffer = event.buf,
+ silent = true,
+ desc = "Quit buffer",
+ })
+ end)
+ end,
+})
+
+-- make it easier to close man-files when opened inline
+vim.api.nvim_create_autocmd("FileType", {
+ group = augroup("man_unlisted"),
+ pattern = { "man" },
+ callback = function(event)
+ vim.bo[event.buf].buflisted = false
+ end,
+})
+
+-- Fix conceallevel for json files
+vim.api.nvim_create_autocmd({ "FileType" }, {
+ group = augroup("json_conceal"),
+ pattern = { "json", "jsonc", "json5" },
+ callback = function()
+ vim.opt_local.conceallevel = 0
end,
})
--- /dev/null
+require("config.lazy")
+require("config.options")
+require("config.autocmds")
+
+local group = vim.api.nvim_create_augroup("Init", { clear = true })
+vim.api.nvim_create_autocmd("User", {
+ group = group,
+ pattern = "VeryLazy",
+ callback = function()
+ require("config.keymaps")
+ end,
+})
-- Keymaps are automatically loaded on the VeryLazy event
--- NOTE: Default LazyVim keys are not loaded automatically, review upstream keymas occasionnaly.
--- ~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/config/keymaps.lua
-local Util = require("lazyvim.util")
+local map = vim.keymap.set
+
+-- better up/down
+map({ "n", "x" }, "j", "v:count == 0 ? 'gj' : 'j'", { desc = "Down", expr = true, silent = true })
+map({ "n", "x" }, "<Down>", "v:count == 0 ? 'gj' : 'j'", { desc = "Down", expr = true, silent = true })
+map({ "n", "x" }, "k", "v:count == 0 ? 'gk' : 'k'", { desc = "Up", expr = true, silent = true })
+map({ "n", "x" }, "<Up>", "v:count == 0 ? 'gk' : 'k'", { desc = "Up", expr = true, silent = true })
+
+-- Move to window using the <ctrl> hjkl keys
+map("n", "<C-h>", "<C-w>W", { desc = "Go to Prev Window", remap = true })
+map("n", "<C-l>", "<C-w>w", { desc = "Go to Next Window", remap = true })
+map("n", "<C-j>", "<C-w>j", { desc = "Go to Lower Window", remap = true })
+map("n", "<C-k>", "<C-w>k", { desc = "Go to Upper Window", remap = true })
-- Resize window using <ctrl> arrow keys
-- TODO: this is cool, but should also support a number
-vim.keymap.set("n", "<C-Up>", "<cmd>resize +2<cr>", { desc = "Increase window height" })
-vim.keymap.set("n", "<C-Down>", "<cmd>resize -2<cr>", { desc = "Decrease window height" })
-vim.keymap.set("n", "<C-Left>", "<cmd>vertical resize -2<cr>", { desc = "Decrease window width" })
-vim.keymap.set("n", "<C-Right>", "<cmd>vertical resize +2<cr>", { desc = "Increase window width" })
+map("n", "<C-Up>", "<cmd>resize +2<cr>", { desc = "Increase Window Height" })
+map("n", "<C-Down>", "<cmd>resize -2<cr>", { desc = "Decrease Window Height" })
+map("n", "<C-Left>", "<cmd>vertical resize -2<cr>", { desc = "Decrease Window Width" })
+map("n", "<C-Right>", "<cmd>vertical resize +2<cr>", { desc = "Increase Window Width" })
-- Move Lines
-vim.keymap.set("n", "<A-j>", "<cmd>m .+1<cr>==", { desc = "Move down" })
-vim.keymap.set("n", "<A-k>", "<cmd>m .-2<cr>==", { desc = "Move up" })
--- NOTE: this triggers with <esc-j> when I'm too quick at doing "go to normal mode then move line"
-vim.keymap.set("i", "<A-j>", "<esc><cmd>m .+1<cr>==gi", { desc = "Move down" })
-vim.keymap.set("i", "<A-k>", "<esc><cmd>m .-2<cr>==gi", { desc = "Move up" })
-vim.keymap.set("v", "<A-j>", ":m '>+1<cr>gv=gv", { desc = "Move down" })
-vim.keymap.set("v", "<A-k>", ":m '<-2<cr>gv=gv", { desc = "Move up" })
+-- NOTE: these trigger with <esc-j> when I'm too quick at doing "go to normal mode then move line"
+map("n", "<A-j>", "<cmd>execute 'move .+' . v:count1<cr>==", { desc = "Move Down" })
+map("n", "<A-k>", "<cmd>execute 'move .-' . (v:count1 + 1)<cr>==", { desc = "Move Up" })
+map("i", "<A-j>", "<esc><cmd>m .+1<cr>==gi", { desc = "Move Down" })
+map("i", "<A-k>", "<esc><cmd>m .-2<cr>==gi", { desc = "Move Up" })
+map("v", "<A-j>", ":<C-u>execute \"'<,'>move '>+\" . v:count1<cr>gv=gv", { desc = "Move Down" })
+map("v", "<A-k>", ":<C-u>execute \"'<,'>move '<-\" . (v:count1 + 1)<cr>gv=gv", { desc = "Move Up" })
-- buffers
-vim.keymap.set("n", "<S-h>", "<cmd>BufferLineCyclePrev<cr>", { desc = "Prev buffer" })
-vim.keymap.set("n", "<S-l>", "<cmd>BufferLineCycleNext<cr>", { desc = "Next buffer" })
-vim.keymap.set("n", "[b", "<cmd>BufferLineCyclePrev<cr>", { desc = "Prev buffer" })
-vim.keymap.set("n", "]b", "<cmd>BufferLineCycleNext<cr>", { desc = "Next buffer" })
+map("n", "<S-h>", "<cmd>BufferLineCyclePrev<cr>", { desc = "Prev Buffer" })
+map("n", "<S-l>", "<cmd>BufferLineCycleNext<cr>", { desc = "Next Buffer" })
+map("n", "[b", "<cmd>BufferLineCyclePrev<cr>", { desc = "Prev Buffer" })
+map("n", "]b", "<cmd>BufferLineCycleNext<cr>", { desc = "Next Buffer" })
-vim.keymap.set("n", "<leader>bb", "<cmd>e #<cr>", { desc = "Switch to Other Buffer" })
+map("n", "<leader>bb", "<cmd>e #<cr>", { desc = "Switch to Other Buffer" })
--- Clear search with <esc>
-vim.keymap.set({ "i", "n" }, "<esc>", "<cmd>noh<cr><esc>", { desc = "Escape and clear hlsearch" })
+-- Clear search and stop snippet on escape
+map({ "i", "n", "s" }, "<esc>", function()
+ vim.cmd("noh")
+ -- TODO: stop snippet with esc *but don't do it in insert mode*
+ -- require("luasnip").unlink_current()
+ return "<esc>"
+end, { expr = true, desc = "Escape and Clear hlsearch" })
-- Clear search, diff update and redraw
-- taken from runtime/lua/_editor.lua
-vim.keymap.set(
+map(
"n",
"<leader>ur",
"<Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>",
- { desc = "Redraw / clear hlsearch / diff update" }
+ { desc = "Redraw / Clear hlsearch / Diff Update" }
)
-vim.keymap.set({ "n", "x" }, "gw", "*N", { desc = "Search word under cursor" })
+map({ "n", "x" }, "gw", "*N", { desc = "Search word under cursor" })
-- Add undo break-points
-vim.keymap.set("i", ",", ",<c-g>u")
-vim.keymap.set("i", ".", ".<c-g>u")
-vim.keymap.set("i", ";", ";<c-g>u")
+map("i", ",", ",<c-g>u")
+map("i", ".", ".<c-g>u")
+map("i", ";", ";<c-g>u")
+
+--keywordprg
+map("n", "<leader>K", "<cmd>norm! K<cr>", { desc = "Keywordprg" })
-- lazy
-vim.keymap.set("n", "<leader>l", "<cmd>:Lazy<cr>", { desc = "Lazy" })
+map("n", "<leader>l", "<cmd>Lazy<cr>", { desc = "Lazy" })
-- new file
-vim.keymap.set("n", "<leader>fn", "<cmd>enew<cr>", { desc = "New File" })
-
-vim.keymap.set("n", "[q", vim.cmd.cprev, { desc = "Previous quickfix" })
-vim.keymap.set("n", "]q", vim.cmd.cnext, { desc = "Next quickfix" })
+map("n", "<leader>fn", "<cmd>enew<cr>", { desc = "New File" })
-- diagnostic
local diagnostic_goto = function(next, severity)
go({ severity = severity })
end
end
-vim.keymap.set("n", "<leader>cd", vim.diagnostic.open_float, { desc = "Line Diagnostics" })
-vim.keymap.set("n", "]d", diagnostic_goto(true), { desc = "Next Diagnostic" })
-vim.keymap.set("n", "[d", diagnostic_goto(false), { desc = "Prev Diagnostic" })
-vim.keymap.set("n", "]e", diagnostic_goto(true, "ERROR"), { desc = "Next Error" })
-vim.keymap.set("n", "[e", diagnostic_goto(false, "ERROR"), { desc = "Prev Error" })
-vim.keymap.set("n", "]w", diagnostic_goto(true, "WARN"), { desc = "Next Warning" })
-vim.keymap.set("n", "[w", diagnostic_goto(false, "WARN"), { desc = "Prev Warning" })
+map("n", "<leader>cd", vim.diagnostic.open_float, { desc = "Line Diagnostics" })
--- stylua: ignore start
+map("n", "]d", diagnostic_goto(true), { desc = "Next Diagnostic" })
+map("n", "[d", diagnostic_goto(false), { desc = "Prev Diagnostic" })
+map("n", "]e", diagnostic_goto(true, "ERROR"), { desc = "Next Error" })
+map("n", "[e", diagnostic_goto(false, "ERROR"), { desc = "Prev Error" })
+map("n", "]w", diagnostic_goto(true, "WARN"), { desc = "Next Warning" })
+map("n", "[w", diagnostic_goto(false, "WARN"), { desc = "Prev Warning" })
-- toggle options
-vim.keymap.set("n", "<leader>uf", Util.format.toggle, { desc = "Toggle format on Save" })
-vim.keymap.set("n", "<leader>ud", Snacks.toggle.diagnostics, { desc = "Toggle Diagnostics" })
-local conceallevel = vim.o.conceallevel > 0 and vim.o.conceallevel or 3
-vim.keymap.set("n", "<leader>uc", function() Snacks.toggle("conceallevel", false, {0, conceallevel}) end, { desc = "Toggle Conceal" })
+Snacks.toggle.option("spell", { name = "Spelling" }):map("<leader>us")
+Snacks.toggle.option("wrap", { name = "Wrap" }):map("<leader>uw")
+Snacks.toggle.option("relativenumber", { name = "Relative Number" }):map("<leader>uL")
+Snacks.toggle.diagnostics():map("<leader>ud")
+Snacks.toggle.line_number():map("<leader>ul")
+Snacks.toggle.option("conceallevel", { off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2, name = "Conceal Level" }):map("<leader>uc")
+Snacks.toggle.option("showtabline", { off = 0, on = vim.o.showtabline > 0 and vim.o.showtabline or 2, name = "Tabline" }):map("<leader>uA")
+Snacks.toggle.treesitter():map("<leader>uT")
+Snacks.toggle.option("background", { off = "light", on = "dark" , name = "Dark Background" }):map("<leader>ub")
+Snacks.toggle.dim():map("<leader>uD")
+Snacks.toggle.animate():map("<leader>ua")
+Snacks.toggle.indent():map("<leader>ug")
+Snacks.toggle.scroll():map("<leader>uS")
+Snacks.toggle.profiler():map("<leader>dpp")
+Snacks.toggle.profiler_highlights():map("<leader>dph")
+
+if vim.lsp.inlay_hint then
+ Snacks.toggle.inlay_hints():map("<leader>uh")
+end
+
+map({ "n", "x" }, "<leader>gB", function() Snacks.gitbrowse() end, { desc = "Git Browse (open)" })
+map({"n", "x" }, "<leader>gY", function()
+ Snacks.gitbrowse({ open = function(url) vim.fn.setreg("+", url) end, notify = false })
+end, { desc = "Git Browse (copy)" })
-- highlights under cursor
-if vim.fn.has("nvim-0.9.0") == 1 then
- vim.keymap.set("n", "<leader>ui", vim.show_pos, { desc = "Inspect Pos" })
-end
+map("n", "<leader>ui", vim.show_pos, { desc = "Inspect Pos" })
+map("n", "<leader>uI", "<cmd>InspectTree<cr>", { desc = "Inspect Tree" })
-- floating terminal
-- TODO: I prefer a split buffer for terminal, need to review how to make this more vim-like
-local lazyterm = function() LazyVim.terminal(nil, { cwd = LazyVim.root() }) end
-vim.keymap.set("n", "<leader>ft", lazyterm, { desc = "Terminal (Root Dir)" })
-vim.keymap.set("n", "<leader>fT", function() LazyVim.terminal() end, { desc = "Terminal (cwd)" })
+map("n", "<c-/>", function() Snacks.terminal() end, { desc = "Terminal (cmd)" })
-- Terminal Mappings
-vim.keymap.set("t", "<esc><esc>", "<c-\\><c-n>", { desc = "Enter Normal Mode" })
-vim.keymap.set("t", "<C-h>", "<cmd>wincmd h<cr>", { desc = "Go to Left Window" })
-vim.keymap.set("t", "<C-j>", "<cmd>wincmd j<cr>", { desc = "Go to Lower Window" })
-vim.keymap.set("t", "<C-k>", "<cmd>wincmd k<cr>", { desc = "Go to Upper Window" })
-vim.keymap.set("t", "<C-l>", "<cmd>wincmd l<cr>", { desc = "Go to Right Window" })
-vim.keymap.set("t", "<C-/>", "<cmd>close<cr>", { desc = "Hide Terminal" })
-vim.keymap.set("t", "<c-_>", "<cmd>close<cr>", { desc = "which_key_ignore" })
+map("t", "<esc><esc>", "<c-\\><c-n>", { desc = "Enter Normal Mode" })
+map("t", "<C-/>", "<cmd>close<cr>", { desc = "Hide Terminal" })
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
-- bootstrap lazy.nvim
- -- stylua: ignore
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath })
end
vim.opt.rtp:prepend(vim.env.LAZY or lazypath)
require("lazy").setup({
spec = {
- -- add LazyVim and import its plugins
- { "LazyVim/LazyVim", import = "lazyvim.plugins" },
- -- import any extras modules here
- -- { import = "lazyvim.plugins.extras.lang.typescript" },
- -- { import = "lazyvim.plugins.extras.lang.json" },
- -- { import = "lazyvim.plugins.extras.ui.mini-animate" },
- -- import/override with your plugins
{ import = "plugins" },
{ import = "plugins.lang" },
},
defaults = {
- -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup.
- -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default.
lazy = false,
- -- It's recommended to leave version=false for now, since a lot the plugin that support versioning,
- -- have outdated releases, which may break your Neovim install.
version = false, -- always use the latest git commit
- -- version = "*", -- try installing the latest stable version for plugins that support semver
},
- install = { colorscheme = { "tokyonight", "habamax" } },
+ install = { colorscheme = { "onenord", "habamax" } },
checker = {
- -- automatically check for plugin updates
enabled = true,
notify = false,
},
local opt = vim.opt
+opt.fillchars = {
+ foldopen = "",
+ foldclose = "",
+ fold = " ",
+ foldsep = " ",
+ eob = " ",
+ diff = "⣿",
+ vert = "│",
+}
+
vim.g.man_hardwrap = 1
vim.env.MANWIDTH = 80
opt.showmode = false -- Dont show mode since we have a statusline
opt.signcolumn = "yes" -- Always show the signcolumn, otherwise it would shift the text each time
opt.updatetime = 200 -- Save swap file and trigger CursorHold
-if vim.fn.has("nvim-0.9.0") == 1 then
- opt.splitkeep = "screen"
- opt.shortmess:append({ C = true })
-end
+opt.splitkeep = "screen"
+opt.shortmess:append({ C = true })
+opt.foldmethod = "expr"
+opt.foldexpr = "v:lua.require'rmz.util'.foldexpr()"
+
-- do not let markdown plugin change indent
vim.g.markdown_recommended_style = 0
-
-vim.g.lazyvim_picker = "telescope"
-
-vim.g.snacks_animate = false
--- /dev/null
+return {
+ {
+ "saghen/blink.cmp",
+ version = "*",
+ -- build = "cargo build --release",
+ dependencies = {
+ "rafamadriz/friendly-snippets",
+ },
+ -- NOTE: not described in upstream install docs
+ event = "InsertEnter",
+
+ ---@module 'blink.cmp'
+ ---@type blink.cmp.Config
+ opts = {
+ completion = {
+ menu = { draw = { treesitter = { "lsp" }, }, },
+ documentation = {
+ auto_show = true,
+ auto_show_delay_ms = 200,
+ },
+ ghost_text = {
+ enabled = true,
+ },
+ },
+
+ cmdline = {
+ enabled = false,
+ },
+ sources = {
+ default = { "lsp", "path", "snippets", "buffer" },
+ },
+ snippets = {
+ preset = "luasnip",
+ },
+
+ keymap = {
+ preset = "enter",
+ ["<C-y>"] = { "select_and_accept" },
+ },
+ },
+ opts_extend = { "sources.default", },
+ },
+
+ -- add icons
+ {
+ "saghen/blink.cmp",
+ opts = function(_, opts)
+ opts.appearance = opts.appearance or {}
+ opts.appearance.kind_icons = vim.tbl_extend("force", opts.appearance.kind_icons or {}, rmz.ui.icons.kinds)
+ end,
+ },
+
+ -- lazydev
+ {
+ "saghen/blink.cmp",
+ opts = {
+ sources = {
+ -- add lazydev to your completion providers
+ default = { "lazydev" },
+ providers = {
+ lazydev = {
+ name = "LazyDev",
+ module = "lazydev.integrations.blink",
+ score_offset = 100, -- show at a higher priority than lsp
+ },
+ },
+ },
+ },
+ },
+ -- catppuccin support
+ {
+ "catppuccin",
+ optional = true,
+ opts = {
+ integrations = { blink_cmp = true },
+ },
+ },
+}
----@type LazyPluginSpec
+---@type LazySpec
return {
-- snippets
- {
- "L3MON4D3/LuaSnip",
- -- disable luasnip bindings for <tab> and <s-tab>
+ { "l3mon4d3/luasnip",
+ build = "make install_jsregexp", -- optional
dependencies = {
- {
- "honza/vim-snippets",
- config = function()
- require("luasnip.loaders.from_snipmate").lazy_load()
- require("luasnip.loaders.from_lua").load({ paths = vim.fn.stdpath("config") .. "/lua/snippets" })
- end,
- },
+ { "honza/vim-snippets", },
},
+ config = function()
+ local snippets = vim.fn.stdpath("config").."/snippets"
+ require("luasnip.loaders.from_snipmate").load({ paths = { snippets }})
+ require("luasnip.loaders.from_lua").load({ paths = { snippets }})
+ end,
keys = function()
return {}
end,
opts = {
+ history = true,
+ delete_check_events = "TextChanged",
store_selection_keys = "<Tab>",
},
},
- -- auto completion
- {
- "hrsh7th/nvim-cmp",
- version = false, -- last release is way too old
- event = "InsertEnter",
- dependencies = {
- "hrsh7th/cmp-nvim-lsp",
- "hrsh7th/cmp-buffer",
- "hrsh7th/cmp-path",
- "saadparwaiz1/cmp_luasnip",
+ { "echasnovski/mini.pairs",
+ event = "VeryLazy",
+ opts = {
+ modes = { insert = true, command = true, terminal = false },
+ -- skip autopair when next character is one of these
+ skip_next = [=[[%w%%%'%[%"%.%`%$]]=],
+ -- skip autopair when the cursor is inside these treesitter nodes
+ skip_ts = { "string" },
+ -- skip autopair when next character is closing pair
+ -- and there are more closing pairs than opening pairs
+ skip_unbalanced = true,
+ -- better deal with markdown code blocks
+ markdown = true,
},
- ---@param opts cmp.ConfigSchema
- opts = function(_, opts)
- local has_words_before = function()
- unpack = unpack or table.unpack
- local line, col = unpack(vim.api.nvim_win_get_cursor(0))
- return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
- end
-
- local cmp = require("cmp")
- local luasnip = require("luasnip")
-
- local upstream_format = opts.formatting.format
- opts.formatting.format = function(entry, vim_item)
- vim_item = upstream_format(entry, vim_item)
- local menu = {
- nvim_lsp = "[lsp]",
- luasnip = "[snip]",
- buffer = "[buf]",
- path = "[path]",
- }
- vim_item.menu = menu[entry.source.name]
- return vim_item
- end
+ config = function(_, opts)
+ Snacks.toggle({
+ name = "Mini Pairs",
+ get = function()
+ return not vim.g.minipairs_disable
+ end,
+ set = function(state)
+ vim.g.minipairs_disable = not state
+ end,
+ }):map("<leader>up")
- opts.completion = vim.tbl_extend("force", opts.completion, {
- completeopt = "menu,menuone,noselect",
- })
- -- TODO: review if I want to keep any of LazyVim's mappings
- opts.mapping = {
- -- lazyvims
- ["<C-n>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
- ["<C-p>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
- ["<C-b>"] = cmp.mapping.scroll_docs(-4),
- ["<C-f>"] = cmp.mapping.scroll_docs(4),
- ["<C-e>"] = cmp.mapping.abort(),
- ["<C-Space>"] = cmp.mapping.complete(),
- -- mine
- ["<Tab>"] = cmp.mapping(function(fallback)
- if cmp.visible() then
- cmp.select_next_item()
- elseif luasnip.expand_or_jumpable() then
- luasnip.expand_or_jump()
- elseif has_words_before() then
- cmp.complete()
- else
- fallback()
+ local pairs = require("mini.pairs")
+ pairs.setup(opts)
+ local open = pairs.open
+ --- Custom open command with extensions from LazyVim
+ ---@diagnostic disable-next-line: duplicate-set-field
+ pairs.open = function(pair, neigh_pattern)
+ if vim.fn.getcmdline() ~= "" then
+ return open(pair, neigh_pattern)
+ end
+ local o, c = pair:sub(1, 1), pair:sub(2, 2)
+ local line = vim.api.nvim_get_current_line()
+ local cursor = vim.api.nvim_win_get_cursor(0)
+ local next = line:sub(cursor[2] + 1, cursor[2] + 1)
+ local before = line:sub(1, cursor[2])
+ -- don't add fourth ` in markdown ```
+ if opts.markdown and o == "`" and vim.bo.filetype == "markdown" and before:match("^%s*``") then
+ return "`\n```" .. vim.api.nvim_replace_termcodes("<up>", true, true, true)
+ end
+ if opts.skip_next and next ~= "" and next:match(opts.skip_next) then
+ return o
+ end
+ if opts.skip_ts and #opts.skip_ts > 0 then
+ local ok, captures = pcall(vim.treesitter.get_captures_at_pos, 0, cursor[1] - 1, math.max(cursor[2] - 1, 0))
+ for _, capture in ipairs(ok and captures or {}) do
+ if vim.tbl_contains(opts.skip_ts, capture.capture) then
+ return o
+ end
end
- end, { "i", "s" }),
- ["<S-Tab>"] = cmp.mapping(function(fallback)
- if cmp.visible() then
- cmp.select_prev_item()
- elseif luasnip.jumpable(-1) then
- luasnip.jump(-1)
- else
- fallback()
+ end
+ if opts.skip_unbalanced and next == c and c ~= o then
+ local _, count_open = line:gsub(vim.pesc(pair:sub(1, 1)), "")
+ local _, count_close = line:gsub(vim.pesc(pair:sub(2, 2)), "")
+ if count_close > count_open then
+ return o
end
- end, { "i", "s" }),
- }
+ end
+ return open(pair, neigh_pattern)
+ end
end,
},
- -- auto pairs
- {
- "echasnovski/mini.pairs",
- },
-
- -- surround
- {
- "echasnovski/mini.surround",
+ { "echasnovski/mini.surround",
keys = function()
-- HACK: use function to disable merging with LazyVim's keys definition
return {
vim.keymap.set("x", "S", [[:<C-u>lua MiniSurround.add('visual')<CR>]], { silent = true })
end,
},
- -- comments
- {
- "numToStr/Comment.nvim",
+
+ { "echasnovski/mini.ai",
+ -- TODO: port vim text objects over
+ event = "VeryLazy",
+ opts = function()
+ local ai = require("mini.ai")
+ return {
+ n_lines = 500,
+ custom_textobjects = {
+ o = ai.gen_spec.treesitter({ -- code block
+ a = { "@block.outer", "@conditional.outer", "@loop.outer" },
+ i = { "@block.inner", "@conditional.inner", "@loop.inner" },
+ }),
+ f = ai.gen_spec.treesitter({ a = "@function.outer", i = "@function.inner" }), -- function
+ c = ai.gen_spec.treesitter({ a = "@class.outer", i = "@class.inner" }), -- class
+ t = { "<([%p%w]-)%f[^<%w][^<>]->.-</%1>", "^<.->().*()</[^/]->$" }, -- tags
+ d = { "%f[%d]%d+" }, -- digits
+ e = { -- Word with case
+ { "%u[%l%d]+%f[^%l%d]", "%f[%S][%l%d]+%f[^%l%d]", "%f[%P][%l%d]+%f[^%l%d]", "^[%l%d]+%f[^%l%d]" },
+ "^().*()$",
+ },
+ u = ai.gen_spec.function_call(), -- u for "Usage"
+ U = ai.gen_spec.function_call({ name_pattern = "[%w_]" }), -- without dot in function name
+ },
+ }
+ end,
+ },
+ { "numToStr/Comment.nvim",
+ dependencies = {
+ { "JoosepAlviste/nvim-ts-context-commentstring", -- nested language commenting (f.ex markdown code blocks)
+ opts = { enable_autocmd = false, },
+ }
+ },
+ opts = function(_, opts)
+ local tscci = require('ts_context_commentstring.integrations.comment_nvim')
+ vim.tbl_deep_extend('force', opts, {
+ toggler = {
+ line = "gcc",
+ block = "gbb",
+ },
+ mappings = {
+ basic = true,
+ extra = true,
+ },
+ pre_hook = tscci.create_pre_hook()
+ })
+ return opts
+ end,
+ },
+ { "danymat/neogen", -- Generate annotations like doxygen
+ cmd = "Neogen",
+ keys = {
+ { "<leader>cn", function() require("neogen").generate() end, desc = "Generate Annotations (Neogen)", },
+ },
opts = {
- toggler = {
- line = "gcc",
- block = "gbb",
+ snippet_engine = "luasnip",
+ },
+ },
+ { "folke/lazydev.nvim",
+ ft = "lua",
+ cmd = "LazyDev",
+ opts = {
+ library = {
+ { path = "${3rd}/luv/library", words = { "vim%.uv" } },
+ { path = "snacks.nvim", words = { "Snacks" } },
+ { path = "lazy.nvim", words = { "LazySpec" } },
},
- mappings = {
- basic = true,
- extra = true,
+ },
+ },
+ { "gbprod/yanky.nvim", enabled = false, -- better yank/paste
+ -- TODO: integrate?
+ -- I'm not entirely convinced, it doesn't provide functionality like vim-peekaboo,
+ -- maybe it can supplement it though?
+ -- Also, see issues on OSC52: https://github.com/gbprod/yanky.nvim/issues/213
+ recommended = true,
+ desc = "Better Yank/Paste",
+ event = "LazyFile",
+ opts = {
+ highlight = { timer = 150 },
+ },
+ keys = {
+ {
+ "<leader>p",
+ function() vim.cmd([[YankyRingHistory]]) end,
+ mode = { "n", "x" },
+ desc = "Open Yank History",
},
+ -- stylua: ignore
+ { "y", "<Plug>(YankyYank)", mode = { "n", "x" }, desc = "Yank Text" },
+ { "p", "<Plug>(YankyPutAfter)", mode = { "n", "x" }, desc = "Put Text After Cursor" },
+ { "P", "<Plug>(YankyPutBefore)", mode = { "n", "x" }, desc = "Put Text Before Cursor" },
+ { "gp", "<Plug>(YankyGPutAfter)", mode = { "n", "x" }, desc = "Put Text After Selection" },
+ { "gP", "<Plug>(YankyGPutBefore)", mode = { "n", "x" }, desc = "Put Text Before Selection" },
+ { "[y", "<Plug>(YankyCycleForward)", desc = "Cycle Forward Through Yank History" },
+ { "]y", "<Plug>(YankyCycleBackward)", desc = "Cycle Backward Through Yank History" },
+ { "]p", "<Plug>(YankyPutIndentAfterLinewise)", desc = "Put Indented After Cursor (Linewise)" },
+ { "[p", "<Plug>(YankyPutIndentBeforeLinewise)", desc = "Put Indented Before Cursor (Linewise)" },
+ { "]P", "<Plug>(YankyPutIndentAfterLinewise)", desc = "Put Indented After Cursor (Linewise)" },
+ { "[P", "<Plug>(YankyPutIndentBeforeLinewise)", desc = "Put Indented Before Cursor (Linewise)" },
+ { ">p", "<Plug>(YankyPutIndentAfterShiftRight)", desc = "Put and Indent Right" },
+ { "<p", "<Plug>(YankyPutIndentAfterShiftLeft)", desc = "Put and Indent Left" },
+ { ">P", "<Plug>(YankyPutIndentBeforeShiftRight)", desc = "Put Before and Indent Right" },
+ { "<P", "<Plug>(YankyPutIndentBeforeShiftLeft)", desc = "Put Before and Indent Left" },
+ { "=p", "<Plug>(YankyPutAfterFilter)", desc = "Put After Applying a Filter" },
+ { "=P", "<Plug>(YankyPutBeforeFilter)", desc = "Put Before Applying a Filter" },
},
},
- { "JoosepAlviste/nvim-ts-context-commentstring", enabled = false },
- { "echasnovski/mini.comment", enabled = false },
+
+ { "andrewferrier/debugprint.nvim",
+ dependencies = { "nvim-treesitter" },
+ -- TODO: setup debugprint (or maybe not)
+ opts = { }
+ }
}
----@type LazyPluginSpec
+---@type LazySpec
return {
- {
- "LazyVim",
- opts = { colorscheme = "onenord" },
- dependencies = { "onenord.nvim" },
- },
- {
- -- this meta plugin can be used to install all colorschemes to test with telescope
- name = "colorschemes",
- dir = "",
- lazy = true,
- dependencies = {
- {
- -- requires too much configuration to make look good
- "rmehri01/onenord.nvim",
- opts = function(_, opts)
- local colors = require("onenord.colors").load()
- opts = vim.tbl_extend("force", opts, {
- custom_highlights = {
- ["@parameter"] = { fg = colors.fg },
- ["@namespace"] = { fg = colors.fg },
- ["@type"] = { fg = colors.fg },
- ["@variable.builtin"] = { fg = colors.fg },
- },
- })
- return opts
- end,
- },
- { "folke/tokyonight.nvim" },
- {
- "catppuccin/nvim",
- name = "catppuccin",
- opts = {
- color_overrides = {
- -- https://github.com/catppuccin/nvim/discussions/323#discussioncomment-5760383
- mocha = {
- rosewater = "#BF616A",
- flamingo = "#BF616A",
- pink = "#B48EAD",
- mauve = "#B48EAD",
- red = "#BF616A",
- maroon = "#BF616A",
- peach = "#D08770",
- yellow = "#EBCB8B",
- green = "#A3BE8C",
- teal = "#88c0d0",
- sky = "#88c0d0",
- sapphire = "#88c0d0",
- blue = "#81a1c1",
- lavender = "#81a1c1",
- text = "#ECEFF4",
- subtext1 = "#E5E9F0",
- subtext0 = "#D8DEE9",
- overlay2 = "#8d9196",
- overlay1 = "#81858b",
- overlay0 = "#4C566A",
- surface2 = "#434C5E",
- surface1 = "#3B4252",
- surface0 = "#292e39",
- base = "#242933",
- mantle = "#20242d",
- crust = "#1c2028",
- },
- },
+ { "rmehri01/onenord.nvim",
+ lazy = false,
+ priority = 1000,
+ opts = function(_, opts)
+ local colors = require("onenord.colors").load()
+ opts = vim.tbl_extend("force", opts, {
+ custom_highlights = {
+ ["@parameter"] = { fg = colors.fg },
+ ["@namespace"] = { fg = colors.fg },
+ ["@type"] = { fg = colors.fg },
+ ["@variable.builtin"] = { fg = colors.fg },
},
- },
- {
- "shaunsingh/nord.nvim",
- dev = true,
- init = function()
- vim.g.nord_contrats = true
- vim.g.nord_borders = true
- vim.g.nord_bold = false
- vim.g.nord_uniform_diff_background = false
- vim.g.nord_disable_background = false
- end,
- },
- -- conflicts with above
- -- { "gbprod/nord.nvim"},
- },
+ })
+ return opts
+ end,
},
+ -- FIXME: Find a way to lazy load all colorschemes when invoking the picker
+ -- https://github.com/folke/lazy.nvim/discussions/1167
+ -- { name = "colorschemes",
+ -- -- this meta plugin can be used to install all colorschemes to test with a picker
+ -- dir = "", -- NOTE: empty dir no longer works
+ -- lazy = true,
+ -- dependencies = {
+ -- {
+ -- "catppuccin/nvim",
+ -- name = "catppuccin",
+ -- opts = {
+ -- color_overrides = {
+ -- -- https://github.com/catppuccin/nvim/discussions/323#discussioncomment-5760383
+ -- mocha = {
+ -- rosewater = "#BF616A",
+ -- flamingo = "#BF616A",
+ -- pink = "#B48EAD",
+ -- mauve = "#B48EAD",
+ -- red = "#BF616A",
+ -- maroon = "#BF616A",
+ -- peach = "#D08770",
+ -- yellow = "#EBCB8B",
+ -- green = "#A3BE8C",
+ -- teal = "#88c0d0",
+ -- sky = "#88c0d0",
+ -- sapphire = "#88c0d0",
+ -- blue = "#81a1c1",
+ -- lavender = "#81a1c1",
+ -- text = "#ECEFF4",
+ -- subtext1 = "#E5E9F0",
+ -- subtext0 = "#D8DEE9",
+ -- overlay2 = "#8d9196",
+ -- overlay1 = "#81858b",
+ -- overlay0 = "#4C566A",
+ -- surface2 = "#434C5E",
+ -- surface1 = "#3B4252",
+ -- surface0 = "#292e39",
+ -- base = "#242933",
+ -- mantle = "#20242d",
+ -- crust = "#1c2028",
+ -- },
+ -- },
+ -- },
+ -- },
+ -- {
+ -- "shaunsingh/nord.nvim",
+ -- init = function()
+ -- vim.g.nord_contrats = true
+ -- vim.g.nord_borders = true
+ -- vim.g.nord_bold = false
+ -- vim.g.nord_uniform_diff_background = false
+ -- vim.g.nord_disable_background = false
+ -- end,
+ -- },
+ -- -- conflicts with above
+ -- -- { "gbprod/nord.nvim"},
+ -- },
+ -- },
}
----@type LazyPluginSpec
+---@type LazySpec
return {
- {
- "LazyVim/LazyVim",
- opts = {
- defaults = {
- autocmds = false,
- options = false,
- keymaps = false,
- },
- },
- },
- {
- "vhyrro/luarocks.nvim",
+ { "vhyrro/luarocks.nvim",
priority = 1000,
config = true,
+ },
+ { "dstein64/vim-startuptime",
+ cmd = "StartupTime",
+ config = function()
+ vim.g.startuptime_tries = 10
+ end,
}
}
----@param config {args?:string[]|fun():string[]?}
+---@param config {type?:string, args?:string[]|fun():string[]?}
local function get_args(config)
- local args = type(config.args) == "function" and (config.args() or {}) or config.args or {}
+ local args = type(config.args) == "function" and (config.args() or {}) or config.args or {} --[[@as string[] | string ]]
+ local args_str = type(args) == "table" and table.concat(args, " ") or args --[[@as string]]
+
config = vim.deepcopy(config)
---@cast args string[]
config.args = function()
- local new_args = vim.fn.input("Run with args: ", table.concat(args, " ")) --[[@as string]]
- return vim.split(vim.fn.expand(new_args) --[[@as string]], " ")
+ local new_args = vim.fn.expand(vim.fn.input("Run with args: ", args_str)) --[[@as string]]
+ return require("dap.utils").splitstr(new_args)
end
return config
end
return {
- "mfussenegger/nvim-dap",
-
- dependencies = {
- -- fancy UI for the debugger
- {
+ { "mfussenegger/nvim-dap",
+ dependencies = {
"rcarriga/nvim-dap-ui",
- -- stylua: ignore
- keys = {
- { "<leader>du", function() require("dapui").toggle({ }) end, desc = "Dap UI" },
- { "<leader>de", function() require("dapui").eval() end, desc = "Eval", mode = {"n", "v"} },
+ { "theHamsta/nvim-dap-virtual-text", -- virtual text for the debugger
+ opts = {},
},
- opts = {},
- config = function(_, opts)
- local dap = require("dap")
- local dapui = require("dapui")
- dapui.setup(opts)
- dap.listeners.after.event_initialized["dapui_config"] = function()
- dapui.open({})
- end
- end,
},
- -- virtual text for the debugger
- {
- "theHamsta/nvim-dap-virtual-text",
- opts = {},
+ -- stylua: ignore
+ keys = {
+ { "<leader>dB", function() require("dap").set_breakpoint(vim.fn.input('Breakpoint condition: ')) end, desc = "Breakpoint Condition" },
+ { "<leader>db", function() require("dap").toggle_breakpoint() end, desc = "Toggle Breakpoint" },
+ { "<leader>dc", function() require("dap").continue() end, desc = "Run/Continue" },
+ { "<leader>da", function() require("dap").continue({ before = get_args }) end, desc = "Run with Args" },
+ { "<leader>dC", function() require("dap").run_to_cursor() end, desc = "Run to Cursor" },
+ { "<C-T>", function() require("dap").run_to_cursor() end, desc = "Run to Cursor" },
+ { "<leader>dg", function() require("dap").goto_() end, desc = "Go to Line (No Execute)" },
+ { "<leader>di", function() require("dap").step_into() end, desc = "Step Into" },
+ { "<C-S>", function() require("dap").step_into() end, desc = "Step Into" },
+ { "<leader>dj", function() require("dap").down() end, desc = "Down" },
+ { "<leader>dk", function() require("dap").up() end, desc = "Up" },
+ { "<leader>dl", function() require("dap").run_last() end, desc = "Run Last" },
+ { "<leader>do", function() require("dap").step_out() end, desc = "Step Out" },
+ { "<C-F>", function() require("dap").step_out() end, desc = "Step Over" },
+ { "<leader>dO", function() require("dap").step_over() end, desc = "Step Over" },
+ { "<C-N>", function() require("dap").step_over() end, desc = "Step Over" },
+ { "<leader>dP", function() require("dap").pause() end, desc = "Pause" },
+ { "<leader>dr", function() require("dap").repl.toggle() end, desc = "Toggle REPL" },
+ { "<leader>ds", function() require("dap").session() end, desc = "Session" },
+ { "<leader>dt", function() require("dap").terminate() end, desc = "Terminate" },
+ { "<leader>dw", function() require("dap.ui.widgets").hover() end, desc = "Widgets" },
},
- -- which key integration
- {
- "folke/which-key.nvim",
- opts = {
- defaults = {
- ["<leader>d"] = { name = "+debug" },
- },
- },
- },
+ config = function()
+ -- load mason-nvim-dap here, after all adapters have been setup
+ require("mason-nvim-dap").setup(rmz.lazy.opts("mason-nvim-dap.nvim"))
- -- mason.nvim integration
- {
- "jay-babu/mason-nvim-dap.nvim",
- dependencies = "mason.nvim",
- cmd = { "DapInstall", "DapUninstall" },
- opts = {
- -- Makes a best effort to setup the various debuggers with
- -- reasonable debug configurations
- automatic_installation = true,
+ vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" })
- -- You can provide additional configuration to the handlers,
- -- see mason-nvim-dap README for more information
- handlers = {},
- },
- },
- {
- "jbyuki/one-small-step-for-vimkind",
- -- stylua: ignore
- keys = {
- { "<leader>daL", function() require("osv").launch({ port = 8086 }) end, desc = "Adapter Lua Server" },
- { "<leader>dal", function() require("osv").run_this() end, desc = "Adapter Lua" },
- },
- config = function()
- local dap = require("dap")
- dap.adapters.nlua = function(callback, config)
- local adapter = {
- type = "server",
- host = config.host or "127.0.0.1",
- port = config.port or 8086,
- }
- if config.start_neovim then
- local dap_run = dap.run
- dap.run = function(c)
- adapter.port = c.port
- adapter.host = c.host
- end
- require("osv").run_this()
- dap.run = dap_run
- end
- callback(adapter)
- end
- dap.configurations.lua = {
- {
- type = "nlua",
- request = "attach",
- name = "Run this file",
- start_neovim = {},
- },
- {
- type = "nlua",
- request = "attach",
- name = "Attach to running Neovim instance (port 8086)",
- port = 8086,
- },
- }
- end,
+ for name, sign in pairs(rmz.ui.icons.dap) do
+ sign = type(sign) == "table" and sign or { sign } ---@cast sign table
+ vim.fn.sign_define(
+ "Dap" .. name,
+ { text = sign[1], texthl = sign[2] or "DiagnosticInfo", linehl = sign[3], numhl = sign[3] }
+ )
+ end
+
+ -- setup dap config by VsCode launch.json file
+ local vscode = require("dap.ext.vscode")
+ local json = require("plenary.json")
+ vscode.json_decode = function(str)
+ return vim.json.decode(json.json_strip_comments(str))
+ end
+ end,
+ },
+ { "mason.nvim",
+ opts = {
+ log_level = vim.log.levels.TRACE,
+ }
+ },
+ { "rcarriga/nvim-dap-ui", -- fancy UI for the debugger
+ dependencies = { "nvim-neotest/nvim-nio" },
+ -- stylua: ignore
+ keys = {
+ { "<leader>du", function() require("dapui").toggle({ }) end, desc = "Dap UI" },
+ { "<leader>de", function() require("dapui").eval() end, desc = "Eval", mode = {"n", "v"} },
},
+ opts = {},
+ config = function(_, opts)
+ local dap = require("dap")
+ local dapui = require("dapui")
+ dapui.setup(opts)
+ dap.listeners.after.event_initialized["dapui_config"] = function()
+ dapui.open({})
+ end
+ end,
},
-
- -- stylua: ignore
- keys = {
- { "<leader>dB", function() require("dap").set_breakpoint(vim.fn.input('Breakpoint condition: ')) end, desc = "Breakpoint Condition" },
- { "<leader>db", function() require("dap").toggle_breakpoint() end, desc = "Toggle Breakpoint" },
- { "<leader>dc", function() require("dap").continue() end, desc = "Continue" },
- { "<leader>da", function() require("dap").continue({ before = get_args }) end, desc = "Run with Args" },
- { "<leader>dC", function() require("dap").run_to_cursor() end, desc = "Run to Cursor" },
- { "<C-T>", function() require("dap").run_to_cursor() end, desc = "Run to Cursor" },
- { "<leader>dg", function() require("dap").goto_() end, desc = "Go to line (no execute)" },
- { "<leader>di", function() require("dap").step_into() end, desc = "Step Into" },
- { "<C-S>", function() require("dap").step_into() end, desc = "Step Into" },
- { "<leader>dj", function() require("dap").down() end, desc = "Down" },
- { "<leader>dk", function() require("dap").up() end, desc = "Up" },
- { "<leader>dl", function() require("dap").run_last() end, desc = "Run Last" },
- { "<leader>do", function() require("dap").step_out() end, desc = "Step Out" },
- { "<C-F>", function() require("dap").step_out() end, desc = "Step Over" },
- { "<leader>dO", function() require("dap").step_over() end, desc = "Step Over" },
- { "<C-N>", function() require("dap").step_over() end, desc = "Step Over" },
- { "<leader>dp", function() require("dap").pause() end, desc = "Pause" },
- { "<leader>dr", function() require("dap").repl.toggle() end, desc = "Toggle REPL" },
- { "<leader>ds", function() require("dap").session() end, desc = "Session" },
- { "<leader>dt", function() require("dap").terminate() end, desc = "Terminate" },
- { "<leader>dw", function() require("dap.ui.widgets").hover() end, desc = "Widgets" },
+ -- mason.nvim integration
+ { "jay-babu/mason-nvim-dap.nvim",
+ dependencies = "mason.nvim",
+ cmd = { "DapInstall", "DapUninstall" },
+ opts_extend = { "ensure_installed" },
+ opts = {
+ automatic_installation = true,
+ handlers = {},
+ ensure_installed = { },
+ },
+ -- mason-nvim-dap is loaded when nvim-dap loads
+ config = function() end,
},
-
- config = function()
- local Config = require("lazyvim.config")
- vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" })
-
- for name, sign in pairs(Config.icons.dap) do
- sign = type(sign) == "table" and sign or { sign }
- vim.fn.sign_define(
- "Dap" .. name,
- { text = sign[1], texthl = sign[2] or "DiagnosticInfo", linehl = sign[3], numhl = sign[3] }
- )
- end
- end,
}
----@type LazyPluginSpec
+---@type LazySpec
return {
- {
- "nvim-telescope/telescope.nvim",
- keys = {
- { "<leader>fF", LazyVim.pick("files", { cwd = false }), desc = "Find Files (cwd)" },
- -- from lazyvim
- { "<leader>,", "<cmd>Telescope buffers show_all_buffers=true<cr>", desc = "Switch Buffer" },
- { "<leader>/", LazyVim.pick("live_grep"), desc = "Grep (root dir)" },
- { "<leader>:", "<cmd>Telescope command_history<cr>", desc = "Command History" },
- { "<leader><space>", LazyVim.pick("files"), desc = "Find Files (root dir)" },
- { "<leader><space>", false },
- -- find
- { "<leader>fb", "<cmd>Telescope buffers sort_lastused=true<CR>", desc = "Buffers" },
- -- { "<leader>ff", LazyVim.pick("files"), desc = "Find Files (root dir)" },
- { "<leader>ff", false }, -- fswitch
- { "<leader>fF", LazyVim.pick("files", { cwd = false }), desc = "Find Files (cwd)" },
- { "<leader>fr", "<cmd>Telescope oldfiles<cr>", desc = "Recent" },
- { "<leader>fR", LazyVim.pick("oldfiles", { cwd = vim.loop.cwd() }), desc = "Recent (cwd)" },
- -- git
- -- { "<leader>gc", "<cmd>Telescope git_commits<CR>", desc = "commits" },
- { "<leader>gc", false },
- -- { "<leader>gs", "<cmd>Telescope git_status<CR>", desc = "status" },
- { "<leader>gs", false },
- -- search
- { "<leader>sa", "<cmd>Telescope autocommands<cr>", desc = "Auto Commands" },
- { "<leader>sb", "<cmd>Telescope current_buffer_fuzzy_find<cr>", desc = "Buffer" },
- { "<leader>sc", "<cmd>Telescope command_history<cr>", desc = "Command History" },
- { "<leader>sC", "<cmd>Telescope commands<cr>", desc = "Commands" },
- { "<leader>sd", "<cmd>Telescope diagnostics bufnr=0<cr>", desc = "Document diagnostics" },
- { "<leader>sD", "<cmd>Telescope diagnostics<cr>", desc = "Workspace diagnostics" },
- { "<leader>sg", LazyVim.pick("live_grep"), desc = "Grep (root dir)" },
- { "<leader>sG", LazyVim.pick("live_grep", { cwd = false }), desc = "Grep (cwd)" },
- { "<leader>sh", "<cmd>Telescope help_tags<cr>", desc = "Help Pages" },
- { "<leader>sH", "<cmd>Telescope highlights<cr>", desc = "Search Highlight Groups" },
- { "<leader>sk", "<cmd>Telescope keymaps<cr>", desc = "Key Maps" },
- { "<leader>sM", "<cmd>Telescope man_pages<cr>", desc = "Man Pages" },
- { "<leader>sm", "<cmd>Telescope marks<cr>", desc = "Jump to Mark" },
- { "<leader>so", "<cmd>Telescope vim_options<cr>", desc = "Options" },
- { "<leader>sR", "<cmd>Telescope resume<cr>", desc = "Resume" },
- { "<leader>sw", LazyVim.pick("grep_string"), desc = "Word (root dir)" },
- { "<leader>sW", LazyVim.pick("grep_string", { cwd = false }), desc = "Word (cwd)" },
- { "<leader>uC", LazyVim.pick("colorscheme", { enable_preview = true }), desc = "Colorscheme with preview" },
- -- {
- -- "<leader>ss",
- -- LazyVim.pick("lsp_document_symbols", {
- -- symbols = {
- -- "Class",
- -- "Function",
- -- "Method",
- -- "Constructor",
- -- "Interface",
- -- "Module",
- -- "Struct",
- -- "Trait",
- -- "Field",
- -- "Property",
- -- },
- -- }),
- -- desc = "Goto Symbol",
- -- },
- { "<leader>ss", false }, -- use for snippets below
- {
- "<leader>sS",
- LazyVim.pick("lsp_dynamic_workspace_symbols", {
- symbols = {
- "Class",
- "Function",
- "Method",
- "Constructor",
- "Interface",
- "Module",
- "Struct",
- "Trait",
- "Field",
- "Property",
- },
- }),
- desc = "Goto Symbol (Workspace)",
- },
- },
- },
- {
- "benfowler/telescope-luasnip.nvim",
- dependencies = {
- "telescope.nvim",
- },
- config = function()
- require("telescope").load_extension("luasnip")
- end,
- keys = { { "<leader>ss", "<cmd>Telescope luasnip<cr>", desc = "Snippets" } },
- },
- {
- "stevearc/oil.nvim",
+ { "stevearc/oil.nvim",
opts = {
keymaps = {
["g?"] = "actions.show_help",
{ "folke/trouble.nvim",
cmd = { "Trouble" },
opts = {
- keys = {
- ["<space><space>"] = "fold_toggle",
- },
modes = {
lsp = {
win = { position = "right" },
},
},
{ "folke/todo-comments.nvim",
- cmd = { "TodoTrouble", "TodoTelescope" },
- event = "LazyFile",
+ -- Finds and lists all of the TODO, HACK, BUG, etc comment
+ -- in your project and loads them into a browsable list.
+ cmd = { "TodoTrouble"},
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" },
-- stylua: ignore
keys = {
{ "]t", function() require("todo-comments").jump_next() end, desc = "Next Todo Comment" },
{ "[t", function() require("todo-comments").jump_prev() end, desc = "Previous Todo Comment" },
{ "<leader>xt", "<cmd>Trouble todo toggle<cr>", desc = "Todo (Trouble)" },
{ "<leader>xT", "<cmd>Trouble todo toggle filter = {tag = {TODO,FIX,FIXME}}<cr>", desc = "Todo/Fix/Fixme (Trouble)" },
- { "<leader>st", "<cmd>TodoTelescope<cr>", desc = "Todo" },
- { "<leader>sT", "<cmd>TodoTelescope keywords=TODO,FIX,FIXME<cr>", desc = "Todo/Fix/Fixme" },
},
+ opts = {}
},
- {
- "neo-tree.nvim",
- enabled = false,
- lazy = false,
- opts = {
- filesystem = {
- -- TODO: review these
- bind_to_cwd = false,
- follow_current_file = {
- enabled = false,
- },
- },
- },
- keys = function()
- local NeoTree = function(args)
- return function()
- require("neo-tree.command").execute(args)
- end
- end
+ { "echasnovski/mini.hipatterns", -- highlight hex colours and other matched words
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" },
+ opts = function()
+ local hi = require("mini.hipatterns")
return {
- { "<leader>fe", NeoTree({ toggle = true, dir = vim.loop.cwd() }) },
+ highlighters = {
+ hex_color = hi.gen_highlighter.hex_color({ priority = 2000 }),
+ },
}
end,
},
+ { "folke/flash.nvim",
+ -- Flash enhances the built-in search functionality by showing labels
+ -- at the end of each match, letting you quickly jump to a specific
+ -- location.
+ event = "VeryLazy",
+ vscode = true,
+ ---@type Flash.Config
+ opts = {},
+ -- stylua: ignore
+ keys = {
+ { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
+ { "S", mode = { "n", "o", "x" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
+ { "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
+ { "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
+ { "<c-s>", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
+ },
+ },
+ { "lewis6991/gitsigns.nvim",
+ -- git signs highlights text that has changed since the list
+ -- git commit, and also lets you interactively stage & unstage
+ -- hunks in a commit.
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" },
+ opts = {
+ signs = {
+ add = { text = "▎" },
+ change = { text = "▎" },
+ delete = { text = "" },
+ topdelete = { text = "" },
+ changedelete = { text = "▎" },
+ untracked = { text = "▎" },
+ },
+ signs_staged = {
+ add = { text = "▎" },
+ change = { text = "▎" },
+ delete = { text = "" },
+ topdelete = { text = "" },
+ changedelete = { text = "▎" },
+ },
+ on_attach = function(buffer)
+ local gs = package.loaded.gitsigns
+
+ local function map(mode, l, r, desc)
+ vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc })
+ end
+
+ -- stylua: ignore start
+ map("n", "]h", function()
+ if vim.wo.diff then
+ vim.cmd.normal({ "]c", bang = true })
+ else
+ gs.nav_hunk("next")
+ end
+ end, "Next Hunk")
+ map("n", "[h", function()
+ if vim.wo.diff then
+ vim.cmd.normal({ "[c", bang = true })
+ else
+ gs.nav_hunk("prev")
+ end
+ end, "Prev Hunk")
+ map("n", "]H", function() gs.nav_hunk("last") end, "Last Hunk")
+ map("n", "[H", function() gs.nav_hunk("first") end, "First Hunk")
+ map({ "n", "v" }, "<leader>ghs", ":Gitsigns stage_hunk<CR>", "Stage Hunk")
+ map({ "n", "v" }, "<leader>ghr", ":Gitsigns reset_hunk<CR>", "Reset Hunk")
+ map("n", "<leader>ghS", gs.stage_buffer, "Stage Buffer")
+ map("n", "<leader>ghu", gs.undo_stage_hunk, "Undo Stage Hunk")
+ map("n", "<leader>ghR", gs.reset_buffer, "Reset Buffer")
+ map("n", "<leader>ghp", gs.preview_hunk_inline, "Preview Hunk Inline")
+ map("n", "<leader>ghb", function() gs.blame_line({ full = true }) end, "Blame Line")
+ map("n", "<leader>ghB", function() gs.blame() end, "Blame Buffer")
+ map("n", "<leader>ghd", gs.diffthis, "Diff This")
+ map("n", "<leader>ghD", function() gs.diffthis("~") end, "Diff This ~")
+ map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>", "GitSigns Select Hunk")
+ Snacks.toggle({
+ name = "Git Signs",
+ get = function()
+ return require("gitsigns.config").config.signcolumn
+ end,
+ set = function(state)
+ require("gitsigns").toggle_signs(state)
+ end,
+ }):map("<leader>uG")
+ end,
+ },
+ },
+
+ -- TODO: currently unused plugins, check and enable/remove
+ { "MagicDuck/grug-far.nvim", enabled = false,
+ -- search/replace in multiple files
+ opts = { headerMaxWidth = 80 },
+ cmd = "GrugFar",
+ keys = {
+ {
+ "<leader>sr",
+ function()
+ local grug = require("grug-far")
+ local ext = vim.bo.buftype == "" and vim.fn.expand("%:e")
+ grug.open({
+ transient = true,
+ prefills = {
+ filesFilter = ext and ext ~= "" and "*." .. ext or nil,
+ },
+ })
+ end,
+ mode = { "n", "v" },
+ desc = "Search and Replace",
+ },
+ },
+ },
+ { "aymericbeaumet/vim-symlink",
+ dependencies = { "moll/vim-bbye" }, -- NOTE: Snacks.buddelete also provides this
+ },
}
--- /dev/null
+--- TODO: add toggle for format on save
+--- https://github.com/stevearc/conform.nvim/blob/master/doc/recipes.md#command-to-toggle-format-on-save
+--- previous keymap was <leader>uf
+
+---@type LazySpec
+return {
+ { "stevearc/conform.nvim",
+ dependencies = { "mason.nvim" },
+ lazy = true,
+ cmd = "ConformInfo",
+ keys = {
+ {"<leader>cf", function() require("conform").format({ async = true }) end, mode = "", desc = "Format buffer" },
+ {
+ "<leader>cF",
+ function()
+ require("conform").format({ formatters = { "injected" }, timeout_ms = 3000 })
+ end,
+ mode = { "n", "v" },
+ desc = "Format Injected Langs",
+ },
+ },
+ ---@module "conform"
+ ---@type conform.setupOpts
+ opts = {
+ default_format_opts = {
+ timeout_ms = 3000,
+ async = false, -- not recommended to change
+ quiet = false, -- not recommended to change
+ lsp_format = "fallback", -- not recommended to change
+ },
+ formatters_by_ft = {
+ lua = { "stylua" },
+ fish = { "fish_indent" },
+ sh = { "shfmt" },
+ },
+ -- The options you set here will be merged with the builtin formatters.
+ -- You can also define any custom formatters here.
+ ---@type table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride>
+ formatters = {
+ injected = { options = { ignore_errors = true } },
+ },
+ },
+ init = function ()
+ vim.opt.formatexpr = "v:lua.require'conform'.formatexpr()"
+ end,
+ },
+}
--- /dev/null
+return {
+ { "folke/lazy.nvim", version = "*" },
+ { "folke/snacks.nvim", priority = 1000, lazy = false },
+}
--- /dev/null
+return {
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "cmake" } },
+ },
+ {
+ "nvimtools/none-ls.nvim",
+ optional = true,
+ opts = function(_, opts)
+ local nls = require("null-ls")
+ opts.sources = vim.list_extend(opts.sources or {}, {
+ nls.builtins.diagnostics.cmake_lint,
+ })
+ end,
+ },
+ {
+ "mfussenegger/nvim-lint",
+ optional = true,
+ opts = {
+ linters_by_ft = {
+ cmake = { "cmakelint" },
+ },
+ },
+ },
+ {
+ "mason.nvim",
+ opts = { ensure_installed = { "cmakelang", "cmakelint" } },
+ },
+ {
+ "neovim/nvim-lspconfig",
+ opts = {
+ servers = {
+ neocmake = {},
+ },
+ },
+ },
+ {
+ "Civitasv/cmake-tools.nvim",
+ lazy = true,
+ init = function()
+ local loaded = false
+ local function check()
+ local cwd = vim.uv.cwd()
+ if vim.fn.filereadable(cwd .. "/CMakeLists.txt") == 1 then
+ require("lazy").load({ plugins = { "cmake-tools.nvim" } })
+ loaded = true
+ end
+ end
+ check()
+ vim.api.nvim_create_autocmd("DirChanged", {
+ callback = function()
+ if not loaded then
+ check()
+ end
+ end,
+ })
+ end,
+ opts = {},
+ },
+}
-- Add C/C++ to treesitter
{
"nvim-treesitter/nvim-treesitter",
- opts = function(_, opts)
- if type(opts.ensure_installed) == "table" then
- vim.list_extend(opts.ensure_installed, { "c", "cpp" })
- end
- end,
+ opts = { ensure_installed = { "c", "cpp" } },
},
{
-- Ensure mason installs the server
clangd = {
keys = {
- { "<leader>cR", "<cmd>ClangdSwitchSourceHeader<cr>", desc = "Switch Source/Header (C/C++)" },
+ { "<leader>ch", "<cmd>ClangdSwitchSourceHeader<cr>", desc = "Switch Source/Header (C/C++)" },
},
root_dir = function(fname)
return require("lspconfig.util").root_pattern( "compile_commands.json", "compile_flags.txt")(fname)
},
setup = {
clangd = function(_, opts)
- local clangd_ext_opts = require("lazyvim.util").opts("clangd_extensions.nvim")
+ local clangd_ext_opts = rmz.lazy.opts("clangd_extensions.nvim")
require("clangd_extensions").setup(vim.tbl_deep_extend("force", clangd_ext_opts or {}, { server = opts }))
return false
end,
},
},
},
-
- {
- "nvim-cmp",
- opts = function(_, opts)
- table.insert(opts.sorting.comparators, 1, require("clangd_extensions.cmp_scores"))
- end,
- },
-
- {
- "mfussenegger/nvim-dap",
+ -- { "blink.cmp",
+ -- opts = function(_, opts)
+ -- -- TODO: make sure this works
+ -- table.insert(opts.fuzzy.sorts, 1, require("clangd_extensions.cmp_scores"))
+ -- end,
+ -- },
+ { "mfussenegger/nvim-dap",
dependencies = {
-- Ensure C/C++ debugger is installed
"williamboman/mason.nvim",
- opts = function(_, opts)
- if type(opts.ensure_installed) == "table" then
- vim.list_extend(opts.ensure_installed, { "codelldb" })
- end
- end,
+ opts = { ensure_installed = { "codelldb" } },
},
opts = function()
local dap = require("dap")
type = "codelldb",
request = "attach",
name = "Attach to process",
- processId = require("dap.utils").pick_process,
+ pid = require("dap.utils").pick_process,
cwd = "${workspaceFolder}",
},
}
--- /dev/null
+return {
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "dockerfile" } },
+ },
+ {
+ "mason.nvim",
+ opts = { ensure_installed = { "hadolint" } },
+ },
+ {
+ "nvimtools/none-ls.nvim",
+ optional = true,
+ opts = function(_, opts)
+ local nls = require("null-ls")
+ opts.sources = vim.list_extend(opts.sources or {}, {
+ nls.builtins.diagnostics.hadolint,
+ })
+ end,
+ },
+ {
+ "mfussenegger/nvim-lint",
+ optional = true,
+ opts = {
+ linters_by_ft = {
+ dockerfile = { "hadolint" },
+ },
+ },
+ },
+ {
+ "neovim/nvim-lspconfig",
+ opts = {
+ servers = {
+ dockerls = {},
+ docker_compose_language_service = {},
+ },
+ },
+ },
+}
--- /dev/null
+return {
+ -- Treesitter git support
+ { "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "git_config", "gitcommit", "git_rebase", "gitignore", "gitattributes" } },
+ },
+
+ {
+ "hrsh7th/nvim-cmp",
+ optional = true,
+ dependencies = {
+ { "petertriho/cmp-git", opts = {} },
+ },
+ ---@module 'cmp'
+ ---@param opts cmp.ConfigSchema
+ opts = function(_, opts)
+ table.insert(opts.sources, { name = "git" })
+ end,
+ },
+}
--- /dev/null
+return {
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "go", "gomod", "gowork", "gosum" } },
+ },
+ {
+ "neovim/nvim-lspconfig",
+ opts = {
+ servers = {
+ gopls = {
+ settings = {
+ gopls = {
+ gofumpt = true,
+ codelenses = {
+ gc_details = false,
+ generate = true,
+ regenerate_cgo = true,
+ run_govulncheck = true,
+ test = true,
+ tidy = true,
+ upgrade_dependency = true,
+ vendor = true,
+ },
+ hints = {
+ assignVariableTypes = true,
+ compositeLiteralFields = true,
+ compositeLiteralTypes = true,
+ constantValues = true,
+ functionTypeParameters = true,
+ parameterNames = true,
+ rangeVariableTypes = true,
+ },
+ analyses = {
+ fieldalignment = true,
+ nilness = true,
+ unusedparams = true,
+ unusedwrite = true,
+ useany = true,
+ },
+ usePlaceholders = true,
+ completeUnimported = true,
+ staticcheck = true,
+ directoryFilters = { "-.git", "-.vscode", "-.idea", "-.vscode-test", "-node_modules" },
+ semanticTokens = true,
+ },
+ },
+ },
+ },
+ setup = {
+ gopls = function(_, opts)
+ -- workaround for gopls not supporting semanticTokensProvider
+ -- https://github.com/golang/go/issues/54531#issuecomment-1464982242
+ rmz.lsp.on_attach(function(client, _)
+ if not client.server_capabilities.semanticTokensProvider then
+ local semantic = client.config.capabilities.textDocument.semanticTokens
+ client.server_capabilities.semanticTokensProvider = {
+ full = true,
+ legend = {
+ tokenTypes = semantic.tokenTypes,
+ tokenModifiers = semantic.tokenModifiers,
+ },
+ range = true,
+ }
+ end
+ end, "gopls")
+ -- end workaround
+ end,
+ },
+ },
+ },
+ -- Ensure Go tools are installed
+ {
+ "williamboman/mason.nvim",
+ opts = { ensure_installed = { "goimports", "gofumpt" } },
+ },
+ {
+ "nvimtools/none-ls.nvim",
+ optional = true,
+ dependencies = {
+ {
+ "williamboman/mason.nvim",
+ opts = { ensure_installed = { "gomodifytags", "impl" } },
+ },
+ },
+ opts = function(_, opts)
+ local nls = require("null-ls")
+ opts.sources = vim.list_extend(opts.sources or {}, {
+ nls.builtins.code_actions.gomodifytags,
+ nls.builtins.code_actions.impl,
+ nls.builtins.formatting.goimports,
+ nls.builtins.formatting.gofumpt,
+ })
+ end,
+ },
+ {
+ "stevearc/conform.nvim",
+ optional = true,
+ opts = {
+ formatters_by_ft = {
+ go = { "goimports", "gofumpt" },
+ },
+ },
+ },
+ {
+ "mfussenegger/nvim-dap",
+ optional = true,
+ dependencies = {
+ {
+ "williamboman/mason.nvim",
+ opts = { ensure_installed = { "delve" } },
+ },
+ {
+ "leoluz/nvim-dap-go",
+ opts = {},
+ },
+ },
+ },
+ {
+ "nvim-neotest/neotest",
+ optional = true,
+ dependencies = {
+ "fredrikaverpil/neotest-golang",
+ },
+ opts = {
+ adapters = {
+ ["neotest-golang"] = {
+ -- Here we can set options for neotest-golang, e.g.
+ -- go_test_args = { "-v", "-race", "-count=1", "-timeout=60s" },
+ dap_go_enabled = true, -- requires leoluz/nvim-dap-go
+ },
+ },
+ },
+ },
+
+ -- Filetype icons
+ {
+ "echasnovski/mini.icons",
+ opts = {
+ file = {
+ [".go-version"] = { glyph = "", hl = "MiniIconsBlue" },
+ },
+ filetype = {
+ gotmpl = { glyph = "", hl = "MiniIconsGrey" },
+ },
+ },
+ },
+}
--- /dev/null
+return {
+
+ -- Add Haskell to treesitter
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "haskell" } },
+ },
+
+ {
+ "mrcjkb/haskell-tools.nvim",
+ version = "^3",
+ ft = { "haskell", "lhaskell", "cabal", "cabalproject" },
+ dependencies = {
+ { "nvim-telescope/telescope.nvim", optional = true },
+ },
+ config = function()
+ local ok, telescope = pcall(require, "telescope")
+ if ok then
+ telescope.load_extension("ht")
+ end
+ end,
+ },
+
+ {
+ "williamboman/mason.nvim",
+ opts = { ensure_installed = { "haskell-language-server" } },
+ },
+
+ {
+ "mfussenegger/nvim-dap",
+ optional = true,
+ dependencies = {
+ {
+ "williamboman/mason.nvim",
+ opts = { ensure_installed = { "haskell-debug-adapter" } },
+ },
+ },
+ },
+
+ {
+ "nvim-neotest/neotest",
+ optional = true,
+ dependencies = {
+ { "mrcjkb/neotest-haskell" },
+ },
+ opts = {
+ adapters = {
+ ["neotest-haskell"] = {},
+ },
+ },
+ },
+
+ {
+ "mrcjkb/haskell-snippets.nvim",
+ dependencies = { "l3mon4d3/luasnip" },
+ ft = { "haskell", "lhaskell", "cabal", "cabalproject" },
+ config = function()
+ local haskell_snippets = require("haskell-snippets").all
+ require("luasnip").add_snippets("haskell", haskell_snippets, { key = "haskell" })
+ end,
+ },
+
+ {
+ "luc-tielen/telescope_hoogle",
+ ft = { "haskell", "lhaskell", "cabal", "cabalproject" },
+ dependencies = {
+ { "nvim-telescope/telescope.nvim" },
+ },
+ config = function()
+ local ok, telescope = pcall(require, "telescope")
+ if ok then
+ telescope.load_extension("hoogle")
+ end
+ end,
+ },
+
+ -- Make sure lspconfig doesn't start hls,
+ -- as it conflicts with haskell-tools
+ {
+ "neovim/nvim-lspconfig",
+ opts = {
+ setup = {
+ hls = function()
+ return true
+ end,
+ },
+ },
+ },
+}
--- /dev/null
+return {
+ -- add json to treesitter
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "json5" } },
+ },
+
+ -- yaml schema support
+ {
+ "b0o/SchemaStore.nvim",
+ lazy = true,
+ version = false, -- last release is way too old
+ },
+
+ -- correctly setup lspconfig
+ {
+ "neovim/nvim-lspconfig",
+ opts = {
+ -- make sure mason installs the server
+ servers = {
+ jsonls = {
+ -- lazy-load schemastore when needed
+ on_new_config = function(new_config)
+ new_config.settings.json.schemas = new_config.settings.json.schemas or {}
+ vim.list_extend(new_config.settings.json.schemas, require("schemastore").json.schemas())
+ end,
+ settings = {
+ json = {
+ format = {
+ enable = true,
+ },
+ validate = { enable = true },
+ },
+ },
+ },
+ },
+ },
+ },
+}
--- /dev/null
+return {
+ {
+ "stevearc/conform.nvim",
+ optional = true,
+ opts = {
+ formatters = {
+ ["markdown-toc"] = {
+ condition = function(_, ctx)
+ for _, line in ipairs(vim.api.nvim_buf_get_lines(ctx.buf, 0, -1, false)) do
+ if line:find("<!%-%- toc %-%->") then
+ return true
+ end
+ end
+ end,
+ },
+ ["markdownlint-cli2"] = {
+ condition = function(_, ctx)
+ local diag = vim.tbl_filter(function(d)
+ return d.source == "markdownlint"
+ end, vim.diagnostic.get(ctx.buf))
+ return #diag > 0
+ end,
+ },
+ },
+ formatters_by_ft = {
+ ["markdown"] = { "prettier", "markdownlint-cli2", "markdown-toc" },
+ ["markdown.mdx"] = { "prettier", "markdownlint-cli2", "markdown-toc" },
+ },
+ },
+ },
+ {
+ "williamboman/mason.nvim",
+ opts = { ensure_installed = { "markdownlint-cli2", "markdown-toc" } },
+ },
+ {
+ "nvimtools/none-ls.nvim",
+ optional = true,
+ opts = function(_, opts)
+ local nls = require("null-ls")
+ opts.sources = vim.list_extend(opts.sources or {}, {
+ nls.builtins.diagnostics.markdownlint_cli2,
+ })
+ end,
+ },
+ {
+ "mfussenegger/nvim-lint",
+ optional = true,
+ opts = {
+ linters_by_ft = {
+ markdown = { "markdownlint-cli2" },
+ },
+ },
+ },
+ {
+ "neovim/nvim-lspconfig",
+ opts = {
+ servers = {
+ marksman = {},
+ },
+ },
+ },
+
+ -- Markdown preview
+ {
+ "iamcco/markdown-preview.nvim",
+ cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" },
+ build = function()
+ require("lazy").load({ plugins = { "markdown-preview.nvim" } })
+ vim.fn["mkdp#util#install"]()
+ end,
+ keys = {
+ {
+ "<leader>cp",
+ ft = "markdown",
+ "<cmd>MarkdownPreviewToggle<cr>",
+ desc = "Markdown Preview",
+ },
+ },
+ config = function()
+ vim.cmd([[do FileType]])
+ end,
+ },
+
+ {
+ "MeanderingProgrammer/render-markdown.nvim",
+ opts = {
+ code = {
+ sign = false,
+ width = "block",
+ right_pad = 1,
+ },
+ heading = {
+ sign = false,
+ icons = {},
+ },
+ checkbox = {
+ enabled = false,
+ },
+ },
+ ft = { "markdown", "norg", "rmd", "org", "codecompanion" },
+ config = function(_, opts)
+ require("render-markdown").setup(opts)
+ Snacks.toggle({
+ name = "Render Markdown",
+ get = function()
+ return require("render-markdown.state").enabled
+ end,
+ set = function(enabled)
+ local m = require("render-markdown")
+ if enabled then
+ m.enable()
+ else
+ m.disable()
+ end
+ end,
+ }):map("<leader>um")
+ end,
+ },
+}
--- /dev/null
+return {
+ { "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "nix" } },
+ },
+ { "neovim/nvim-lspconfig",
+ opts = {
+ servers = {
+ -- nil_ls = {}, -- FIXME: this causes big CPU usage when tried to be installed and eventually just fails
+ },
+ },
+ },
+ { "stevearc/conform.nvim",
+ opts = {
+ formatters_by_ft = {
+ nix = { "nixfmt" },
+ },
+ },
+ },
+}
--- /dev/null
+return {
+ "mfussenegger/nvim-dap",
+ dependencies = {
+ {
+ "jbyuki/one-small-step-for-vimkind",
+ config = function()
+ local dap = require("dap")
+ dap.adapters.nlua = function(callback, conf)
+ local adapter = {
+ type = "server",
+ host = conf.host or "127.0.0.1",
+ port = conf.port or 8086,
+ }
+ if conf.start_neovim then
+ local dap_run = dap.run
+ dap.run = function(c)
+ adapter.port = c.port
+ adapter.host = c.host
+ end
+ require("osv").run_this()
+ dap.run = dap_run
+ end
+ callback(adapter)
+ end
+ dap.configurations.lua = {
+ {
+ type = "nlua",
+ request = "attach",
+ name = "Run this file",
+ start_neovim = {},
+ },
+ {
+ type = "nlua",
+ request = "attach",
+ name = "Attach to running Neovim instance (port = 8086)",
+ port = 8086,
+ },
+ }
+ end,
+ },
+ },
+}
return {
- {
- "nvim-treesitter/nvim-treesitter",
- opts = function(_, opts)
- if type(opts.ensure_installed) == "table" then
- vim.list_extend(opts.ensure_installed, { "ninja", "python", "rst", "toml" })
- end
- end,
+ { "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "ninja", "rst" } },
},
- {
- "neovim/nvim-lspconfig",
+ { "neovim/nvim-lspconfig",
opts = {
- ---@type lspconfig.options
servers = {
- pyright = {},
ruff = {
- root_dir = function(fname)
- return require("lspconfig.util").root_pattern("pyproject.toml", "setup.cfg", "ruff.toml")(fname)
- end,
+ cmd_env = { RUFF_TRACE = "messages" },
+ init_options = {
+ settings = {
+ logLevel = "error",
+ },
+ },
keys = {
{
"<leader>co",
- function()
- vim.lsp.buf.code_action({
- apply = true,
- context = {
- only = { "source.organizeImports" },
- diagnostics = {},
- },
- })
- end,
+ rmz.lsp.action["source.organizeImports"],
desc = "Organize Imports",
},
},
},
- pylsp = {
- settings = {
- pylsp = {
- plugins = {
- autopep8 = { enabled = false },
- flake8 = { enabled = false },
- mccabe = { enabled = false },
- pycodestyle = { enabled = false },
- pydocstyle = { enabled = false },
- pyflakes = { enabled = false }, -- covered by flake8
- }
- }
- }
- }
},
setup = {
- ruff_lsp = function()
- require("lazyvim.util").lsp.on_attach(function(client, _)
- if client.name == "ruff_lsp" then
- -- Disable hover in favor of Pyright
- client.server_capabilities.hoverProvider = false
- end
- end)
+ ["ruff"] = function()
+ rmz.lsp.on_attach(function(client, _)
+ -- Disable hover in favor of Pyright
+ client.server_capabilities.hoverProvider = false
+ end, "ruff")
end,
},
},
},
+ {
+ "neovim/nvim-lspconfig",
+ opts = function(_, opts)
+ local servers = { "pyright", "ruff"}
+ for _, server in ipairs(servers) do
+ opts.servers[server] = opts.servers[server] or {}
+ opts.servers[server].enabled = server == lsp or server == ruff
+ end
+ end,
+ },
{
"nvim-neotest/neotest",
dependencies = {
"mfussenegger/nvim-dap",
dependencies = {
"mfussenegger/nvim-dap-python",
- -- stylua: ignore
keys = {
{ "<leader>dPt", function() require('dap-python').test_method() end, desc = "Debug Method", ft = "python" },
{ "<leader>dPc", function() require('dap-python').test_class() end, desc = "Debug Class", ft = "python" },
end,
},
},
- {
- "linux-cultist/venv-selector.nvim",
+ { "jay-babu/mason-nvim-dap.nvim",
+ opts = {
+ handlers = {
+ python = function() end,
+ },
+ ensure_installed = { "python" },
+ },
+ },
+ { "linux-cultist/venv-selector.nvim", enabled = false,
+ -- TODO needs fd to be installed (I don't know what that is)
+ branch = "regexp", -- Use this branch for the new version
cmd = "VenvSelect",
- opts = function(_, opts)
- if require("lazyvim.util").has("nvim-dap-python") then
- opts.dap_enabled = true
- end
- return vim.tbl_deep_extend("force", opts, {
- name = {
- "venv",
- ".venv",
- "env",
- ".env",
+ opts = {
+ settings = {
+ options = {
+ notify_user_on_venv_activation = true,
},
- })
+ },
+ },
+ -- Call config for python files and load the cached venv automatically
+ ft = "python",
+ keys = { { "<leader>cv", "<cmd>:VenvSelect<cr>", desc = "Select VirtualEnv", ft = "python" } },
+ },
+ { "hrsh7th/nvim-cmp",
+ optional = true,
+ opts = function(_, opts)
+ opts.auto_brackets = opts.auto_brackets or {}
+ table.insert(opts.auto_brackets, "python")
end,
- keys = { { "<leader>cv", "<cmd>:VenvSelect<cr>", desc = "Select VirtualEnv" } },
},
}
--- /dev/null
+return {
+ { "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "ruby" } },
+ },
+ { "neovim/nvim-lspconfig",
+ ---@class PluginLspOpts
+ opts = {
+ ---@type lspconfig.options
+ servers = {
+ ruby_lsp = { enabled = true, },
+ rubocop = { enabled = true, },
+ },
+ },
+ },
+ { "williamboman/mason.nvim",
+ opts = { ensure_installed = { "erb-formatter", "erb-lint" } },
+ },
+ {
+ "mfussenegger/nvim-dap",
+ dependencies = {
+ "suketa/nvim-dap-ruby",
+ config = function()
+ require("dap-ruby").setup()
+ end,
+ },
+ },
+ { "stevearc/conform.nvim",
+ opts = {
+ formatters_by_ft = {
+ ruby = { "rubocop" },
+ eruby = { "erb_format" },
+ },
+ },
+ },
+ { "nvim-neotest/neotest",
+ dependencies = {
+ "olimorris/neotest-rspec",
+ },
+ opts = {
+ adapters = {
+ ["neotest-rspec"] = {
+ -- NOTE: By default neotest-rspec uses the system wide rspec gem instead of the one through bundler
+ -- rspec_cmd = function()
+ -- return vim.tbl_flatten({
+ -- "bundle",
+ -- "exec",
+ -- "rspec",
+ -- })
+ -- end,
+ },
+ },
+ },
+ },
+}
--- /dev/null
+return {
+ { "Saecki/crates.nvim",
+ event = { "BufRead Cargo.toml" },
+ opts = {
+ completion = {
+ crates = {
+ enabled = true,
+ },
+ },
+ lsp = {
+ enabled = true,
+ actions = true,
+ completion = true,
+ hover = true,
+ },
+ },
+ },
+ { "nvim-treesitter/nvim-treesitter",
+ opts = { ensure_installed = { "rust", "ron" } },
+ },
+ { "williamboman/mason.nvim",
+ optional = true,
+ opts = function(_, opts)
+ opts.ensure_installed = opts.ensure_installed or {}
+ vim.list_extend(opts.ensure_installed, { "codelldb" })
+ end,
+ },
+ { "mrcjkb/rustaceanvim",
+ version = vim.fn.has("nvim-0.10.0") == 0 and "^4" or false,
+ ft = { "rust" },
+ opts = {
+ server = {
+ on_attach = function(_, bufnr)
+ vim.keymap.set("n", "<leader>cR", function()
+ vim.cmd.RustLsp("codeAction")
+ end, { desc = "Code Action", buffer = bufnr })
+ vim.keymap.set("n", "<leader>dr", function()
+ vim.cmd.RustLsp("debuggables")
+ end, { desc = "Rust Debuggables", buffer = bufnr })
+ end,
+ default_settings = {
+ -- rust-analyzer language server configuration
+ ["rust-analyzer"] = {
+ cargo = {
+ allFeatures = true,
+ loadOutDirsFromCheck = true,
+ buildScripts = {
+ enable = true,
+ },
+ },
+ -- Add clippy lints for Rust if using rust-analyzer
+ checkOnSave = true,
+ -- Enable diagnostics if using rust-analyzer
+ diagnostics = {
+ enable = true,
+ },
+ procMacro = {
+ enable = true,
+ ignored = {
+ ["async-trait"] = { "async_trait" },
+ ["napi-derive"] = { "napi" },
+ ["async-recursion"] = { "async_recursion" },
+ },
+ },
+ files = {
+ excludeDirs = {
+ ".direnv",
+ ".git",
+ ".github",
+ ".gitlab",
+ "bin",
+ "node_modules",
+ "target",
+ "venv",
+ ".venv",
+ },
+ },
+ },
+ },
+ },
+ },
+ config = function(_, opts)
+ local package_path = require("mason-registry").get_package("codelldb"):get_install_path()
+ local codelldb = package_path .. "/extension/adapter/codelldb"
+ local library_path = package_path .. "/extension/lldb/lib/liblldb.dylib"
+ local uname = io.popen("uname"):read("*l")
+ if uname == "Linux" then
+ library_path = package_path .. "/extension/lldb/lib/liblldb.so"
+ end
+ opts.dap = {
+ adapter = require("rustaceanvim.config").get_codelldb_adapter(codelldb, library_path),
+ }
+ vim.g.rustaceanvim = vim.tbl_deep_extend("keep", vim.g.rustaceanvim or {}, opts or {})
+ if vim.fn.executable("rust-analyzer") == 0 then
+ rmz.lazy.error(
+ "**rust-analyzer** not found in PATH, please install it.\nhttps://rust-analyzer.github.io/",
+ { title = "rustaceanvim" }
+ )
+ end
+ end,
+ },
+ { "neovim/nvim-lspconfig",
+ opts = {
+ servers = {
+ rust_analyzer = { enabled = false }, -- rustaceanvim is used instead
+ },
+ },
+ },
+ { "nvim-neotest/neotest",
+ optional = true,
+ opts = {
+ adapters = {
+ ["rustaceanvim.neotest"] = {},
+ },
+ },
+ },
+}
--- /dev/null
+return {
+ -- Add BibTeX/LaTeX to treesitter
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = function(_, opts)
+ opts.highlight = opts.highlight or {}
+ if type(opts.ensure_installed) == "table" then
+ vim.list_extend(opts.ensure_installed, { "bibtex" })
+ end
+ if type(opts.highlight.disable) == "table" then
+ vim.list_extend(opts.highlight.disable, { "latex" })
+ else
+ opts.highlight.disable = { "latex" }
+ end
+ end,
+ },
+
+ {
+ "lervag/vimtex",
+ lazy = false, -- lazy-loading will disable inverse search
+ config = function()
+ vim.g.vimtex_mappings_disable = { ["n"] = { "K" } } -- disable `K` as it conflicts with LSP hover
+ vim.g.vimtex_quickfix_method = vim.fn.executable("pplatex") == 1 and "pplatex" or "latexlog"
+ end,
+ keys = {
+ { "<localLeader>l", "", desc = "+vimtex", ft = "tex" },
+ },
+ },
+
+ -- Correctly setup lspconfig for LaTeX 🚀
+ {
+ "neovim/nvim-lspconfig",
+ optional = true,
+ opts = {
+ servers = {
+ texlab = {
+ keys = {
+ { "<Leader>K", "<plug>(vimtex-doc-package)", desc = "Vimtex Docs", silent = true },
+ },
+ },
+ },
+ },
+ },
+}
--- /dev/null
+return {
+ "neovim/nvim-lspconfig",
+ opts = {
+ servers = {
+ taplo = {},
+ },
+ },
+}
--- /dev/null
+return {
+ -- yaml schema support
+ {
+ "b0o/SchemaStore.nvim",
+ lazy = true,
+ version = false, -- last release is way too old
+ },
+
+ -- correctly setup lspconfig
+ {
+ "neovim/nvim-lspconfig",
+ opts = {
+ -- make sure mason installs the server
+ servers = {
+ yamlls = {
+ -- Have to add this for yamlls to understand that we support line folding
+ capabilities = {
+ textDocument = {
+ foldingRange = {
+ dynamicRegistration = false,
+ lineFoldingOnly = true,
+ },
+ },
+ },
+ -- lazy-load schemastore when needed
+ on_new_config = function(new_config)
+ new_config.settings.yaml.schemas = vim.tbl_deep_extend(
+ "force",
+ new_config.settings.yaml.schemas or {},
+ require("schemastore").yaml.schemas()
+ )
+ end,
+ settings = {
+ redhat = { telemetry = { enabled = false } },
+ yaml = {
+ keyOrdering = false,
+ format = {
+ enable = true,
+ },
+ validate = true,
+ schemaStore = {
+ -- Must disable built-in schemaStore support to use
+ -- schemas from SchemaStore.nvim plugin
+ enable = false,
+ -- Avoid TypeError: Cannot read properties of undefined (reading 'length')
+ url = "",
+ },
+ },
+ },
+ },
+ },
+ setup = {
+ yamlls = function()
+ -- Neovim < 0.10 does not have dynamic registration for formatting
+ if vim.fn.has("nvim-0.10") == 0 then
+ rmz.lsp.on_attach(function(client, _)
+ client.server_capabilities.documentFormattingProvider = true
+ end, "yamlls")
+ end
+ end,
+ },
+ },
+ },
+}
--- /dev/null
+local M = {}
+
+return {
+ { "mfussenegger/nvim-lint",
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" },
+ opts = {
+ -- Event to trigger linters
+ events = { "BufWritePost", "BufReadPost", "InsertLeave" },
+ linters_by_ft = { },
+ -- NOTE: LazyVim had an extension to support global and fallback linters,
+ -- and conditionally enable a linter
+ },
+ config = function(_, opts)
+ function M.debounce(ms, fn)
+ local timer = vim.uv.new_timer()
+ return function(...)
+ local argv = { ... }
+ timer:start(ms, 0, function()
+ timer:stop()
+ vim.schedule_wrap(fn)(unpack(argv))
+ end)
+ end
+ end
+
+ local lint = require('lint')
+ function M.lint()
+ lint.try_lint()
+ end
+ vim.api.nvim_create_autocmd(opts.events, {
+ group = vim.api.nvim_create_augroup("nvim-lint", { clear = true }),
+ callback = M.debounce(100, M.lint),
+ })
+ end,
+ },
+}
+++ /dev/null
-return {
- -- lspconfig
- {
- "neovim/nvim-lspconfig",
- ---@class PluginLspOpts
- opts = function()
- local keys = require("lazyvim.plugins.lsp.keymaps").get()
- -- TODO: setup a new mapping for this
- -- { "gr", "<cmd>Telescope lsp_references<cr>", desc = "References" },
- keys[#keys+1] = { "gr", false }
-
- return {
- diagnostics = {
- underline = true,
- update_in_insert = false,
- virtual_text = {
- spacing = 4,
- source = "if_mani",
- prefix = "●",
- },
- severity_sort = true,
- signs = {
- text = {
- [vim.diagnostic.severity.ERROR] = " ",
- [vim.diagnostic.severity.WARN] = " ",
- [vim.diagnostic.severity.HINT] = " ",
- [vim.diagnostic.severity.INFO] = " ",
- },
- },
- },
- inlay_hints = { enabled = false, },
- codelens = { enabled = false, },
- document_highlight = { enabled = true, },
- capabilities = {
- workspace = {
- fileOperations = {
- didRename = true,
- willRename = true,
- },
- },
- },
- format = {
- formatting_options = nil,
- timeout_ms = nil,
- },
- -- Automatically format on save
- -- autoformat = false,
- -- LSP Server Settings
- ---@type lspconfig.options
- servers = {
- lua_ls = {
- settings = {
- Lua = {
- workspace = { checkThirdParty = false, },
- codeLens = { enable = true, },
- completion = { callSnippet = "Replace", },
- doc = { privateName = { "^_" }, },
- hint = {
- enable = true,
- setType = false,
- paramType = true,
- paramName = "Disable",
- semicolon = "Disable",
- arrayIndex = "Disable",
- },
- diagnostics = {
- disable = { "missing-fields", },
- },
- },
- },
- },
- -- Add clangd extensions
- -- https://github.com/p00f/clangd_extensions.nvim
- },
- -- you can do any additional lsp server setup here
- -- return true if you don't want this server to be setup with lspconfig
- ---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
- setup = {
- -- example to setup with typescript.nvim
- -- tsserver = function(_, opts)
- -- require("typescript").setup({ server = opts })
- -- return true
- -- end,
- -- Specify * to use this function as a fallback for any server
- -- ["*"] = function(server, opts) end,
- },
- }
- end,
- },
-
- -- cmdline tools and lsp servers
- {
-
- "williamboman/mason.nvim",
- cmd = "Mason",
- keys = { { "<leader>cm", "<cmd>Mason<cr>", desc = "Mason" } },
- opts = {
- ensure_installed = {
- "stylua",
- "shfmt",
- -- "flake8",
- },
- },
- ---@param opts MasonSettings | {ensure_installed: string[]}
- config = function(_, opts)
- require("mason").setup(opts)
- local mr = require("mason-registry")
- local function ensure_installed()
- for _, tool in ipairs(opts.ensure_installed) do
- local p = mr.get_package(tool)
- if not p:is_installed() then
- p:install()
- end
- end
- end
- if mr.refresh then
- mr.refresh(ensure_installed)
- else
- ensure_installed()
- end
- end,
- },
-}
--- /dev/null
+return {
+ { "neovim/nvim-lspconfig",
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" },
+ dependencies = {
+ "mason.nvim",
+ { "williamboman/mason-lspconfig.nvim", config = function() end }, -- don't configure yet
+ },
+ ---@class PluginLspOpts
+ opts = {
+ ---@type vim.diagnostic.Opts
+ diagnostics = {
+ underline = true,
+ update_in_insert = false,
+ virtual_text = {
+ spacing = 4,
+ source = "if_many",
+ prefix = "●",
+ },
+ severity_sort = true,
+ signs = {
+ text = {
+ [vim.diagnostic.severity.ERROR] = " ",
+ [vim.diagnostic.severity.WARN] = " ",
+ [vim.diagnostic.severity.HINT] = " ",
+ [vim.diagnostic.severity.INFO] = " ",
+ },
+ },
+ },
+ inlay_hints = { enabled = false, },
+ codelens = { enabled = false, },
+ document_highlight = { enabled = true, },
+ capabilities = {
+ workspace = {
+ fileOperations = {
+ didRename = true,
+ willRename = true,
+ },
+ },
+ },
+ format = {
+ formatting_options = nil,
+ timeout_ms = nil,
+ },
+ -- LSP Server Settings
+ ---@type lspconfig.options
+ servers = {
+ lua_ls = {
+ settings = {
+ Lua = {
+ workspace = { checkThirdParty = false, },
+ codeLens = { enable = true, },
+ completion = { callSnippet = "Replace", },
+ doc = { privateName = { "^_" }, },
+ hint = {
+ enable = true,
+ setType = false,
+ paramType = true,
+ paramName = "Disable",
+ semicolon = "Disable",
+ arrayIndex = "Disable",
+ },
+ diagnostics = {
+ disable = { "missing-fields", },
+ },
+ },
+ },
+ },
+ -- TODO: Add clangd extensions
+ -- https://github.com/p00f/clangd_extensions.nvim
+ },
+ -- you can do any additional lsp server setup here
+ -- return true if you don't want this server to be setup with lspconfig
+ ---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
+ setup = {
+ -- example to setup with typescript.nvim
+ -- tsserver = function(_, opts)
+ -- require("typescript").setup({ server = opts })
+ -- return true
+ -- end,
+ -- Specify * to use this function as a fallback for any server
+ -- ["*"] = function(server, opts) end,
+ },
+ },
+ ---@param opts PluginLspOpts
+ config = function(_, opts)
+ local lspconfig = require('lspconfig')
+ for server, config in pairs(opts.servers) do
+ local capabilities = vim.tbl_deep_extend("force",
+ vim.lsp.protocol.make_client_capabilities() or {},
+ require('blink.cmp').get_lsp_capabilities() or {},
+ config.capabilities or {}
+ )
+ config.capabilities = capabilities
+ lspconfig[server].setup(config)
+ end
+
+ -- setup keymaps
+ rmz.lsp.on_attach(function(client, buffer)
+ require("plugins.lsp.keymaps").on_attach(client, buffer)
+ end)
+
+ rmz.lsp.setup()
+ rmz.lsp.on_dynamic_capability(require("plugins.lsp.keymaps").on_attach)
+ -- TODO: should vim.diagnostics be condigured directly?
+ vim.diagnostic.config(vim.deepcopy(opts.diagnostics))
+
+ -- get all the servers that are available through mason-lspconfig
+ local mlsp = require("mason-lspconfig")
+ -- TODO: use mason-lspconfig.get_available_servers()?
+ local all_mslp_servers = vim.tbl_keys(require("mason-lspconfig.mappings.server").lspconfig_to_package)
+
+ local ensure_installed = {} ---@type string[]
+ for server, server_opts in pairs(opts.servers) do
+ if server_opts then
+ server_opts = server_opts == true and {} or server_opts
+ if server_opts.enabled ~= false then
+ -- run manual setup if mason=false or if this is a server that cannot be installed with mason-lspconfig
+ if server_opts.mason == false or not vim.tbl_contains(all_mslp_servers, server) then
+ require("lspconfig")[server].setup(server_opts)
+ else
+ ensure_installed[#ensure_installed + 1] = server
+ end
+ end
+ end
+ end
+
+ mlsp.setup({
+ ensure_installed = vim.tbl_deep_extend(
+ "force",
+ ensure_installed,
+ rmz.lazy.opts("mason-lspconfig.nvim").ensure_installed or {}
+ ),
+ handlers = { setup },
+ })
+ end
+ },
+ { "williamboman/mason.nvim",
+ cmd = "Mason",
+ keys = { { "<leader>cm", "<cmd>Mason<cr>", desc = "Mason" } },
+ build = ":MasonUpdate",
+ opts_extend = { "ensure_installed" },
+ opts = {
+ ensure_installed = {
+ "stylua",
+ "shfmt",
+ },
+ },
+ ---@param opts MasonSettings | {ensure_installed: string[]}
+ config = function(_, opts)
+ require("mason").setup(opts)
+ local mr = require("mason-registry")
+ mr:on("package:install:success", function()
+ vim.defer_fn(function()
+ -- trigger FileType event to possibly load this newly installed LSP server
+ require("lazy.core.handler.event").trigger({
+ event = "FileType",
+ buf = vim.api.nvim_get_current_buf(),
+ })
+ end, 100)
+ end)
+
+ mr.refresh(function()
+ for _, tool in ipairs(opts.ensure_installed) do
+ local p = mr.get_package(tool)
+ if not p:is_installed() then
+ p:install()
+ end
+ end
+ end)
+ end,
+ },
+}
--- /dev/null
+local M = {}
+
+---@type LazyKeysLspSpec[]|nil
+M._keys = nil
+
+---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], cond?:fun():boolean}
+---@alias LazyKeysLsp LazyKeys|{has?:string|string[], cond?:fun():boolean}
+
+---@return LazyKeysLspSpec[]
+function M.get()
+ if M._keys then
+ return M._keys
+ end
+ -- stylua: ignore
+ M._keys = {
+ { "<leader>cl", "<cmd>LspInfo<cr>", desc = "Lsp Info" },
+ { "gd", vim.lsp.buf.definition, desc = "Goto Definition", has = "definition" },
+ -- { "gr", vim.lsp.buf.references, desc = "References", nowait = true },
+ { "gI", vim.lsp.buf.implementation, desc = "Goto Implementation" },
+ { "gy", vim.lsp.buf.type_definition, desc = "Goto T[y]pe Definition" },
+ { "gD", vim.lsp.buf.declaration, desc = "Goto Declaration" },
+ { "K", function() return vim.lsp.buf.hover() end, desc = "Hover" },
+ { "gK", function() return vim.lsp.buf.signature_help() end, desc = "Signature Help", has = "signatureHelp" },
+ { "<c-k>", function() return vim.lsp.buf.signature_help() end, mode = "i", desc = "Signature Help", has = "signatureHelp" },
+ { "<leader>ca", vim.lsp.buf.code_action, desc = "Code Action", mode = { "n", "v" }, has = "codeAction" },
+ { "<leader>cc", vim.lsp.codelens.run, desc = "Run Codelens", mode = { "n", "v" }, has = "codeLens" },
+ { "<leader>cC", vim.lsp.codelens.refresh, desc = "Refresh & Display Codelens", mode = { "n" }, has = "codeLens" },
+ { "<leader>cR", function() Snacks.rename.rename_file() end, desc = "Rename File", mode ={"n"}, has = { "workspace/didRenameFiles", "workspace/willRenameFiles" } },
+ { "<leader>cr", vim.lsp.buf.rename, desc = "Rename", has = "rename" },
+ { "<leader>cA", rmz.lsp.action.source, desc = "Source Action", has = "codeAction" },
+ { "]]", function() Snacks.words.jump(vim.v.count1) end, has = "documentHighlight",
+ desc = "Next Reference", cond = function() return Snacks.words.is_enabled() end },
+ { "[[", function() Snacks.words.jump(-vim.v.count1) end, has = "documentHighlight",
+ desc = "Prev Reference", cond = function() return Snacks.words.is_enabled() end },
+ { "<a-n>", function() Snacks.words.jump(vim.v.count1, true) end, has = "documentHighlight",
+ desc = "Next Reference", cond = function() return Snacks.words.is_enabled() end },
+ { "<a-p>", function() Snacks.words.jump(-vim.v.count1, true) end, has = "documentHighlight",
+ desc = "Prev Reference", cond = function() return Snacks.words.is_enabled() end },
+ }
+
+ return M._keys
+end
+
+---@param method string|string[]
+function M.has(buffer, method)
+ if type(method) == "table" then
+ for _, m in ipairs(method) do
+ if M.has(buffer, m) then
+ return true
+ end
+ end
+ return false
+ end
+ method = method:find("/") and method or "textDocument/" .. method
+ local clients = rmz.lsp.get_clients({ bufnr = buffer })
+ for _, client in ipairs(clients) do
+ if client.supports_method(method) then
+ return true
+ end
+ end
+ return false
+end
+
+---@return LazyKeysLsp[]
+function M.resolve(buffer)
+ local Keys = require("lazy.core.handler.keys")
+ if not Keys.resolve then
+ return {}
+ end
+ local spec = vim.tbl_extend("force", {}, M.get())
+ local opts = rmz.lazy.opts("nvim-lspconfig")
+ local clients = rmz.lsp.get_clients({ bufnr = buffer })
+ for _, client in ipairs(clients) do
+ local maps = opts.servers[client.name] and opts.servers[client.name].keys or {}
+ vim.list_extend(spec, maps)
+ end
+ return Keys.resolve(spec)
+end
+
+function M.on_attach(_, buffer)
+ local Keys = require("lazy.core.handler.keys")
+ local keymaps = M.resolve(buffer)
+
+ for _, keys in pairs(keymaps) do
+ local has = not keys.has or M.has(buffer, keys.has)
+ local cond = not (keys.cond == false or ((type(keys.cond) == "function") and not keys.cond()))
+
+ if has and cond then
+ local opts = Keys.opts(keys)
+ opts.cond = nil
+ opts.has = nil
+ opts.silent = opts.silent ~= false
+ opts.buffer = buffer
+ vim.keymap.set(keys.mode or "n", keys.lhs, keys.rhs, opts)
+ end
+ end
+end
+
+return M
+++ /dev/null
-return {
- -- add more treesitter parsers
- {
- "nvim-treesitter/nvim-treesitter",
- opts = {
- -- overwrites the settings from LazyVim
- ensure_installed = {
- "bash",
- "c",
- "html",
- "json",
- "lua",
- "markdown",
- "markdown_inline",
- "python",
- "regex",
- "vim",
- "vimdoc",
- "yaml",
- },
- },
- },
-}
--- /dev/null
+---@type LazySpec
+return {
+ desc = "Fast and modern file picker",
+ { "folke/snacks.nvim",
+ opts = {
+ picker = {
+ win = {
+ input = {
+ keys = {
+ ["<c-t>"] = { "trouble_open", mode = { "n", "i" }, },
+ },
+ },
+ },
+ actions = {
+ actions = require("trouble.sources.snacks").actions,
+ },
+ },
+ },
+ -- stylua: ignore
+ keys = {
+ { "<leader>,", function() Snacks.picker.buffers() end, desc = "Buffers" },
+ { "<leader>/", function() Snacks.picker.grep() end, desc = "Grep" },
+ { "<leader>:", function() Snacks.picker.command_history() end, desc = "Command History" },
+ { "<leader>n", function() Snacks.picker.notifications() end, desc = "Notification History" },
+ -- find
+ { "<leader>fb", function() Snacks.picker.buffers() end, desc = "Buffers" },
+ { "<leader>fB", function() Snacks.picker.buffers({ hidden = true, nofile = true }) end, desc = "Buffers (all)" },
+ { "<leader>fc", function() Snacks.picker.files({ cwd = vim.fn.stdpath("config") }) end, desc = "Find Config File" },
+ { "<leader>fF", function() Snacks.picker.files() end, desc = "Find Files" },
+ { "<leader>fg", function() Snacks.picker.git_files() end, desc = "Find Files (git-files)" },
+ -- TODO: swap fr and fR ?
+ { "<leader>fr", function() Snacks.picker.recent() end, desc = "Recent" },
+ { "<leader>fR", function() Snacks.picker.recent({ filter = { cwd = true }}) end, desc = "Recent (cwd)" },
+ { "<leader>fp", function() Snacks.picker.projects() end, desc = "Projects" },
+ -- git
+ -- { "<leader>gc", function() Snacks.picker.git_log() end, desc = "Git Log" },
+ -- { "<leader>gd", function() Snacks.picker.git_diff() end, desc = "Git Diff (hunks)" },
+ -- { "<leader>gs", function() Snacks.picker.git_status() end, desc = "Git Status" },
+ -- Grep
+ { "<leader>sb", function() Snacks.picker.lines() end, desc = "Buffer Lines" },
+ { "<leader>sB", function() Snacks.picker.grep_buffers() end, desc = "Grep Open Buffers" },
+ { "<leader>sg", function() Snacks.picker.grep() end, desc = "Grep" },
+ { "<leader>sp", function() Snacks.picker.lazy() end, desc = "Search for Plugin Spec" },
+ { "<leader>sw", function() Snacks.picker.grep_word() end, desc = "Visual selection or word", mode = { "n", "x" } },
+ -- search
+ { '<leader>s"', function() Snacks.picker.registers() end, desc = "Registers" },
+ { "<leader>sa", function() Snacks.picker.autocmds() end, desc = "Autocmds" },
+ { "<leader>sc", function() Snacks.picker.command_history() end, desc = "Command History" },
+ { "<leader>sC", function() Snacks.picker.commands() end, desc = "Commands" },
+ { "<leader>sd", function() Snacks.picker.diagnostics() end, desc = "Diagnostics" },
+ { "<leader>sh", function() Snacks.picker.help() end, desc = "Help Pages" },
+ { "<leader>sH", function() Snacks.picker.highlights() end, desc = "Highlights" },
+ { "<leader>si", function() Snacks.picker.icons() end, desc = "Icons" },
+ { "<leader>sj", function() Snacks.picker.jumps() end, desc = "Jumps" },
+ { "<leader>sk", function() Snacks.picker.keymaps() end, desc = "Keymaps" },
+ { "<leader>sl", function() Snacks.picker.loclist() end, desc = "Location List" },
+ { "<leader>sM", function() Snacks.picker.man() end, desc = "Man Pages" },
+ { "<leader>sm", function() Snacks.picker.marks() end, desc = "Marks" },
+ { "<leader>sR", function() Snacks.picker.resume() end, desc = "Resume" },
+ { "<leader>sq", function() Snacks.picker.qflist() end, desc = "Quickfix List" },
+ { "<leader>su", function() Snacks.picker.undo() end, desc = "Undotree" },
+ -- ui
+ { "<leader>uC", function() Snacks.picker.colorschemes() end, desc = "Colorschemes" },
+ },
+ },
+ { "neovim/nvim-lspconfig",
+ opts = function()
+ local Keys = require("plugins.lsp.keymaps").get()
+ -- stylua: ignore
+ vim.list_extend(Keys, {
+ { "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },
+ -- { "gr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" },
+ { "gI", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" },
+ { "gy", function() Snacks.picker.lsp_type_definitions() end, desc = "Goto T[y]pe Definition" },
+ { "<leader>ss", function() Snacks.picker.lsp_symbols({ filter = rmz.lsp.kind_filter }) end, desc = "LSP Symbols", has = "documentSymbol" },
+ { "<leader>sS", function() Snacks.picker.lsp_workspace_symbols({ filter = rmz.lsp.kind_filter }) end, desc = "LSP Workspace Symbols", has = "workspace/symbols" },
+ })
+ end,
+ },
+ { "folke/todo-comments.nvim",
+ optional = true,
+ -- stylua: ignore
+ keys = {
+ { "<leader>st", function() Snacks.picker.todo_comments() end, desc = "Todo" },
+ { "<leader>sT", function () Snacks.picker.todo_comments({ keywords = { "TODO", "FIX", "FIXME" } }) end, desc = "Todo/Fix/Fixme" },
+ },
+ },
+ { "folke/flash.nvim",
+ -- TODO: verify if I want to keep this
+ specs = {
+ {
+ "folke/snacks.nvim",
+ opts = {
+ picker = {
+ win = {
+ input = {
+ keys = {
+ ["<a-s>"] = { "flash", mode = { "n", "i" } },
+ ["s"] = { "flash" },
+ },
+ },
+ },
+ actions = {
+ flash = function(picker)
+ require("flash").jump({
+ pattern = "^",
+ label = { after = { 0, 0 } },
+ search = {
+ mode = "search",
+ exclude = {
+ function(win)
+ return vim.bo[vim.api.nvim_win_get_buf(win)].filetype ~= "snacks_picker_list"
+ end,
+ },
+ },
+ action = function(match)
+ local idx = picker.list:row2idx(match.pos[1])
+ picker.list:_move(idx, true, true)
+ end,
+ })
+ end,
+ },
+ },
+ },
+ },
+ },
+ },
+}
--- /dev/null
+-- Terminal Mappings
+local function term_nav(dir)
+ ---@param self snacks.terminal
+ return function(self)
+ return self:is_floating() and "<c-" .. dir .. ">" or vim.schedule(function()
+ vim.cmd.wincmd(dir)
+ end)
+ end
+end
+
+return {
+ { "folke/snacks.nvim",
+ -- stylua: ignore
+ keys = {
+ -- Snacks Scratch
+ { "<leader>.", function() Snacks.scratch() end, desc = "Toggle Scratch Buffer" },
+ { "<leader>S", function() Snacks.scratch.select() end, desc = "Select Scratch Buffer" },
+ { "<leader>dps", function() Snacks.profiler.scratch() end, desc = "Profiler Scratch Buffer" },
+ },
+ opts = {
+ bigfile = { enabled = true },
+ indent = { enabled = true },
+ input = { enabled = true }, -- NOTE: seems unecessary
+ quickfile = { enabled = true }, -- TODO: review if needed
+ scope = { enabled = true },
+ scroll = { enabled = false }, -- fuck this!
+ statuscolumn = { enabled = true },
+ terminal = {
+ win = {
+ keys = {
+ nav_h = { "<C-h>", term_nav("W"), desc = "Go to Prev Window", expr = true, mode = "t" },
+ nav_j = { "<C-j>", term_nav("j"), desc = "Go to Lower Window", expr = true, mode = "t" },
+ nav_k = { "<C-k>", term_nav("k"), desc = "Go to Upper Window", expr = true, mode = "t" },
+ nav_l = { "<C-l>", term_nav("w"), desc = "Go to Next Window", expr = true, mode = "t" },
+ },
+ },
+ },
+ dashboard = {
+ preset = {
+ -- TODO: replace header
+ header = [[
+ ██╗ █████╗ ██╗ ██╗███████╗██╗ ██╗██╗ ██╗██╗███╗ ███╗ Z
+ ██║ ██╔══██╗██║ ██║╚══███╔╝╚██╗ ██╔╝██║ ██║██║████╗ ████║ Z
+ ██║ ██║ ██║██║ ██║ ███╔╝ ╚████╔╝ ██║ ██║██║██╔████╔██║ z
+ ██║ ██║ ██║██║ ██║ ███╔╝ ╚██╔╝ ╚██╗ ██╔╝██║██║╚██╔╝██║ z
+ ███████╗╚█████╔╝╚██████╔╝███████╗ ██║ ╚████╔╝ ██║██║ ╚═╝ ██║
+ ╚══════╝ ╚════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ ]],
+ -- stylua: ignore
+ ---@type snacks.dashboard.Item[]
+ keys = {
+ { icon = " ", key = "f", desc = "Find File", action = ":lua Snacks.dashboard.pick('files')" },
+ { icon = " ", key = "n", desc = "New File", action = ":ene | startinsert" },
+ { icon = " ", key = "g", desc = "Find Text", action = ":lua Snacks.dashboard.pick('live_grep')" },
+ { icon = " ", key = "r", desc = "Recent Files", action = ":lua Snacks.dashboard.pick('oldfiles')" },
+ { icon = " ", key = "c", desc = "Config", action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})" },
+ { icon = " ", key = "s", desc = "Restore Session", section = "session" },
+ { icon = " ", key = "x", desc = "Lazy Extras", action = ":LazyExtras" },
+ { icon = " ", key = "l", desc = "Lazy", action = ":Lazy" },
+ },
+ },
+ },
+ },
+ },
+ { "folke/snacks.nvim",
+ opts = {
+ notifier = { enabled = true },
+ },
+ -- stylua: ignore
+ keys = {
+ -- TODO: review after picking picker (ha)
+ { "<leader>n", function()
+ if Snacks.config.picker and Snacks.config.picker.enabled then
+ Snacks.picker.notifications()
+ else
+ Snacks.notifier.show_history()
+ end
+ end, desc = "Notification History" },
+ { "<leader>un", function() Snacks.notifier.hide() end, desc = "Dismiss All Notifications" },
+ },
+ }
+}
return {
- {
- "folke/which-key.nvim",
- opts = {
- defaults = { ["<leader>t"] = { name = "+test" }, },
- },
- },
- {
- "nvim-neotest/neotest",
+ { "nvim-neotest/neotest",
+ dependencies = { "nvim-neotest/nvim-nio" },
opts = {
+ adapters = {},
status = { virtual_text = true },
output = { open_on_run = true },
quickfix = {
open = function()
- if require("lazyvim.util").has("trouble.nvim") then
- require("trouble").open({ mode = "quickfix", focus = false })
- else
- vim.cmd("copen")
- end
+ -- TODO: review if I'd prefer to just use quickfix here
+ -- vim.cmd("copen")
+ require("trouble").open({ mode = "quickfix", focus = false })
end,
},
},
},
}, neotest_ns)
- if require("lazyvim.util").has("trouble.nvim") then
- opts.consumers = opts.consumers or {}
- -- Refresh and auto close trouble after running tests
- ---@type neotest.Consumer
- opts.consumers.trouble = function(client)
- client.listeners.results = function(adapter_id, results, partial)
- if partial then
- return
- end
- local tree = assert(client:get_position(nil, { adapter = adapter_id }))
+ opts.consumers = opts.consumers or {}
+ -- Refresh and auto close trouble after running tests
+ ---@type neotest.Consumer
+ opts.consumers.trouble = function(client)
+ client.listeners.results = function(adapter_id, results, partial)
+ if partial then
+ return
+ end
+ local tree = assert(client:get_position(nil, { adapter = adapter_id }))
- local failed = 0
- for pos_id, result in pairs(results) do
- if result.status == "failed" and tree:get_key(pos_id) then
- failed = failed + 1
- end
+ local failed = 0
+ for pos_id, result in pairs(results) do
+ if result.status == "failed" and tree:get_key(pos_id) then
+ failed = failed + 1
end
- vim.schedule(function()
- local trouble = require("trouble")
- if trouble.is_open() then
- trouble.refresh()
- if failed == 0 then
- trouble.close()
- end
- end
- end)
end
- return {}
+ vim.schedule(function()
+ local trouble = require("trouble")
+ if trouble.is_open() then
+ trouble.refresh()
+ if failed == 0 then
+ trouble.close()
+ end
+ end
+ end)
end
+ return {}
end
+ -- NOTE: support setting up test adapters in lang
if opts.adapters then
local adapters = {}
for name, config in pairs(opts.adapters or {}) do
local meta = getmetatable(adapter)
if adapter.setup then
adapter.setup(config)
+ elseif adapter.adapter then
+ adapter.adapter(config)
+ adapter = adapter.adapter
elseif meta and meta.__call then
- adapter(config)
+ adapter = adapter(config)
else
error("Adapter " .. name .. " does not support setup")
end
end,
-- stylua: ignore
keys = {
+ {"<leader>t", "", desc = "+test"},
{ "<leader>tt", function() require("neotest").run.run(vim.fn.expand("%")) end, desc = "Run File" },
{ "<leader>tT", function() require("neotest").run.run(vim.loop.cwd()) end, desc = "Run All Test Files" },
{ "<leader>tr", function() require("neotest").run.run() end, desc = "Run Nearest" },
+ { "<leader>tl", function() require("neotest").run.run_last() end, desc = "Run Last" },
{ "<leader>ts", function() require("neotest").summary.toggle() end, desc = "Toggle Summary" },
{ "<leader>to", function() require("neotest").output.open({ enter = true, auto_close = true }) end, desc = "Show Output" },
{ "<leader>tO", function() require("neotest").output_panel.toggle() end, desc = "Toggle Output Panel" },
{ "<leader>tS", function() require("neotest").run.stop() end, desc = "Stop" },
+ { "<leader>tw", function() require("neotest").watch.toggle(vim.fn.expand("%")) end, desc = "Toggle Watch" },
},
},
{
--- /dev/null
+return {
+ { "nvim-treesitter/nvim-treesitter",
+ dependencies = { "nvim-treesitter/nvim-treesitter-textobjects" },
+ build = ":TSUpdate",
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" , "VeryLazy" },
+ lazy = vim.fn.argc(-1) == 0, -- load treesitter early when opening a file from the cmdline
+ init = function(plugin)
+ -- PERF: add nvim-treesitter queries to the rtp and it's custom query predicates early
+ -- This is needed because a bunch of plugins no longer `require("nvim-treesitter")`, which
+ -- no longer trigger the **nvim-treesitter** module to be loaded in time.
+ -- Luckily, the only things that those plugins need are the custom queries, which we make available
+ -- during startup.
+ require("lazy.core.loader").add_to_rtp(plugin)
+ require("nvim-treesitter.query_predicates")
+ end,
+ cmd = { "TSUpdateSync", "TSUpdate", "TSInstall" },
+ keys = {
+ { "<c-space>", desc = "Increment Selection" },
+ { "<bs>", desc = "Decrement Selection", mode = "x" },
+ },
+ opts_extend = { "ensure_installed" },
+ ---@type TSConfig
+ ---@diagnostic disable-next-line: missing-fields
+ opts = {
+ highlight = { enable = true },
+ indent = { enable = true },
+ ensure_installed = {
+ "bash",
+ "c",
+ "diff",
+ "git_config",
+ "git_rebase",
+ "gitattributes",
+ "gitcommit",
+ "gitignore",
+ "html",
+ "javascript",
+ "jsdoc",
+ "json",
+ "jsonc",
+ "lua",
+ "luadoc",
+ "luap",
+ "markdown",
+ "markdown_inline",
+ "printf",
+ "python",
+ "query",
+ "regex",
+ "toml",
+ "tsx",
+ "typescript",
+ "vim",
+ "vimdoc",
+ "xml",
+ "yaml",
+ },
+ incremental_selection = {
+ enable = true,
+ keymaps = {
+ init_selection = "<C-space>",
+ node_incremental = "<C-space>",
+ scope_incremental = false,
+ node_decremental = "<bs>",
+ },
+ },
+ textobjects = {
+ move = {
+ enable = true,
+ goto_next_start = { ["]f"] = "@function.outer", ["]c"] = "@class.outer", ["]a"] = "@parameter.inner" },
+ goto_next_end = { ["]F"] = "@function.outer", ["]C"] = "@class.outer", ["]A"] = "@parameter.inner" },
+ goto_previous_start = { ["[f"] = "@function.outer", ["[c"] = "@class.outer", ["[a"] = "@parameter.inner" },
+ goto_previous_end = { ["[F"] = "@function.outer", ["[C"] = "@class.outer", ["[A"] = "@parameter.inner" },
+ },
+ },
+ },
+ ---@param opts TSConfig
+ config = function(_, opts)
+ -- make sure extra langs are not duplicated
+ opts.ensure_installed = rmz.dedup(opts.ensure_installed)
+
+ local configs = require("nvim-treesitter.configs")
+ configs.setup(opts)
+
+ -- When in diff mode, we want to use the default
+ -- vim text objects c & C instead of the treesitter ones.
+ local move = require("nvim-treesitter.textobjects.move") ---@type table<string,fun(...)>
+ for name, fn in pairs(move) do
+ if name:find("goto") == 1 then
+ move[name] = function(q, ...)
+ if not vim.wo.diff then return fn(q, ...) end
+
+ local config = configs.get_module("textobjects.move")[name] ---@type table<string,string>
+ for key, query in pairs(config or {}) do
+ if q == query and key:find("[%]%[][cC]") then
+ vim.cmd("normal! " .. key)
+ return
+ end
+ end
+ end
+ end
+ end
+ end,
+ },
+
+ -- Automatically add closing tags for HTML and JSX
+ {
+ "windwp/nvim-ts-autotag",
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" },
+ opts = {},
+ },
+}
+
----@type LazyPluginSpec
+local M = {}
+
+---@param component any -- actually a lualine.component
+---@param text string
+---@param hl_group? string
+---@return string
+function M.format(component, text, hl_group)
+ text = text:gsub("%%", "%%%%")
+ if not hl_group or hl_group == "" then
+ return text
+ end
+ --- hl_cache is added here, not modified
+ ---@type table<string, string>
+ component.hl_cache = component.hl_cache or {}
+ local lualine_hl_group = component.hl_cache[hl_group]
+ if not lualine_hl_group then
+ local utils = require("lualine.utils.utils")
+ ---@type string[]
+ local gui = vim.tbl_filter(function(x) return x end, {
+ utils.extract_highlight_colors(hl_group, "bold") and "bold",
+ utils.extract_highlight_colors(hl_group, "italic") and "italic",
+ })
+
+ lualine_hl_group = component:create_hl({
+ fg = utils.extract_highlight_colors(hl_group, "fg"),
+ gui = #gui > 0 and table.concat(gui, ",") or nil,
+ }, "LV_" .. hl_group) --[[@as string]]
+ component.hl_cache[hl_group] = lualine_hl_group
+ end
+ return component:format_hl(lualine_hl_group) .. text .. component:get_default_hl()
+end
+
+function M.pretty_path()
+ return function(self)
+ local opts = {
+ directory_hl = "",
+ filename_hl = "Bold",
+ length = 3,
+ modified_hl = "MatchParen", -- hl group when file is modified
+ modified_sign = "",
+ readonly_icon = " ",
+ }
+
+ local path = vim.fn.expand("%:p") --[[@as string]]
+
+ if path == "" then
+ return ""
+ end
+
+ path = require("lazy.core.util").norm(path)
+ local cwd = vim.uv.cwd()
+
+ if path:find(cwd, 1, true) == 1 then
+ path = path:sub(#cwd + 2)
+ end
+
+ local sep = package.config:sub(1, 1)
+ local parts = vim.split(path, "[\\/]")
+
+ if opts.length == 0 then
+ parts = parts
+ elseif #parts > opts.length then
+ parts = { parts[1], "…", unpack(parts, #parts - opts.length + 2, #parts) }
+ end
+
+ if vim.bo.modified then
+ parts[#parts] = parts[#parts] .. opts.modified_sign
+ parts[#parts] = M.format(self, parts[#parts], opts.modified_hl)
+ else
+ parts[#parts] = M.format(self, parts[#parts], opts.filename_hl)
+ end
+
+ local dir = ""
+ if #parts > 1 then
+ dir = table.concat({ unpack(parts, 1, #parts - 1) }, sep)
+ dir = M.format(self, dir .. sep, opts.directory_hl)
+ end
+
+ local readonly = ""
+ if vim.bo.readonly then
+ readonly = M.format(self, opts.readonly_icon, opts.modified_hl)
+ end
+ return dir .. parts[#parts] .. readonly
+ end
+end
+
+---@type LazySpec
return {
- -- disabled plugins {{{
- { "folke/which-key.nvim",
- enabled = false,
- },
- -- }}}
{ 'echasnovski/mini.clue',
-- NOTE: this caused some issue with unterminated mappings, i.e. <L>gc when there
-- is also <L>gcc. It would simply terminate early and not allow for next mapping.
},
},
},
- {
- "nvim-notify",
- },
- {
- "bufferline.nvim",
+ { "akinsho/bufferline.nvim",
+ event = "VeryLazy",
+ keys = {
+ { "<leader>bp", "<Cmd>BufferLineTogglePin<CR>", desc = "Toggle Pin" },
+ { "<leader>bP", "<Cmd>BufferLineGroupClose ungrouped<CR>", desc = "Delete Non-Pinned Buffers" },
+ { "<leader>br", "<Cmd>BufferLineCloseRight<CR>", desc = "Delete Buffers to the Right" },
+ { "<leader>bl", "<Cmd>BufferLineCloseLeft<CR>", desc = "Delete Buffers to the Left" },
+ { "<S-h>", "<cmd>BufferLineCyclePrev<cr>", desc = "Prev Buffer" },
+ { "<S-l>", "<cmd>BufferLineCycleNext<cr>", desc = "Next Buffer" },
+ { "[b", "<cmd>BufferLineCyclePrev<cr>", desc = "Prev Buffer" },
+ { "]b", "<cmd>BufferLineCycleNext<cr>", desc = "Next Buffer" },
+ { "[B", "<cmd>BufferLineMovePrev<cr>", desc = "Move buffer prev" },
+ { "]B", "<cmd>BufferLineMoveNext<cr>", desc = "Move buffer next" },
+ },
---@type BufferlineConfig
opts = {
options = {
+ close_command = function(n) Snacks.bufdelete(n) end,
+ right_mouse_command = function(n) Snacks.bufdelete(n) end,
+ diagnostics = "nvim_lsp",
always_show_bufferline = false,
- },
- },
- },
- {
- "stevearc/dressing.nvim",
- lazy = true,
- opts = {
- input = {
- start_in_insert = false,
- insert_only = false,
- },
- },
- },
- {
- "noice.nvim",
- enabled = false,
- ---@type NoiceConfig
- opts = {
- presets = {
- command_palette = false, -- don't position the cmdline and popupmenu together
- lsp_doc_border = true,
- long_message_to_split = true,
- },
- cmdline = {
- view = "cmdline",
- },
- routes = {
- { -- send file written messages to mini
- filter = {
- event = "msg_show",
- kind = "",
- find = "%[w%]",
+ diagnostics_indicator = function(_, _, diag)
+ local icons = rmz.ui.icons.diagnostics
+ local ret = (diag.error and icons.Error .. diag.error .. " " or "")
+ .. (diag.warning and icons.Warn .. diag.warning or "")
+ return vim.trim(ret)
+ end,
+ offsets = {
+ {
+ filetype = "man",
+ text = "Man page",
+ highlight = "Directory",
+ text_align = "left",
},
- opts = { skip = true },
},
+ ---@param opts bufferline.IconFetcherOpts
+ get_element_icon = function(opts)
+ return rmz.ui.icons.ft[opts.filetype]
+ end,
},
},
- config = function(_, opts)
- -- ensure [w] is written to msg_show so we can match it
- vim.opt.shortmess:append("w")
- vim.opt.shortmess:remove("W")
-
- require("noice").setup(opts)
- end,
},
- {
- "lualine.nvim",
- --TODO: Things that were in vim but are missing
+ { "nvim-lualine/lualine.nvim",
+ -- TODO: Things that were in vim but are missing
-- - git line add/mod/del ar next to branch name rather on right
-- - one status line per splits
-- - maybe a single one is OK too?
-- - unix/dos eof markers
-- - really I only want to know if it's not unix
-- - filetype in text form. It's quite important to glance this quickly
- },
- {
- "indent-blankline.nvim",
- },
- {
- "echasnovski/mini.indentscope",
- version = false, -- wait till new 0.7.0 release to put it back on semver
- event = "LazyFile",
- opts = function (_, opts)
- return {
- draw = {
- animation = require("mini.indentscope").gen_animation.linear({ duration = 10 })
- }
- }
+ event = "VeryLazy",
+ init = function()
+ vim.g.lualine_laststatus = vim.o.laststatus
+ if vim.fn.argc(-1) > 0 then
+ -- set an empty statusline till lualine loads
+ vim.o.statusline = " "
+ else
+ -- hide the statusline on the starter page
+ vim.o.laststatus = 0
+ end
end,
- },
- {
- "nvimdev/dashboard-nvim",
- -- TODO: create cool dashboard header
- -- generate logo from text here:
- -- https://patorjk.com/software/taag/#p=testall&v=0&f=Computer&t=NEOVIM
- -- Can also use use `chafa` and aplha.term to generate text from cli, see
- -- https://github.com/goolord/alpha-nvim/discussions/16#discussioncomment-4915947
- -- https://github.com/goolord/alpha-nvim/discussions/16#discussioncomment-5065731
- -- To add orgmode agenda button in alpha
- -- dashboard.button("a", " " .. " View Agenda", ":lua require('orgmode').action('agenda.agenda')<CR>"),
opts = function()
- local logo = [[
- ██╗ █████╗ ███████╗██╗ ██╗██╗ ██╗██╗███╗ ███╗ Z
- ██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝██║ ██║██║████╗ ████║ Z
- ██║ ███████║ ███╔╝ ╚████╔╝ ██║ ██║██║██╔████╔██║ z
- ██║ ██╔══██║ ███╔╝ ╚██╔╝ ╚██╗ ██╔╝██║██║╚██╔╝██║ z
- ███████╗██║ ██║███████╗ ██║ ╚████╔╝ ██║██║ ╚═╝ ██║
- ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═╝
- ]]
+ -- PERF: we don't need this lualine require madness 🤷
+ local lualine_require = require("lualine_require")
+ lualine_require.require = require
+
+ local icons = rmz.ui.icons
- logo = string.rep("\n", 8) .. logo .. "\n\n"
+ vim.o.laststatus = vim.g.lualine_laststatus
local opts = {
- theme = "doom",
- hide = {
- -- this is taken care of by lualine
- -- enabling this messes up the actual laststatus setting after loading a file
- statusline = false,
+ options = {
+ theme = "auto",
+ globalstatus = vim.o.laststatus == 3,
+ disabled_filetypes = { statusline = { "dashboard", "alpha", "ministarter", "snacks_dashboard" } },
},
- config = {
- header = vim.split(logo, "\n"),
- -- stylua: ignore
- center = {
- { action = [[lua require('orgmode').action('agenda.agenda')]], desc = " View Agenda", icon = " ", key = "a" },
- { action = "Telescope find_files", desc = " Find file", icon = " ", key = "f" },
- { action = "ene | startinsert", desc = " New file", icon = " ", key = "n" },
- { action = "Telescope oldfiles", desc = " Recent files", icon = " ", key = "r" },
- { action = [[lua require("lazyvim.util").telescope.config_files()()]], desc = " Config", icon = " ", key = "c" },
- { action = 'lua require("persistence").load()', desc = " Restore Session", icon = " ", key = "s" },
- { action = "LazyExtras", desc = " Lazy Extras", icon = " ", key = "x" },
- { action = "Lazy", desc = " Lazy", icon = " ", key = "l" },
+ sections = {
+ lualine_a = { "mode" },
+ lualine_b = { "branch" },
+
+ lualine_c = {
+ {
+ "diagnostics",
+ symbols = {
+ error = icons.diagnostics.Error,
+ warn = icons.diagnostics.Warn,
+ info = icons.diagnostics.Info,
+ hint = icons.diagnostics.Hint,
+ },
+ },
+ { "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } },
+ { M.pretty_path() },
+ },
+ lualine_x = {
+ Snacks.profiler.status(),
+ -- stylua: ignore
+ {
+ function() return " " .. require("dap").status() end,
+ cond = function() return package.loaded["dap"] and require("dap").status() ~= "" end,
+ color = function() return { fg = Snacks.util.color("Debug") } end,
+ },
+ -- stylua: ignore
+ {
+ require("lazy.status").updates,
+ cond = require("lazy.status").has_updates,
+ color = function() return { fg = Snacks.util.color("Special") } end,
+ },
+ {
+ "diff",
+ symbols = {
+ added = icons.git.added,
+ modified = icons.git.modified,
+ removed = icons.git.removed,
+ },
+ source = function()
+ local gitsigns = vim.b.gitsigns_status_dict
+ if gitsigns then
+ return {
+ added = gitsigns.added,
+ modified = gitsigns.changed,
+ removed = gitsigns.removed,
+ }
+ end
+ end,
+ },
+ },
+ lualine_y = {
+ { "progress", separator = " ", padding = { left = 1, right = 0 } },
+ { "location", padding = { left = 0, right = 1 } },
+ },
+ lualine_z = {
+ function()
+ return " " .. os.date("%R")
+ end,
},
- footer = function()
- local stats = require("lazy").stats()
- local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100)
- return { "⚡ Neovim loaded " .. stats.loaded .. "/" .. stats.count .. " plugins in " .. ms .. "ms" }
- end,
},
+ inactive_sections = {
+ lualine_c = {
+ { "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } },
+ { M.pretty_path() },
+ },
+ },
+ extensions = { "neo-tree", "lazy", "fzf" },
}
- for _, button in ipairs(opts.config.center) do
- button.desc = button.desc .. string.rep(" ", 43 - #button.desc)
- button.key_format = " %s"
- end
-
- -- close Lazy and re-open when the dashboard is ready
- if vim.o.filetype == "lazy" then
- vim.cmd.close()
- vim.api.nvim_create_autocmd("User", {
- pattern = "DashboardLoaded",
- callback = function()
- require("lazy").show()
- end,
- })
- end
+ local trouble = require("trouble")
+ local symbols = trouble.statusline({
+ mode = "symbols",
+ groups = {},
+ title = false,
+ filter = { range = true },
+ format = "{kind_icon}{symbol.name:Normal}",
+ hl_group = "lualine_c_normal",
+ })
+ table.insert(opts.sections.lualine_c, {
+ symbols and symbols.get,
+ cond = function()
+ return vim.b.trouble_lualine ~= false and symbols.has()
+ end,
+ })
return opts
- end
+ end,
},
{
- "SmiteshP/nvim-navic",
+ "echasnovski/mini.icons",
+ lazy = true,
+ opts = {
+ file = {
+ [".keep"] = { glyph = "", hl = "MiniIconsGrey" },
+ ["devcontainer.json"] = { glyph = "", hl = "MiniIconsAzure" },
+ },
+ filetype = {
+ dotenv = { glyph = "", hl = "MiniIconsYellow" },
+ },
+ },
+ init = function()
+ -- TODO: try without this
+ -- see :h MiniIcons.mock_nvim_web_devicons()
+ package.preload["nvim-web-devicons"] = function()
+ require("mini.icons").mock_nvim_web_devicons()
+ return package.loaded["nvim-web-devicons"]
+ end
+ end,
},
- {
- "nvim-web-devicons",
+ { "MunifTanjim/nui.nvim", lazy = true },
+ { "stevearc/dressing.nvim",
+ enabled = false, -- replaced by snacks.input
+ lazy = true,
+ opts = {
+ input = {
+ start_in_insert = false,
+ insert_only = false,
+ },
+ },
},
- {
- "nui.nvim",
+ { "indent-blankline.nvim",
+ enabled = false, -- replaced by snacks.indent
+ },
+ { "echasnovski/mini.indentscope",
+ enabled = false, -- replaced by snacks.indent
+ version = false, -- wait till new 0.7.0 release to put it back on semver
+ event = { "BufReadPost", "BufNewFile", "BufWritePre" },
+ opts = function (_, opts)
+ return {
+ draw = {
+ animation = require("mini.indentscope").gen_animation.linear({ duration = 10 })
+ }
+ }
+ end,
+ },
+ { "SmiteshP/nvim-navic",
+ lazy = true,
+ init = function()
+ vim.g.navic_silence = true
+ rmz.lsp.on_attach(function(client, buffer)
+ if client.supports_method("textDocument/documentSymbol") then
+ require("nvim-navic").attach(client, buffer)
+ end
+ end)
+ end,
+ opts = function()
+ return {
+ separator = " ",
+ highlight = true,
+ depth_limit = 5,
+ icons = rmz.ui.icons.kinds,
+ lazy_update_context = true,
+ }
+ end,
+ },
+ { "nvim-lualine/lualine.nvim",
+ optional = true,
+ opts = function(_, opts)
+ if not vim.g.trouble_lualine then
+ table.insert(opts.sections.lualine_c, { "navic", color_correction = "dynamic" })
+ end
+ end,
},
}
--- /dev/null
+---@class rmz.util
+local M = {
+ ui = require("rmz.util.ui"),
+ lazy = require("rmz.util.lazy"),
+ lsp = require("rmz.util.lsp"),
+}
+
+--- Deduplicates a list.
+---@generic T
+---@param list T[]
+---@return T[]
+function M.dedup(list)
+ local ret = {}
+ local seen = {}
+ for _, v in ipairs(list) do
+ if not seen[v] then
+ table.insert(ret, v)
+ seen[v] = true
+ end
+ end
+ return ret
+end
+
+function M.foldexpr()
+ local buf = vim.api.nvim_get_current_buf()
+ if vim.b[buf].ts_folds == nil then
+ -- as long as we don't have a filetype, don't bother
+ -- checking if treesitter is available (it won't)
+ if vim.bo[buf].filetype == "" then
+ return "0"
+ end
+ if vim.bo[buf].filetype:find("dashboard") then
+ vim.b[buf].ts_folds = false
+ else
+ vim.b[buf].ts_folds = pcall(vim.treesitter.get_parser, buf)
+ end
+ end
+ return vim.b[buf].ts_folds and vim.treesitter.foldexpr() or "0"
+end
+
+return M
--- /dev/null
+---@class rmz.util.lazy
+local M = {}
+
+---@param name string
+function M.get_plugin(name)
+ return require("lazy.core.config").spec.plugins[name]
+end
+
+---@param name string
+function M.opts(name)
+ local plugin = M.get_plugin(name)
+ if not plugin then
+ return {}
+ end
+ local Plugin = require("lazy.core.plugin")
+ return Plugin.values(plugin, "opts", false)
+end
+
+for _, level in ipairs({ "info", "warn", "error" }) do
+ M[level] = function(msg, opts)
+ opts = opts or {}
+ opts.title = opts.title or "RmZ"
+ local Util = require("lazy.core.util")
+ return Util[level](msg, opts)
+ end
+end
+
+return M
--- /dev/null
+-- Absorbed from LazyVim
+-- TODO: review, understand and adapt
+---@class rmz.util.lsp
+local M = {}
+
+---@alias lsp.Client.filter {id?: number, bufnr?: number, name?: string, method?: string, filter?:fun(client: lsp.Client):boolean}
+
+M.kind_filter = {
+ default = {
+ "Class",
+ "Constructor",
+ "Enum",
+ "Field",
+ "Function",
+ "Interface",
+ "Method",
+ "Module",
+ "Namespace",
+ "Package",
+ "Property",
+ "Struct",
+ "Trait",
+ },
+ markdown = false,
+ help = false,
+ -- you can specify a different filter for each filetype
+ lua = {
+ "Class",
+ "Constructor",
+ "Enum",
+ "Field",
+ "Function",
+ "Interface",
+ "Method",
+ "Module",
+ "Namespace",
+ -- "Package", -- remove package since luals uses it for control flow structures
+ "Property",
+ "Struct",
+ "Trait",
+ },
+}
+
+---@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
+
+---@param on_attach fun(client:vim.lsp.Client, buffer)
+---@param name? string
+function M.on_attach(on_attach, name)
+ return vim.api.nvim_create_autocmd("LspAttach", {
+ callback = function(args)
+ local buffer = args.buf ---@type number
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+ if client and (not name or client.name == name) then
+ return on_attach(client, buffer)
+ end
+ end,
+ })
+end
+
+---@type table<string, table<vim.lsp.Client, table<number, boolean>>>
+M._supports_method = {}
+
+function M.setup()
+ local register_capability = vim.lsp.handlers["client/registerCapability"]
+ vim.lsp.handlers["client/registerCapability"] = function(err, res, ctx)
+ ---@diagnostic disable-next-line: no-unknown
+ local ret = register_capability(err, res, ctx)
+ local client = vim.lsp.get_client_by_id(ctx.client_id)
+ if client then
+ for buffer in pairs(client.attached_buffers) do
+ vim.api.nvim_exec_autocmds("User", {
+ pattern = "LspDynamicCapability",
+ data = { client_id = client.id, buffer = buffer },
+ })
+ end
+ end
+ return ret
+ end
+ M.on_attach(M._check_methods)
+ M.on_dynamic_capability(M._check_methods)
+end
+
+---@param client vim.lsp.Client
+function M._check_methods(client, buffer)
+ -- don't trigger on invalid buffers
+ if not vim.api.nvim_buf_is_valid(buffer) then
+ return
+ end
+ -- don't trigger on non-listed buffers
+ if not vim.bo[buffer].buflisted then
+ return
+ end
+ -- don't trigger on nofile buffers
+ if vim.bo[buffer].buftype == "nofile" then
+ return
+ end
+ for method, clients in pairs(M._supports_method) do
+ clients[client] = clients[client] or {}
+ if not clients[client][buffer] then
+ if client.supports_method and client.supports_method(method, { bufnr = buffer }) then
+ clients[client][buffer] = true
+ vim.api.nvim_exec_autocmds("User", {
+ pattern = "LspSupportsMethod",
+ data = { client_id = client.id, buffer = buffer, method = method },
+ })
+ end
+ end
+ end
+end
+
+---@param fn fun(client:vim.lsp.Client, buffer):boolean?
+---@param opts? {group?: integer}
+function M.on_dynamic_capability(fn, opts)
+ return vim.api.nvim_create_autocmd("User", {
+ pattern = "LspDynamicCapability",
+ group = opts and opts.group or nil,
+ callback = function(args)
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+ local buffer = args.data.buffer ---@type number
+ if client then
+ return fn(client, buffer)
+ end
+ end,
+ })
+end
+
+---@param method string
+---@param fn fun(client:vim.lsp.Client, buffer)
+function M.on_supports_method(method, fn)
+ M._supports_method[method] = M._supports_method[method] or setmetatable({}, { __mode = "k" })
+ return vim.api.nvim_create_autocmd("User", {
+ pattern = "LspSupportsMethod",
+ callback = function(args)
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+ local buffer = args.data.buffer ---@type number
+ if client and method == args.data.method then
+ return fn(client, buffer)
+ end
+ end,
+ })
+end
+
+---@return _.lspconfig.options
+function M.get_config(server)
+ local configs = require("lspconfig.configs")
+ return rawget(configs, server)
+end
+
+---@return {default_config:lspconfig.Config}
+function M.get_raw_config(server)
+ local ok, ret = pcall(require, "lspconfig.configs." .. server)
+ if ok then
+ return ret
+ end
+ return require("lspconfig.server_configurations." .. server)
+end
+
+function M.is_enabled(server)
+ local c = M.get_config(server)
+ return c and c.enabled ~= false
+end
+
+---@param server string
+---@param cond fun( root_dir, config): boolean
+function M.disable(server, cond)
+ local util = require("lspconfig.util")
+ local def = M.get_config(server)
+ ---@diagnostic disable-next-line: undefined-field
+ def.document_config.on_new_config = util.add_hook_before(def.document_config.on_new_config, function(config, root_dir)
+ if cond(root_dir, config) then
+ config.enabled = false
+ end
+ end)
+end
+
+M.action = setmetatable({}, {
+ __index = function(_, action)
+ return function()
+ vim.lsp.buf.code_action({
+ apply = true,
+ context = {
+ only = { action },
+ diagnostics = {},
+ },
+ })
+ end
+ end,
+})
+
+return M
--- /dev/null
+local M = {}
+
+-- icons used by other plugins
+M.icons = {
+ misc = {
+ dots = "",
+ },
+ ft = {
+ octo = "",
+ },
+ dap = {
+ Stopped = { " ", "DiagnosticWarn", "DapStoppedLine" },
+ Breakpoint = " ",
+ BreakpointCondition = " ",
+ BreakpointRejected = { " ", "DiagnosticError" },
+ LogPoint = ".>",
+ },
+ diagnostics = {
+ Error = " ",
+ Warn = " ",
+ Hint = " ",
+ Info = " ",
+ },
+ git = {
+ added = " ",
+ modified = " ",
+ removed = " ",
+ },
+ kinds = {
+ Array = " ",
+ Boolean = " ",
+ Class = " ",
+ Codeium = " ",
+ Color = " ",
+ Control = " ",
+ Collapsed = " ",
+ Constant = " ",
+ Constructor = " ",
+ Copilot = " ",
+ Enum = " ",
+ EnumMember = " ",
+ Event = " ",
+ Field = " ",
+ File = " ",
+ Folder = " ",
+ Function = " ",
+ Interface = " ",
+ Key = " ",
+ Keyword = " ",
+ Method = " ",
+ Module = " ",
+ Namespace = " ",
+ Null = " ",
+ Number = " ",
+ Object = " ",
+ Operator = " ",
+ Package = " ",
+ Property = " ",
+ Reference = " ",
+ Snippet = " ",
+ String = " ",
+ Struct = " ",
+ Supermaven = " ",
+ TabNine = " ",
+ Text = " ",
+ TypeParameter = " ",
+ Unit = " ",
+ Value = " ",
+ Variable = " ",
+ },
+}
+return M
--- /dev/null
+# Add TextMate style snippets here
+# see https://github.com/L3MON4D3/LuaSnip/blob/master/DOC.md#snipmate
au StdinReadPost * :set buftype=nofile
augroup END
-" Jump to last known cursor position {{{2
-augroup last_loc
+if !has("nvim")
+ " autocmds that already exist in neovim
+ " Jump to last known cursor position {{{2
+ augroup last_loc
+ au!
+ " blacklist certain filetype
+ let blacklist = ['gitcommit']
+ autocmd BufReadPost *
+ \ if index(blacklist, &ft) < 0 && line("'\"") > 1 && line("'\"") <= line("$") |
+ \ exe "normal! g`\"" |
+ \ endif
+ augroup END
+
+ " Check for file modifications automatically {{{2
+ " (current buffer only)
+ " Use :NoAutoChecktime to disable it (uses b:autochecktime)
+ fun! MyAutoCheckTime()
+ " only check timestamp for normal files
+ if &buftype != '' | return | endif
+ if ! exists('b:autochecktime') || b:autochecktime
+ checktime %
+ let b:autochecktime = 1
+ endif
+ endfun
+ augroup MyAutoChecktime
au!
- " blacklist certain filetype
- let blacklist = ['gitcommit']
- autocmd BufReadPost *
- \ if index(blacklist, &ft) < 0 && line("'\"") > 1 && line("'\"") <= line("$") |
- \ exe "normal! g`\"" |
- \ endif
-augroup END
-
-" Check for file modifications automatically {{{2
-" (current buffer only)
-" Use :NoAutoChecktime to disable it (uses b:autochecktime)
-fun! MyAutoCheckTime()
- " only check timestamp for normal files
- if &buftype != '' | return | endif
- if ! exists('b:autochecktime') || b:autochecktime
- checktime %
- let b:autochecktime = 1
- endif
-endfun
-augroup MyAutoChecktime
- au!
- au FocusGained,BufEnter,CursorHold,InsertEnter * call MyAutoCheckTime()
-augroup END
-command! NoAutoChecktime let b:autochecktime=0
-command! ToggleAutoChecktime let b:autochecktime=!get(b:, 'autochecktime', 0) | echom "b:autochecktime:" b:autochecktime
+ au FocusGained,BufEnter,CursorHold,InsertEnter * call MyAutoCheckTime()
+ augroup END
+ command! NoAutoChecktime let b:autochecktime=0
+ command! ToggleAutoChecktime let b:autochecktime=!get(b:, 'autochecktime', 0) | echom "b:autochecktime:" b:autochecktime
+endif
" bindings {{{1