From 1c23c8ea7ba03303798f17a8559d5fe8c55a87e8 Mon Sep 17 00:00:00 2001 From: Omar Zeghouani Date: Sun, 12 Apr 2026 00:33:11 +0100 Subject: [PATCH 1/3] Update config for neovim 0.12 --- dot_config/nvim/autoload/utils.vim | 19 +- dot_config/nvim/lua/modules/cmp.lua | 63 - .../nvim/lua/modules/feline/statusline.lua | 3 +- dot_config/nvim/lua/modules/feline/winbar.lua | 2 +- dot_config/nvim/lua/modules/hydra/window.lua | 6 +- .../lua/modules/language/servers.lua.tmpl | 11 +- dot_config/nvim/lua/modules/treesitter.lua | 70 -- dot_config/nvim/lua/utils/completion.lua | 174 +++ dot_config/nvim/lua/utils/misc.lua | 52 +- dot_config/nvim/lua/utils/pack.lua | 169 +++ dot_config/nvim/plugin/20-globals.lua | 31 + dot_config/nvim/plugin/30-settings.lua.tmpl | 8 + dot_config/nvim/plugin/41-autocommands.lua | 56 +- dot_config/nvim/plugin/50-plugins.lua | 1017 ++++++----------- dot_config/nvim/plugin/60-mappings.lua | 19 +- 15 files changed, 803 insertions(+), 897 deletions(-) delete mode 100644 dot_config/nvim/lua/modules/cmp.lua delete mode 100644 dot_config/nvim/lua/modules/treesitter.lua create mode 100644 dot_config/nvim/lua/utils/completion.lua create mode 100644 dot_config/nvim/lua/utils/pack.lua diff --git a/dot_config/nvim/autoload/utils.vim b/dot_config/nvim/autoload/utils.vim index 264aff13..850615d4 100644 --- a/dot_config/nvim/autoload/utils.vim +++ b/dot_config/nvim/autoload/utils.vim @@ -44,7 +44,7 @@ endfunction " Used to set darker winhighlight for specific filetypes function! utils#handle_win() - let l:sidebar = ['undotree', 'Outline', 'qf', 'DiffviewFiles', 'DiffviewFileHistory', 'aerial'] + let l:sidebar = ['nvim-undotree', 'Outline', 'qf', 'DiffviewFiles', 'DiffviewFileHistory', 'aerial'] if index(l:sidebar, &filetype) >= 0 setlocal winhighlight=Normal:TabLineFill endif @@ -55,20 +55,3 @@ function! utils#setccol() let &l:colorcolumn=&l:textwidth+1 endif endfunction - -function! utils#blank_up() - let cmd = 'put!=repeat(nr2char(10), v:count1)|silent '']+' - if &modifiable - let cmd .= '|silent! call repeat#set("\(BlankUp)", v:count1)' - endif - return cmd -endfunction - -function! utils#blank_down() - let cmd = 'put =repeat(nr2char(10), v:count1)|silent ''[-' - if &modifiable - let cmd .= '|silent! call repeat#set("\(BlankDown)", v:count1)' - endif - return cmd -endfunction - diff --git a/dot_config/nvim/lua/modules/cmp.lua b/dot_config/nvim/lua/modules/cmp.lua deleted file mode 100644 index cd99e75e..00000000 --- a/dot_config/nvim/lua/modules/cmp.lua +++ /dev/null @@ -1,63 +0,0 @@ --- Avoid showing extra message when using completion -vim.o.shortmess = vim.o.shortmess .. "c" - --- Limit menu items to 5 -vim.o.pumheight = 5 - -local cmp = require("cmp") -local cmp_types = require("cmp.types.cmp") - -cmp.setup({ - snippet = { - expand = function(args) - require("luasnip").lsp_expand(args.body) - end, - }, - preselect = cmp.PreselectMode.None, - view = { - entries = "native", - }, - mapping = { - [""] = cmp.mapping.select_next_item({ behavior = cmp_types.SelectBehavior.Select }), - [""] = cmp.mapping.select_prev_item({ behavior = cmp_types.SelectBehavior.Select }), - [""] = cmp.mapping.select_next_item({ behavior = cmp_types.SelectBehavior.Insert }), - [""] = cmp.mapping.select_prev_item({ behavior = cmp_types.SelectBehavior.Insert }), - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = function() - if cmp.visible() then - cmp.close() - else - cmp.complete() - end - end, - [""] = cmp.mapping.confirm({ - behavior = cmp.ConfirmBehavior.Replace, - select = false, - }), - -- [""] = cmp.mapping.confirm({ - -- behavior = cmp.ConfirmBehavior.Insert, - -- select = false, - -- }), - }, - formatting = { - format = function(_, vim_item) - local codicons = require("codicons") - local symbols = require("codicons.extensions.completion_item_kind").symbols - local icon = codicons.get(symbols[vim_item.kind].icon) - -- vim_item.kind = string.format("%s %s", vim_item.kind, icon) - vim_item.kind = icon - return vim_item - end, - }, - sources = cmp.config.sources({ - { name = "nvim_lsp", keyword_length = 1 }, - { name = "nvim_lsp_signature_help" }, - { name = "pandoc_references" }, - { name = "luasnip", keyword_length = 2 }, - { name = "nvim_lua" }, - { name = "path" }, - }, { - { name = "buffer", keyword_length = 4 }, - }), -}) diff --git a/dot_config/nvim/lua/modules/feline/statusline.lua b/dot_config/nvim/lua/modules/feline/statusline.lua index d80f9375..ed5db772 100644 --- a/dot_config/nvim/lua/modules/feline/statusline.lua +++ b/dot_config/nvim/lua/modules/feline/statusline.lua @@ -20,8 +20,7 @@ local components = { } force_inactive.filetypes = { - "packer", - "undotree", + "nvim-undotree", "Outline", "help", "nnn", diff --git a/dot_config/nvim/lua/modules/feline/winbar.lua b/dot_config/nvim/lua/modules/feline/winbar.lua index f95fd115..1528872d 100644 --- a/dot_config/nvim/lua/modules/feline/winbar.lua +++ b/dot_config/nvim/lua/modules/feline/winbar.lua @@ -18,7 +18,7 @@ local components = { disable.filetypes = { "Outline", - "undotree", + "nvim-undotree", "DiffviewFileHistory", "DiffviewFiles", "TelescopePicker", diff --git a/dot_config/nvim/lua/modules/hydra/window.lua b/dot_config/nvim/lua/modules/hydra/window.lua index 02785f68..ab834a09 100644 --- a/dot_config/nvim/lua/modules/hydra/window.lua +++ b/dot_config/nvim/lua/modules/hydra/window.lua @@ -9,8 +9,8 @@ hydra({ ^ ^ _k_ ^ ^ ^ ^ _K_ ^ ^ _s_: horizontally _+_ _-_: height _h_ ^ ^ _l_ _H_ ^ ^ _L_ _v_: vertically _>_ _<_: width ^ ^ _j_ ^ ^ ^ ^ _J_ ^ ^ _q_, _c_: close ^ _=_ ^: equalize - focus^^^^^^ window^^^^^^ _z_: maximize - ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ _o_: remain only ^ ^ ^ ^ __ + focus^^^^^^ window^^^^^^ _o_: remain only + ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ __ ]], config = { color = "pink", @@ -37,8 +37,6 @@ hydra({ -- Split { "s", "s" }, { "v", "v" }, - { "z", cmd("WindowsMaximize"), { exit = true, desc = "maximize" } }, - { "", cmd("WindowsMaximize"), { exit = true, desc = false } }, { "c", pcmd("close", "E444") }, { "q", pcmd("close", "E444"), { desc = "close window" } }, { "", pcmd("close", "E444"), { desc = false } }, diff --git a/dot_config/nvim/lua/modules/language/servers.lua.tmpl b/dot_config/nvim/lua/modules/language/servers.lua.tmpl index aeb004d1..a9016ada 100644 --- a/dot_config/nvim/lua/modules/language/servers.lua.tmpl +++ b/dot_config/nvim/lua/modules/language/servers.lua.tmpl @@ -110,10 +110,6 @@ jsonnet_ls = {}, marksman = {}, {{- $servers = add1 $servers -}} {{- end }} -{{ if lookPath "sqls" -}} --- sqls = {}, -{{- $servers = add1 $servers -}} -{{- end }} {{ if lookPath "buf" -}} buf_ls = {}, {{- $servers = add1 $servers -}} @@ -163,18 +159,13 @@ vim.api.nvim_create_autocmd("LspAttach", { vim.keymap.set("n", "r", vim.lsp.buf.rename, { buffer = true }) vim.keymap.set("n", "gr", vim.lsp.buf.references, { buffer = true }) vim.keymap.set("n", "gi", vim.lsp.buf.implementation, { buffer = true }) - - if client.name == "sqls" then - client.server_capabilities.documentFormattingProvider = false - require("sqls").on_attach(client, bufnr) - end end }) function M.setup() {{ if gt $servers 0 -}} vim.lsp.config("*", { - capabilities = require("cmp_nvim_lsp").default_capabilities(), + capabilities = vim.lsp.protocol.make_client_capabilities(), flags = { debounce_text_changes = 500, } diff --git a/dot_config/nvim/lua/modules/treesitter.lua b/dot_config/nvim/lua/modules/treesitter.lua deleted file mode 100644 index 257be42f..00000000 --- a/dot_config/nvim/lua/modules/treesitter.lua +++ /dev/null @@ -1,70 +0,0 @@ --- TreeSitter Config -local tree_sitter = require("nvim-treesitter.configs") - -local ts_config = { - -- ensure_installed = 'maintained', - highlight = { - enable = true, - disable = { "html" }, - additional_vim_regex_highlighting = { "markdown" }, - }, - -- incremental_selection = { - -- enable = true, - -- keymaps = { - -- init_selection = "gnn", - -- node_incremental = "grn", - -- scope_incremental = "grc", - -- node_decremental = "grm", - -- }, - -- } - -- NOTE: testing this after #2275 - -- indent = { - -- enable = true, - -- disable = { "html", "xml" }, - -- }, - -- refactor = { - -- highlight_definitions = { enable = true }, - -- smart_rename = { - -- enable = true, - -- keymaps = { - -- smart_rename = "grr", - -- }, - -- }, - -- navigation = { - -- enable = true, - -- keymaps = { - -- -- goto_definition_lsp_fallback = "gnd", - -- list_definitions = "gnD", - -- list_definitions_toc = "gO", - -- goto_next_usage = "[r", - -- goto_previous_usage = "]r", - -- }, - -- }, - -- }, - -- vim-matchup - -- matchup = { - -- enable = true, - -- }, - -- Query linter - query_linter = { - enable = true, - use_virtual_text = true, - lint_events = { "BufWrite" }, - }, - -- pairs - pairs = { - enable = true, - disable = {}, - highlight_pair_events = { "CursorHoldI", "CursorHold" }, - highlight_self = true, -- whether to highlight also the part of the pair under cursor (or only the partner) - goto_right_end = true, -- whether to go to the end of the right partner or the beginning - fallback_cmd_normal = "", - keymaps = { - goto_partner = "%", - }, - }, -} - -require("nvim-treesitter.install").compilers = { "clang", "gcc", "cc" } - -tree_sitter.setup(ts_config) diff --git a/dot_config/nvim/lua/utils/completion.lua b/dot_config/nvim/lua/utils/completion.lua new file mode 100644 index 00000000..62294e36 --- /dev/null +++ b/dot_config/nvim/lua/utils/completion.lua @@ -0,0 +1,174 @@ +local uv = vim.uv or vim.loop + +local M = {} + +local function current_line_before_cursor() + local row, col = unpack(vim.api.nvim_win_get_cursor(0)) + local line = vim.api.nvim_buf_get_lines(0, row - 1, row, true)[1] or "" + return line:sub(1, col), col +end + +local function current_buffer_dir() + return vim.fn.expand(("#%d:p:h"):format(vim.api.nvim_get_current_buf())) +end + +local function is_slash_comment() + local commentstring = vim.bo.commentstring or "" + local no_filetype = vim.bo.filetype == "" + local slash_comment = commentstring:match("/%*") or commentstring:match("//") + return slash_comment and not no_filetype +end + +local function is_valid_absolute_prefix(prefix) + if prefix:match("%a+:%s*$") then + return false + end + + if prefix:match("]*)$") + if start_col and token then + return start_col, token + end + + start_col, _, token = line:find("(~/[^%s\"'`|<>]*)$") + if start_col and token then + return start_col, token + end + + start_col, _, token = line:find("(%.%./[^%s\"'`|<>]*)$") + if start_col and token then + return start_col, token + end + + start_col, _, token = line:find("(%./[^%s\"'`|<>]*)$") + if start_col and token then + return start_col, token + end + + start_col, _, token = line:find("(/[^%s\"'`|<>]*)$") + if start_col and token and is_valid_absolute_prefix(line:sub(1, start_col - 1)) then + return start_col, token + end + + return nil +end + +local function split_token(token) + local dirname, partial = token:match("^(.*[/])([^/]*)$") + return dirname, partial or "" +end + +local function resolve_dir(dirname) + if dirname:match("^%./") or dirname:match("^%.%./") then + return vim.fs.normalize(current_buffer_dir() .. "/" .. dirname) + end + + if dirname:match("^~/") then + return vim.fs.normalize(vim.fn.expand("~") .. dirname:sub(2)) + end + + local env_var = dirname:match("^%$([%a_][%w_]*)/") + if env_var then + local value = vim.fn.getenv(env_var) + if value ~= vim.NIL and value ~= "" then + return vim.fs.normalize(value .. dirname:sub(#env_var + 2)) + end + end + + if dirname:match("^/") then + return vim.fs.normalize(dirname) + end + + return nil +end + +local function scandir_matches(path, partial) + local fs, err = uv.fs_scandir(path) + if not fs or err then + return {} + end + + local include_hidden = partial:sub(1, 1) == "." + local items = {} + + while true do + local name, file_type = uv.fs_scandir_next(fs) + if not name then + break + end + + if (include_hidden or name:sub(1, 1) ~= ".") and name:sub(1, #partial) == partial then + local is_dir = file_type == "directory" + items[#items + 1] = { + word = is_dir and (name .. "/") or name, + abbr = is_dir and (name .. "/") or name, + menu = "[path]", + kind = is_dir and "d" or "f", + } + end + end + + table.sort(items, function(a, b) + if a.kind ~= b.kind then + return a.kind == "d" + end + + return a.abbr < b.abbr + end) + + return items +end + +function M.path_complete(findstart, base) + local line, cursor_col = current_line_before_cursor() + local start_col, token = detect_path_context(line) + + if findstart == 1 then + if not start_col or not token then + return cursor_col + end + + local dirname, _ = split_token(token) + if not dirname then + return cursor_col + end + + return start_col + #dirname - 1 + end + + if not start_col or not token then + return {} + end + + local dirname = split_token(token) + local path = dirname and resolve_dir(dirname) + if not path then + return {} + end + + return scandir_matches(path, base) +end + +_G.native_path_complete = M.path_complete + +return M diff --git a/dot_config/nvim/lua/utils/misc.lua b/dot_config/nvim/lua/utils/misc.lua index cbb90f90..18cbf760 100644 --- a/dot_config/nvim/lua/utils/misc.lua +++ b/dot_config/nvim/lua/utils/misc.lua @@ -1,10 +1,6 @@ local M = {} local cmd = vim.api.nvim_command -M.t = function(str) - return vim.api.nvim_replace_termcodes(str, true, true, true) -end - -- Checks if prev col doesn't exist M.invalid_prev_col = function() local lnum, col_no = unpack(vim.api.nvim_win_get_cursor(0)) @@ -21,52 +17,6 @@ M.invalid_prev_col = function() return true end --- Usage for current buffer --- local lnum, _ = unpack(vim.api.nvim_win_get_cursor(0)) --- local buf = vim.api.nvim_get_current_buf() --- require'utils.misc'.is_comment(buf, lnum - 1) --- This method returns nil if this buf doesn't have a treesitter parser --- @return true or false otherwise -M.is_comment = function(buf, line) - local highlighter = require("vim.treesitter.highlighter") - local hl = highlighter.active[buf] - - if not hl then - return - end - - local is_comment = false - hl.tree:for_each_tree(function(tree, lang_tree) - if is_comment then - return - end - - local query = hl:get_query(lang_tree:lang()) - if not (query and query:query()) then - return - end - - local iter = query:query():iter_captures(tree:root(), buf, line, line + 1) - - for capture, _ in iter do - if query._query.captures[capture] == "comment" then - is_comment = true - end - end - end) - return is_comment -end - --- Returns path seperator based on OS -M.pathSep = function() - local os = string.lower(U.os.name) - if os == "linux" or os == "osx" or os == "bsd" then - return "/" - else - return "\\" - end -end - -- Expects undo files to be directories -- Requires plenary -- FIXME: clean up this awful code @@ -108,7 +58,7 @@ M.purge_old_undos = function() if parent_path:find(undodir) then parent = P:new(parent_path) if parent:is_dir() then - parent_files = S.scan_dir(parent_path, { hidden = true }) + local parent_files = S.scan_dir(parent_path, { hidden = true }) if #parent_files == 0 then parent:rmdir() depth = depth + 1 diff --git a/dot_config/nvim/lua/utils/pack.lua b/dot_config/nvim/lua/utils/pack.lua new file mode 100644 index 00000000..3190a18c --- /dev/null +++ b/dot_config/nvim/lua/utils/pack.lua @@ -0,0 +1,169 @@ +local M = {} + +local misc = require("mini.misc") + +local on_event = function(events, f) + misc.safely("event:" .. events, f) +end + +local function plugin_name(spec) + return spec.name or (spec.src or ""):match("/([^/]+)$") +end + +local function is_src_spec(spec) + return spec.src ~= nil +end + +local function is_pack_spec(spec) + return spec.pack ~= nil +end + +local function validate_spec(spec) + local has_src = spec.src ~= nil + local has_pack = spec.pack ~= nil + if has_src and has_pack then + error("spec must have either 'src' or 'pack', not both") + end + if not has_src and not has_pack then + error("spec must have either 'src' or 'pack'") + end +end + +local function to_pack_spec(spec) + if not is_src_spec(spec) then + return nil + end + local url = spec.src + local pack_spec = { src = url } + if spec.version then + pack_spec.version = spec.version + end + if spec.data then + pack_spec.data = spec.data + end + return pack_spec +end + +local function plugin_dir(name) + return vim.fs.joinpath(vim.fn.stdpath("data"), "site", "pack", "core", "opt", name) +end + +local function load_spec(spec) + if is_src_spec(spec) then + vim.pack.add({ to_pack_spec(spec) }) + elseif is_pack_spec(spec) then + vim.cmd.packadd(spec.pack) + end +end + +local function run_data_load(spec) + local load = ((spec or {}).data or {}).load + if type(load) ~= "function" then + return + end + + pcall(load, { + spec = to_pack_spec(spec), + name = plugin_name(spec), + path = plugin_dir(plugin_name(spec)), + }) +end + +local function make_loader(spec) + local loaded = false + + return function() + if loaded then + return + end + load_spec(spec) + run_data_load(spec) + if spec.setup then + spec.setup() + end + loaded = true + end +end + +local function register_key_triggers(spec, load) + if not spec.keys then + return + end + for _, key in ipairs(spec.keys) do + local mode = key.mode or "n" + local rhs = key.rhs + local opts = key.opts or {} + vim.keymap.set(mode, key.lhs, function() + load() + rhs() + end, opts) + end +end + +local function load_eager(specs) + local src_specs = {} + local pack_specs = {} + + for _, spec in ipairs(specs) do + if is_src_spec(spec) then + table.insert(src_specs, spec) + elseif is_pack_spec(spec) then + table.insert(pack_specs, spec) + end + end + + if #src_specs > 0 then + local pack_specs_only = vim.tbl_map(function(s) return to_pack_spec(s) end, src_specs) + vim.pack.add(pack_specs_only) + end + + for _, spec in ipairs(pack_specs) do + vim.cmd.packadd(spec.pack) + end + + for _, spec in ipairs(specs) do + run_data_load(spec) + if spec.setup then + spec.setup() + end + end +end + +function M.setup(specs) + vim.api.nvim_create_autocmd("PackChanged", { + callback = function(ev) + local plugin = ev.data + local run = (plugin.spec.data or {}).run + if plugin.kind ~= "delete" and type(run) == "function" then + pcall(run, vim.tbl_extend("force", plugin, { path = plugin_dir(plugin.spec.name) })) + end + end, + }) + + vim.keymap.set("", "", function() + vim.pack.update() + end, { silent = true, desc = "Update plugins" }) + + local eager_specs = {} + + for _, spec in ipairs(specs) do + validate_spec(spec) + + local loader = make_loader(spec) + local trigger = spec.event or spec.keys + + if not trigger then + table.insert(eager_specs, spec) + elseif spec.event then + on_event(spec.event, function() + loader() + end) + elseif spec.keys then + register_key_triggers(spec, loader) + end + end + + load_eager(eager_specs) +end + +return M \ No newline at end of file diff --git a/dot_config/nvim/plugin/20-globals.lua b/dot_config/nvim/plugin/20-globals.lua index 39bb8378..1318e5a2 100644 --- a/dot_config/nvim/plugin/20-globals.lua +++ b/dot_config/nvim/plugin/20-globals.lua @@ -8,3 +8,34 @@ U.os = { config = vim.fn.stdpath("config"), name = jit.os, } + +-- Completion +U.completion = { + lsp_kind_icons = { + Text = "", + Method = "", + Function = "", + Constructor = "", + Field = "", + Variable = "", + Class = "", + Interface = "", + Module = "", + Property = "", + Unit = "", + Value = "", + Enum = "", + Keyword = "", + Snippet = "", + Color = "", + File = "", + Reference = "", + Folder = "", + EnumMember = "", + Constant = "", + Struct = "", + Event = "", + Operator = "", + TypeParameter = "", + }, +} diff --git a/dot_config/nvim/plugin/30-settings.lua.tmpl b/dot_config/nvim/plugin/30-settings.lua.tmpl index 1ecd3570..57066290 100644 --- a/dot_config/nvim/plugin/30-settings.lua.tmpl +++ b/dot_config/nvim/plugin/30-settings.lua.tmpl @@ -67,6 +67,14 @@ vim.opt.fillchars = { diff = "╱", } +-- Native autocompletion (Neovim 0.12+) +require("utils.completion") +vim.opt.completeopt = "menu,menuone,popup,noselect" +vim.opt.pumheight = 5 +vim.opt.shortmess:append("c") +vim.opt.autocomplete = true +vim.opt.complete = ".^1,w^5,b^5,u^5,t,Fv:lua.native_path_complete" + vim.opt.showtabline = 0 vim.opt.laststatus = 3 diff --git a/dot_config/nvim/plugin/41-autocommands.lua b/dot_config/nvim/plugin/41-autocommands.lua index 7dd7b3cf..c462d280 100644 --- a/dot_config/nvim/plugin/41-autocommands.lua +++ b/dot_config/nvim/plugin/41-autocommands.lua @@ -1,4 +1,5 @@ vim.api.nvim_create_autocmd("BufReadPost", { + desc = "Return cursor to the last known position when opening a file", callback = function() local mark = vim.api.nvim_buf_get_mark(0, '"') local lcount = vim.api.nvim_buf_line_count(0) @@ -9,33 +10,32 @@ vim.api.nvim_create_autocmd("BufReadPost", { }) vim.api.nvim_create_autocmd("TextYankPost", { + desc = "Flash the yanked text and copy it to the system clipboard", callback = function() if vim.v.event.operator == "y" and vim.v.event.regname == "" then vim.highlight.on_yank() - require("osc52").copy_register('"') + local status, osc52 = pcall(require, "osc52") + if status then + osc52.copy_register('"') + end end end, }) vim.api.nvim_create_autocmd("BufEnter", { + desc = "Force consistent text-wrapping and list-formatting rules", callback = function() + -- t: wrap text, c: wrap comments, q: format comments, + -- n: numbered lists, j: remove comment leaders on join vim.opt_local.formatoptions = "tcqnbj" end, }) -vim.api.nvim_create_autocmd("TermOpen", { - callback = function() - vim.cmd("startinsert") - vim.opt_local.number = false - vim.opt_local.relativenumber = false - vim.opt_local.signcolumn = "no" - end, -}) - local numbertoggle_group = vim.api.nvim_create_augroup("numbertoggle", {}) vim.api.nvim_create_autocmd({ "BufEnter", "FocusGained", "WinEnter" }, { group = numbertoggle_group, + desc = "Switch to relative numbering when the window is active", callback = function() if vim.opt_local.number._value == true then vim.opt_local.relativenumber = true @@ -45,9 +45,45 @@ vim.api.nvim_create_autocmd({ "BufEnter", "FocusGained", "WinEnter" }, { vim.api.nvim_create_autocmd({ "BufLeave", "FocusLost", "WinLeave" }, { group = numbertoggle_group, + desc = "Switch to absolute numbering when the window loses focus", callback = function() if vim.opt_local.number._value == true then vim.opt_local.relativenumber = false end end, }) + +vim.api.nvim_create_autocmd("FileType", { + desc = "Enable treesitter highlighting", + callback = function(args) + local ft = vim.bo[args.buf].filetype + local lang = vim.treesitter.language.get_lang(ft) + + -- Check if the language mapping exists AND if the parser is installed + if lang and vim.treesitter.query.get(lang, "highlights") then + pcall(vim.treesitter.start, args.buf, lang) + end + end, +}) + +-- Enable native LSP completion +vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('native_completion', {}), + desc = "Enable native LSP autocompletion", + callback = function(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + if client and client:supports_method('textDocument/completion') then + vim.lsp.completion.enable(true, client.id, ev.buf, { + autotrigger = true, + convert = function(item) + local kind_name = vim.lsp.protocol.CompletionItemKind[item.kind] or "" + local icon = U.completion.lsp_kind_icons[kind_name] or "" + return { + abbr = icon ~= "" and (icon .. " " .. item.label) or item.label, + menu = "[LSP]", + } + end, + }) + end + end, +}) diff --git a/dot_config/nvim/plugin/50-plugins.lua b/dot_config/nvim/plugin/50-plugins.lua index 3e9a7b23..7dbe955d 100644 --- a/dot_config/nvim/plugin/50-plugins.lua +++ b/dot_config/nvim/plugin/50-plugins.lua @@ -1,677 +1,378 @@ --- Install packer -local execute = vim.api.nvim_command - -local install_path = vim.fn.stdpath("data") .. "/site/pack/packer/opt/packer.nvim" - -if vim.fn.empty(vim.fn.glob(install_path)) > 0 then - execute("!git clone https://github.com/wbthomason/packer.nvim " .. install_path) -end -execute("packadd packer.nvim") - -local packer = require("packer") - -vim.keymap.set("", "", function() - packer.sync({ preview_updates = true }) -end, { silent = true, desc = "Sync packer preview" }) - -packer.startup({ - function(use) - use({ - "wbthomason/packer.nvim", - opt = true, - }) - - -- Common dependencies - use({ - "nvim-lua/plenary.nvim", - module_pattern = "plenary.*", - config = function() - require("plenary.filetype").add_file("extra") - end, - }) - - -- - -- LSP, treesitter and completion - -- - use({ - "neovim/nvim-lspconfig", - config = [[require'modules.language.servers'.setup()]], - }) - - use({ - "https://git.sr.ht/~whynothugo/lsp_lines.nvim", - }) - - use({ - "j-hui/fidget.nvim", - config = function() - require("fidget").setup({ - notification = { - window = { - winblend = 0, - relative = "editor", - }, - }, - }) - end, - }) +vim.pack.add({ 'https://github.com/nvim-mini/mini.misc' }) - use({ - "Wansmer/symbol-usage.nvim", - config = function() - require("symbol-usage").setup({ hl = { link = "DiagnosticUnnecessary" } }) - end, - }) - - use({ - "mfussenegger/nvim-dap", - config = [[require'modules.language.debuggers'.setup()]], - }) - - use({ - "stevearc/conform.nvim", - config = [[require'modules.language.formatters'.setup()]], - }) - - use({ - "mfussenegger/nvim-lint", - config = [[require'modules.language.linters'.setup()]], - }) - - use({ - "b0o/schemastore.nvim", - module = "schemastore", - }) - - use({ - "stevearc/aerial.nvim", - cmd = "AerialToggle", - setup = function() - vim.keymap.set("n", "a", "AerialToggle", { silent = true }) - end, - config = function() - require("aerial").setup({ - nerd_font = false, - }) - end, - }) - - use({ - "hrsh7th/nvim-cmp", - requires = { - { "hrsh7th/cmp-nvim-lsp" }, - { "hrsh7th/cmp-path" }, - { "hrsh7th/cmp-buffer" }, - { "saadparwaiz1/cmp_luasnip" }, - { "hrsh7th/cmp-nvim-lsp-signature-help" }, - { "jc-doyle/cmp-pandoc-references" }, - }, - config = [[require'modules.cmp']], - }) - - use({ - "lewis6991/hover.nvim", - config = function() - require("hover").setup({ - init = function() - -- Require providers - require("hover.providers.lsp") - require("hover.providers.gh") - require("hover.providers.man") - end, - preview_opts = { - border = nil, +require("utils.pack").setup({ + { + src = "https://github.com/nvim-lua/plenary.nvim", + }, + + { + src = "https://github.com/neovim/nvim-lspconfig", + setup = function() + require("modules.language.servers").setup() + end, + }, + + { + src = "https://git.sr.ht/~whynothugo/lsp_lines.nvim", + }, + + { + src = "https://github.com/j-hui/fidget.nvim", + setup = function() + require("fidget").setup({ + notification = { + window = { + winblend = 0, + relative = "editor", }, - -- Whether the contents of a currently open hover window should be moved - -- to a :h preview-window when pressing the hover keymap. - preview_window = false, - title = true, - }) - - -- Setup keymaps - vim.keymap.set("n", "K", require("hover").hover, { desc = "hover.nvim" }) - vim.keymap.set("n", "gK", require("hover").hover_select, { desc = "hover.nvim (select)" }) - end, - }) + }, + }) + end, + }, - use({ - "ii14/emmylua-nvim", - }) + { + src = "https://github.com/Wansmer/symbol-usage.nvim", + setup = function() + require("symbol-usage").setup({ hl = { link = "DiagnosticUnnecessary" } }) + end, + }, - use({ - "aspeddro/pandoc.nvim", - config = function() - require("pandoc").setup() - end, - }) - - use({ - "L3MON4D3/LuaSnip", - -- event = "BufReadPost", - -- module_pattern = "luasnip.*", - config = [[require'modules.snippets']], - }) - - use({ - "rafamadriz/friendly-snippets", - }) - - use({ - "kosayoda/nvim-lightbulb", - module = "nvim-lightbulb", - }) - - use({ - -- '~/Downloads/nvim-treesitter', - "nvim-treesitter/nvim-treesitter", - -- NOTE: maybe don't lazyload? - -- with lazyload, if file is opened directly ts plugins won't work until :e! - -- might have something to do with BufReadPre event and after key idk - config = [[require'modules.treesitter']], - run = ":TSUpdate", - }) - - use({ - -- "~/src/dev-comments.nvim", - "ram02z/dev-comments.nvim", - config = function() - require("dev_comments").setup() - end, - }) - - use({ - "nvim-treesitter/playground", - cmd = { "TSPlaygroundToggle", "TSHighlightCapturesUnderCursor" }, - setup = function() - vim.keymap.set("n", "tp", "TSPlaygroundToggle", { silent = true }) - vim.keymap.set("n", "th", "TSHighlightCapturesUnderCursor", { silent = true }) - end, - config = function() - require("utils.keychord").cancel("t") - end, - }) + { + src = "https://github.com/mfussenegger/nvim-dap", + setup = function() + require("modules.language.debuggers").setup() + end, + }, - use({ - "monkoose/matchparen.nvim", - config = function() - require("matchparen").setup() - end, - }) + { + src = "https://github.com/stevearc/conform.nvim", + setup = function() + require("modules.language.formatters").setup() + end, + }, - use({ - "ram02z/nvim-treesitter-pairs", - }) + { + src = "https://github.com/mfussenegger/nvim-lint", + setup = function() + require("modules.language.linters").setup() + end, + }, - use({ - "mfussenegger/nvim-treehopper", - config = function() - vim.keymap.set({ "o", "x" }, "m", ":lua require'tsht'.nodes()", { silent = true }) - end, - }) - - -- - -- UI - -- - - -- Icons - use({ - "kyazdani42/nvim-web-devicons", - module = "nvim-web-devicons", - }) - - -- Statusline - use({ - "feline-nvim/feline.nvim", - config = [[require'modules.feline']], - }) - - -- - -- Misc - -- - - -- OSC52 yank - use({ - "ojroques/nvim-osc52", - module = "osc52", - }) - - -- Wrapper around codicons - use({ - "mortepau/codicons.nvim", - module = "codicons", - }) - - -- Repeat support - use({ - "tpope/vim-repeat", - }) - - -- - -- Language support - -- - - use({ - "alker0/chezmoi.vim", - }) - - use({ - "terrastruct/d2-vim", - }) - - use({ - "AckslD/nvim-FeMaco.lua", - cmd = "FeMaco", - setup = function() - vim.keymap.set("n", "m", "FeMaco") - end, - config = function() - require("femaco").setup({ - prepare_buffer = function(opts) - vim.cmd("belowright split") - local win = vim.api.nvim_get_current_win() - local buf = vim.api.nvim_create_buf(false, false) - return vim.api.nvim_win_set_buf(win, buf) - end, - }) - end, - }) - - -- Tex support - use({ - "lervag/vimtex", - ft = "tex", - setup = function() - vim.g.tex_flavor = "latex" - vim.g.vimtex_syntax_enabled = 0 - vim.g.vimtex_view_method = "zathura" - vim.g.tex_conceal = "abdmg" - vim.g.vimtex_matchparen_enabled = 0 - end, - }) - - -- SQL - use({ - "nanotee/sqls.nvim", - module = "sqls", - }) - - -- Comment snippets - use({ - "danymat/neogen", - cmd = "Neogen", - config = function() - require("neogen").setup({ snippet_engine = "luasnip" }) - end, - }) + { + src = "https://github.com/b0o/schemastore.nvim", + }, - -- Git integration - use({ - { - "rhysd/committia.vim", - event = "BufReadPost COMMIT_EDITMSG,MERGE_MSG", - }, - { - "lewis6991/gitsigns.nvim", - config = [[require'modules.gitsigns']], - }, - { - "akinsho/git-conflict.nvim", - config = function() - require("git-conflict").setup({ - disable_diagnostics = true, - highlights = { - incoming = "DiffIncoming", - current = "DiffAdd", - }, - }) - vim.keymap.set("n", "cq", "GitConflictListQf") + { + src = "https://github.com/lewis6991/hover.nvim", + setup = function() + require("hover").config({ + init = function() + require("hover.providers.lsp") + require("hover.providers.gh") + require("hover.providers.man") end, - }, - }) - - -- Toggle terminal - use({ - "akinsho/toggleterm.nvim", - cmd = { "ToggleTerm", "TermExec" }, - keys = [[]], - setup = function() - vim.api.nvim_create_user_command("Ca", "TermExec cmd='chezmoi apply'", {}) - vim.cmd([[cabbrev ca Ca]]) - end, - config = function() - require("toggleterm").setup({ - shell = "/usr/bin/env fish", - open_mapping = [[]], - }) - end, - }) - - -- File manager - use({ - "mcchrish/nnn.vim", - config = function() - require("nnn").setup({ - set_default_mappings = false, - -- NOTE: might not work because we are using bash as shell - -- command = 'n', - action = { - [""] = "tab split", - [""] = "split", - [""] = "vsplit", - }, - layout = { - window = { - width = 0.9, - height = 0.6, - highlight = "FloatBorder", - }, - }, - replace_netrw = true, - statusline = false, - }) - vim.keymap.set("", "n", "NnnPicker", { silent = true }) - end, - }) - - -- Fuzzy finder - use({ - "nvim-telescope/telescope.nvim", - requires = { - { - "nvim-telescope/telescope-fzf-native.nvim", - after = "telescope.nvim", - run = "make", - config = function() - require("telescope").load_extension("fzf") - end, + preview_opts = { + border = nil, }, - }, - setup = function() - -- Register pickers - vim.keymap.set("i", "", "Telescope registers theme=get_cursor layout_config={height=18}") - vim.keymap.set( - { "x", "n" }, - '"', - "Telescope registers theme=get_cursor layout_config={height=18}" - ) - end, - config = [[require'modules.telescope']], - }) - - use({ - "nvim-telescope/telescope-ui-select.nvim", - after = "telescope.nvim", - config = function() - require("telescope").load_extension("ui-select") - end, - }) - - -- Extends f/t motions - use({ - "rhysd/clever-f.vim", - event = "BufReadPost", - setup = function() - vim.g.clever_f_smart_case = 1 - vim.g.clever_f_chars_match_any_signs = "#" - vim.g.clever_f_fix_key_direction = 1 - vim.g.clever_f_mark_direct = 1 - end, - config = function() - vim.keymap.set("", ";", "(clever-f-repeat-forward)", { silent = true }) - vim.keymap.set("", ",", "(clever-f-repeat-back)", { silent = true }) - -- FIXME: Issue #61 - vim.keymap.set("n", "", "(clever-f-reset)nod", { silent = true }) - end, - }) - - -- Improves w/e/b motions - use({ - "chrisgrieser/nvim-spider", - config = function() - vim.keymap.set({ "n", "o", "x" }, "w", "lua require('spider').motion('w')") - vim.keymap.set({ "n", "o", "x" }, "e", "lua require('spider').motion('e')") - vim.keymap.set({ "n", "o", "x" }, "b", "lua require('spider').motion('b')") - vim.keymap.set({ "n", "o", "x" }, "ge", "lua require('spider').motion('ge');", "HopWord", { silent = true }) - vim.keymap.set("n", "/", "HopPattern", { silent = true }) - end, - config = function() - require("hop").setup({ keys = "asdghklwertyuipzxcvbnmfj" }) - end, - }) - - use({ - "Wansmer/treesj", - module = "treesj", - setup = function() - vim.api.nvim_create_autocmd({ "FileType" }, { - pattern = "*", - callback = function() - local opts = { buffer = true } - local langs = require("treesj.langs")["presets"] - if langs[vim.bo.filetype] then - vim.keymap.set("n", "gJ", "TSJSplit", opts) - vim.keymap.set("n", "J", "TSJJoin", opts) - end - end, - }) - end, - config = function() - require("treesj").setup({ use_default_keymaps = false }) - end, - }) - - -- Swap delimiter seperated items - use({ - "mizlan/iswap.nvim", - cmd = "ISwap*", - setup = function() - vim.keymap.set("n", "gs", "ISwap", { silent = true }) - vim.keymap.set("n", "gS", "ISwapWith", { silent = true }) - end, - }) - - -- Comments - use({ - "numToStr/Comment.nvim", - keys = { "gc", "gb" }, - config = function() - local ft = require("Comment.ft") - ft.dosini = "#%s" - require("Comment").setup({ - ignore = "^$", - }) - end, - }) - - -- Manipulate pairs - use({ - "machakann/vim-sandwich", - event = "BufReadPost", - config = function() - vim.cmd([[runtime macros/sandwich/keymap/surround.vim]]) - end, - }) - - -- Color highlighting - use({ - "uga-rosa/ccc.nvim", - event = "BufReadPre", - config = function() - require("ccc").setup({ - highlighter = { - auto_enable = true, - lsp = true, - }, - }) - end, - }) - - -- Increment/decrement - use({ - "monaqa/dial.nvim", - keys = { "", "" }, - config = function() - local augend = require("dial.augend") - - require("dial.config").augends:register_group({ - default = { - augend.integer.alias.decimal_int, - augend.semver.alias.semver, - augend.constant.new({ - elements = { "true", "false" }, - word = true, - cyclic = true, - }), - augend.constant.new({ - elements = { "True", "False" }, - word = true, - cyclic = true, - }), - augend.constant.new({ - elements = { "&&", "||" }, - word = false, - cyclic = true, - }), - }, - visual = { - augend.integer.new({ - radix = 16, - prefix = "0x", - natural = true, - case = "upper", - }), - }, - }) - vim.keymap.set("n", "", require("dial.map").inc_normal(), { silent = true }) - vim.keymap.set("v", "", require("dial.map").inc_visual(), { silent = true }) - vim.keymap.set("n", "", require("dial.map").dec_normal(), { silent = true }) - vim.keymap.set("v", "", require("dial.map").dec_visual(), { silent = true }) - end, - }) + preview_window = false, + title = true, + }) + vim.keymap.set("n", "K", function() + require("hover").open() + end, { desc = "hover.nvim (open)" }) + vim.keymap.set("n", "gK", function() + require("hover").enter() + end, { desc = "hover.nvim (enter)" }) + end, + }, - -- Emacs hydra for neovim - use({ - "nvimtools/hydra.nvim", - config = function() - require("modules.hydra") - end, - }) - - use({ - "anuvyklack/windows.nvim", - requires = { "anuvyklack/middleclass" }, - cmd = "Windows*", - config = function() - require("windows").setup() - end, - }) - - -- Window shift - use({ - "sindrets/winshift.nvim", - cmd = "WinShift", - config = function() - require("winshift").setup() - end, - }) - - -- Multiple cursors - use({ - "mg979/vim-visual-multi", - keys = { - "", - "", - "", - "", - "", - "\\\\", - }, - setup = function() - vim.g.VM_set_statusline = 0 - end, - }) + { + src = "https://github.com/ii14/emmylua-nvim", + }, - -- Text manipulation - use({ - "booperlv/nvim-gomove", - config = function() - require("gomove").setup() - end, - }) - - -- Smooth scrolling - use({ - "karb94/neoscroll.nvim", - event = "BufReadPost", - config = [[require'neoscroll'.setup()]], - }) - - -- Peek at lines - use({ - "nacro90/numb.nvim", - event = "CmdlineEnter", - config = [[require'numb'.setup({show_cursorline = true})]], - }) - - -- Undo tree - use({ - "mbbill/undotree", - cmd = "UndotreeToggle", - setup = function() - vim.g.undotree_SplitWidth = 40 - vim.g.undotree_SetFocusWhenToggle = 1 - vim.g.undotree_DiffAutoOpen = 0 - vim.keymap.set("n", "ut", "UndotreeToggle", { silent = true }) + { + src = "https://github.com/L3MON4D3/LuaSnip", + setup = function() + require("modules.snippets") + end, + }, + + { + src = "https://github.com/rafamadriz/friendly-snippets", + }, + + { + src = "https://github.com/kosayoda/nvim-lightbulb", + }, + + { + src = "https://github.com/nvim-treesitter/nvim-treesitter", + version = "main", + data = { + load = function(plugin) + vim.opt.rtp:prepend(vim.fs.joinpath(plugin.path, "runtime")) end, - config = function() - require("utils.keychord").cancel("u") + run = function(plugin) + if not plugin.active then + vim.cmd.packadd("nvim-treesitter") + end + vim.cmd("TSUpdate") end, - }) - - -- Remove annoying search highlighting - use({ - "romainl/vim-cool", - event = { "InsertEnter", "CmdlineEnter" }, - }) - - -- Quickfix helper - use({ - "kevinhwang91/nvim-bqf", - event = { "FileType qf", "QuickFixCmdPre" }, - config = function() - require("bqf").setup({ - preview = { - auto_preview = false, - delay_syntax = 0, + }, + }, + + { + src = "https://github.com/monkoose/matchparen.nvim", + setup = function() + require("matchparen").setup() + end, + }, + + { + src = "https://github.com/mfussenegger/nvim-treehopper", + setup = function() + vim.keymap.set({ "o", "x" }, "m", function() + require("tsht").nodes() + end, { silent = true }) + end, + }, + + { + src = "https://github.com/kyazdani42/nvim-web-devicons", + }, + + { + src = "https://github.com/feline-nvim/feline.nvim", + setup = function() + require("modules.feline") + end, + }, + + { + src = "https://github.com/ojroques/nvim-osc52", + }, + + { + src = "https://github.com/tpope/vim-repeat", + }, + + { + src = "https://github.com/alker0/chezmoi.vim", + }, + + { + src = "https://github.com/lewis6991/gitsigns.nvim", + setup = function() + require("modules.gitsigns") + end, + }, + + { + src = "https://github.com/akinsho/git-conflict.nvim", + setup = function() + require("git-conflict").setup({ + disable_diagnostics = true, + highlights = { + incoming = "DiffIncoming", + current = "DiffAdd", + }, + }) + vim.keymap.set("n", "cq", "GitConflictListQf") + end, + }, + + { + src = "https://github.com/mcchrish/nnn.vim", + setup = function() + require("nnn").setup({ + set_default_mappings = false, + action = { + [""] = "tab split", + [""] = "split", + [""] = "vsplit", + }, + layout = { + window = { + width = 0.9, + height = 0.6, + highlight = "FloatBorder", }, - }) + }, + replace_netrw = true, + statusline = false, + }) + vim.keymap.set("", "n", "NnnPicker", { silent = true }) + end, + }, + + { + src = "https://github.com/nvim-telescope/telescope.nvim", + setup = function() + vim.keymap.set("i", "", "Telescope registers theme=get_cursor layout_config={height=18}") + vim.keymap.set( + { "x", "n" }, + '"', + "Telescope registers theme=get_cursor layout_config={height=18}" + ) + require("modules.telescope") + require("telescope").load_extension("fzf") + require("telescope").load_extension("ui-select") + end, + }, + + { + src = "https://github.com/nvim-telescope/telescope-fzf-native.nvim", + data = { + run = function(plugin) + vim.system({ "make" }, { cwd = plugin.path }):wait() end, - }) - - -- Profiling - use({ - "dstein64/vim-startuptime", - cmd = "StartupTime", - }) - end, - config = { - profile = { - enable = true, }, - display = { - prompt_border = "single", - open_fn = function() - return require("packer.util").float({ border = "single" }) - end, + }, + + { + src = "https://github.com/nvim-telescope/telescope-ui-select.nvim", + }, + + { + src = "https://github.com/chrisgrieser/nvim-spider", + setup = function() + vim.keymap.set({ "n", "o", "x" }, "w", "lua require('spider').motion('w')") + vim.keymap.set({ "n", "o", "x" }, "e", "lua require('spider').motion('e')") + vim.keymap.set({ "n", "o", "x" }, "b", "lua require('spider').motion('b')") + vim.keymap.set({ "n", "o", "x" }, "ge", "lua require('spider').motion('ge')") + end, + }, + + { + src = "https://github.com/phaazon/hop.nvim", + setup = function() + require("hop").setup({ keys = "asdghklwertyuipzxcvbnmfj" }) + end, + keys = { + { mode = "n", lhs = ";", rhs = function() vim.cmd.HopWord() end, opts = { silent = true } }, + { mode = "n", lhs = "/", rhs = function() vim.cmd.HopPattern() end, opts = { silent = true } }, + }, + }, + + { + src = "https://github.com/mizlan/iswap.nvim", + keys = { + { mode = "n", lhs = "gs", rhs = function() vim.cmd.ISwap() end, opts = { silent = true } }, + { mode = "n", lhs = "gS", rhs = function() vim.cmd.ISwapWith() end, opts = { silent = true } }, + }, + }, + + { + src = "https://github.com/machakann/vim-sandwich", + event = "BufReadPost", + setup = function() + vim.cmd([[runtime macros/sandwich/keymap/surround.vim]]) + end, + }, + + { + src = "https://github.com/monaqa/dial.nvim", + setup = function() + local augend = require("dial.augend") + require("dial.config").augends:register_group({ + default = { + augend.integer.alias.decimal_int, + augend.semver.alias.semver, + augend.constant.new({ + elements = { "true", "false" }, + word = true, + cyclic = true, + }), + augend.constant.new({ + elements = { "True", "False" }, + word = true, + cyclic = true, + }), + augend.constant.new({ + elements = { "&&", "||" }, + word = false, + cyclic = true, + }), + }, + visual = { + augend.integer.new({ + radix = 16, + prefix = "0x", + natural = true, + case = "upper", + }), + }, + }) + vim.keymap.set("n", "", require("dial.map").inc_normal(), { silent = true }) + vim.keymap.set("v", "", require("dial.map").inc_visual(), { silent = true }) + vim.keymap.set("n", "", require("dial.map").dec_normal(), { silent = true }) + vim.keymap.set("v", "", require("dial.map").dec_visual(), { silent = true }) + end, + }, + + { + src = "https://github.com/ram02z/hydra.nvim", + setup = function() + require("modules.hydra") + end, + }, + + { + src = "https://github.com/sindrets/winshift.nvim", + setup = function() + require("winshift").setup() + end, + }, + + { + src = "https://github.com/mg979/vim-visual-multi", + setup = function() + vim.g.VM_set_statusline = 0 + end, + }, + + { + src = "https://github.com/booperlv/nvim-gomove", + setup = function() + require("gomove").setup() + end, + }, + + { + src = "https://github.com/karb94/neoscroll.nvim", + event = "BufReadPost", + setup = function() + require("neoscroll").setup() + end, + }, + + { + src = "https://github.com/nacro90/numb.nvim", + event = "CmdlineEnter", + setup = function() + require("numb").setup({ show_cursorline = true }) + end, + }, + + { + pack = "nvim.undotree", + keys = { + { + mode = "n", + lhs = "ut", + rhs = function() + require("undotree").open({ command = "40vnew" }) + end, + opts = { silent = true }, + }, }, + setup = function() + require("utils.keychord").cancel("u") + end, + }, + + { + src = "https://github.com/romainl/vim-cool", + event = "InsertEnter,CmdlineEnter", }, -}) +}) \ No newline at end of file diff --git a/dot_config/nvim/plugin/60-mappings.lua b/dot_config/nvim/plugin/60-mappings.lua index 83fb77c7..6617c0bd 100644 --- a/dot_config/nvim/plugin/60-mappings.lua +++ b/dot_config/nvim/plugin/60-mappings.lua @@ -37,16 +37,6 @@ K.set("v", "", ">gv") K.set("n", "k", "v:count == 0 ? 'gk' : 'k'", { silent = true, expr = true }) K.set("n", "j", "v:count == 0 ? 'gj' : 'j'", { silent = true, expr = true }) --- Insert blankline -K.set("n", "(BlankDown)", ":exe utils#blank_down()", { silent = true }) -K.set("n", "o", ":exe utils#blank_down()", { silent = true }) - -K.set("n", "(BlankUp)", ":exe utils#blank_up()", { silent = true }) -K.set("n", "O", ":exe utils#blank_up()", { silent = true }) - --- Leave terminal mode -K.set("t", "", "", { silent = true }) - -- Zero toggles between itself and ^ K.set("", "0", "getline('.')[0 : col('.') - 2] =~# '^\\s\\+$' ? '0' : '^'", { silent = true, expr = true }) @@ -59,3 +49,12 @@ K.set("n", "w", "lua require('utils.window').pick()", { silent -- Toggle lists K.set("n", "]", "lua require('utils.misc').toggle_qf()", { silent = true }) K.set("n", "[", "lua require('utils.misc').toggle_loc()", { silent = true }) + +-- Completion toggle +K.set('i', '', function() + if vim.fn.pumvisible() == 1 then + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('', true, false, true), 'n', false) + else + vim.lsp.completion.get() + end +end, { silent = true }) From 364a13646067334203e0d11bfdc2541c90a252bb Mon Sep 17 00:00:00 2001 From: Omar Zeghouani Date: Sun, 12 Apr 2026 01:32:57 +0100 Subject: [PATCH 2/3] Add lock file --- dot_config/nvim/nvim-pack-lock.json | 169 +++++++++++++++++++++ dot_config/nvim/plugin/41-autocommands.lua | 3 +- 2 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 dot_config/nvim/nvim-pack-lock.json diff --git a/dot_config/nvim/nvim-pack-lock.json b/dot_config/nvim/nvim-pack-lock.json new file mode 100644 index 00000000..6ddb7f95 --- /dev/null +++ b/dot_config/nvim/nvim-pack-lock.json @@ -0,0 +1,169 @@ +{ + "plugins": { + "LuaSnip": { + "rev": "a62e1083a3cfe8b6b206e7d3d33a51091df25357", + "src": "https://github.com/L3MON4D3/LuaSnip" + }, + "chezmoi.vim": { + "rev": "73b30df35c6b645ebd2e6a440eea8463ef3c3f47", + "src": "https://github.com/alker0/chezmoi.vim" + }, + "conform.nvim": { + "rev": "086a40dc7ed8242c03be9f47fbcee68699cc2395", + "src": "https://github.com/stevearc/conform.nvim" + }, + "dial.nvim": { + "rev": "f2634758455cfa52a8acea6f142dcd6271a1bf57", + "src": "https://github.com/monaqa/dial.nvim" + }, + "emmylua-nvim": { + "rev": "694dc07bdb5bc233b1a5f585fa894bb411ff3754", + "src": "https://github.com/ii14/emmylua-nvim" + }, + "feline.nvim": { + "rev": "3587f57480b88e8009df7b36dc84e9c7ff8f2c49", + "src": "https://github.com/feline-nvim/feline.nvim" + }, + "fidget.nvim": { + "rev": "889e2e96edef4e144965571d46f7a77bcc4d0ddf", + "src": "https://github.com/j-hui/fidget.nvim" + }, + "friendly-snippets": { + "rev": "6cd7280adead7f586db6fccbd15d2cac7e2188b9", + "src": "https://github.com/rafamadriz/friendly-snippets" + }, + "git-conflict.nvim": { + "rev": "a1badcd070d176172940eb55d9d59029dad1c5a6", + "src": "https://github.com/akinsho/git-conflict.nvim" + }, + "gitsigns.nvim": { + "rev": "8d82c240f190fc33723d48c308ccc1ed8baad69d", + "src": "https://github.com/lewis6991/gitsigns.nvim" + }, + "hop.nvim": { + "rev": "1a1eceafe54b5081eae4cb91c723abd1d450f34b", + "src": "https://github.com/phaazon/hop.nvim" + }, + "hover.nvim": { + "rev": "e73c00da3a9c87a21d2a8ddf7ab4a39824bd5d56", + "src": "https://github.com/lewis6991/hover.nvim" + }, + "hydra.nvim": { + "rev": "eaf0f029a3390501c31ca08a94fda1cedc18292e", + "src": "https://github.com/ram02z/hydra.nvim" + }, + "iswap.nvim": { + "rev": "d828a3adb2e21d4fc0b264b55059402aaff1f08a", + "src": "https://github.com/mizlan/iswap.nvim" + }, + "lsp_lines.nvim": { + "rev": "a92c755f182b89ea91bd8a6a2227208026f27b4d", + "src": "https://git.sr.ht/~whynothugo/lsp_lines.nvim" + }, + "matchparen.nvim": { + "rev": "1a2dcbd026bf99b20b89345883d54823f80a2bee", + "src": "https://github.com/monkoose/matchparen.nvim" + }, + "mini.misc": { + "rev": "c72c90e083bcf24bfb2827d63b4752e414023f3e", + "src": "https://github.com/nvim-mini/mini.misc" + }, + "neoscroll.nvim": { + "rev": "c8d29979cb0cb3a2437a8e0ae683fd82f340d3b8", + "src": "https://github.com/karb94/neoscroll.nvim" + }, + "nnn.vim": { + "rev": "e0104e369508fc12e3651ad4dee20261b5b3e87f", + "src": "https://github.com/mcchrish/nnn.vim" + }, + "numb.nvim": { + "rev": "12ef3913dea8727d4632c6f2ed47957a993de627", + "src": "https://github.com/nacro90/numb.nvim" + }, + "nvim-dap": { + "rev": "45a69eba683a2c448dd9ecfc4de89511f0646b5f", + "src": "https://github.com/mfussenegger/nvim-dap" + }, + "nvim-gomove": { + "rev": "2b44ae7ac0804f4e3959228122f7c85bef1964e3", + "src": "https://github.com/booperlv/nvim-gomove" + }, + "nvim-lightbulb": { + "rev": "e974b1a93c917c840545f51b9a66cfd72c520522", + "src": "https://github.com/kosayoda/nvim-lightbulb" + }, + "nvim-lint": { + "rev": "eab58b48eb11d7745c11c505e0f3057165902461", + "src": "https://github.com/mfussenegger/nvim-lint" + }, + "nvim-lspconfig": { + "rev": "cb5bc0b2b35a6d513e3298d285db81453e791f4f", + "src": "https://github.com/neovim/nvim-lspconfig" + }, + "nvim-osc52": { + "rev": "04cfaba1865ae5c53b6f887c3ca7304973824fb2", + "src": "https://github.com/ojroques/nvim-osc52" + }, + "nvim-spider": { + "rev": "af2f73ffd62e61a091b3503845b7704d76d81d95", + "src": "https://github.com/chrisgrieser/nvim-spider" + }, + "nvim-treehopper": { + "rev": "e3861c0231631c6af317d6746bb78fdb428a58f3", + "src": "https://github.com/mfussenegger/nvim-treehopper" + }, + "nvim-treesitter": { + "rev": "4916d6592ede8c07973490d9322f187e07dfefac", + "src": "https://github.com/nvim-treesitter/nvim-treesitter", + "version": "'main'" + }, + "nvim-web-devicons": { + "rev": "c72328a5494b4502947a022fe69c0c47e53b6aa6", + "src": "https://github.com/kyazdani42/nvim-web-devicons" + }, + "plenary.nvim": { + "rev": "74b06c6c75e4eeb3108ec01852001636d85a932b", + "src": "https://github.com/nvim-lua/plenary.nvim" + }, + "schemastore.nvim": { + "rev": "f5df9e70403b5d4c0642702a64534f04f3d71d03", + "src": "https://github.com/b0o/schemastore.nvim" + }, + "symbol-usage.nvim": { + "rev": "6a449e6b37be61a110606e9a67a7a308774f120f", + "src": "https://github.com/Wansmer/symbol-usage.nvim" + }, + "telescope-fzf-native.nvim": { + "rev": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c", + "src": "https://github.com/nvim-telescope/telescope-fzf-native.nvim" + }, + "telescope-ui-select.nvim": { + "rev": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2", + "src": "https://github.com/nvim-telescope/telescope-ui-select.nvim" + }, + "telescope.nvim": { + "rev": "f7c673b8e46e8f233ff581d3624a517d33a7e264", + "src": "https://github.com/nvim-telescope/telescope.nvim" + }, + "vim-cool": { + "rev": "9ea940c0d537e55de0de4c0298c04b976960fb12", + "src": "https://github.com/romainl/vim-cool" + }, + "vim-repeat": { + "rev": "65846025c15494983dafe5e3b46c8f88ab2e9635", + "src": "https://github.com/tpope/vim-repeat" + }, + "vim-sandwich": { + "rev": "74cf93d58ccc567d8e2310a69860f1b93af19403", + "src": "https://github.com/machakann/vim-sandwich" + }, + "vim-visual-multi": { + "rev": "a6975e7c1ee157615bbc80fc25e4392f71c344d4", + "src": "https://github.com/mg979/vim-visual-multi" + }, + "winshift.nvim": { + "rev": "37468ed6f385dfb50402368669766504c0e15583", + "src": "https://github.com/sindrets/winshift.nvim" + } + } +} diff --git a/dot_config/nvim/plugin/41-autocommands.lua b/dot_config/nvim/plugin/41-autocommands.lua index c462d280..2aeac4e5 100644 --- a/dot_config/nvim/plugin/41-autocommands.lua +++ b/dot_config/nvim/plugin/41-autocommands.lua @@ -59,8 +59,7 @@ vim.api.nvim_create_autocmd("FileType", { local ft = vim.bo[args.buf].filetype local lang = vim.treesitter.language.get_lang(ft) - -- Check if the language mapping exists AND if the parser is installed - if lang and vim.treesitter.query.get(lang, "highlights") then + if lang and vim.treesitter.language.add(lang) then pcall(vim.treesitter.start, args.buf, lang) end end, From 728292aaaaf95e29eec49e72636a780ddbcb0d8b Mon Sep 17 00:00:00 2001 From: Omar Zeghouani Date: Sun, 12 Apr 2026 13:10:14 +0100 Subject: [PATCH 3/3] Lazy load --- dot_config/nvim/init.lua | 1 - dot_config/nvim/lua/modules/gitsigns/init.lua | 54 ++++ dot_config/nvim/lua/modules/hydra/debug.lua | 42 +++ .../nvim/lua/modules/{ => hydra}/gitsigns.lua | 68 +---- dot_config/nvim/lua/modules/hydra/init.lua | 1 - .../nvim/lua/modules/hydra/telescope.lua | 47 +++ dot_config/nvim/lua/modules/hydra/window.lua | 4 +- .../nvim/lua/modules/language/debuggers.lua | 40 --- .../lua/modules/language/servers.lua.tmpl | 30 +- dot_config/nvim/lua/modules/snippets.lua | 267 +----------------- .../nvim/lua/modules/telescope/init.lua | 52 +--- dot_config/nvim/lua/utils/misc.lua | 4 + dot_config/nvim/nvim-pack-lock.json | 6 +- dot_config/nvim/plugin/30-settings.lua.tmpl | 18 -- dot_config/nvim/plugin/41-autocommands.lua | 11 +- dot_config/nvim/plugin/50-plugins.lua | 181 ++++++++++-- dot_config/nvim/plugin/70-diagnostic.lua | 3 - 17 files changed, 346 insertions(+), 483 deletions(-) create mode 100644 dot_config/nvim/lua/modules/gitsigns/init.lua create mode 100644 dot_config/nvim/lua/modules/hydra/debug.lua rename dot_config/nvim/lua/modules/{ => hydra}/gitsigns.lua (63%) delete mode 100644 dot_config/nvim/lua/modules/hydra/init.lua create mode 100644 dot_config/nvim/lua/modules/hydra/telescope.lua diff --git a/dot_config/nvim/init.lua b/dot_config/nvim/init.lua index a77ae338..eacab15f 100644 --- a/dot_config/nvim/init.lua +++ b/dot_config/nvim/init.lua @@ -1,5 +1,4 @@ local function disable_default_plugins() - -- FIXME: WSL register bug vim.g.loaded_clipboard_provider = 1 vim.g.loaded_matchit = 1 vim.g.loaded_matchparen = 1 diff --git a/dot_config/nvim/lua/modules/gitsigns/init.lua b/dot_config/nvim/lua/modules/gitsigns/init.lua new file mode 100644 index 00000000..c17666ba --- /dev/null +++ b/dot_config/nvim/lua/modules/gitsigns/init.lua @@ -0,0 +1,54 @@ +local gitsigns = require("gitsigns") + +gitsigns.setup({ + numhl = false, + linehl = false, + on_attach = function(bufnr) + local function map(mode, l, r, opts) + opts = opts or {} + opts.buffer = bufnr + vim.keymap.set(mode, l, r, opts) + end + + -- Navigation + map("n", "]g", function() + if vim.wo.diff then + return "]g" + end + vim.schedule(function() + gitsigns.next_hunk() + end) + return "" + end, { expr = true }) + map("n", "[g", function() + if vim.wo.diff then + return "[g" + end + vim.schedule(function() + gitsigns.prev_hunk() + end) + return "" + end, { expr = true }) + + -- Text object + map({ "o", "x" }, "ig", ":Gitsigns select_hunk") + end, + watch_gitdir = { + interval = 1000, + follow_files = true, + }, + current_line_blame = false, + current_line_blame_opts = { + delay = 0, + }, + sign_priority = 6, + update_debounce = 100, + status_formatter = nil, + word_diff = false, + diff_opts = { + algorithm = "myers", + internal = true, + indent_heuristic = true, + linematch = true, + }, +}) \ No newline at end of file diff --git a/dot_config/nvim/lua/modules/hydra/debug.lua b/dot_config/nvim/lua/modules/hydra/debug.lua new file mode 100644 index 00000000..fdaec271 --- /dev/null +++ b/dot_config/nvim/lua/modules/hydra/debug.lua @@ -0,0 +1,42 @@ +local hydra = require("hydra") +local dap = require("dap") + +local hint = [[ + ^ ^Step^ ^ ^ ^ ^ Action +----^-^-^-^--^-^---- ^-^------------------- + ^ ^back^ ^ ^ ^_t_: toggle breakpoint + ^ ^ _K_^ ^ _T_: clear breakpoints +out _H_ ^ ^ _L_ into _c_: continue + ^ ^ _J_ ^ ^ _x_: terminate + ^ ^over ^ ^ ^^_r_: open repl + + ^ ^ _q_: exit +]] + +local debug_hydra = hydra({ + name = "Debug", + hint = hint, + config = { + color = "pink", + invoke_on_body = true, + hint = { + type = "window", + }, + }, + mode = { "n" }, + body = "s", + heads = { + { "H", dap.step_out, { desc = "step out" } }, + { "J", dap.step_over, { desc = "step over" } }, + { "K", dap.step_back, { desc = "step back" } }, + { "L", dap.step_into, { desc = "step into" } }, + { "t", dap.toggle_breakpoint, { desc = "toggle breakpoint" } }, + { "T", dap.clear_breakpoints, { desc = "clear breakpoints" } }, + { "c", dap.continue, { desc = "continue" } }, + { "x", dap.terminate, { desc = "terminate" } }, + { "r", dap.repl.open, { exit = true, desc = "open repl" } }, + { "q", nil, { exit = true, nowait = true, desc = "exit" } }, + }, +}) + +return debug_hydra \ No newline at end of file diff --git a/dot_config/nvim/lua/modules/gitsigns.lua b/dot_config/nvim/lua/modules/hydra/gitsigns.lua similarity index 63% rename from dot_config/nvim/lua/modules/gitsigns.lua rename to dot_config/nvim/lua/modules/hydra/gitsigns.lua index 436368b1..1c92c489 100644 --- a/dot_config/nvim/lua/modules/gitsigns.lua +++ b/dot_config/nvim/lua/modules/hydra/gitsigns.lua @@ -1,6 +1,4 @@ -local gitsigns = require("gitsigns") - -local Hydra = require("hydra") +local hydra = require("hydra") local gitsigns = require("gitsigns") local hint = [[ @@ -10,7 +8,8 @@ local hint = [[ ^ ^ ^ _q_: exit ]] -Hydra({ + +local gitsigns_hydra = hydra({ name = "Git", hint = hint, config = { @@ -23,14 +22,18 @@ Hydra({ }, }, on_enter = function() - vim.cmd("mkview") + if vim.fn.bufname() ~= "" then + vim.cmd("mkview") + end vim.cmd("silent! %foldopen!") vim.bo.modifiable = true gitsigns.toggle_linehl(true) end, on_exit = function() local cursor_pos = vim.api.nvim_win_get_cursor(0) - vim.cmd("loadview") + if vim.fn.bufname() ~= "" then + vim.cmd("loadview") + end vim.api.nvim_win_set_cursor(0, cursor_pos) vim.cmd("normal zv") gitsigns.toggle_linehl(false) @@ -84,55 +87,4 @@ Hydra({ }, }) -gitsigns.setup({ - numhl = false, - linehl = false, - on_attach = function(bufnr) - local function map(mode, l, r, opts) - opts = opts or {} - opts.buffer = bufnr - vim.keymap.set(mode, l, r, opts) - end - - -- Navigation - map("n", "]g", function() - if vim.wo.diff then - return "]g" - end - vim.schedule(function() - gitsigns.next_hunk() - end) - return "" - end, { expr = true }) - map("n", "[g", function() - if vim.wo.diff then - return "[g" - end - vim.schedule(function() - gitsigns.prev_hunk() - end) - return "" - end, { expr = true }) - - -- Text object - map({ "o", "x" }, "ig", ":Gitsigns select_hunk") - end, - watch_gitdir = { - interval = 1000, - follow_files = true, - }, - current_line_blame = false, - current_line_blame_opts = { - delay = 0, - }, - sign_priority = 6, - update_debounce = 100, - status_formatter = nil, -- Use default - word_diff = false, - diff_opts = { - algorithm = "myers", - internal = true, - indent_heuristic = true, - linematch = true, - }, -}) +return gitsigns_hydra \ No newline at end of file diff --git a/dot_config/nvim/lua/modules/hydra/init.lua b/dot_config/nvim/lua/modules/hydra/init.lua deleted file mode 100644 index f9919ea0..00000000 --- a/dot_config/nvim/lua/modules/hydra/init.lua +++ /dev/null @@ -1 +0,0 @@ -require("modules.hydra.window") diff --git a/dot_config/nvim/lua/modules/hydra/telescope.lua b/dot_config/nvim/lua/modules/hydra/telescope.lua new file mode 100644 index 00000000..8c7fe39e --- /dev/null +++ b/dot_config/nvim/lua/modules/hydra/telescope.lua @@ -0,0 +1,47 @@ +local hydra = require("hydra") +local tscope = require("modules.telescope.functions") + +local function cmd(command) + return table.concat({ "", command, "" }) +end + +local hint = [[ + _g_: git status _l_: live grep _h_: highlights _r_: old files + _s_: spell suggest _c_: commands _k_: keymaps _b_: buffers + _o_: live grep open _a_: autocommands _m_: help tags + ^ + ^ ^ __: Resume ^ ^ _?_: all ^ ^ __ +]] + +local telescope_hydra = hydra({ + hint = hint, + config = { + invoke_on_body = true, + color = "teal", + hint = { + float_opts = { + border = "rounded", + }, + }, + }, + mode = "n", + body = "p", + heads = { + { "g", cmd("Telescope git_status") }, + { "l", cmd("Telescope live_grep") }, + { "h", cmd("Telescope highlights") }, + { "r", cmd("Telescope oldfiles") }, + { "s", cmd("Telescope spell_suggest theme=get_cursor layout_config={height=6}"), desc = "Spell suggest" }, + { "c", tscope.commands }, + { "k", tscope.keymaps }, + { "b", cmd("Telescope buffers") }, + { "o", cmd("Telescope live_grep grep_open_files=true"), desc = "Grep only open files" }, + { "a", cmd("Telescope autocommands") }, + { "m", cmd("Telescope help_tags") }, + { "", cmd("Telescope resume") }, + { "?", cmd("Telescope"), desc = "List all pickers" }, + { "", nil, { nowait = true } }, + }, +}) + +return telescope_hydra \ No newline at end of file diff --git a/dot_config/nvim/lua/modules/hydra/window.lua b/dot_config/nvim/lua/modules/hydra/window.lua index ab834a09..73780b1d 100644 --- a/dot_config/nvim/lua/modules/hydra/window.lua +++ b/dot_config/nvim/lua/modules/hydra/window.lua @@ -2,7 +2,7 @@ local hydra = require("hydra") local cmd = require("hydra.keymap-util").cmd local pcmd = require("hydra.keymap-util").pcmd -hydra({ +local window_hydra = hydra({ hint = [[ ^^^^^^ Move ^^^^^^ ^^ Split ^^^^ Size ^^^^^^--------------^^^^^^ ^^--------------- ^^^^------------- @@ -53,3 +53,5 @@ hydra({ { "", nil, { exit = true } }, }, }) + +return window_hydra diff --git a/dot_config/nvim/lua/modules/language/debuggers.lua b/dot_config/nvim/lua/modules/language/debuggers.lua index 7485c4e1..d0d91331 100644 --- a/dot_config/nvim/lua/modules/language/debuggers.lua +++ b/dot_config/nvim/lua/modules/language/debuggers.lua @@ -1,45 +1,6 @@ local M = {} local dap = require("dap") -local setup_hydra = function() - local hint = [[ - ^ ^Step^ ^ ^ ^ ^ Action - ----^-^-^-^--^-^---- ^-^------------------- - ^ ^back^ ^ ^ ^_t_: toggle breakpoint - ^ ^ _K_^ ^ _T_: clear breakpoints - out _H_ ^ ^ _L_ into _c_: continue - ^ ^ _J_ ^ ^ _x_: terminate - ^ ^over ^ ^ ^^_r_: open repl - - ^ ^ _q_: exit - ]] - require("hydra")({ - name = "Debug", - hint = hint, - config = { - color = "pink", - invoke_on_body = true, - hint = { - type = "window", - }, - }, - mode = { "n" }, - body = "s", - heads = { - { "H", dap.step_out, { desc = "step out" } }, - { "J", dap.step_over, { desc = "step over" } }, - { "K", dap.step_back, { desc = "step back" } }, - { "L", dap.step_into, { desc = "step into" } }, - { "t", dap.toggle_breakpoint, { desc = "toggle breakpoint" } }, - { "T", dap.clear_breakpoints, { desc = "clear breakpoints" } }, - { "c", dap.continue, { desc = "continue" } }, - { "x", dap.terminate, { desc = "terminate" } }, - { "r", dap.repl.open, { exit = true, desc = "open repl" } }, - { "q", nil, { exit = true, nowait = true, desc = "exit" } }, - }, - }) -end - M.setup = function() dap.adapters.python = function(cb, config) if config.request == "attach" then @@ -84,7 +45,6 @@ M.setup = function() end, }, } - setup_hydra() end return M diff --git a/dot_config/nvim/lua/modules/language/servers.lua.tmpl b/dot_config/nvim/lua/modules/language/servers.lua.tmpl index a9016ada..35acf8fd 100644 --- a/dot_config/nvim/lua/modules/language/servers.lua.tmpl +++ b/dot_config/nvim/lua/modules/language/servers.lua.tmpl @@ -55,16 +55,6 @@ html = {}, cssls = {}, {{- $servers = add1 $servers -}} {{- end }} -{{ if lookPath "vscode-json-language-server" -}} -jsonls = { - settings = { - json = { - schemas = require("schemastore").json.schemas(), - }, - }, -}, -{{- $servers = add1 $servers -}} -{{- end }} {{ if lookPath "vscode-eslint-language-server" -}} eslint = {}, {{- $servers = add1 $servers -}} @@ -162,6 +152,26 @@ vim.api.nvim_create_autocmd("LspAttach", { end }) +{{ if lookPath "vscode-json-language-server" -}} +vim.api.nvim_create_autocmd("FileType", { + pattern = { "json", "jsonc" }, + group = vim.api.nvim_create_augroup("jsonls_lazy", { clear = true }), + desc = "Enable jsonls with schemas on JSON file open", + once = true, + callback = function() + local schemas = require("schemastore").json.schemas() + vim.lsp.config("jsonls", { + settings = { + json = { + schemas = schemas, + }, + }, + }) + vim.lsp.enable("jsonls") + end, +}) +{{- end }} + function M.setup() {{ if gt $servers 0 -}} vim.lsp.config("*", { diff --git a/dot_config/nvim/lua/modules/snippets.lua b/dot_config/nvim/lua/modules/snippets.lua index 22447e0a..aeb8a7e8 100644 --- a/dot_config/nvim/lua/modules/snippets.lua +++ b/dot_config/nvim/lua/modules/snippets.lua @@ -1,18 +1,10 @@ local ls = require("luasnip") local s = ls.s -local sn = ls.snippet_node local t = ls.t local i = ls.i -local d = ls.dynamic_node -local m = require("luasnip.extras").match -local r = require("luasnip.extras").rep --- TODO: use treesitter to for pairs --- ref tabout.nvim for inspiration local function char_count_nequal(c1, c2) local line = vim.api.nvim_get_current_line() - -- '%'-escape chars to force explicit match (gsub accepts patterns). - -- second return value is number of substitutions. local _, ct1 = string.gsub(line, "%" .. c1, "") local _, ct2 = string.gsub(line, "%" .. c2, "") return ct1 ~= ct2 @@ -24,10 +16,7 @@ local function odd_count(ch) return ct % 2 ~= 0 end --- This makes creation of pair-type snippets easier. local function pair(pair_begin, pair_end, ...) - -- triggerd by opening part of pair, wordTrig=false to trigger anywhere. - -- ... is used to pass any args following the expand_func to it. return s({ trig = pair_begin, wordTrig = false }, { t({ pair_begin }), i(1), @@ -49,28 +38,6 @@ ls.config.set_config({ ft_func = require("luasnip.extras.filetype_functions").from_pos_or_filetype, }) -vim.keymap.set({ "i", "s" }, "", function() - local utils = require("utils.misc") - if require("utils.misc").invalid_prev_col() then - vim.fn.feedkeys(utils.t(""), "n") - elseif ls.expand_or_locally_jumpable() then - ls.expand_or_jump() - else - vim.fn.feedkeys(utils.t(""), "n") - end -end, { desc = "Expand/jump snippet or tab" }) - -vim.keymap.set({ "i", "s" }, "", function() - local utils = require("utils.misc") - if ls.jumpable(-1) then - ls.jump(-1) - else - vim.fn.feedkeys(utils.t(""), "n") - end -end, { desc = "Jump to last snippet or shift tab" }) - -vim.keymap.set({ "i", "s" }, "", "luasnip-next-choice") - ls.add_snippets(nil, { all = { pair("(", ")", { condition = partial(char_count_nequal, "(", ")") }), @@ -80,228 +47,30 @@ ls.add_snippets(nil, { pair("'", "'", { condition = partial(odd_count, "'") }), pair('"', '"', { condition = partial(odd_count, '"') }), pair("`", "`", { condition = partial(odd_count, "`") }), - -- Expands to [\t\n] s({ trig = "[;", wordTrig = false }, { t({ "[", "\t" }), i(1), t({ "", "]" }), i(0), }), - -- Expands to (\t\n) s({ trig = "(;", wordTrig = false }, { t({ "(", "\t" }), i(1), t({ "", ")" }), i(0), }), - -- Expands to {\t\n} s({ trig = "{;", wordTrig = false }, { t({ "{", "\t" }), i(1), t({ "", "}" }), i(0), }), - -- Expands to {\t\n}, s({ trig = "{,;", wordTrig = false }, { t({ "{", "\t" }), i(1), t({ "", "}," }), i(0), - }), - ls.parser.parse_snippet({ trig = "date;", wordTrig = true }, os.date("%d %B %Y")), - ls.parser.parse_snippet({ trig = "time;", wordTrig = true }, os.date("%H:%M")), - ls.parser.parse_snippet({ trig = "datetime;", wordTrig = true }, os.date("%d-%m-%Y %H:%M")), - }, - norg = { - pair("/", "/", { condition = partial(odd_count, "/") }), - pair("_", "_", { condition = partial(odd_count, "_") }), - pair("*", "*", { condition = partial(odd_count, "*") }), - pair("#", "#", { condition = partial(odd_count, "#") }), - }, - lua = { - s("if", { - t({ "if " }), - i(1), - t({ " then", "\t" }), - i(2), - t({ "", "end" }), - i(0), - }), - s("el", { - t({ "else", "\t" }), - i(0), - }), - s("eli", { - t({ "elseif " }), - i(1), - t({ " then", "\t" }), - i(0), - }), - }, - lean3 = { - -- s("\\and", { - -- t({ "∧" }), - -- i(0), - -- }), - -- s("\\or", { - -- t({ "∨" }), - -- i(0), - -- }), - -- s("\\->", { - -- t({ "→" }), - -- i(0), - -- }), - -- s("\\neg", { - -- t({ "¬" }), - -- i(0), - -- }), - -- s("\\<->", { - -- t({ "↔" }), - -- i(0), - -- }), - s("begin", { - t({ "begin", "\t" }), - i(0), - t({ "", "end" }), - }), - s("theorem", { - t({ "theorem " }), - i(1, "I"), - t({ " : " }), - i(2), - t({ " :=", "" }), - i(0), - }), - s("example", { - t({ "example " }), - t({ " : " }), - i(1), - t({ " :=", "" }), - i(0), - }), - }, - c = { - s("if", { - t({ "if (" }), - i(1), - t({ ") {", "\t" }), - i(2), - t({ "", "}" }), - i(0), - }), - s("el", { - t({ "else {", "\t" }), - i(1), - t({ "", "}" }), - i(0), - }), - s("eli", { - t({ "else if (" }), - i(1), - t({ ") {", "\t" }), - i(2), - t({ "", "}" }), - i(0), - }), - s("#inc", { - t({ "#include " }), - i(0), - }), - s("#def", { - t({ "#define " }), - i(0), - }), - s("main", { - t({ "int main (int argc, char *argv[])", "" }), - t({ "{", "\t" }), - i(1), - t({ "", "}" }), - i(0), - }), - s("ret", { - t({ "return " }), - i(1), - t({ ";" }), - i(0), - }), - s("pf", { - t({ "printf(" }), - i(1), - t(");"), - i(0), - }), - s("sf", { - t({ "scanf(" }), - i(1), - t(");"), - i(0), - }), - s("for", { - t({ "for (" }), - i(1), - t({ "; " }), - i(2), - t({ "; " }), - i(3), - t({ ") {", "\t" }), - i(4), - t({ "", "}" }), - i(0), - }), - s("fori", { - t({ "for (" }), - i(1, "i"), - t({ " = " }), - i(2, "0"), - t({ "; " }), - r(1), - i(3, " < num"), - t({ "; " }), - r(1), - i(4, "++"), - t({ ") {", "\t" }), - i(5), - t({ "", "}" }), - i(0), - }), - s("struct", { - t({ "struct " }), - i(1), - t({ " {", "\t" }), - i(2), - t({ "", "}" }), - i(3), - t({ ";" }), - i(0), - }), - s("enum", { - t({ "enum " }), - i(1), - t({ " {", "\t" }), - i(2), - t({ "", "};" }), - i(0), - }), - s("switch", { - t({ "switch (" }), - i(1), - t({ ") {", "\t" }), - i(2), - t({ "", "}" }), - i(0), - }), - }, - cpp = { - s("class", { - t({ "class " }), - i(1), - t({ " {", "\t" }), - i(2), - t({ "", "}" }), - i(3), - t({ ";" }), - i(0), - }), + }) }, python = { s({ trig = '"""', wordTrig = false }, { @@ -310,41 +79,9 @@ ls.add_snippets(nil, { t({ '"""' }), }), }, - markdown_inline = { - s({ trig = "table(%d+)x(%d+)", regTrig = true }, { - d(1, function(args, snip) - local nodes = {} - local i_counter = 0 - local hlines = "" - for _ = 1, snip.captures[2] do - i_counter = i_counter + 1 - table.insert(nodes, t("| ")) - table.insert(nodes, i(i_counter, "Column" .. i_counter)) - table.insert(nodes, t(" ")) - hlines = hlines .. "|---" - end - table.insert(nodes, t({ "|", "" })) - hlines = hlines .. "|" - table.insert(nodes, t({ hlines, "" })) - for _ = 1, snip.captures[1] do - for _ = 1, snip.captures[2] do - i_counter = i_counter + 1 - table.insert(nodes, t("| ")) - table.insert(nodes, i(i_counter)) - print(i_counter) - table.insert(nodes, t(" ")) - end - table.insert(nodes, t({ "|", "" })) - end - return sn(nil, nodes) - end), - }), - }, }) --- in a cpp file: search c-snippets, then all-snippets only (no cpp-snippets!!). ls.filetype_set("cpp", { "c", "cpp" }) require("luasnip/loaders/from_vscode").lazy_load({ paths = { "~/.config/nvim/snippets/" } }) --- friendly-snippets -require("luasnip/loaders/from_vscode").lazy_load({ include = { "html", "java", "python", "latex", "go" } }) +require("luasnip/loaders/from_vscode").lazy_load({ include = { "html", "java", "python", "latex", "go" } }) \ No newline at end of file diff --git a/dot_config/nvim/lua/modules/telescope/init.lua b/dot_config/nvim/lua/modules/telescope/init.lua index 68b1a4b8..90009673 100644 --- a/dot_config/nvim/lua/modules/telescope/init.lua +++ b/dot_config/nvim/lua/modules/telescope/init.lua @@ -1,5 +1,3 @@ --- Nvim-telescope config - local telescope = require("telescope") local actions = require("telescope.actions") @@ -59,52 +57,4 @@ local tscope_config = { }, } -telescope.setup(tscope_config) - -local hydra = require("hydra") -local tscope = require("modules.telescope.functions") -local cancel = require("utils.keychord").cancel -local function cmd(command) - return table.concat({ "", command, "" }) -end -local hint = [[ - _g_: git status _l_: live grep _h_: highlights _r_: old files - _s_: spell suggest _c_: commands _k_: keymaps _b_: buffers - _o_: live grep open _a_: autocommands _m_: help tags _d_: comments - ^ - ^ ^ __: Resume ^ ^ _?_: all ^ ^ __ -]] - -hydra({ - hint = hint, - config = { - invoke_on_body = true, - color = "teal", - hint = { - float_opts = { - border = "rounded", - }, - }, - }, - mode = "n", - body = "p", - heads = { - { "g", cmd("Telescope git_status") }, - { "l", cmd("Telescope live_grep") }, - { "h", cmd("Telescope highlights") }, - { "r", cmd("Telescope oldfiles") }, - { "s", cmd("Telescope spell_suggest theme=get_cursor layout_config={height=6}"), { desc = "Spell suggest" } }, - { "c", tscope.commands }, - { "k", tscope.keymaps }, - { "b", cmd("Telescope buffers") }, - { "o", cmd("Telescope live_grep grep_open_files=true"), { desc = "Grep only open files" } }, - { "a", cmd("Telescope autocommands") }, - { "m", cmd("Telescope help_tags") }, - { "d", cmd("Telescope dev_comments current") }, - { "", cmd("Telescope resume") }, - { "?", cmd("Telescope"), { desc = "List all pickers" } }, - { "", nil, { nowait = true } }, - }, -}) - -cancel("p") +telescope.setup(tscope_config) \ No newline at end of file diff --git a/dot_config/nvim/lua/utils/misc.lua b/dot_config/nvim/lua/utils/misc.lua index 18cbf760..48d48167 100644 --- a/dot_config/nvim/lua/utils/misc.lua +++ b/dot_config/nvim/lua/utils/misc.lua @@ -1,6 +1,10 @@ local M = {} local cmd = vim.api.nvim_command +M.t = function(str) + return vim.api.nvim_replace_termcodes(str, true, true, true) +end + -- Checks if prev col doesn't exist M.invalid_prev_col = function() local lnum, col_no = unpack(vim.api.nvim_win_get_cursor(0)) diff --git a/dot_config/nvim/nvim-pack-lock.json b/dot_config/nvim/nvim-pack-lock.json index 6ddb7f95..a41870e2 100644 --- a/dot_config/nvim/nvim-pack-lock.json +++ b/dot_config/nvim/nvim-pack-lock.json @@ -4,10 +4,6 @@ "rev": "a62e1083a3cfe8b6b206e7d3d33a51091df25357", "src": "https://github.com/L3MON4D3/LuaSnip" }, - "chezmoi.vim": { - "rev": "73b30df35c6b645ebd2e6a440eea8463ef3c3f47", - "src": "https://github.com/alker0/chezmoi.vim" - }, "conform.nvim": { "rev": "086a40dc7ed8242c03be9f47fbcee68699cc2395", "src": "https://github.com/stevearc/conform.nvim" @@ -126,7 +122,7 @@ "src": "https://github.com/nvim-lua/plenary.nvim" }, "schemastore.nvim": { - "rev": "f5df9e70403b5d4c0642702a64534f04f3d71d03", + "rev": "b2e84d00db4d5432f471d58898e796b478f075a7", "src": "https://github.com/b0o/schemastore.nvim" }, "symbol-usage.nvim": { diff --git a/dot_config/nvim/plugin/30-settings.lua.tmpl b/dot_config/nvim/plugin/30-settings.lua.tmpl index 57066290..0a9520aa 100644 --- a/dot_config/nvim/plugin/30-settings.lua.tmpl +++ b/dot_config/nvim/plugin/30-settings.lua.tmpl @@ -89,21 +89,3 @@ vim.opt.number = true vim.opt.relativenumber = true vim.opt.signcolumn = "yes:1" - -{{ if (eq .chezmoi.os "linux") -}} -{{ if .is_wsl -}} -{{ if lookPath "win32yank.exe" -}} -vim.g.clipyank = '{{ lookPath "win32yank.exe" }} -i --crlf' -{{ else -}} -vim.g.clipyank = '{{ lookPath "clip.exe" }}' -{{- end }} -{{ else if .is_wayland -}} -vim.g.clipyank = '{{ lookPath "wl-copy" }}' -{{ else if .is_x11 -}} -vim.g.clipyank = '{{ lookPath "xclip" }}' -{{ end }} -{{ else if (eq .chezmoi.os "windows") -}} -vim.g.clipyank = '{{ lookPath "clip.exe" }}' -{{ else if (eq .chezmoi.os "darwin") -}} -vim.g.clipyank = '{{ lookPath "pbcopy" }}' -{{- end }} diff --git a/dot_config/nvim/plugin/41-autocommands.lua b/dot_config/nvim/plugin/41-autocommands.lua index 2aeac4e5..6b90b60c 100644 --- a/dot_config/nvim/plugin/41-autocommands.lua +++ b/dot_config/nvim/plugin/41-autocommands.lua @@ -9,25 +9,26 @@ vim.api.nvim_create_autocmd("BufReadPost", { end, }) +local osc52_copy = require("vim.ui.clipboard.osc52").copy("+") + vim.api.nvim_create_autocmd("TextYankPost", { desc = "Flash the yanked text and copy it to the system clipboard", callback = function() if vim.v.event.operator == "y" and vim.v.event.regname == "" then vim.highlight.on_yank() - local status, osc52 = pcall(require, "osc52") - if status then - osc52.copy_register('"') - end + osc52_copy(vim.fn.getreg('"', 1, true), vim.fn.getregtype('"')) end end, }) vim.api.nvim_create_autocmd("BufEnter", { - desc = "Force consistent text-wrapping and list-formatting rules", + desc = "Set formatoptions and enable autocomplete for normal buffers", callback = function() -- t: wrap text, c: wrap comments, q: format comments, -- n: numbered lists, j: remove comment leaders on join vim.opt_local.formatoptions = "tcqnbj" + -- Enable autocomplete for normal file buffers + vim.bo.autocomplete = vim.bo.buftype == "" end, }) diff --git a/dot_config/nvim/plugin/50-plugins.lua b/dot_config/nvim/plugin/50-plugins.lua index 7dbe955d..6fd3e68b 100644 --- a/dot_config/nvim/plugin/50-plugins.lua +++ b/dot_config/nvim/plugin/50-plugins.lua @@ -1,4 +1,4 @@ -vim.pack.add({ 'https://github.com/nvim-mini/mini.misc' }) +vim.pack.add({ "https://github.com/nvim-mini/mini.misc" }) require("utils.pack").setup({ { @@ -14,10 +14,15 @@ require("utils.pack").setup({ { src = "https://git.sr.ht/~whynothugo/lsp_lines.nvim", + event = "LspAttach", + setup = function() + require("lsp_lines").setup() + end, }, { src = "https://github.com/j-hui/fidget.nvim", + event = "LspAttach", setup = function() require("fidget").setup({ notification = { @@ -32,6 +37,7 @@ require("utils.pack").setup({ { src = "https://github.com/Wansmer/symbol-usage.nvim", + event = "BufReadPre", setup = function() require("symbol-usage").setup({ hl = { link = "DiagnosticUnnecessary" } }) end, @@ -41,6 +47,9 @@ require("utils.pack").setup({ src = "https://github.com/mfussenegger/nvim-dap", setup = function() require("modules.language.debuggers").setup() + vim.keymap.set("n", "s", function() + require("modules.hydra.debug"):activate() + end, { desc = "Debug hydra" }) end, }, @@ -95,6 +104,44 @@ require("utils.pack").setup({ setup = function() require("modules.snippets") end, + keys = { + { + mode = "i", + lhs = "", + rhs = function() + local utils = require("utils.misc") + if require("utils.misc").invalid_prev_col() then + vim.fn.feedkeys(utils.t(""), "n") + elseif require("luasnip").expand_or_locally_jumpable() then + require("luasnip").expand_or_jump() + else + vim.fn.feedkeys(utils.t(""), "n") + end + end, + opts = { desc = "Expand/jump snippet or tab" }, + }, + { + mode = "i", + lhs = "", + rhs = function() + local utils = require("utils.misc") + if require("luasnip").jumpable(-1) then + require("luasnip").jump(-1) + else + vim.fn.feedkeys(utils.t(""), "n") + end + end, + opts = { desc = "Jump to last snippet or shift tab" }, + }, + { + mode = "i", + lhs = "", + rhs = function() + vim.fn.feedkeys(require("utils.misc").t("luasnip-next-choice"), "t") + end, + opts = { desc = "Next snippet choice" }, + }, + }, }, { @@ -148,22 +195,17 @@ require("utils.pack").setup({ end, }, - { - src = "https://github.com/ojroques/nvim-osc52", - }, - { src = "https://github.com/tpope/vim-repeat", }, - { - src = "https://github.com/alker0/chezmoi.vim", - }, - { src = "https://github.com/lewis6991/gitsigns.nvim", setup = function() require("modules.gitsigns") + vim.keymap.set("n", "g", function() + require("modules.hydra.gitsigns"):activate() + end, { desc = "Git hydra" }) end, }, @@ -208,16 +250,45 @@ require("utils.pack").setup({ { src = "https://github.com/nvim-telescope/telescope.nvim", setup = function() - vim.keymap.set("i", "", "Telescope registers theme=get_cursor layout_config={height=18}") - vim.keymap.set( - { "x", "n" }, - '"', - "Telescope registers theme=get_cursor layout_config={height=18}" - ) require("modules.telescope") require("telescope").load_extension("fzf") require("telescope").load_extension("ui-select") + require("utils.keychord").cancel("p") end, + keys = { + { + mode = "i", + lhs = "", + rhs = function() + vim.cmd("Telescope registers theme=get_cursor layout_config={height=18}") + end, + opts = { silent = true }, + }, + { + mode = "n", + lhs = '"', + rhs = function() + vim.cmd("Telescope registers theme=get_cursor layout_config={height=18}") + end, + opts = { silent = true }, + }, + { + mode = "x", + lhs = '"', + rhs = function() + vim.cmd("Telescope registers theme=get_cursor layout_config={height=18}") + end, + opts = { silent = true }, + }, + { + mode = "n", + lhs = "p", + rhs = function() + require("modules.hydra.telescope"):activate() + end, + opts = { desc = "Telescope" }, + }, + }, }, { @@ -249,16 +320,44 @@ require("utils.pack").setup({ require("hop").setup({ keys = "asdghklwertyuipzxcvbnmfj" }) end, keys = { - { mode = "n", lhs = ";", rhs = function() vim.cmd.HopWord() end, opts = { silent = true } }, - { mode = "n", lhs = "/", rhs = function() vim.cmd.HopPattern() end, opts = { silent = true } }, + { + mode = "n", + lhs = ";", + rhs = function() + vim.cmd.HopWord() + end, + opts = { silent = true }, + }, + { + mode = "n", + lhs = "/", + rhs = function() + vim.cmd.HopPattern() + end, + opts = { silent = true }, + }, }, }, { src = "https://github.com/mizlan/iswap.nvim", keys = { - { mode = "n", lhs = "gs", rhs = function() vim.cmd.ISwap() end, opts = { silent = true } }, - { mode = "n", lhs = "gS", rhs = function() vim.cmd.ISwapWith() end, opts = { silent = true } }, + { + mode = "n", + lhs = "gs", + rhs = function() + vim.cmd.ISwap() + end, + opts = { silent = true }, + }, + { + mode = "n", + lhs = "gS", + rhs = function() + vim.cmd.ISwapWith() + end, + opts = { silent = true }, + }, }, }, @@ -303,17 +402,49 @@ require("utils.pack").setup({ }), }, }) - vim.keymap.set("n", "", require("dial.map").inc_normal(), { silent = true }) - vim.keymap.set("v", "", require("dial.map").inc_visual(), { silent = true }) - vim.keymap.set("n", "", require("dial.map").dec_normal(), { silent = true }) - vim.keymap.set("v", "", require("dial.map").dec_visual(), { silent = true }) end, + keys = { + { + mode = "n", + lhs = "", + rhs = function() + require("dial.map").manipulate("increment", "normal") + end, + opts = { silent = true }, + }, + { + mode = "v", + lhs = "", + rhs = function() + require("dial.map").manipulate("increment", "visual") + end, + opts = { silent = true }, + }, + { + mode = "n", + lhs = "", + rhs = function() + require("dial.map").manipulate("decrement", "normal") + end, + opts = { silent = true }, + }, + { + mode = "v", + lhs = "", + rhs = function() + require("dial.map").manipulate("decrement", "visual") + end, + opts = { silent = true }, + }, + }, }, { src = "https://github.com/ram02z/hydra.nvim", setup = function() - require("modules.hydra") + vim.keymap.set("n", "", function() + require("modules.hydra.window"):activate() + end, { desc = "Window hydra" }) end, }, @@ -375,4 +506,4 @@ require("utils.pack").setup({ src = "https://github.com/romainl/vim-cool", event = "InsertEnter,CmdlineEnter", }, -}) \ No newline at end of file +}) diff --git a/dot_config/nvim/plugin/70-diagnostic.lua b/dot_config/nvim/plugin/70-diagnostic.lua index 7b71ec63..12a9898d 100644 --- a/dot_config/nvim/plugin/70-diagnostic.lua +++ b/dot_config/nvim/plugin/70-diagnostic.lua @@ -1,9 +1,6 @@ local M = {} local K = vim.keymap --- lsp_lines.nvim plugin -require("lsp_lines").setup() - -- Global config vim.diagnostic.config({ virtual_text = true,