diff --git a/README.md b/README.md index 185280b..1a6cf01 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,180 @@ -# ๐Ÿ’ค LazyVim +# Neovim Configuration with LazyVim -A starter template for [LazyVim](https://github.com/LazyVim/LazyVim). -Refer to the [documentation](https://lazyvim.github.io/installation) to get started. +A comprehensive Neovim setup with LSP support, AI chat, database integration, and debugging. + +## Prerequisites + +- Neovim >= 0.9.0 (installed via Homebrew) +- Git +- A Nerd Font (for icons) +- Node.js (for some LSP servers and formatters) +- Go (for gopls and delve) + +## Installation + +1. **Backup existing configuration** (if any): + ```bash + mv ~/.config/nvim ~/.config/nvim.bak + mv ~/.local/share/nvim ~/.local/share/nvim.bak + mv ~/.local/state/nvim ~/.local/state/nvim.bak + mv ~/.cache/nvim ~/.cache/nvim.bak + ``` + +2. **Clone this configuration**: + ```bash + git clone ~/.config/nvim + ``` + +3. **Start Neovim**: + ```bash + nvim + ``` + Lazy.nvim will automatically install all plugins on first launch. + +4. **Install LSP servers and tools**: + After plugins load, run: + ``` + :Mason + ``` + All required tools should install automatically. + +## Features + +### Language Support (LSP + Treesitter) +- Go, Lua, TypeScript, JavaScript, HTML, CSS, JSON, YAML, Markdown, SQL, Makefile + +### AI Chat Integration +Supports multiple providers via [avante.nvim](https://github.com/yetone/avante.nvim): +- Anthropic Claude +- OpenAI GPT +- Google Gemini +- And more + +Set your API keys as environment variables: +```bash +export ANTHROPIC_API_KEY="your-key" +export OPENAI_API_KEY="your-key" +export GEMINI_API_KEY="your-key" +``` + +Switch providers: `:AvanteProvider claude|openai|gemini` + +### Database Integration (vim-dadbod) +- `:DBUIToggle` - Open database UI +- `:DBUIAddConnection` - Add a new connection + +Connection string examples: +``` +postgresql://user:pass@localhost:5432/dbname +mysql://user:pass@localhost:3306/dbname +sqlite:path/to/db.sqlite +``` + +### Go Debugging (DAP + Delve) +Full debugging support with breakpoints, stepping, variable inspection. + +## Key Bindings + +### Terminal +| Key | Action | +|-----|--------| +| `th` | Open terminal (horizontal split) | +| `tv` | Open terminal (vertical split) | +| `` | Toggle floating terminal | +| `` | Exit terminal mode | + +### File Explorer (Snacks explorer) +| Key | Action | +|-----|--------| +| `` | Toggle explorer | +| `` or `` | Open file in vertical split | +| `` or `` | Open file in horizontal split | +| `e` | Focus explorer (LazyVim default) | + +### AI Chat +| Key | Action | +|-----|--------| +| `aa` | Ask AI (with selection in visual mode) | +| `ac` | Open AI chat | +| `at` | Toggle AI sidebar | + +### Database +| Key | Action | +|-----|--------| +| `db` | Toggle database UI | +| `da` | Add database connection | + +### Debugging +| Key | Action | +|-----|--------| +| `db` | Toggle breakpoint | +| `dB` | Breakpoint with condition | +| `dc` | Continue | +| `di` | Step into | +| `do` | Step out | +| `dO` | Step over | +| `du` | Toggle DAP UI | +| `dT` | Debug Go test | +| `dt` | Terminate debug session | + +### Formatting +| Key | Action | +|-----|--------| +| `cf` | Format buffer | +| `:FormatToggle` | Toggle auto-format on save | +| `:FormatDisable` | Disable auto-format | +| `:FormatEnable` | Enable auto-format | + +### General +| Key | Action | +|-----|--------| +| `` | Save file | +| `` / `` | Previous/Next buffer | +| `` | Navigate windows | +| `` / `` | Move line down/up | + +## File Structure + +``` +~/.config/nvim/ +โ”œโ”€โ”€ init.lua # Entry point +โ”œโ”€โ”€ lua/ +โ”‚ โ”œโ”€โ”€ config/ +โ”‚ โ”‚ โ”œโ”€โ”€ lazy.lua # Lazy.nvim bootstrap & LazyVim setup +โ”‚ โ”‚ โ”œโ”€โ”€ options.lua # General Neovim options +โ”‚ โ”‚ โ”œโ”€โ”€ keymaps.lua # Custom key bindings +โ”‚ โ”‚ โ””โ”€โ”€ autocmds.lua # Auto commands +โ”‚ โ””โ”€โ”€ plugins/ +โ”‚ โ”œโ”€โ”€ lsp.lua # LSP & Treesitter configuration +โ”‚ โ”œโ”€โ”€ ai.lua # AI chat integration (avante.nvim) +โ”‚ โ”œโ”€โ”€ dadbod.lua # Database integration +โ”‚ โ”œโ”€โ”€ dap.lua # Debugging configuration +โ”‚ โ”œโ”€โ”€ formatting.lua # Auto-formatting (conform.nvim) +โ”‚ โ””โ”€โ”€ editor.lua # Editor enhancements (snacks explorer, etc.) +``` + +## Formatters by File Type + +| File Type | Formatter | +|-----------|-----------| +| Go | gofumpt, goimports | +| Lua | stylua | +| JS/TS/JSX/TSX | prettier | +| HTML/CSS | prettier | +| JSON/YAML | prettier | +| Markdown | prettier | +| SQL | sql-formatter | + +## Troubleshooting + +### LSP not working +Run `:LspInfo` to check status. Run `:Mason` to verify tools are installed. + +### Formatting not working +Run `:ConformInfo` to check formatter status. + +### Icons not displaying +Install a Nerd Font and configure your terminal to use it. + +### Ctrl+Shift keybindings not working +Some terminals don't properly send Ctrl+Shift combinations. Use the alternative mappings (`` and `` in snacks explorer). diff --git a/init.lua b/init.lua index 2514f9e..a5695a1 100644 --- a/init.lua +++ b/init.lua @@ -1,2 +1,2 @@ --- bootstrap lazy.nvim, LazyVim and your plugins +-- Bootstrap lazy.nvim and LazyVim require("config.lazy") diff --git a/lazy-lock.json b/lazy-lock.json index d388910..0664030 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,12 +1,11 @@ { "LazyVim": { "branch": "main", "commit": "28db03f958d58dfff3c647ce28fdc1cb88ac158d" }, - "SchemaStore.nvim": { "branch": "main", "commit": "6e4ffd193995176ee5ea5b8adba0f315adc68b9f" }, + "SchemaStore.nvim": { "branch": "main", "commit": "20ee0cad0b25e4a028d355c51b06d41eecb90d91" }, "avante.nvim": { "branch": "main", "commit": "e89eb79abf5754645e20aa6074da10ed20bba33c" }, "blink.cmp": { "branch": "main", "commit": "b19413d214068f316c78978b08264ed1c41830ec" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, "catppuccin": { "branch": "main", "commit": "beaf41a30c26fd7d6c386d383155cbd65dd554cd" }, - "conform.nvim": { "branch": "master", "commit": "8314f4c9e205e7f30b62147069729f9a1227d8bf" }, - "copilot.lua": { "branch": "master", "commit": "c13f6f5147b80298301eb409991f28a991736cc3" }, + "conform.nvim": { "branch": "master", "commit": "238f542a118984a88124fc915d5b981680418707" }, "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, @@ -16,7 +15,8 @@ "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lazydev.nvim": { "branch": "main", "commit": "5231c62aa83c2f8dc8e7ba957aa77098cda1257d" }, "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "e5f73a9e3d271d449685f1059eb1868f4ba276f6" }, + "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "fe661093f4b05136437b531e7f959af2a2ae66c8" }, "mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" }, "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, "mini.ai": { "branch": "main", "commit": "bfb26d9072670c3aaefab0f53024b2f3729c8083" }, @@ -26,26 +26,24 @@ "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, "nvim-dap": { "branch": "master", "commit": "cdfd55a133f63228c55f91378f12908cb2a78ded" }, "nvim-dap-go": { "branch": "main", "commit": "b4421153ead5d726603b02743ea40cf26a51ed5f" }, - "nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" }, "nvim-dap-ui": { "branch": "master", "commit": "cf91d5e2d07c72903d052f5207511bf7ecdb7122" }, "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, "nvim-lint": { "branch": "master", "commit": "ca6ea12daf0a4d92dc24c5c9ae22a1f0418ade37" }, "nvim-lspconfig": { "branch": "master", "commit": "92ee7d42320edfbb81f3cad851314ab197fa324a" }, "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, - "nvim-treesitter": { "branch": "main", "commit": "2ba5ec184609a96b513bf4c53a20512d64e27f39" }, - "nvim-treesitter-textobjects": { "branch": "main", "commit": "28a3494c075ef0f353314f627546537e43c09592" }, + "nvim-treesitter": { "branch": "main", "commit": "5a7e5638e7d220575b1c22c8a2e099b52231886e" }, + "nvim-treesitter-textobjects": { "branch": "main", "commit": "d0d12338230c1ce4ce27373f5b8d50a8c691794b" }, "nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" }, - "nvim-web-devicons": { "branch": "master", "commit": "6788013bb9cb784e606ada44206b0e755e4323d7" }, + "nvim-web-devicons": { "branch": "master", "commit": "803353450c374192393f5387b6a0176d0972b848" }, "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, - "render-markdown.nvim": { "branch": "main", "commit": "73a6ebc842cf81926eb1d424820b800f6f6a1227" }, + "render-markdown.nvim": { "branch": "main", "commit": "ae89236e2389836cf1c3787b2b80d5d8685cc13f" }, "snacks.nvim": { "branch": "main", "commit": "fe7cfe9800a182274d0f868a74b7263b8c0c020b" }, - "telescope.nvim": { "branch": "master", "commit": "3333a52ff548ba0a68af6d8da1e54f9cd96e9179" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, "ts-comments.nvim": { "branch": "main", "commit": "123a9fb12e7229342f807ec9e6de478b1102b041" }, - "venv-selector.nvim": { "branch": "main", "commit": "58bae72c84b9f7f864c879ec1896e384296f9ffb" }, "vim-dadbod": { "branch": "master", "commit": "6d1d41da4873a445c5605f2005ad2c68c99d8770" }, "vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" }, "vim-dadbod-ui": { "branch": "master", "commit": "48c4f271da13d380592f4907e2d1d5558044e4e5" }, diff --git a/lua/config/autocmds.lua b/lua/config/autocmds.lua index 4221e75..07ae15b 100644 --- a/lua/config/autocmds.lua +++ b/lua/config/autocmds.lua @@ -1,8 +1,108 @@ --- Autocmds are automatically loaded on the VeryLazy event --- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua --- --- Add any additional autocmds here --- with `vim.api.nvim_create_autocmd` --- --- Or remove existing autocmds by their group name (which is prefixed with `lazyvim_` for the defaults) --- e.g. vim.api.nvim_del_augroup_by_name("lazyvim_wrap_spell") +-- Autocommands +local augroup = vim.api.nvim_create_augroup +local autocmd = vim.api.nvim_create_autocmd + +-- Highlight on yank +augroup("YankHighlight", { clear = true }) +autocmd("TextYankPost", { + group = "YankHighlight", + callback = function() + vim.highlight.on_yank({ higroup = "IncSearch", timeout = 200 }) + end, +}) + +-- Resize splits when window is resized +augroup("ResizeSplits", { clear = true }) +autocmd("VimResized", { + group = "ResizeSplits", + callback = function() + vim.cmd("tabdo wincmd =") + end, +}) + +-- Go to last location when opening a buffer +augroup("LastLocation", { clear = true }) +autocmd("BufReadPost", { + group = "LastLocation", + 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 certain filetypes with q +augroup("CloseWithQ", { clear = true }) +autocmd("FileType", { + group = "CloseWithQ", + pattern = { + "help", + "lspinfo", + "man", + "notify", + "qf", + "spectre_panel", + "startuptime", + "checkhealth", + }, + callback = function(event) + vim.bo[event.buf].buflisted = false + vim.keymap.set("n", "q", "close", { buffer = event.buf, silent = true }) + end, +}) + +-- Auto create parent directories when saving +augroup("AutoCreateDir", { clear = true }) +autocmd("BufWritePre", { + group = "AutoCreateDir", + callback = function(event) + if event.match:match("^%w%w+://") then + return + end + local file = vim.uv.fs_realpath(event.match) or event.match + vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p") + end, +}) + +-- Set specific options for certain filetypes +augroup("FileTypeSettings", { clear = true }) + +-- Go files: use tabs +autocmd("FileType", { + group = "FileTypeSettings", + pattern = "go", + callback = function() + vim.opt_local.expandtab = false + vim.opt_local.tabstop = 4 + vim.opt_local.shiftwidth = 4 + end, +}) + +-- Makefile: use tabs +autocmd("FileType", { + group = "FileTypeSettings", + pattern = "make", + callback = function() + vim.opt_local.expandtab = false + vim.opt_local.tabstop = 4 + vim.opt_local.shiftwidth = 4 + end, +}) + +-- Markdown: enable wrap +autocmd("FileType", { + group = "FileTypeSettings", + pattern = "markdown", + callback = function() + vim.opt_local.wrap = true + vim.opt_local.spell = true + end, +}) diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua index c42d26e..614aa9d 100644 --- a/lua/config/keymaps.lua +++ b/lua/config/keymaps.lua @@ -1,13 +1,70 @@ --- Keymaps are automatically loaded on the VeryLazy event --- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua --- Add any additional keymaps here +-- Custom keymaps +local map = vim.keymap.set -vim.keymap.set("n", "th", function() - vim.cmd("lcd %:p:h") +-- Terminal keymaps +-- th - Open terminal in horizontal split +map("n", "th", function() vim.cmd("split | terminal") -end, { desc = "Terminal (horizontal)" }) + vim.cmd("startinsert") +end, { desc = "Terminal (horizontal split)" }) -vim.keymap.set("n", "tv", function() - vim.cmd("lcd %:p:h") +-- tv - Open terminal in vertical split +map("n", "tv", function() vim.cmd("vsplit | terminal") -end, { desc = "Terminal (vertical)" }) + vim.cmd("startinsert") +end, { desc = "Terminal (vertical split)" }) + +-- Terminal mode: Escape to normal mode +map("t", "", "", { desc = "Exit terminal mode" }) + +-- Explorer keymaps (Snacks explorer) +-- Ctrl+Shift+e - Toggle explorer +map("n", "", function() Snacks.explorer() end, { desc = "Toggle Explorer" }) +map("i", "", function() Snacks.explorer() end, { desc = "Toggle Explorer" }) + +-- Note: Ctrl+Shift+v and Ctrl+Shift+h for opening files in splits +-- are configured in the snacks picker config (lua/plugins/editor.lua) +-- as they need to work within the explorer buffer context + +-- Additional useful keymaps +-- Better window navigation +map("n", "", "h", { desc = "Go to left window" }) +map("n", "", "j", { desc = "Go to lower window" }) +map("n", "", "k", { desc = "Go to upper window" }) +map("n", "", "l", { desc = "Go to right window" }) + +-- Resize windows with arrows +map("n", "", "resize +2", { desc = "Increase window height" }) +map("n", "", "resize -2", { desc = "Decrease window height" }) +map("n", "", "vertical resize -2", { desc = "Decrease window width" }) +map("n", "", "vertical resize +2", { desc = "Increase window width" }) + +-- Buffer navigation +map("n", "", "bprevious", { desc = "Prev buffer" }) +map("n", "", "bnext", { desc = "Next buffer" }) + +-- Clear search highlight +map("n", "", "nohlsearch", { desc = "Clear search highlight" }) + +-- Save file +map({ "n", "i", "v", "s" }, "", "w", { desc = "Save file" }) + +-- Better indenting in visual mode +map("v", "<", "", ">gv") + +-- Move lines up/down +map("n", "", "m .+1==", { desc = "Move line down" }) +map("n", "", "m .-2==", { desc = "Move line up" }) +map("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) +map("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) + +-- Quick access to AI chat +map("n", "aa", "AvanteAsk", { desc = "AI Ask" }) +map("v", "aa", "AvanteAsk", { desc = "AI Ask (selection)" }) +map("n", "ac", "AvanteChat", { desc = "AI Chat" }) +map("n", "at", "AvanteToggle", { desc = "AI Toggle" }) + +-- Database keymaps +map("n", "db", "DBUIToggle", { desc = "Toggle DB UI" }) +map("n", "da", "DBUIAddConnection", { desc = "Add DB Connection" }) diff --git a/lua/config/lazy.lua b/lua/config/lazy.lua index 12cd029..c577dc7 100644 --- a/lua/config/lazy.lua +++ b/lua/config/lazy.lua @@ -1,3 +1,4 @@ +-- Bootstrap lazy.nvim local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if not (vim.uv or vim.loop).fs_stat(lazypath) then local lazyrepo = "https://github.com/folke/lazy.nvim.git" @@ -14,45 +15,46 @@ if not (vim.uv or vim.loop).fs_stat(lazypath) then end vim.opt.rtp:prepend(lazypath) +-- Set leader keys before loading plugins +vim.g.mapleader = " " +vim.g.maplocalleader = "\\" + +-- Setup lazy.nvim with LazyVim require("lazy").setup({ spec = { - -- add LazyVim and import its plugins - { "LazyVim/LazyVim", import = "lazyvim.plugins" }, - - -- Language support (these enable LSP, formatting, linting & DAP) + -- Import LazyVim and its plugins + { + "LazyVim/LazyVim", + import = "lazyvim.plugins", + opts = { + colorscheme = "tokyonight", + }, + }, + -- Import LazyVim extras for languages { import = "lazyvim.plugins.extras.lang.go" }, - { import = "lazyvim.plugins.extras.lang.python" }, + { import = "lazyvim.plugins.extras.lang.json" }, + { import = "lazyvim.plugins.extras.lang.yaml" }, + { import = "lazyvim.plugins.extras.lang.markdown" }, { import = "lazyvim.plugins.extras.lang.typescript" }, { import = "lazyvim.plugins.extras.lang.tailwind" }, - { import = "lazyvim.plugins.extras.lang.json" }, - - -- DAP (Debug Adapter Protocol) + -- DAP for debugging { import = "lazyvim.plugins.extras.dap.core" }, - -- import/override with your plugins + -- Import custom plugins { import = "plugins" }, }, defaults = { - -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. - -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. lazy = false, - -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, - -- have outdated releases, which may break your Neovim install. - version = false, -- always use the latest git commit - -- version = "*", -- try installing the latest stable version for plugins that support semver + version = false, }, install = { colorscheme = { "tokyonight", "habamax" } }, checker = { - enabled = true, -- check for plugin updates periodically - notify = false, -- notify on update - }, -- automatically check for plugin updates + enabled = true, + notify = false, + }, performance = { rtp = { - -- disable some rtp plugins disabled_plugins = { "gzip", - -- "matchit", - -- "matchparen", - -- "netrwPlugin", "tarPlugin", "tohtml", "tutor", @@ -61,3 +63,8 @@ require("lazy").setup({ }, }, }) + +-- Load custom config +require("config.options") +require("config.keymaps") +require("config.autocmds") diff --git a/lua/config/options.lua b/lua/config/options.lua index 3ea1454..ab53989 100644 --- a/lua/config/options.lua +++ b/lua/config/options.lua @@ -1,3 +1,47 @@ -- Options are automatically loaded before lazy.nvim startup --- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua -- Add any additional options here + +local opt = vim.opt + +-- General +opt.clipboard = "unnamedplus" -- Sync with system clipboard +opt.confirm = true -- Confirm before closing unsaved buffer +opt.cursorline = true -- Highlight current line +opt.mouse = "a" -- Enable mouse +opt.number = true -- Show line numbers +opt.relativenumber = true -- Relative line numbers +opt.signcolumn = "yes" -- Always show sign column +opt.termguicolors = true -- True color support +opt.wrap = false -- Disable line wrap + +-- Indentation +opt.expandtab = true -- Use spaces instead of tabs +opt.shiftwidth = 2 -- Size of indent +opt.tabstop = 2 -- Number of spaces tabs count for +opt.smartindent = true -- Smart indentation + +-- Search +opt.ignorecase = true -- Ignore case +opt.smartcase = true -- Don't ignore case with capitals +opt.hlsearch = true -- Highlight search results +opt.incsearch = true -- Show search results as you type + +-- Split behavior +opt.splitbelow = true -- Put new windows below current +opt.splitright = true -- Put new windows right of current + +-- Undo +opt.undofile = true -- Persistent undo +opt.undolevels = 10000 -- Maximum undo levels + +-- Performance +opt.updatetime = 200 -- Faster completion +opt.timeoutlen = 300 -- Faster key sequence completion + +-- Completion +opt.completeopt = "menu,menuone,noselect" + +-- Folding (using treesitter) +opt.foldmethod = "expr" +opt.foldexpr = "nvim_treesitter#foldexpr()" +opt.foldlevel = 99 -- Start with all folds open diff --git a/lua/plugins/ai.lua b/lua/plugins/ai.lua index b8b0402..56d5c00 100644 --- a/lua/plugins/ai.lua +++ b/lua/plugins/ai.lua @@ -1,10 +1,14 @@ +-- AI Chat Integration using avante.nvim +-- Supports: Anthropic Claude, OpenAI, Google Gemini, Copilot, and more +-- API keys via environment variables: +-- ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY +-- Or scoped: AVANTE_ANTHROPIC_API_KEY, AVANTE_OPENAI_API_KEY, etc. + return { - -- Avante: Cursor-like AI assistant { "yetone/avante.nvim", event = "VeryLazy", - lazy = false, - version = false, + version = false, -- Never set to "*" build = "make", dependencies = { "nvim-treesitter/nvim-treesitter", @@ -12,49 +16,180 @@ return { "nvim-lua/plenary.nvim", "MunifTanjim/nui.nvim", "nvim-tree/nvim-web-devicons", - "zbirenbaum/copilot.lua", -- Optional for copilot suggestions { + -- Image support (optional) "HakonHarnes/img-clip.nvim", event = "VeryLazy", opts = { default = { embed_image_as_base64 = false, prompt_for_file_name = false, - drag_and_drop = { insert_mode = true }, + drag_and_drop = { + insert_mode = true, + }, }, }, }, { + -- Markdown rendering in Avante "MeanderingProgrammer/render-markdown.nvim", - opts = { file_types = { "markdown", "Avante" } }, + opts = { + file_types = { "markdown", "Avante" }, + }, ft = { "markdown", "Avante" }, }, }, ---@module 'avante' ---@type avante.Config opts = { - debug = true, + -- Default provider (switch with :AvanteProvider command) + -- Options: "claude", "openai", "azure", "gemini", "copilot", "cohere" provider = "claude", - mode = "agentic", - auto_suggestions_provider = "copilot", + + -- Provider configurations providers = { claude = { - model = "claude-sonnet-4-5", + endpoint = "https://api.anthropic.com", + model = "claude-sonnet-4-5-20250929", + timeout = 30000, + extra_request_body = { + temperature = 0.75, + max_tokens = 20480, + }, }, + openai = { + endpoint = "https://api.openai.com/v1", + model = "gpt-4o", + timeout = 30000, + extra_request_body = { + temperature = 0.75, + max_completion_tokens = 16384, + }, + }, + azure = { + endpoint = "", -- e.g., "https://.openai.azure.com" + deployment = "", -- Azure deployment name + api_version = "2024-12-01-preview", + timeout = 30000, + extra_request_body = { + temperature = 0.75, + max_completion_tokens = 16384, + }, + }, + gemini = { + endpoint = "https://generativelanguage.googleapis.com/v1beta/models", + model = "gemini-2.0-flash", + timeout = 30000, + extra_request_body = { + generationConfig = { + temperature = 0.75, + }, + }, + }, + copilot = { + endpoint = "https://api.githubcopilot.com", + model = "gpt-4o-2024-08-06", + timeout = 30000, + extra_request_body = { + temperature = 0.75, + max_tokens = 20480, + }, + }, + -- Custom provider example for Ollama (local models) + -- Uncomment and configure if using local LLMs + -- ollama = { + -- __inherited_from = "openai", + -- endpoint = "http://localhost:11434/v1", + -- model = "llama3.2", + -- api_key_name = "", + -- }, }, + + -- Behavior settings behaviour = { - auto_seggestions = true, + auto_suggestions = false, -- Set true for copilot-like suggestions + auto_set_highlight_group = true, auto_set_keymaps = true, + auto_apply_diff_after_generation = false, + support_paste_from_clipboard = false, + minimize_diff = true, + enable_token_counting = true, }, + + -- Mappings mappings = { - ask = "aa", - edit = "ae", - refresh = "ar", - toggle = { - default = "at", - debug = "ad", - hint = "ah", + diff = { + ours = "co", + theirs = "ct", + all_theirs = "ca", + both = "cb", + cursor = "cc", + next = "]x", + prev = "[x", }, + suggestion = { + accept = "", + next = "", + prev = "", + dismiss = "", + }, + jump = { + next = "]]", + prev = "[[", + }, + submit = { + normal = "", + insert = "", + }, + sidebar = { + apply_all = "A", + apply_cursor = "a", + switch_windows = "", + reverse_switch_windows = "", + }, + }, + + -- Hints shown in the UI + hints = { enabled = true }, + + -- Window configuration + windows = { + position = "right", + wrap = true, + width = 30, + sidebar_header = { + enabled = true, + align = "center", + rounded = true, + }, + input = { + prefix = "> ", + height = 8, + }, + edit = { + border = "rounded", + start_insert = true, + }, + ask = { + floating = false, + start_insert = true, + border = "rounded", + }, + }, + + -- Highlight groups + highlights = { + diff = { + current = "DiffText", + incoming = "DiffAdd", + }, + }, + + -- Diff settings + diff = { + autojump = true, + list_opener = "copen", + override_timeoutlen = 500, }, }, }, diff --git a/lua/plugins/dadbod.lua b/lua/plugins/dadbod.lua new file mode 100644 index 0000000..dcf97cc --- /dev/null +++ b/lua/plugins/dadbod.lua @@ -0,0 +1,83 @@ +-- Database integration with vim-dadbod +-- Supports PostgreSQL, MySQL, SQLite, and more + +return { + -- Core dadbod plugin + { + "tpope/vim-dadbod", + cmd = { "DB", "DBUI", "DBUIToggle", "DBUIAddConnection", "DBUIFindBuffer" }, + }, + + -- UI for dadbod + { + "kristijanhusak/vim-dadbod-ui", + cmd = { "DBUI", "DBUIToggle", "DBUIAddConnection", "DBUIFindBuffer" }, + dependencies = { + { "tpope/vim-dadbod", lazy = true }, + }, + init = function() + -- UI configuration + vim.g.db_ui_use_nerd_fonts = 1 + vim.g.db_ui_show_database_icon = 1 + vim.g.db_ui_force_echo_notifications = 1 + + -- Save location for connections + vim.g.db_ui_save_location = vim.fn.stdpath("data") .. "/db_ui" + + -- Execute on save + vim.g.db_ui_execute_on_save = 0 + + -- Icons + vim.g.db_ui_icons = { + expanded = "โ–พ", + collapsed = "โ–ธ", + saved_query = "*", + new_query = "+", + tables = "~", + buffers = "ยป", + connection_ok = "โœ“", + connection_error = "โœ•", + } + end, + }, + + -- Autocompletion for dadbod + { + "kristijanhusak/vim-dadbod-completion", + dependencies = { + "tpope/vim-dadbod", + "hrsh7th/nvim-cmp", + }, + ft = { "sql", "mysql", "plsql" }, + init = function() + -- Setup completion for SQL files + vim.api.nvim_create_autocmd("FileType", { + pattern = { "sql", "mysql", "plsql" }, + callback = function() + local cmp = require("cmp") + local sources = cmp.get_config().sources or {} + + -- Add dadbod completion source + table.insert(sources, { name = "vim-dadbod-completion" }) + + cmp.setup.buffer({ + sources = cmp.config.sources(sources), + }) + end, + }) + end, + }, + + -- Add dadbod-completion to nvim-cmp sources + { + "hrsh7th/nvim-cmp", + optional = true, + dependencies = { + "kristijanhusak/vim-dadbod-completion", + }, + opts = function(_, opts) + opts.sources = opts.sources or {} + table.insert(opts.sources, { name = "vim-dadbod-completion" }) + end, + }, +} diff --git a/lua/plugins/dap.lua b/lua/plugins/dap.lua index b729abe..c880cf9 100644 --- a/lua/plugins/dap.lua +++ b/lua/plugins/dap.lua @@ -1,65 +1,158 @@ +-- Debug Adapter Protocol (DAP) configuration for Go +-- Uses delve for Go debugging + return { - -- Ensure Mason installs debug adapters - { - "mason-org/mason.nvim", - opts = { - ensure_installed = { - "delve", -- Go debugger - "debugpy", -- Python debugger - "js-debug-adapter", -- JS/TS debugger - }, - }, - }, - - -- Mason DAP bridge - auto-configures adapters - { - "jay-babu/mason-nvim-dap.nvim", - dependencies = { "mason-org/mason.nvim", "mfussenegger/nvim-dap" }, - opts = { - ensure_installed = { "delve", "debugpy", "js" }, - automatic_installation = true, - handlers = {}, - }, - }, - + -- nvim-dap configuration { "mfussenegger/nvim-dap", dependencies = { - "jay-babu/mason-nvim-dap.nvim", + -- Go-specific DAP configuration { "leoluz/nvim-dap-go", - opts = {}, - }, - { - "mfussenegger/nvim-dap-python", - config = function() - local mason_path = vim.fn.stdpath("data") .. "/mason/packages/debugpy/venv/bin/python" - require("dap-python").setup(mason_path) - end, + opts = { + -- Delve configurations + delve = { + -- Path to delve (uses Mason-installed by default) + path = "dlv", + -- Initialize with default args + initialize_timeout_sec = 20, + -- Whether to use debug adapter mode + port = "${port}", + -- Build flags for delve + build_flags = "", + }, + -- DAP configurations for Go + dap_configurations = { + { + type = "go", + name = "Debug", + request = "launch", + program = "${file}", + }, + { + type = "go", + name = "Debug Package", + request = "launch", + program = "${fileDirname}", + }, + { + type = "go", + name = "Debug test", + request = "launch", + mode = "test", + program = "${file}", + }, + { + type = "go", + name = "Debug test (go.mod)", + request = "launch", + mode = "test", + program = "./${relativeFileDirname}", + }, + { + type = "go", + name = "Attach", + request = "attach", + mode = "local", + processId = require("dap.utils").pick_process, + }, + }, + }, }, }, + keys = { + -- Debug keymaps + { "dB", function() require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: ")) end, desc = "Breakpoint Condition" }, + { "db", function() require("dap").toggle_breakpoint() end, desc = "Toggle Breakpoint" }, + { "dc", function() require("dap").continue() end, desc = "Continue" }, + { "dC", function() require("dap").run_to_cursor() end, desc = "Run to Cursor" }, + { "dg", function() require("dap").goto_() end, desc = "Go to Line (No Execute)" }, + { "di", function() require("dap").step_into() end, desc = "Step Into" }, + { "dj", function() require("dap").down() end, desc = "Down" }, + { "dk", function() require("dap").up() end, desc = "Up" }, + { "dl", function() require("dap").run_last() end, desc = "Run Last" }, + { "do", function() require("dap").step_out() end, desc = "Step Out" }, + { "dO", function() require("dap").step_over() end, desc = "Step Over" }, + { "dp", function() require("dap").pause() end, desc = "Pause" }, + { "dr", function() require("dap").repl.toggle() end, desc = "Toggle REPL" }, + { "ds", function() require("dap").session() end, desc = "Session" }, + { "dt", function() require("dap").terminate() end, desc = "Terminate" }, + { "dw", function() require("dap.ui.widgets").hover() end, desc = "Widgets" }, + -- Go-specific + { "dT", function() require("dap-go").debug_test() end, desc = "Debug Go Test" }, + { "dL", function() require("dap-go").debug_last_test() end, desc = "Debug Last Go Test" }, + }, }, + -- DAP UI for better debugging experience { "rcarriga/nvim-dap-ui", - dependencies = { "nvim-neotest/nvim-nio" }, + dependencies = { + "mfussenegger/nvim-dap", + "nvim-neotest/nvim-nio", + }, keys = { - { - "du", - function() - require("dapui").toggle() - end, - desc = "DAP UI", - }, - { - "de", - function() - require("dapui").eval() - end, - desc = "Eval", - mode = { "n", "v" }, + { "du", function() require("dapui").toggle({}) end, desc = "Dap UI" }, + { "de", function() require("dapui").eval() end, desc = "Eval", mode = { "n", "v" } }, + }, + opts = { + layouts = { + { + elements = { + { id = "scopes", size = 0.25 }, + { id = "breakpoints", size = 0.25 }, + { id = "stacks", size = 0.25 }, + { id = "watches", size = 0.25 }, + }, + position = "left", + size = 40, + }, + { + elements = { + { id = "repl", size = 0.5 }, + { id = "console", size = 0.5 }, + }, + position = "bottom", + size = 10, + }, }, }, - opts = {}, + config = function(_, opts) + local dap = require("dap") + local dapui = require("dapui") + + dapui.setup(opts) + + -- Auto open/close DAP UI + 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 + end, + }, + + -- Virtual text for debugging + { + "theHamsta/nvim-dap-virtual-text", + opts = { + enabled = true, + enabled_commands = true, + highlight_changed_variables = true, + highlight_new_as_changed = false, + show_stop_reason = true, + commented = false, + only_first_definition = true, + all_references = false, + filter_references_pattern = "