diff --git a/init.lua b/init.lua index c228226..bcd55d8 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,9 @@ +vim.g.mapleader = " " +vim.g.maplocalleader = "," + require("plugins.init") +require("config.autocmd") +require("config.binds") -- Colorcheme vim.cmd.colorscheme("catppuccin-mocha") diff --git a/lua/config/autocmd.lua b/lua/config/autocmd.lua new file mode 100644 index 0000000..b9fa53f --- /dev/null +++ b/lua/config/autocmd.lua @@ -0,0 +1,44 @@ +-- Autocommand to check git status +vim.api.nvim_create_autocmd("VimEnter", { + callback = function() + -- Verify if the current directory is a git repo + local is_git = os.execute("git rev-parse --is-inside-work-tree > /dev/null 2>&1") + if is_git ~= 0 then + return + end + + -- Perform an async fetch to avoid startup lag + vim.fn.jobstart("git fetch", { + on_exit = function() + -- Get the number of commits the remote is ahead of local HEAD + local count = vim.fn.system("git rev-list --count HEAD..@{u} 2>/dev/null"):gsub("%s+", "") + + if count ~= "" and tonumber(count) > 0 then + vim.schedule(function() + vim.notify( + "󰊢 " .. count .. " new commit(s) available on remote.", + vim.log.levels.INFO, + { title = "Git Status", icon = "󰊢" } + ) + end) + end + end, + }) + end, +}) + +local cursorline_group = vim.api.nvim_create_augroup("CursorLineControl", { clear = true }) + +vim.api.nvim_create_autocmd({ "WinEnter", "BufEnter" }, { + group = cursorline_group, + callback = function() + vim.opt_local.cursorline = true + end, +}) + +vim.api.nvim_create_autocmd({ "WinLeave" }, { + group = cursorline_group, + callback = function() + vim.opt_local.cursorline = false + end, +}) diff --git a/lua/config/binds.lua b/lua/config/binds.lua new file mode 100644 index 0000000..0920543 --- /dev/null +++ b/lua/config/binds.lua @@ -0,0 +1,34 @@ +-- Keymap function +function Keymap(mode, key, binding, opts) + local options = { noremap = true, silent = true } + if opts then + options = vim.tbl_extend("force", options, opts) + end + vim.keymap.set(mode, key, binding, options) +end + +Keymap("n", "q:", ":") -- remove nonsense command +Keymap("n", "bd", function() -- delete buffer + vim.cmd("bd") + vim.cmd("echo 'Buffer deleted'") +end) + +for _, bind in ipairs({ "i", "a", "A" }) do + -- Pass { expr = true } as the fourth argument + Keymap("n", bind, function() + if vim.fn.getline("."):match("^%s*$") then + return [["_cc]] + else + return bind + end + end, { expr = true }) +end + +Keymap("i", "", "") -- C-Backscpace for whole words + +-- Open Lazygit +Keymap("n", "l", function() + Snacks.lazygit.open() +end) + +Keymap("n", "d", "lua vim.diagnostic.open_float()") -- Diagnostics for Linter diff --git a/lua/plugins/completion/conform.lua b/lua/plugins/completion/conform.lua new file mode 100644 index 0000000..50404d7 --- /dev/null +++ b/lua/plugins/completion/conform.lua @@ -0,0 +1,14 @@ +vim.pack.add({ { src = "https://github.com/stevearc/conform.nvim", name = "conform" } }) + +require("conform").setup({ + formatters_by_ft = { + lua = { "stylua" }, + javascript = { "prettier" }, + python = { "black" }, + nix = { "nixfmt" }, + css = { "prettier" }, + rust = { "rustfmt" }, + }, + format_on_save = true, + undojoin = true, +}) diff --git a/lua/plugins/completion/lspconfig.lua b/lua/plugins/completion/lspconfig.lua new file mode 100644 index 0000000..405c7ea --- /dev/null +++ b/lua/plugins/completion/lspconfig.lua @@ -0,0 +1,85 @@ +vim.pack.add({ + { src = "https://github.com/neovim/nvim-lspconfig", name = "lspconfig" }, + { src = "https://github.com/saghen/blink.cmp", name = "blink" }, +}) + +vim.lsp.config("lua_ls", { + settings = { + Lua = { + -- Tell the server to let Neovim handle snippet expansion + completion = { + callSnippet = "Replace", + }, + -- Use LuaJIT (which Neovim uses) + runtime = { + version = "LuaJIT", + }, + }, + }, +}) +vim.lsp.config("emmet_ls", { + -- capabilities = require("cmp_nvim_lsp").default_capabilities(), + filetypes = { "html", "css", "javascriptreact", "typescriptreact" }, + init_options = { + html = { + options = { + ["bem.enabled"] = true, + }, + }, + }, +}) +vim.lsp.enable({ + "lua_ls", + "ts_ls", + "pylsp", + "cssls", + "nixd", + "rust_analyzer", + "emmet_ls", +}) + +vim.o.pumborder = "rounded" + +require("blink.cmp").setup({ + -- Snippet configuration + -- snippets = { + -- preset = "luasnip", -- Tells blink.cmp to use LuaSnip + -- }, + + fuzzy = { implementation = "lua" }, + + signature = { + enabled = true, + }, + + completion = { + list = { + selection = { + preselect = false, + auto_insert = true, + }, + }, + }, + + -- Keymaps + keymap = { + [""] = { "select_next", "snippet_forward", "fallback" }, + }, + sources = { + default = { + "lsp", -- (Equivalent to cmp-nvim-lsp) + "snippets", -- (Handled by the snippets config, replaces cmp_luasnip source) + "buffer", -- (Equivalent to cmp-buffer) + "path", -- (Equivalent to cmp-path) + -- "cmdline", -- Generally configured separately, but often included by default + }, + providers = { + -- lazydev = { + -- name = "LazyDev", + -- module = "lazydev.integrations.blink", + -- -- make lazydev completions top priority (see `:h blink.cmp`) + -- score_offset = 100, + -- }, + }, + }, +}) diff --git a/lua/plugins/completion/treesitter.lua b/lua/plugins/completion/treesitter.lua new file mode 100644 index 0000000..256da87 --- /dev/null +++ b/lua/plugins/completion/treesitter.lua @@ -0,0 +1,24 @@ +vim.pack.add({ { src = "https://github.com/nvim-treesitter/nvim-treesitter", name = "treesitter" } }) + +require("nvim-treesitter").setup({ + highlight = { enable = true }, + indent = { enable = true }, +}) + +require("nvim-treesitter").install({ + "bash", + "html", + "latex", + "javascript", + "json", + "lua", + "markdown", + "markdown_inline", + "query", + "regex", + "tsx", + "typescript", + "python", + "vim", + "yaml", +}) diff --git a/lua/plugins/init.lua b/lua/plugins/init.lua new file mode 100644 index 0000000..155def3 --- /dev/null +++ b/lua/plugins/init.lua @@ -0,0 +1,35 @@ +local plugins = {} + +-- 1. Setup paths +local lua_path = vim.fn.stdpath("config") .. "/lua" +local plugin_dir = lua_path .. "/plugins" + +-- 2. Use ** to search recursively for all .lua files +local files = vim.fn.split(vim.fn.globpath(plugin_dir, "**/*.lua"), "\n") + +for _, file in ipairs(files) do + -- Get path relative to the 'lua' directory + -- Example: /home/user/.config/nvim/lua/plugins/ui/statusline.lua + -- Becomes: plugins/ui/statusline.lua + local relative_path = file:sub(#lua_path + 2) + + -- Remove the .lua extension + local module_path = relative_path:gsub("%.lua$", "") + + -- Convert path slashes to Lua dots (plugins/ui/statusline -> plugins.ui.statusline) + module_path = module_path:gsub("/", ".") + + -- 3. The Guard: Don't require the current file (plugins.init) + if not module_path:match("%.init$") and module_path ~= "plugins" then + local status_ok, module_content = pcall(require, module_path) + + if status_ok then + table.insert(plugins, module_content) + else + -- Optional: notify if a file failed to load + vim.notify("Error loading " .. module_path .. ": " .. module_content, vim.log.levels.ERROR) + end + end +end + +return plugins diff --git a/plugins/ui/catppuccin.lua b/lua/plugins/ui/catppuccin.lua similarity index 100% rename from plugins/ui/catppuccin.lua rename to lua/plugins/ui/catppuccin.lua diff --git a/lua/plugins/ui/lualine.lua b/lua/plugins/ui/lualine.lua new file mode 100644 index 0000000..5d4efe8 --- /dev/null +++ b/lua/plugins/ui/lualine.lua @@ -0,0 +1,71 @@ +vim.pack.add({ + { src = "https://github.com/nvim-lualine/lualine.nvim", name = "lualine" }, + { src = "https://github.com/nvim-tree/nvim-web-devicons", name = "devicons" }, + { src = "https://github.com/archibate/lualine-time", name = "lualine-time" }, +}) + +require("lualine").setup({ + options = { + icons_enabled = true, + theme = "auto", + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = { + statusline = {}, + winbar = {}, + }, + ignore_focus = {}, + always_divide_middle = true, + always_show_tabline = true, + globalstatus = false, + refresh = { + statusline = 1000, + tabline = 1000, + winbar = 1000, + refresh_time = 16, -- ~60fps + events = { + "WinEnter", + "BufEnter", + "BufWritePost", + "SessionLoadPost", + "FileChangedShellPost", + "VimResized", + "Filetype", + "CursorMoved", + "CursorMovedI", + "ModeChanged", + }, + }, + }, + sections = { + lualine_a = { + "mode", + { + function() + local reg = vim.fn.reg_recording() + if reg == "" then + return "" + end -- not recording + return "MACRO " .. string.upper(tostring(reg)) + end, + }, + }, + lualine_b = { "branch", "diff", "diagnostics" }, + lualine_c = { "filename" }, + lualine_x = { "filetype" }, + lualine_y = { "lsp_status" }, + lualine_z = { "ctime" }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = { "branch", "diff", "diagnostics" }, + lualine_c = { "filename" }, + lualine_x = { "location" }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + winbar = {}, + inactive_winbar = {}, + extensions = {}, +}) diff --git a/lua/plugins/ui/noice.lua b/lua/plugins/ui/noice.lua new file mode 100644 index 0000000..f0be596 --- /dev/null +++ b/lua/plugins/ui/noice.lua @@ -0,0 +1,41 @@ +vim.pack.add({ + { src = "https://github.com/folke/noice.nvim", name = "noice" }, + { src = "https://github.com/MunifTanjim/nui.nvim", name = "nui" }, + { src = "https://github.com/rcarriga/nvim-notify", name = "notify" }, +}) + +vim.notify = require("notify").setup({ + background_colour = "#000000", + render = "compact", + stages = "slide", +}) +require("noice").setup({ + messages = { + enabled = true, + view = "mini", + view_error = "notify", -- view for errors + view_warn = "notify", -- view for warnings + view_history = "messages", -- view for :messages + view_search = "virtualtext", -- view for search count messages. Set to `false` to disable + }, + notify = { + enabled = true, + view = "notify", + }, + hover = { + enabled = false, + }, + lsp = { + hover = { + enabled = false, + }, + signature = { + enabled = false, + }, + }, + presets = { + long_message_to_split = true, -- long messages will be sent to a split + inc_rename = false, -- enables an input dialog for inc-rename.nvim + lsp_doc_border = false, -- add a border to hover docs and signature help + }, +}) diff --git a/lua/plugins/utils/mini.lua b/lua/plugins/utils/mini.lua new file mode 100644 index 0000000..fab7e4e --- /dev/null +++ b/lua/plugins/utils/mini.lua @@ -0,0 +1,52 @@ +vim.pack.add({ { src = "https://github.com/echasnovski/mini.nvim", name = "mini" } }) + +require("mini.pairs").setup() -- Bracket pairs and stuff + +require("mini.ai").setup() -- Around and In extension for visual mode + +require("mini.cursorword").setup() -- Underline current word below cursor (makes it easier to c and d) + +require("mini.indentscope").setup({ -- shows indents + symbol = "│", + draw = { + delay = 10, + animation = require("mini.indentscope").gen_animation.linear({ + duration = 15, + unit = "step", + easing = "out", + }), + }, +}) + +require("mini.trailspace").setup() -- Shows useless spaces + +require("mini.sessions").setup({ -- dir based session management + autoread = true, + autowrite = true, + file = ".session", + force = { read = false, write = true, delete = true }, +}) + +require("mini.surround").setup() -- Suround selections with characters + +require("mini.move").setup({ -- move selection in visual mode + mappings = { + down = "J", + up = "K", + }, +}) + +require("mini.icons").setup() -- Icon provider + +local animate = require("mini.animate") -- animations ovs +require("mini.animate").setup({ + cursor = { + enable = false, + }, + scroll = { + -- Animate for 200 milliseconds with linear easing + timing = animate.gen_timing.linear({ duration = 100, unit = "total" }), + -- Animate equally but with at most 120 steps instead of default 60 + subscroll = animate.gen_subscroll.equal({ max_output_steps = 60 }), + }, +}) diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json new file mode 100644 index 0000000..011ae33 --- /dev/null +++ b/nvim-pack-lock.json @@ -0,0 +1,64 @@ +{ + "plugins": { + "blink": { + "rev": "456d38d1cd3743926f329204c2340f3e7840aad6", + "src": "https://github.com/saghen/blink.cmp" + }, + "catppuccin": { + "rev": "426dbebe06b5c69fd846ceb17b42e12f890aedf1", + "src": "https://github.com/catppuccin/nvim" + }, + "conform": { + "rev": "086a40dc7ed8242c03be9f47fbcee68699cc2395", + "src": "https://github.com/stevearc/conform.nvim" + }, + "devicons": { + "rev": "c72328a5494b4502947a022fe69c0c47e53b6aa6", + "src": "https://github.com/nvim-tree/nvim-web-devicons" + }, + "lspconfig": { + "rev": "c588db330592fa477a70d2fee6ba20a57194bdc3", + "src": "https://github.com/neovim/nvim-lspconfig" + }, + "lspkind": { + "rev": "c7274c48137396526b59d86232eabcdc7fed8a32", + "src": "https://github.com/onsails/lspkind.nvim" + }, + "lualine": { + "rev": "f5d2a8570f8b736ddb9bb4be504355bcd6e15ec8", + "src": "https://github.com/nvim-lualine/lualine.nvim" + }, + "lualine-time": { + "rev": "8838875e2e787293bb905d23dbb91ef4bde188ea", + "src": "https://github.com/archibate/lualine-time" + }, + "mini": { + "rev": "69b7433355664cf76898eb86a12a019f39bd86d1", + "src": "https://github.com/echasnovski/mini.nvim" + }, + "neorg": { + "rev": "1f14d72aad7165eac307a2a2f6be0fb97a04b3c2", + "src": "https://github.com/nvim-neorg/neorg" + }, + "noice": { + "rev": "7bfd942445fb63089b59f97ca487d605e715f155", + "src": "https://github.com/folke/noice.nvim" + }, + "notify": { + "rev": "8701bece920b38ea289b457f902e2ad184131a5d", + "src": "https://github.com/rcarriga/nvim-notify" + }, + "nui": { + "rev": "de740991c12411b663994b2860f1a4fd0937c130", + "src": "https://github.com/MunifTanjim/nui.nvim" + }, + "plenary": { + "rev": "74b06c6c75e4eeb3108ec01852001636d85a932b", + "src": "https://github.com/nvim-lua/plenary.nvim" + }, + "treesitter": { + "rev": "4916d6592ede8c07973490d9322f187e07dfefac", + "src": "https://github.com/nvim-treesitter/nvim-treesitter" + } + } +} diff --git a/plugins/init.lua b/plugins/init.lua deleted file mode 100644 index 97d6405..0000000 --- a/plugins/init.lua +++ /dev/null @@ -1 +0,0 @@ -require("plugins.ui.catppuccin")