From be85b7164d8ed1d126d220d5a92f82f8e9fb62f6 Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Thu, 12 Jun 2025 10:39:21 +0200 Subject: [PATCH] configuration works now --- README.md | 68 ++- init.lua | 1472 ++++++++++------------------------------------------- 2 files changed, 337 insertions(+), 1203 deletions(-) diff --git a/README.md b/README.md index b0aa220..313030f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,67 @@ -# neofig +๐Ÿš€ GENERAL KEYBINDS: + e - Show diagnostic float + [d / ]d - Navigate diagnostics + n - Toggle file explorer (Neo-tree) + ff - Find files (Telescope) + fg - Live grep (Telescope) + gs - Git status (Fugitive) + gg - Open LazyGit -neovim config \ No newline at end of file +๐Ÿ“ EDITING: + gd - Go to definition + gr - Find references + K - Hover documentation + rn - Rename symbol + - Next completion item + - Previous completion item + - Confirm completion + - Trigger completion + ( - Auto-complete parentheses + +๐ŸŒฒ NEO-TREE: + o / - Open file + t - Open in new tab + v - Open in vertical split + s - Open in horizontal split + r - Rename + d - Delete + a - Add file + A - Add directory + R - Refresh + . - Toggle hidden files + +๐Ÿ”ญ TELESCOPE: + / - Next/previous item + / - Move selection + - Open in new tab + - Open in vertical split + - Open in horizontal split + - Clear prompt + - Close telescope + +๐Ÿ’ป LSP: + d - Show diagnostics + ca - Code actions + f - Format file + wa - Add workspace folder + wr - Remove workspace folder + wl - List workspace folders + +๐Ÿ’พ BUFFER MANAGEMENT: + bd - Delete buffer + bn - Next buffer + bp - Previous buffer + bl - List buffers + +๐Ÿฑ GIT: + gc - Git commit + gp - Git push + gl - Git log + gd - Git diff + gb - Git blame + +๐Ÿ”„ TERMINAL: + - Toggle terminal + - Exit terminal mode + tt - New terminal + tf - New floating terminal diff --git a/init.lua b/init.lua index 9cfd1bb..5144298 100644 --- a/init.lua +++ b/init.lua @@ -1,1259 +1,329 @@ --- Bootstrap Lazy.nvim -local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" -if not vim.loop.fs_stat(lazypath) then - local result = vim.fn.system({ - "git", "clone", "--filter=blob:none", - "https://github.com/folke/lazy.nvim.git", - "--branch=stable", -- latest stable release - lazypath - }) - if vim.v.shell_error ~= 0 then - vim.api.nvim_echo({ - { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, - { result, "WarningMsg" }, - { "\nPress any key to exit...", "MoreMsg" }, - }, true, {}) - vim.fn.getchar() - os.exit(1) - end -end -vim.opt.rtp:prepend(lazypath) +-- ~/.config/nvim/init.lua +-- Complete VSCode-like Neovim Config with Enhanced Tab Completion --- Leader key must be set before lazy setup +-- ====================== +-- 1. Basic Configuration +-- ====================== vim.g.mapleader = " " -vim.g.maplocalleader = "\\" +vim.g.maplocalleader = " " --- Core vim settings +-- Optimized Editor Settings vim.opt.number = true vim.opt.relativenumber = true -vim.opt.wrap = false -vim.opt.expandtab = true -vim.opt.shiftwidth = 2 -vim.opt.tabstop = 2 -vim.opt.softtabstop = 2 -vim.opt.smartindent = true -vim.opt.cursorline = true -vim.opt.termguicolors = true +vim.opt.mouse = "a" +vim.opt.showmode = false +vim.opt.clipboard = "unnamedplus" +vim.opt.breakindent = true +vim.opt.undofile = true +vim.opt.ignorecase = true +vim.opt.smartcase = true vim.opt.signcolumn = "yes" vim.opt.updatetime = 250 vim.opt.timeoutlen = 300 vim.opt.splitright = true vim.opt.splitbelow = true -vim.opt.undofile = true -vim.opt.ignorecase = true -vim.opt.smartcase = true -vim.opt.mouse = "a" -vim.opt.clipboard = "unnamedplus" -vim.o.shortmess = vim.o.shortmess .. "I" +vim.opt.list = true +vim.opt.listchars = { tab = "ยป ", trail = "ยท", nbsp = "โฃ" } +vim.opt.inccommand = "split" +vim.opt.cursorline = true +vim.opt.scrolloff = 10 +vim.opt.hlsearch = true +vim.opt.termguicolors = true +vim.opt.expandtab = true +vim.opt.tabstop = 2 +vim.opt.shiftwidth = 2 +vim.opt.smartindent = true +vim.opt.wrap = false +vim.opt.swapfile = false +vim.opt.backup = false +vim.opt.writebackup = false --- Plugin specifications -require("lazy").setup({ - -- LSP and completion setup +-- ====================== +-- 2. Plugin Management +-- ====================== +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +-- ====================== +-- 3. Plugin Specifications +-- ====================== +local plugins = { + -- Theme { - "neovim/nvim-lspconfig", - event = { "BufReadPre", "BufNewFile" }, - dependencies = { - "williamboman/mason.nvim", - "williamboman/mason-lspconfig.nvim", - "hrsh7th/cmp-nvim-lsp", - "folke/neodev.nvim", - }, - config = function() - -- Setup neodev before lspconfig - require("neodev").setup() - - -- Diagnostic configuration - vim.diagnostic.config({ - virtual_text = { - prefix = "โ—", - }, - signs = true, - underline = true, - update_in_insert = false, - severity_sort = true, - }) - - -- Diagnostic signs - local signs = { Error = " ", Warn = " ", Hint = "๓ฐ   ", Info = " " } - for type, icon in pairs(signs) do - local hl = "DiagnosticSign" .. type - vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = "" }) - end - - -- LSP keymaps - local on_attach = function(client, bufnr) - local opts = { buffer = bufnr, silent = true } - local keymap = vim.keymap.set - - keymap("n", "gD", vim.lsp.buf.declaration, opts) - keymap("n", "gd", vim.lsp.buf.definition, opts) - keymap("n", "K", vim.lsp.buf.hover, opts) - keymap("n", "gi", vim.lsp.buf.implementation, opts) - keymap("n", "", vim.lsp.buf.signature_help, opts) - keymap("n", "wa", vim.lsp.buf.add_workspace_folder, opts) - keymap("n", "wr", vim.lsp.buf.remove_workspace_folder, opts) - keymap("n", "wl", function() - print(vim.inspect(vim.lsp.buf.list_workspace_folders())) - end, opts) - keymap("n", "D", vim.lsp.buf.type_definition, opts) - keymap("n", "rn", vim.lsp.buf.rename, opts) - keymap("n", "ca", vim.lsp.buf.code_action, opts) - keymap("n", "gr", vim.lsp.buf.references, opts) - keymap("n", "f", function() - vim.lsp.buf.format({ async = true }) - end, opts) - end - - local capabilities = require("cmp_nvim_lsp").default_capabilities() - local lspconfig = require("lspconfig") - - -- Setup Mason - require("mason").setup({ - ui = { - icons = { - package_installed = "โœ“", - package_pending = "โžœ", - package_uninstalled = "โœ—", - }, - }, - }) - - require("mason-lspconfig").setup({ - ensure_installed = { - "lua_ls", - "pyright", - "clangd", - "html", - "cssls", - "ts_ls", - }, - automatic_installation = true, - }) - - -- LSP server configurations - local servers = { - lua_ls = { - settings = { - Lua = { - workspace = { - checkThirdParty = false, - }, - completion = { - callSnippet = "Replace", - }, - }, - }, - }, - pyright = {}, - clangd = { - cmd = { "clangd", "--background-index", "--clang-tidy" }, - }, - html = { - filetypes = { "html", "htmldjango" }, - }, - cssls = {}, - ts_ls = {}, - } - - require("mason-lspconfig").setup_handlers({ - function(server_name) - local server = servers[server_name] or {} - server.capabilities = vim.tbl_deep_extend("force", {}, capabilities, server.capabilities or {}) - server.on_attach = on_attach - lspconfig[server_name].setup(server) - end, - }) - end, - }, - - -- Mason for managing external tools - { - "williamboman/mason.nvim", - cmd = "Mason", - keys = { { "cm", "Mason", desc = "Mason" } }, - }, - - -- Autocompletion - { - "hrsh7th/nvim-cmp", - version = false, - event = "InsertEnter", - dependencies = { - "hrsh7th/cmp-nvim-lsp", - "hrsh7th/cmp-buffer", - "hrsh7th/cmp-path", - "saadparwaiz1/cmp_luasnip", - }, - opts = function() - vim.api.nvim_set_hl(0, "CmpGhostText", { link = "Comment", default = true }) - local cmp = require("cmp") - local luasnip = require("luasnip") - - return { - completion = { - completeopt = "menu,menuone,noinsert", - }, - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }), - [""] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }), - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.abort(), - [""] = cmp.mapping.confirm({ select = true }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expand_or_jumpable() then - luasnip.expand_or_jump() - else - fallback() - end - end, { "i", "s" }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif luasnip.jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { "i", "s" }), - }), - sources = cmp.config.sources({ - { name = "nvim_lsp" }, - { name = "luasnip" }, - { name = "path" }, - }, { - { name = "buffer" }, - }), - formatting = { - format = function(entry, item) - local icons = { - nvim_lsp = "", - luasnip = "", - buffer = "", - path = "", - } - item.menu = icons[entry.source.name] - return item - end, - }, - experimental = { - ghost_text = { - hl_group = "CmpGhostText", - }, - }, - } - end, - }, - - -- Snippets - { - "L3MON4D3/LuaSnip", - build = (function() - if vim.fn.has("win32") == 1 or vim.fn.executable("make") == 0 then - return - end - return "make install_jsregexp" - end)(), - dependencies = { - "rafamadriz/friendly-snippets", - config = function() - require("luasnip.loaders.from_vscode").lazy_load() - end, - }, - opts = { - history = true, - delete_check_events = "TextChanged", - }, - }, - - -- Neodev for better lua development - { "folke/neodev.nvim", opts = {} }, - - -- Treesitter - { - "nvim-treesitter/nvim-treesitter", - version = false, - build = ":TSUpdate", - event = { "BufReadPost", "BufNewFile" }, - cmd = { "TSUpdateSync" }, - opts = { - ensure_installed = { - "bash", - "c", - "cpp", - "css", - "html", - "javascript", - "json", - "lua", - "markdown", - "markdown_inline", - "python", - "query", - "regex", - "tsx", - "typescript", - "vim", - "yaml", - }, - highlight = { enable = true }, - indent = { enable = true }, - incremental_selection = { - enable = true, - keymaps = { - init_selection = "", - node_incremental = "", - scope_incremental = false, - node_decremental = "", - }, - }, - }, - config = function(_, opts) - require("nvim-treesitter.configs").setup(opts) - end, - }, - - -- Auto tag - { - "windwp/nvim-ts-autotag", - event = "InsertEnter", - opts = {}, - }, - - -- Emmet - { - "mattn/emmet-vim", - ft = { "html", "css", "javascript", "typescript", "javascriptreact", "typescriptreact" }, - init = function() - vim.g.user_emmet_leader_key = "" - end, - }, - - -- Colorscheme - { - "folke/tokyonight.nvim", - lazy = false, + "drewtempelmeyer/palenight.vim", priority = 1000, - opts = { - style = "night", - transparent = false, - terminal_colors = true, - styles = { - comments = { italic = true }, - keywords = { italic = true }, - functions = {}, - variables = {}, - sidebars = "dark", - floats = "dark", - }, - }, - config = function(_, opts) - require("tokyonight").setup(opts) - vim.cmd.colorscheme("tokyonight") + config = function() + vim.g.palenight_terminal_italics = 1 + vim.cmd("colorscheme palenight") end, }, - -- Statusline - { - "nvim-lualine/lualine.nvim", - event = "VeryLazy", - opts = function() - return { - options = { - theme = "tokyonight", - globalstatus = true, - disabled_filetypes = { statusline = { "dashboard", "alpha" } }, - }, - sections = { - lualine_a = { "mode" }, - lualine_b = { "branch" }, - lualine_c = { - { - "diagnostics", - symbols = { - error = " ", - warn = " ", - info = " ", - hint = "๓ฐ   ", - }, - }, - { "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } }, - { "filename", path = 1, symbols = { modified = " ", readonly = "", unnamed = "" } }, - }, - lualine_x = { - { - function() return require("noice").api.status.command.get() end, - cond = function() return package.loaded["noice"] and require("noice").api.status.command.has() end, - color = { fg = "#ff9e64" }, - }, - { - function() return require("noice").api.status.mode.get() end, - cond = function() return package.loaded["noice"] and require("noice").api.status.mode.has() end, - color = { fg = "#ff9e64" }, - }, - { "encoding" }, - { "fileformat" }, - }, - lualine_y = { "progress" }, - lualine_z = { "location" }, - }, - extensions = { "neo-tree", "lazy" }, - } - end, - }, - - -- File explorer + -- File Explorer { "nvim-neo-tree/neo-tree.nvim", branch = "v3.x", - cmd = "Neotree", - keys = { - { "fe", function() require("neo-tree.command").execute({ toggle = true, dir = vim.loop.cwd() }) end, desc = "Explorer NeoTree (cwd)" }, - { "fE", function() require("neo-tree.command").execute({ toggle = true, dir = vim.fn.expand("%:p:h") }) end, desc = "Explorer NeoTree (current file)" }, - { "e", "fe", desc = "Explorer NeoTree (cwd)", remap = true }, - { "E", "fE", desc = "Explorer NeoTree (current file)", remap = true }, - }, - deactivate = function() - vim.cmd([[Neotree close]]) - end, - init = function() - if vim.fn.argc(-1) == 1 then - local stat = vim.loop.fs_stat(vim.fn.argv(0)) - if stat and stat.type == "directory" then - require("neo-tree") - end - end - end, - opts = { - sources = { "filesystem", "buffers", "git_status", "document_symbols" }, - open_files_do_not_replace_types = { "terminal", "Trouble", "qf", "Outline" }, - filesystem = { - bind_to_cwd = false, - follow_current_file = { enabled = true }, - use_libuv_file_watcher = true, - filtered_items = { - visible = true, - hide_dotfiles = false, - hide_gitignored = false, - }, - }, - window = { - position = "left", - width = 30, - mappings = { - [""] = "none", - }, - }, - default_component_configs = { - indent = { - with_expanders = true, - expander_collapsed = "", - expander_expanded = "", - expander_highlight = "NeoTreeExpander", - }, - }, - }, + dependencies = { "nvim-lua/plenary.nvim", "nvim-tree/nvim-web-devicons", "MunifTanjim/nui.nvim" }, }, - -- Fuzzy finder + -- Fuzzy Finder + { "nvim-telescope/telescope.nvim", branch = "0.1.x", dependencies = { "nvim-lua/plenary.nvim" } }, + + -- LSP Configuration { - "nvim-telescope/telescope.nvim", - cmd = "Telescope", - version = false, + "neovim/nvim-lspconfig", dependencies = { - "nvim-lua/plenary.nvim", - { - "nvim-telescope/telescope-fzf-native.nvim", - build = "make", - enabled = vim.fn.executable("make") == 1, - config = function() - require("telescope").load_extension("fzf") - end, - }, - }, - keys = { - { ",", "Telescope buffers show_all_buffers=true", desc = "Switch Buffer" }, - { "/", "Telescope live_grep", desc = "Grep (root dir)" }, - { ":", "Telescope command_history", desc = "Command History" }, - { "", "Telescope find_files", desc = "Find Files (root dir)" }, - { "fb", "Telescope buffers", desc = "Buffers" }, - { "ff", "Telescope find_files", desc = "Find Files (root dir)" }, - { "fF", "Telescope find_files hidden=true no_ignore=true", desc = "Find Files (all)" }, - { "fg", "Telescope live_grep", desc = "Grep (root dir)" }, - { "fh", "Telescope help_tags", desc = "Help Pages" }, - { "fH", "Telescope highlights", desc = "Search Highlight Groups" }, - { "fk", "Telescope keymaps", desc = "Key Maps" }, - { "fl", "Telescope loclist", desc = "Location List" }, - { "fM", "Telescope man_pages", desc = "Man Pages" }, - { "fm", "Telescope marks", desc = "Jump to Mark" }, - { "fo", "Telescope vim_options", desc = "Options" }, - { "fR", "Telescope resume", desc = "Resume" }, - { "fq", "Telescope quickfix", desc = "Quickfix List" }, - { "fw", "Telescope grep_string word_match=-w", desc = "Word (root dir)" }, - { "fW", "Telescope grep_string", desc = "Selection (root dir)", mode = "v" }, - { "uC", "Telescope colorscheme enable_preview=true", desc = "Colorscheme with preview" }, - }, - opts = function() - return { - defaults = { - file_ignore_patterns = { "node_modules", ".git/" }, - vimgrep_arguments = { - "rg", - "-L", - "--color=never", - "--no-heading", - "--with-filename", - "--line-number", - "--column", - "--smart-case", - }, - prompt_prefix = " ", - selection_caret = " ", - entry_prefix = " ", - initial_mode = "insert", - selection_strategy = "reset", - sorting_strategy = "ascending", - layout_strategy = "horizontal", - layout_config = { - horizontal = { - prompt_position = "top", - preview_width = 0.55, - results_width = 0.8, - }, - vertical = { - mirror = false, - }, - width = 0.87, - height = 0.80, - preview_cutoff = 120, - }, - path_display = { "truncate" }, - winblend = 0, - border = {}, - borderchars = { "โ”€", "โ”‚", "โ”€", "โ”‚", "โ•ญ", "โ•ฎ", "โ•ฏ", "โ•ฐ" }, - color_devicons = true, - set_env = { ["COLORTERM"] = "truecolor" }, - }, - pickers = { - live_grep = { - theme = "dropdown", - }, - grep_string = { - theme = "dropdown", - }, - find_files = { - theme = "dropdown", - previewer = false, - }, - buffers = { - theme = "dropdown", - previewer = false, - initial_mode = "normal", - mappings = { - i = { - [""] = function(...) - return require("telescope.actions").delete_buffer(...) - end, - }, - n = { - ["dd"] = function(...) - return require("telescope.actions").delete_buffer(...) - end, - }, - }, - }, - planets = { - show_pluto = true, - show_moon = true, - }, - colorscheme = { - enable_preview = true, - }, - }, - } - end, - }, - - -- Better vim.ui - { - "stevearc/dressing.nvim", - lazy = true, - init = function() - vim.ui.select = function(...) - require("lazy").load({ plugins = { "dressing.nvim" } }) - return vim.ui.select(...) - end - vim.ui.input = function(...) - require("lazy").load({ plugins = { "dressing.nvim" } }) - return vim.ui.input(...) - end - end, - }, - - -- Auto pairs - { - "windwp/nvim-autopairs", - event = "InsertEnter", - opts = {}, - }, - - -- Comments - { - "numToStr/Comment.nvim", - opts = {}, - lazy = false, - }, - - -- Which key - { - "folke/which-key.nvim", - event = "VeryLazy", - opts = { - plugins = { spelling = true }, - defaults = { - mode = { "n", "v" }, - ["g"] = { name = "+goto" }, - ["gz"] = { name = "+surround" }, - ["]"] = { name = "+next" }, - ["["] = { name = "+prev" }, - [""] = { name = "+tabs" }, - ["b"] = { name = "+buffer" }, - ["c"] = { name = "+code" }, - ["f"] = { name = "+file/find" }, - ["g"] = { name = "+git" }, - ["gh"] = { name = "+hunks" }, - ["q"] = { name = "+quit/session" }, - ["s"] = { name = "+search" }, - ["u"] = { name = "+ui" }, - ["w"] = { name = "+windows" }, - ["x"] = { name = "+diagnostics/quickfix" }, - }, - }, - config = function(_, opts) - local wk = require("which-key") - wk.setup(opts) - wk.register(opts.defaults) - end, - }, - - -- Git signs - { - "lewis6991/gitsigns.nvim", - event = { "BufReadPre", "BufNewFile" }, - opts = { - signs = { - add = { text = "โ–Ž" }, - change = { text = "โ–Ž" }, - delete = { text = "" }, - topdelete = { text = "" }, - changedelete = { text = "โ–Ž" }, - untracked = { text = "โ–Ž" }, - }, - on_attach = function(buffer) - local gs = package.loaded.gitsigns - - local function map(mode, l, r, desc) - vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc }) - end - - map("n", "]h", gs.next_hunk, "Next Hunk") - map("n", "[h", gs.prev_hunk, "Prev Hunk") - map({ "n", "v" }, "ghs", ":Gitsigns stage_hunk", "Stage Hunk") - map({ "n", "v" }, "ghr", ":Gitsigns reset_hunk", "Reset Hunk") - map("n", "ghS", gs.stage_buffer, "Stage Buffer") - map("n", "ghu", gs.undo_stage_hunk, "Undo Stage Hunk") - map("n", "ghR", gs.reset_buffer, "Reset Buffer") - map("n", "ghp", gs.preview_hunk, "Preview Hunk") - map("n", "ghb", function() gs.blame_line({ full = true }) end, "Blame Line") - map("n", "ghd", gs.diffthis, "Diff This") - map("n", "ghD", function() gs.diffthis("~") end, "Diff This ~") - map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "GitSigns Select Hunk") - end, - }, - }, - - -- Dashboard - { - "nvimdev/dashboard-nvim", - event = "VimEnter", - opts = function() - local logo = [[ - โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ•— - โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ•šโ•โ• โ–ˆโ–ˆโ•‘ - โ•šโ•โ• โ•šโ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ• โ•šโ•โ•โ•šโ•โ• โ•šโ•โ• - ]] - - logo = string.rep("\n", 8) .. logo .. "\n\n" - - local opts = { - theme = "doom", - hide = { - statusline = false, - }, - config = { - header = vim.split(logo, "\n"), - center = { - { action = "Telescope find_files", desc = " Find file", icon = " ", key = "f" }, - { action = "ene | startinsert", desc = " New file", icon = " ", key = "n" }, - { action = "Telescope oldfiles", desc = " Recent files", icon = " ", key = "r" }, - { action = "Telescope live_grep", desc = " Find text", icon = " ", key = "g" }, - { action = "e $MYVIMRC", desc = " Config", icon = " ", key = "c" }, - { action = "Lazy", desc = " Lazy", icon = "๓ฐ’ฒ ", key = "l" }, - { action = "qa", desc = " Quit", icon = " ", key = "q" }, - }, - footer = function() - local stats = require("lazy").stats() - local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100) - return { "โšก Neovim loaded " .. stats.loaded .. "/" .. stats.count .. " plugins in " .. ms .. "ms" } - end, - }, - } - - for _, button in ipairs(opts.config.center) do - button.desc = button.desc .. string.rep(" ", 43 - #button.desc) - button.key_format = " %s" - end - - if vim.o.filetype == "lazy" then - vim.cmd.close() - vim.api.nvim_create_autocmd("User", { - pattern = "DashboardLoaded", - callback = function() - require("lazy").show() - end, - }) - end - - return opts - end, - }, - - -- Formatting - { - "stevearc/conform.nvim", - dependencies = { "mason.nvim" }, - lazy = true, - cmd = "ConformInfo", - keys = { - { - "cF", - function() - require("conform").format({ formatters = { "injected" } }) - end, - mode = { "n", "v" }, - desc = "Format Injected Langs", - }, - }, - init = function() - vim.o.formatexpr = "v:lua.require'conform'.formatexpr()" - end, - opts = { - formatters_by_ft = { - lua = { "stylua" }, - python = { "isort", "black" }, - javascript = { { "prettierd", "prettier" } }, - typescript = { { "prettierd", "prettier" } }, - html = { { "prettierd", "prettier" } }, - css = { { "prettierd", "prettier" } }, - json = { { "prettierd", "prettier" } }, - yaml = { { "prettierd", "prettier" } }, - markdown = { { "prettierd", "prettier" } }, - cpp = { "clang-format" }, - c = { "clang-format" }, - }, - format_on_save = function(bufnr) - if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then - return - end - local filetype = vim.bo[bufnr].filetype - if filetype == "c" or filetype == "cpp" then - return { timeout_ms = 500 } - end - return { timeout_ms = 500, lsp_fallback = true } - end, - formatters = { - injected = { options = { ignore_errors = true } }, - }, - }, - }, - - -- Linting - { - "mfussenegger/nvim-lint", - event = { "BufReadPre", "BufNewFile" }, - opts = { - events = { "BufWritePost", "BufReadPost", "InsertLeave" }, - linters_by_ft = { - python = { "flake8" }, - cpp = { "cpplint" }, - c = { "cpplint" }, - javascript = { "eslint_d" }, - typescript = { "eslint_d" }, - }, - }, - config = function(_, opts) - local M = {} - - local lint = require("lint") - for name, linter in pairs(opts.linters or {}) do - if type(linter) == "table" and type(lint.linters[name]) == "table" then - lint.linters[name] = vim.tbl_deep_extend("force", lint.linters[name], linter) - else - lint.linters[name] = linter - end - end - lint.linters_by_ft = opts.linters_by_ft - - function M.debounce(ms, fn) - local timer = vim.loop.new_timer() - return function(...) - local argv = { ... } - timer:start(ms, 0, function() - timer:stop() - vim.schedule_wrap(fn)(unpack(argv)) - end) - end - end - - function M.lint() - local names = lint._resolve_linter_by_ft(vim.bo.filetype) - names = vim.list_extend({}, names) - - if #names == 0 then - vim.list_extend(names, lint.linters_by_ft["_"] or {}) - end - - vim.list_extend(names, lint.linters_by_ft["*"] or {}) - - local ctx = { filename = vim.api.nvim_buf_get_name(0) } - ctx.dirname = vim.fn.fnamemodify(ctx.filename, ":h") - names = vim.tbl_filter(function(name) - local linter = lint.linters[name] - if not linter then - return false - end - - return not (type(linter) == "table" and linter.condition and not linter.condition(ctx)) - end, names) - - if #names > 0 then - lint.try_lint(names) - end - end - - vim.api.nvim_create_autocmd(opts.events, { - group = vim.api.nvim_create_augroup("nvim-lint", { clear = true }), - callback = M.debounce(100, M.lint), - }) - end, - }, - - -- Live server for web development - { - "barrett-ruth/live-server.nvim", - build = "npm install -g live-server", - cmd = { "LiveServerStart", "LiveServerStop" }, - config = true, - }, - - -- Debugging - { - "mfussenegger/nvim-dap", - dependencies = { - "rcarriga/nvim-dap-ui", - "nvim-neotest/nvim-nio", "williamboman/mason.nvim", - "jay-babu/mason-nvim-dap.nvim", + "williamboman/mason-lspconfig.nvim", + "WhoIsSethDaniel/mason-tool-installer.nvim", + { "j-hui/fidget.nvim", opts = {} }, + { "folke/neodev.nvim", opts = {} }, }, - keys = function() - local dap = require("dap") - local dapui = require("dapui") - return { - { "dB", function() dap.set_breakpoint(vim.fn.input('Breakpoint condition: ')) end, desc = "Breakpoint Condition" }, - { "db", function() dap.toggle_breakpoint() end, desc = "Toggle Breakpoint" }, - { "dc", function() dap.continue() end, desc = "Continue" }, - { "dC", function() dap.run_to_cursor() end, desc = "Run to Cursor" }, - { "dg", function() dap.goto_() end, desc = "Go to line (no execute)" }, - { "di", function() dap.step_into() end, desc = "Step Into" }, - { "dj", function() dap.down() end, desc = "Down" }, - { "dk", function() dap.up() end, desc = "Up" }, - { "dl", function() dap.run_last() end, desc = "Run Last" }, - { "do", function() dap.step_out() end, desc = "Step Out" }, - { "dO", function() dap.step_over() end, desc = "Step Over" }, - { "dp", function() dap.pause() end, desc = "Pause" }, - { "dr", function() dap.repl.toggle() end, desc = "Toggle REPL" }, - { "ds", function() dap.session() end, desc = "Session" }, - { "dt", function() dap.terminate() end, desc = "Terminate" }, - { "dw", function() require("dap.ui.widgets").hover() end, desc = "Widgets" }, - { "", function() dap.continue() end, desc = "Debug: Start/Continue" }, - { "", function() dap.step_over() end, desc = "Debug: Step Over" }, - { "", function() dap.step_into() end, desc = "Debug: Step Into" }, - { "", function() dap.step_out() end, desc = "Debug: Step Out" }, - } - end, - config = function() - local dap = require("dap") - local dapui = require("dapui") - - require("mason-nvim-dap").setup({ - automatic_setup = true, - handlers = {}, - ensure_installed = { - "python", - "codelldb", - }, - }) - - dapui.setup({ - icons = { expanded = "โ–พ", collapsed = "โ–ธ", current_frame = "*" }, - controls = { - icons = { - pause = "โธ", - play = "โ–ถ", - step_into = "โŽ", - step_over = "โญ", - step_out = "โฎ", - step_back = "b", - run_last = "โ–ถโ–ถ", - terminate = "โน", - disconnect = "โ", - }, - }, - }) - - dap.listeners.after.event_initialized["dapui_config"] = function() - dapui.open({}) - end - dap.listeners.before.event_terminated["dapui_config"] = function() - dapui.close({}) - end - dap.listeners.before.event_exited["dapui_config"] = function() - dapui.close({}) - end - - -- Install language specific config - require("dap-python").setup("~/.virtualenvs/debugpy/bin/python") - end, }, - -- Python debugging + -- Enhanced Autocompletion { - "mfussenegger/nvim-dap-python", - ft = "python", + "hrsh7th/nvim-cmp", + event = "InsertEnter", dependencies = { - "mfussenegger/nvim-dap", - "rcarriga/nvim-dap-ui", - }, - config = function(_, opts) - local path = require("mason-registry").get_package("debugpy"):get_install_path() - require("dap-python").setup(path .. "/venv/bin/python") - end, - }, - - -- Better notifications - { - "rcarriga/nvim-notify", - keys = { - { - "un", - function() - require("notify").dismiss({ silent = true, pending = true }) - end, - desc = "Dismiss all Notifications", - }, - }, - opts = { - timeout = 3000, - max_height = function() - return math.floor(vim.o.lines * 0.75) - end, - max_width = function() - return math.floor(vim.o.columns * 0.75) - end, - }, - init = function() - vim.notify = require("notify") - end, - }, - - -- Better vim.ui - { - "folke/noice.nvim", - event = "VeryLazy", - opts = { - lsp = { - override = { - ["vim.lsp.util.convert_input_to_markdown_lines"] = true, - ["vim.lsp.util.stylize_markdown"] = true, - ["cmp.entry.get_documentation"] = true, - }, - }, - routes = { - { - filter = { - event = "msg_show", - any = { - { find = "%d+L, %d+B" }, - { find = "; after #%d+" }, - { find = "; before #%d+" }, - }, - }, - view = "mini", - }, - }, - presets = { - bottom_search = true, - command_palette = true, - long_message_to_split = true, - inc_rename = true, - lsp_doc_border = false, - }, - }, - dependencies = { - "MunifTanjim/nui.nvim", - "rcarriga/nvim-notify", + "L3MON4D3/LuaSnip", + "saadparwaiz1/cmp_luasnip", + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-path", + "hrsh7th/cmp-buffer", + "rafamadriz/friendly-snippets", }, }, - -- Buffer remove - { - "echasnovski/mini.bufremove", - keys = { - { "bd", function() require("mini.bufremove").delete(0, false) end, desc = "Delete Buffer" }, - { "bD", function() require("mini.bufremove").delete(0, true) end, desc = "Delete Buffer (Force)" }, - }, - }, + -- Git Integration + { "lewis6991/gitsigns.nvim", opts = {} }, + { "tpope/vim-fugitive" }, + { "kdheepak/lazygit.nvim", dependencies = { "nvim-lua/plenary.nvim" } }, + { "akinsho/git-conflict.nvim", version = "*" }, - -- Session management - { - "folke/persistence.nvim", - event = "BufReadPre", - opts = { options = vim.opt.sessionoptions:get() }, - keys = { - { "qs", function() require("persistence").load() end, desc = "Restore Session" }, - { "ql", function() require("persistence").load({ last = true }) end, desc = "Restore Last Session" }, - { "qd", function() require("persistence").stop() end, desc = "Don't Save Current Session" }, + -- UI Enhancements + { "nvim-lualine/lualine.nvim", dependencies = { "nvim-tree/nvim-web-devicons" } }, + { "akinsho/bufferline.nvim", version = "*", dependencies = "nvim-tree/nvim-web-devicons" }, + { "lukas-reineke/indent-blankline.nvim", main = "ibl", opts = {} }, + + -- Syntax & Editing + { "nvim-treesitter/nvim-treesitter", build = ":TSUpdate" }, + { "windwp/nvim-autopairs", event = "InsertEnter" }, + { "numToStr/Comment.nvim", opts = {} }, + + -- Productivity + { "akinsho/toggleterm.nvim", version = "*" }, + { "folke/which-key.nvim", event = "VimEnter" }, + { "stevearc/conform.nvim" }, + { "mfussenegger/nvim-lint", event = { "BufReadPre", "BufNewFile" } }, +} + +-- ====================== +-- 4. Plugin Configuration +-- ====================== +require("lazy").setup(plugins, { + ui = { + icons = vim.g.have_nerd_font and {} or { + cmd = "โŒ˜", + config = "๐Ÿ› ", + event = "๐Ÿ“…", + ft = "๐Ÿ“‚", + init = "โš™", + keys = "๐Ÿ—", + plugin = "๐Ÿ”Œ", + runtime = "๐Ÿ’ป", + require = "๐ŸŒ™", + source = "๐Ÿ“„", + start = "๐Ÿš€", + task = "๐Ÿ“Œ", + lazy = "๐Ÿ’ค", }, }, -}, { +}) + +-- Neo-tree Configuration +require("neo-tree").setup({ + close_if_last_window = false, + popup_border_style = "rounded", + enable_git_status = true, + enable_diagnostics = true, + filesystem = { + follow_current_file = { enabled = true }, + hijack_netrw_behavior = "open_current", + }, + window = { + position = "left", + width = 30, + mappings = { [""] = "none" }, + }, +}) + +-- Telescope Configuration +require("telescope").setup({ defaults = { - lazy = false, - version = false, - }, - install = { colorscheme = { "tokyonight", "habamax" } }, - checker = { enabled = true }, - performance = { - rtp = { - disabled_plugins = { - "gzip", - "tarPlugin", - "tohtml", - "tutor", - "zipPlugin", + mappings = { + i = { + [""] = false, + [""] = false, }, }, }, }) --- Additional keymaps -local keymap = vim.keymap.set -local opts = { silent = true } +-- LSP Setup with Enhanced Completion +local capabilities = vim.lsp.protocol.make_client_capabilities() +capabilities = require("cmp_nvim_lsp").default_capabilities(capabilities) +capabilities.textDocument.completion.completionItem.snippetSupport = true +capabilities.textDocument.completion.completionItem.resolveSupport = { + properties = { "documentation", "detail", "additionalTextEdits" }, +} --- Better up/down -keymap({ "n", "x" }, "j", "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) -keymap({ "n", "x" }, "k", "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) +require("mason").setup() +require("mason-lspconfig").setup({ + ensure_installed = { + "lua_ls", + "pyright", + "ruff", + "ts_ls", + "html", + "cssls", + "tailwindcss", + "bashls", + "jsonls", + "yamlls", + "dockerls", + }, +}) --- Move to window using the hjkl keys -keymap("n", "", "h", { desc = "Go to left window", remap = true }) -keymap("n", "", "j", { desc = "Go to lower window", remap = true }) -keymap("n", "", "k", { desc = "Go to upper window", remap = true }) -keymap("n", "", "l", { desc = "Go to right window", remap = true }) +local lspconfig = require("lspconfig") +lspconfig.lua_ls.setup({ + capabilities = capabilities, + settings = { + Lua = { + completion = { callSnippet = "Replace" }, + }, + }, +}) --- Resize window using arrow keys -keymap("n", "", "resize +2", { desc = "Increase window height" }) -keymap("n", "", "resize -2", { desc = "Decrease window height" }) -keymap("n", "", "vertical resize -2", { desc = "Decrease window width" }) -keymap("n", "", "vertical resize +2", { desc = "Increase window width" }) - --- Move Lines -keymap("n", "", "m .+1==", { desc = "Move down" }) -keymap("n", "", "m .-2==", { desc = "Move up" }) -keymap("i", "", "m .+1==gi", { desc = "Move down" }) -keymap("i", "", "m .-2==gi", { desc = "Move up" }) -keymap("v", "", ":m '>+1gv=gv", { desc = "Move down" }) -keymap("v", "", ":m '<-2gv=gv", { desc = "Move up" }) - --- Buffers -keymap("n", "", "bprevious", { desc = "Prev buffer" }) -keymap("n", "", "bnext", { desc = "Next buffer" }) -keymap("n", "[b", "bprevious", { desc = "Prev buffer" }) -keymap("n", "]b", "bnext", { desc = "Next buffer" }) - --- Clear search with -keymap({ "i", "n" }, "", "noh", { desc = "Escape and clear hlsearch" }) - --- Save file -keymap({ "i", "x", "n", "s" }, "", "w", { desc = "Save file" }) - --- Better indenting -keymap("v", "<", "", ">gv") - --- Lazy -keymap("n", "l", "Lazy", { desc = "Lazy" }) - --- New file -keymap("n", "fn", "enew", { desc = "New File" }) - --- Quit -keymap("n", "qq", "qa", { desc = "Quit all" }) - --- Highlights under cursor -keymap("n", "ui", vim.show_pos, { desc = "Inspect Pos" }) - --- Python run -keymap("n", "r", function() - if vim.bo.filetype == "python" then - vim.cmd("w") - vim.cmd("!python3 %") - else - print("Not a Python file") - end -end, { desc = "Run Python file" }) - --- Toggle options -keymap("n", "uf", function() - vim.g.disable_autoformat = not vim.g.disable_autoformat - if vim.g.disable_autoformat then - print("Disabled format on save") - else - print("Enabled format on save") - end -end, { desc = "Toggle auto format (global)" }) - -keymap("n", "uF", function() - vim.b.disable_autoformat = not vim.b.disable_autoformat - if vim.b.disable_autoformat then - print("Disabled format on save (buffer)") - else - print("Enabled format on save (buffer)") - end -end, { desc = "Toggle auto format (buffer)" }) - --- Auto commands -local function augroup(name) - return vim.api.nvim_create_augroup("lazyvim_" .. name, { clear = true }) +-- Configure other LSP servers similarly +for _, server in ipairs({ "pyright", "ts_ls", "html", "cssls" }) do + lspconfig[server].setup({ capabilities = capabilities }) end --- Check if we need to reload the file when it changed -vim.api.nvim_create_autocmd({ "FocusGained", "TermClose", "TermLeave" }, { - group = augroup("checktime"), - command = "checktime", +-- Advanced Completion Setup +local cmp = require("cmp") +local luasnip = require("luasnip") + +require("luasnip.loaders.from_vscode").lazy_load() + +local has_words_before = function() + unpack = unpack or table.unpack + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil +end + +cmp.setup({ + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_locally_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { "i", "s" }), + + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), + + [""] = cmp.mapping.confirm({ select = true }), + [""] = cmp.mapping.complete(), + }), + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + { name = "luasnip" }, + { name = "path" }, + { name = "buffer" }, + }), + formatting = { + format = function(entry, item) + item.menu = ({ + nvim_lsp = "[LSP]", + luasnip = "[Snippet]", + buffer = "[Buffer]", + path = "[Path]", + })[entry.source.name] + return item + end, + }, }) --- Highlight on yank +-- ====================== +-- 5. Key Mappings +-- ====================== +-- Navigation +vim.keymap.set("n", "e", vim.diagnostic.open_float) +vim.keymap.set("n", "[d", vim.diagnostic.goto_prev) +vim.keymap.set("n", "]d", vim.diagnostic.goto_next) + +-- File Management +vim.keymap.set("n", "n", ":Neotree toggle") +vim.keymap.set("n", "ff", ":Telescope find_files") +vim.keymap.set("n", "fg", ":Telescope live_grep") + +-- LSP +vim.keymap.set("n", "gd", vim.lsp.buf.definition) +vim.keymap.set("n", "gr", vim.lsp.buf.references) +vim.keymap.set("n", "K", vim.lsp.buf.hover) +vim.keymap.set("n", "rn", vim.lsp.buf.rename) + +-- Git +vim.keymap.set("n", "gs", ":Git") +vim.keymap.set("n", "gg", ":LazyGit") + +-- ====================== +-- 6. Autocommands +-- ====================== vim.api.nvim_create_autocmd("TextYankPost", { - group = augroup("highlight_yank"), + pattern = "*", callback = function() vim.highlight.on_yank() end, }) --- Resize splits if window got resized -vim.api.nvim_create_autocmd({ "VimResized" }, { - group = augroup("resize_splits"), - callback = function() - local current_tab = vim.fn.tabpagenr() - vim.cmd("tabdo wincmd =") - vim.cmd("tabnext " .. current_tab) - end, -}) - --- Go to last loc when opening a buffer -vim.api.nvim_create_autocmd("BufReadPost", { - group = augroup("last_loc"), - callback = function(event) - local exclude = { "gitcommit" } - local buf = event.buf - if vim.tbl_contains(exclude, vim.bo[buf].filetype) or vim.b[buf].lazyvim_last_loc then - return - end - vim.b[buf].lazyvim_last_loc = true - local mark = vim.api.nvim_buf_get_mark(buf, '"') - local lcount = vim.api.nvim_buf_line_count(buf) - if mark[1] > 0 and mark[1] <= lcount then - pcall(vim.api.nvim_win_set_cursor, 0, mark) - end - end, -}) - --- Close some filetypes with -vim.api.nvim_create_autocmd("FileType", { - group = augroup("close_with_q"), - pattern = { - "PlenaryTestPopup", - "help", - "lspinfo", - "man", - "notify", - "qf", - "query", - "spectre_panel", - "startuptime", - "tsplayground", - "neotest-output", - "checkhealth", - "neotest-summary", - "neotest-output-panel", - }, - callback = function(event) - vim.bo[event.buf].buflisted = false - vim.keymap.set("n", "q", "close", { buffer = event.buf, silent = true }) - end, -}) - --- Wrap and check for spell in text filetypes -vim.api.nvim_create_autocmd("FileType", { - group = augroup("wrap_spell"), - pattern = { "gitcommit", "markdown" }, - callback = function() - vim.opt_local.wrap = true - vim.opt_local.spell = true - end, -}) - --- Auto create dir when saving a file, in case some intermediate directory does not exist -vim.api.nvim_create_autocmd({ "BufWritePre" }, { - group = augroup("auto_create_dir"), - callback = function(event) - if event.match:match("^%w%w+://") then - return - end - local file = vim.loop.fs_realpath(event.match) or event.match - vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p") - end, -}) - --- Format on save for web files vim.api.nvim_create_autocmd("BufWritePre", { - group = augroup("format_web_files"), - pattern = { "*.html", "*.css", "*.js", "*.ts", "*.json" }, + pattern = "*", callback = function() - if vim.g.disable_autoformat or vim.b.disable_autoformat then - return - end - local conform = require("conform") - conform.format({ async = false, lsp_fallback = true }) + require("conform").format({ async = false, lsp_fallback = true }) end, }) + +print("๐Ÿš€ Neovim configuration fully loaded with:") +print(" - VSCode-like tab completion") +print(" - Enhanced LSP support") +print(" - Git integration") +print(" - Beautiful UI components")