From 693a0a7d159c54e262f928d7f22f5257185993bb Mon Sep 17 00:00:00 2001 From: Wessel Tip Date: Mon, 8 Sep 2025 10:48:06 +0200 Subject: [PATCH] feat: Add neovim config --- .gitignore | 6 +- nvim/init.lua | 111 +++++++++++++++ nvim/lua/plugins/code.lua | 138 +++++++++++++++++++ nvim/lua/plugins/colorscheme.lua | 12 ++ nvim/lua/plugins/configs/cmp.lua | 174 ++++++++++++++++++++++++ nvim/lua/plugins/configs/lspconfig.lua | 22 +++ nvim/lua/plugins/configs/mason.lua | 12 ++ nvim/lua/plugins/configs/null-ls.lua | 26 ++++ nvim/lua/plugins/configs/others.lua | 62 +++++++++ nvim/lua/plugins/configs/treesitter.lua | 12 ++ nvim/lua/plugins/custom.lua | 2 + nvim/lua/plugins/edit.lua | 16 +++ nvim/lua/plugins/init.lua | 5 + nvim/lua/plugins/ui.lua | 91 +++++++++++++ 14 files changed, 688 insertions(+), 1 deletion(-) create mode 100644 nvim/init.lua create mode 100644 nvim/lua/plugins/code.lua create mode 100644 nvim/lua/plugins/colorscheme.lua create mode 100644 nvim/lua/plugins/configs/cmp.lua create mode 100644 nvim/lua/plugins/configs/lspconfig.lua create mode 100644 nvim/lua/plugins/configs/mason.lua create mode 100644 nvim/lua/plugins/configs/null-ls.lua create mode 100644 nvim/lua/plugins/configs/others.lua create mode 100644 nvim/lua/plugins/configs/treesitter.lua create mode 100644 nvim/lua/plugins/custom.lua create mode 100644 nvim/lua/plugins/edit.lua create mode 100644 nvim/lua/plugins/init.lua create mode 100644 nvim/lua/plugins/ui.lua diff --git a/.gitignore b/.gitignore index 66e9196..e848aad 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,8 @@ !ranger/plugins/ranger_devicons/**/* !fastfetch -!fastfetch/config.jsonc \ No newline at end of file +!fastfetch/config.jsonc + +!nvim +!nvim/**/* +nvim/lazy-lock.json \ No newline at end of file diff --git a/nvim/init.lua b/nvim/init.lua new file mode 100644 index 0000000..0431cee --- /dev/null +++ b/nvim/init.lua @@ -0,0 +1,111 @@ +-- filter which-key warnings +local orig_notify = vim.notify +vim.notify = function(msg, level, opts) + if msg:match("which%-key") and level == vim.log.levels.WARN then + return + end + orig_notify(msg, level, opts) +end + +-- Set leader key +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +local firstload = not vim.loop.fs_stat(lazypath) +if firstload then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", -- latest stable release + lazypath, + }) +end + +vim.opt.rtp:prepend(lazypath) + +-- Set highlight on search +vim.o.hlsearch = false + +-- Make line numbers default +vim.wo.number = true + +vim.o.tabstop = 4 -- A TAB character looks like 2 spaces +vim.o.expandtab = true -- Pressing the TAB key will insert spaces instead of a TAB character +vim.o.softtabstop = 4 -- Number of spaces inserted instead of a TAB character +vim.o.shiftwidth = 4 -- Number of spaces inserted when indenting + +-- Ruler at 100 characters +vim.o.colorcolumn = "100" + +-- Relative line numbers +vim.o.number = true +vim.o.relativenumber = true +vim.o.signcolumn = "number" + +-- Enable mouse mode +vim.o.mouse = "a" + +-- Sync clipboard between OS and Neovim. +-- Remove this option if you want your OS clipboard to remain independent. +-- See `:help 'clipboard'` +vim.o.clipboard = "unnamedplus" + +-- Enable break indent +vim.o.breakindent = true + +-- Save undo history +vim.o.undofile = true + +-- Case-insensitive searching UNLESS \C or capital in search +vim.o.ignorecase = true +vim.o.smartcase = true + +-- Keep signcolumn as auto. Set this to 'yes' if you want it enabled +vim.wo.signcolumn = "auto" + +-- Decrease update time +vim.o.updatetime = 250 +vim.o.timeoutlen = 300 + +-- Set completeopt to have a better completion experience +vim.o.completeopt = "menuone,noselect" + +-- Set terminal gui colors to true +vim.o.termguicolors = true + +-- add binaries installed by mason.nvim to path +local is_windows = vim.loop.os_uname().sysname == "Windows_NT" +vim.env.PATH = vim.fn.stdpath("data") .. "/mason/bin" .. (is_windows and ";" or ":") .. vim.env.PATH + +require("lazy").setup("plugins") + +if firstload then + vim.schedule(function() + vim.cmd("MasonInstallAll") + + local packages = {} + for k, v in pairs(vim.g.mason_binaries_list) do + packages[k] = v + end + + local installed = {} + + require("mason-registry"):on("package:install:success", function(pkg) + table.insert(installed, pkg.name) + + if #installed == #packages then + vim.schedule(function() + vim.api.nvim_buf_delete(0, { force = true }) + vim.api.nvim_buf_delete(0, { force = true }) + vim.cmd("echo '' | redraw") + end) + end + end) + end) +end + +-- Transparent background +vim.cmd("hi Normal guibg=NONE ctermbg=NONE") diff --git a/nvim/lua/plugins/code.lua b/nvim/lua/plugins/code.lua new file mode 100644 index 0000000..ef49985 --- /dev/null +++ b/nvim/lua/plugins/code.lua @@ -0,0 +1,138 @@ +-- Plugins that are related to coding. Such as lsp +-- or language specific. +return { + { + "neovim/nvim-lspconfig", + event = "VeryLazy", + config = function() + require("plugins.configs.lspconfig") + end, + }, + { + "williamboman/mason.nvim", + cmd = { "Mason", "MasonInstall", "MasonInstallAll", "MasonUpdate" }, + opts = function() + return require("plugins.configs.mason") + end, + config = function(_, opts) + require("mason").setup(opts) + + vim.api.nvim_create_user_command("MasonInstallAll", function() + if opts.ensure_installed then + vim.cmd("MasonInstall " .. table.concat(opts.ensure_installed, " ")) + end + end, {}) + + vim.g.mason_binaries_list = opts.ensure_installed + end, + }, + { + "numToStr/Comment.nvim", + keys = { + { "gcc", mode = "n", desc = "Comment toggle current line" }, + { "gc", mode = { "n", "o" }, desc = "Comment toggle linewise" }, + { "gc", mode = "x", desc = "Comment toggle linewise (visual)" }, + { "gbc", mode = "n", desc = "Comment toggle current block" }, + { "gb", mode = { "n", "o" }, desc = "Comment toggle blockwise" }, + { "gb", mode = "x", desc = "Comment toggle blockwise (visual)" }, + }, + init = function() + local wk = require("which-key") + wk.register({ + ["/"] = { + function() + require("Comment.api").toggle.linewise.current() + end, + "Toggle comment", + }, + }, { + prefix = "", + mode = "n", + }) + wk.register({ + ["/"] = { + "lua require('Comment.api').toggle.linewise(vim.fn.visualmode())", + "Toggle comment", + }, + }, { + prefix = "", + mode = "v", + }) + end, + config = function(_, opts) + require("Comment").setup(opts) + end, + }, + { + "nvim-treesitter/nvim-treesitter", + event = { "BufReadPost", "BufNewFile" }, + cmd = { "TSInstall", "TSBufEnable", "TSBufDisable", "TSModuleInfo" }, + build = ":TSUpdate", + dependencies = { + "apple/pkl-neovim", + }, + opts = function() + return require("plugins.configs.treesitter") + end, + config = function(_, opts) + require("nvim-treesitter.configs").setup(opts) + end, + }, + { + "hrsh7th/nvim-cmp", + event = "InsertEnter", + dependencies = { + { + -- snippet plugin + "L3MON4D3/LuaSnip", + dependencies = "rafamadriz/friendly-snippets", + opts = { history = true, updateevents = "TextChanged,TextChangedI" }, + config = function(_, opts) + require("plugins.configs.others").luasnip(opts) + end, + }, + + -- autopairing of (){}[] etc + { + "windwp/nvim-autopairs", + opts = { + fast_wrap = {}, + disable_filetype = { "TelescopePrompt", "vim" }, + }, + config = function(_, opts) + require("nvim-autopairs").setup(opts) + + -- setup cmp for autopairs + local cmp_autopairs = require("nvim-autopairs.completion.cmp") + require("cmp").event:on("confirm_done", cmp_autopairs.on_confirm_done()) + end, + }, + "saadparwaiz1/cmp_luasnip", + "hrsh7th/cmp-nvim-lua", + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-path", + }, + opts = function() + return require("plugins.configs.cmp") + end, + config = function(_, opts) + require("cmp").setup(opts) + end, + }, + { + "nvimtools/none-ls.nvim", + opts = function() + return require("plugins.configs.null-ls") + end, + }, + { + "saecki/crates.nvim", + ft = { "rust", "toml" }, + config = function(_, opts) + local crates = require("crates") + crates.setup(opts) + crates.show() + end, + }, +} diff --git a/nvim/lua/plugins/colorscheme.lua b/nvim/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..ed6aa0b --- /dev/null +++ b/nvim/lua/plugins/colorscheme.lua @@ -0,0 +1,12 @@ +-- Use this file for any colorschemes that you wish to install. +-- Comes with catppuccin by default. +return { + { + "catppuccin/nvim", + name = "catppuccin", + priority = 1000, + config = function() + vim.cmd([[colorscheme catppuccin]]) + end, + }, +} diff --git a/nvim/lua/plugins/configs/cmp.lua b/nvim/lua/plugins/configs/cmp.lua new file mode 100644 index 0000000..2b5844f --- /dev/null +++ b/nvim/lua/plugins/configs/cmp.lua @@ -0,0 +1,174 @@ +local cmp = require "cmp" + +local cmp_ui = { + icons = true, + lspkind_text = true, + style = "default", -- default/flat_light/flat_dark/atom/atom_colored + border_color = "grey_fg", -- only applicable for "default" style, use color names from base30 variables + selected_item_bg = "simple", -- colored / simple +} +local cmp_style = cmp_ui.style + +local field_arrangement = { + atom = { "kind", "abbr", "menu" }, + atom_colored = { "kind", "abbr", "menu" }, +} + +local formatting_style = { + -- default fields order i.e completion word + item.kind + item.kind icons + fields = field_arrangement[cmp_style] or { "abbr", "kind", "menu" }, + + format = function(_, item) + --jlocal icons = require "nvchad.icons.lspkind" + local icon = "" --(cmp_ui.icons and icons[item.kind]) or "" + + if cmp_style == "atom" or cmp_style == "atom_colored" then + icon = " " .. icon .. " " + item.menu = cmp_ui.lspkind_text and " (" .. item.kind .. ")" or "" + item.kind = icon + else + icon = cmp_ui.lspkind_text and (" " .. icon .. " ") or icon + item.kind = string.format("%s %s", icon, cmp_ui.lspkind_text and item.kind or "") + end + + return item + end, +} + +local function border(hl_name) + return { + { "╭", hl_name }, + { "─", hl_name }, + { "╮", hl_name }, + { "│", hl_name }, + { "╯", hl_name }, + { "─", hl_name }, + { "╰", hl_name }, + { "│", hl_name }, + } +end + +local options = { + completion = { + completeopt = "menu,menuone", + }, + + window = { + completion = { + side_padding = (cmp_style ~= "atom" and cmp_style ~= "atom_colored") and 1 or 0, + winhighlight = "Normal:CmpPmenu,CursorLine:CmpSel,Search:None", + scrollbar = false, + }, + documentation = { + border = border "CmpDocBorder", + winhighlight = "Normal:CmpDoc", + }, + }, + snippet = { + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + + --formatting = formatting_style, + + mapping = { + [""] = cmp.mapping.select_prev_item(), + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.close(), + [""] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Insert, + select = true, + }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif require("luasnip").expand_or_jumpable() then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-expand-or-jump", true, true, true), "") + else + fallback() + end + end, { + "i", + "s", + }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif require("luasnip").jumpable(-1) then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-jump-prev", true, true, true), "") + else + fallback() + end + end, { + "i", + "s", + }), + }, + sources = { + { name = "nvim_lsp" }, + { name = "luasnip" }, + { name = "buffer" }, + { name = "nvim_lua" }, + { name = "path" }, + { name = "crates" }, + }, +} + +if cmp_style ~= "atom" and cmp_style ~= "atom_colored" then + options.window.completion.border = border "CmpBorder" +end + +return { + sources = { + { name = "nvim_lsp" }, + { name = "buffer" }, + { name = "path" }, + { name = "luasnip" }, + { name = "nvim_lua" }, + }, + snippet = { + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + mapping = { + [""] = cmp.mapping.select_prev_item(), + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.close(), + [""] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Insert, + select = true, + }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif require("luasnip").expand_or_jumpable() then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-expand-or-jump", true, true, true), "") + else + fallback() + end + end, { + "i", + "s", + }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif require("luasnip").jumpable(-1) then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-jump-prev", true, true, true), "") + else + fallback() + end + end, { + "i", + "s", + }), + }, +} diff --git a/nvim/lua/plugins/configs/lspconfig.lua b/nvim/lua/plugins/configs/lspconfig.lua new file mode 100644 index 0000000..a497e65 --- /dev/null +++ b/nvim/lua/plugins/configs/lspconfig.lua @@ -0,0 +1,22 @@ +local lspconfig = require("lspconfig") + +lspconfig.lua_ls.setup({ + settings = { + Lua = { + diagnostics = { + globals = { "vim" }, + disable = { "different-requires" }, + }, + }, + }, +}) + +lspconfig.rust_analyzer.setup({ + cargo = { + features = { "all" }, + }, +}) + +lspconfig.gopls.setup({ + filetypes = { "go", "gomod", "gowork", "gotmpl" }, +}) diff --git a/nvim/lua/plugins/configs/mason.lua b/nvim/lua/plugins/configs/mason.lua new file mode 100644 index 0000000..3b4d904 --- /dev/null +++ b/nvim/lua/plugins/configs/mason.lua @@ -0,0 +1,12 @@ +return { + ensure_installed = { + "gofumpt", + "goimports", + "golines", + "gopls", + "lua-language-server", + "rust-analyzer", + "rustfmt", + "stylua", + }, +} diff --git a/nvim/lua/plugins/configs/null-ls.lua b/nvim/lua/plugins/configs/null-ls.lua new file mode 100644 index 0000000..ee9a144 --- /dev/null +++ b/nvim/lua/plugins/configs/null-ls.lua @@ -0,0 +1,26 @@ +local augroup = vim.api.nvim_create_augroup("LspFormatting", {}) +local null_ls = require("null-ls") + +return { + sources = { + null_ls.builtins.formatting.gofumpt, + null_ls.builtins.formatting.golines, + null_ls.builtins.formatting.goimports, + null_ls.builtins.formatting.stylua, + }, + on_attach = function(client, bufnr) + if client.supports_method("textDocument/formatting") then + vim.api.nvim_clear_autocmds({ + group = augroup, + buffer = bufnr, + }) + vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + buffer = bufnr, + callback = function() + vim.lsp.buf.format({ bufnr = bufnr }) + end, + }) + end + end, +} diff --git a/nvim/lua/plugins/configs/others.lua b/nvim/lua/plugins/configs/others.lua new file mode 100644 index 0000000..88b9f91 --- /dev/null +++ b/nvim/lua/plugins/configs/others.lua @@ -0,0 +1,62 @@ +local M = {} + +M.blankline = { + indentLine_enabled = 1, + filetype_exclude = { + "help", + "terminal", + "lazy", + "lspinfo", + "TelescopePrompt", + "TelescopeResults", + "mason", + "nvdash", + "nvcheatsheet", + "", + }, + buftype_exclude = { "terminal" }, + show_trailing_blankline_indent = false, + show_first_indent_level = false, + show_current_context = true, + show_current_context_start = false, +} + +M.luasnip = function(opts) + require("luasnip").config.set_config(opts) + + -- vscode format + require("luasnip.loaders.from_vscode").lazy_load() + require("luasnip.loaders.from_vscode").lazy_load { paths = vim.g.vscode_snippets_path or "" } + + -- snipmate format + require("luasnip.loaders.from_snipmate").load() + require("luasnip.loaders.from_snipmate").lazy_load { paths = vim.g.snipmate_snippets_path or "" } + + -- lua format + require("luasnip.loaders.from_lua").load() + require("luasnip.loaders.from_lua").lazy_load { paths = vim.g.lua_snippets_path or "" } + + vim.api.nvim_create_autocmd("InsertLeave", { + callback = function() + if + require("luasnip").session.current_nodes[vim.api.nvim_get_current_buf()] + and not require("luasnip").session.jump_active + then + require("luasnip").unlink_current() + end + end, + }) +end + +M.gitsigns = { + signs = { + add = { text = "│" }, + change = { text = "│" }, + delete = { text = "󰍵" }, + topdelete = { text = "‾" }, + changedelete = { text = "~" }, + untracked = { text = "│" }, + }, +} + +return M diff --git a/nvim/lua/plugins/configs/treesitter.lua b/nvim/lua/plugins/configs/treesitter.lua new file mode 100644 index 0000000..7111bea --- /dev/null +++ b/nvim/lua/plugins/configs/treesitter.lua @@ -0,0 +1,12 @@ +return { + ensure_installed = { + "go", + "lua", + "rust", + }, + highlight = { + enable = true, + use_languagetree = true, + }, + indent = { enable = true }, +} diff --git a/nvim/lua/plugins/custom.lua b/nvim/lua/plugins/custom.lua new file mode 100644 index 0000000..8aba764 --- /dev/null +++ b/nvim/lua/plugins/custom.lua @@ -0,0 +1,2 @@ +local plugins = {} +return plugins diff --git a/nvim/lua/plugins/edit.lua b/nvim/lua/plugins/edit.lua new file mode 100644 index 0000000..c14be6d --- /dev/null +++ b/nvim/lua/plugins/edit.lua @@ -0,0 +1,16 @@ +-- File is used for any editing based plugins +-- Contains vim-sleuth, which is used for automatic identations +-- trim.nvim which is used for automatically trimming whitespace +return { + { + "tpope/vim-sleuth", + event = "VeryLazy", + }, + { + "cappyzawa/trim.nvim", + event = "VeryLazy", + opts = { + ft_blocklist = {"markdown"}, + }, + }, +} diff --git a/nvim/lua/plugins/init.lua b/nvim/lua/plugins/init.lua new file mode 100644 index 0000000..02de4b1 --- /dev/null +++ b/nvim/lua/plugins/init.lua @@ -0,0 +1,5 @@ +return { + { "folke/lazy.nvim", version = "*" }, + "nvim-lua/plenary.nvim", + "christoomey/vim-tmux-navigator", +} diff --git a/nvim/lua/plugins/ui.lua b/nvim/lua/plugins/ui.lua new file mode 100644 index 0000000..9c43ea6 --- /dev/null +++ b/nvim/lua/plugins/ui.lua @@ -0,0 +1,91 @@ +-- Use this file for any UI based plugins +-- Contains telescope, icons, lualine & whichkey +return { + { + "nvim-telescope/telescope.nvim", + dependencies = { "nvim-treesitter/nvim-treesitter" }, + cmd = "Telescope", + init = function() + local builtin = require('telescope.builtin') + local wk = require('which-key') + wk.register({ + ['ff'] = { builtin.find_files, "Find File" }, + ['fb'] = { builtin.buffers, "Find Buffer" }, + ['fg'] = { builtin.live_grep, "Find with Grep" }, + ['fh'] = { builtin.help_tags, "Find Help" }, + ['fn'] = { ":Telescope file_browser path=%:p:h select_buffer=true", "File Browser" }, + }, { prefix = "" }) + end, + opts = function() + return { + defaults = { + vimgrep_arguments = { + "rg", + "-L", + "--color=never", + "--no-heading", + "--with-filename", + "--line-number", + "--column", + "--smart-case", + }, + previewer = true, + file_previewer = require 'telescope.previewers'.vim_buffer_cat.new, + grep_previewer = require 'telescope.previewers'.vim_buffer_vimgrep.new, + qflist_previewer = require 'telescope.previewers'.vim_buffer_qflist.new, + }, + extensions = { + file_browser = { + theme = "ivy", + hijack_netrw = true, + }, + }, + extensions_list = { + "file_browser", + }, + } + end, + config = function(_, opts) + local telescope = require "telescope" + telescope.setup(opts) + + -- load extensions + for _, ext in ipairs(opts.extensions_list) do + telescope.load_extension(ext) + end + end, + }, + { + "nvim-telescope/telescope-file-browser.nvim", + dependencies = { "nvim-telescope/telescope.nvim", "nvim-lua/plenary.nvim" } + }, + { + 'nvim-tree/nvim-web-devicons', + }, + { + 'nvim-lualine/lualine.nvim', + dependencies = { 'nvim-tree/nvim-web-devicons' }, + event = "VeryLazy", + opts = { + options = { + icons_enabled = true, + theme = 'auto', + component_separators = '|', + section_separators = { left = '', right = '' }, + }, + }, + }, + -- Only load whichkey after all the gui + { + "folke/which-key.nvim", + keys = { "", "", "", '"', "'", "`", "c", "v", "g" }, + cmd = "WhichKey", + config = function(_, opts) + local wk = require('which-key') + wk.setup(opts) + wk.register({ + ['f'] = { name = "Find" }, + }, { prefix = "" }) + end, + }, +}