diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..f27bf36bd01 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,147 @@ +# AGENTS.md - Development Guide for AI Coding Agents + +This file provides essential information for AI coding agents working in this Neovim configuration repository. It covers build/lint/test commands, code style guidelines, and project conventions. + +## Build/Lint/Test Commands + +### Linting +- **Command**: `:lua require('lint').try_lint()` +- **Description**: Run linting on current buffer using nvim-lint plugin +- **File types**: Currently configured for markdown files with `markdownlint` +- **Manual command**: `markdownlint-cli file.md` (if available globally) +- **CI**: GitHub Actions runs stylua formatting checks + +### Formatting +- **Command**: `:lua require('conform').format({ async = true, lsp_format = 'fallback' })` +- **Keybinding**: `f` (normal/visual mode) +- **Formatters by filetype**: Lua: `stylua`, Python: `isort`/`black`, JavaScript: `prettier`, Go: `gofmt`, Rust: `rustfmt`, YAML: `yamlfix`, TOML: `taplo`, Terraform: `terraform_fmt`, Markdown: `markdownlint` + +### Testing +- **Status**: No automated testing framework configured +- **Manual testing**: `:checkhealth` for Neovim health checks, `:Lazy` for plugin status +- **Single test execution**: N/A - use `:checkhealth` for comprehensive checks + +## Code Style Guidelines + +### Formatting (.stylua.toml) +- Column width: 160 characters, indent: 2 spaces, quote style: auto-prefer single quotes +- Call parentheses: omit when possible, simple statements: always collapse + +### Imports & Naming +```lua +-- Standard require pattern +local module = require('module.name') + +-- Conditional requires with error handling +local ok, plugin = pcall(require, 'optional.plugin') +if not ok then vim.notify('Plugin failed: ' .. result, vim.log.levels.WARN) end +``` +- **Variables/Functions**: `camelCase` (e.g., `local bufferNumber = 1`, `function setupLsp() end`) +- **Constants**: `UPPER_SNAKE_CASE` (e.g., `local MAX_RETRIES = 3`) +- **Modules**: `snake_case` for file names +- **Descriptive names**: Prefer clarity over brevity + +### Error Handling & Comments +```lua +-- Safe plugin loading +local ok, result = pcall(require, 'plugin.name') +if not ok then + vim.notify('Plugin failed to load: ' .. result, vim.log.levels.WARN) + return +end +``` +```lua +-- Single line comments, TODO/FIXME/NOTE +-- EmmyLua annotations: ---@param name type: description +---@param buffer number: The buffer number +---@return boolean: Success status +``` + +### Function & Table Style +```lua +-- Anonymous functions for keymaps +vim.keymap.set('n', 'key', function() end, { desc = 'Description' }) + +-- Named functions for complex logic +local function setupPlugin() end + +-- Consistent table formatting +local config = { + option1 = true, + nested = { setting = 42 }, + timeout_ms = 500, -- Align when readable +} +``` + +### Autocommands & Keymaps +```lua +-- Use descriptive augroup names +local augroup = vim.api.nvim_create_augroup('plugin-name-feature', { clear = true }) +vim.api.nvim_create_autocmd('FileType', { + group = augroup, + pattern = 'lua', + callback = function() end, +}) +``` +```lua +-- Always include descriptions +vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) +-- Use leader key (), group related mappings under prefixes +``` + +## Project Conventions + +### File Organization +``` +lua/ +├── options.lua # Vim options and settings +├── keymaps.lua # Keybindings +├── autocommands.lua # Autocommands +├── lazy-config.lua # Lazy plugin manager setup +├── plugins_config/ # Plugin-specific configurations +└── custom/ # User customizations +``` + +### Plugin Management +- **Manager**: lazy.nvim +- **Commands**: `:Lazy` (status), `:Lazy update`, `:Lazy clean`, `:Lazy profile` + +### Commit Messages +- Follow conventional commit format +- Be descriptive about Neovim-specific changes and plugin references + +### Plugin Configuration Pattern +```lua +return { + 'author/plugin-name', + event = 'VimEnter', -- Lazy loading trigger + dependencies = { 'dep1', 'dep2' }, + opts = { setting = value }, -- Simple options + config = function() -- Complex setup + local plugin = require('plugin') + plugin.setup({ config }) + end, + keys = { -- Keybindings + { 'key', function() end, desc = 'Description' }, + }, +} +``` + +## Development Workflow + +1. **Setup**: Clone repository and start Neovim +2. **Plugin management**: Use `:Lazy` commands +3. **Testing**: `:checkhealth`, `:Lazy`, manual testing +4. **Formatting**: `f` or conform commands +5. **Linting**: Use lint commands for supported file types +6. **Git workflow**: Standard branching, commit, and PR process + +## Neovim-Specific Considerations + +- **API usage**: Prefer `vim.api.nvim_*` over deprecated `vim.*` +- **Version compatibility**: Target latest stable Neovim +- **Plugin compatibility**: Check lazy-lock.json for pinned versions +- **Performance**: Mindful of startup time and memory usage +- **User experience**: Consider mouse and keyboard workflows + +This guide ensures AI agents can contribute effectively while maintaining consistency with existing patterns and conventions. \ No newline at end of file diff --git a/README.md b/README.md index 2b9e52dad85..02756ff59fa 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ A starting point for Neovim that is: * Single-file * Completely Documented + **NOT** a Neovim distribution, but instead a starting point for your configuration. ## Installation diff --git a/init.lua b/init.lua index d5ae6dc9b2a..abb0d600564 100644 --- a/init.lua +++ b/init.lua @@ -1,5 +1,4 @@ --[[ - ===================================================================== ==================== READ THIS BEFORE CONTINUING ==================== ===================================================================== @@ -65,7 +64,7 @@ Kickstart Guide: MOST IMPORTANTLY, we provide a keymap "sh" to [s]earch the [h]elp documentation, which is very useful when you're not exactly sure of what you're looking for. - +g I have left several `:help X` comments throughout the init.lua These are hints about where to find more information about the relevant settings, plugins or Neovim features used in Kickstart. @@ -91,7 +90,12 @@ vim.g.mapleader = ' ' vim.g.maplocalleader = ' ' -- Set to true if you have a Nerd Font installed and selected in the terminal -vim.g.have_nerd_font = false +vim.g.have_nerd_font = true + +-- [[ Global variables ]] +Autocmd = vim.api.nvim_create_autocmd +Augroup = vim.api.nvim_create_augroup +Fugitive = vim.api.nvim_create_augroup('Fugitive', {}) -- [[ Setting options ]] -- See `:help vim.o` @@ -114,7 +118,9 @@ vim.o.showmode = false -- Schedule the setting after `UiEnter` because it can increase startup-time. -- Remove this option if you want your OS clipboard to remain independent. -- See `:help 'clipboard'` -vim.schedule(function() vim.o.clipboard = 'unnamedplus' end) +vim.schedule(function() + vim.o.clipboard = 'unnamedplus' +end) -- Enable break indent vim.o.breakindent = true @@ -146,7 +152,7 @@ vim.o.splitbelow = true -- Notice listchars is set using `vim.opt` instead of `vim.o`. -- It is very similar to `vim.o` but offers an interface for conveniently interacting with tables. -- See `:help lua-options` --- and `:help lua-guide-options` +-- and `:help lua-options-guide` vim.o.list = true vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } @@ -171,22 +177,7 @@ vim.o.confirm = true -- See `:help hlsearch` vim.keymap.set('n', '', 'nohlsearch') --- Diagnostic Config & Keymaps --- See :help vim.diagnostic.Opts -vim.diagnostic.config { - update_in_insert = false, - severity_sort = true, - float = { border = 'rounded', source = 'if_many' }, - underline = { severity = vim.diagnostic.severity.ERROR }, - - -- Can switch between these as you prefer - virtual_text = true, -- Text shows up at the end of the line - virtual_lines = false, -- Teest shows up underneath the line, with virtual lines - - -- Auto open the float, so you can easily read the errors when jumping with `[d` and `]d` - jump = { float = true }, -} - +-- Diagnostic keymaps vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) -- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier @@ -216,7 +207,17 @@ vim.keymap.set('n', '', '', { desc = 'Move focus to the upper win -- vim.keymap.set("n", "", "H", { desc = "Move window to the left" }) -- vim.keymap.set("n", "", "L", { desc = "Move window to the right" }) -- vim.keymap.set("n", "", "J", { desc = "Move window to the lower" }) --- vim.keymap.set("n", "", "K", { desc = "Move window to the upper" }) +-- vim.keymap.set("n", "", "K", { desc = "Move window to the upper" }) + +-- Opencode integration +local function run_opencode_query(query) + local repo = vim.fn.system('git rev-parse --show-toplevel 2>/dev/null'):gsub('\n', '') or vim.fn.getcwd() + vim.fn.jobstart({'opencode', 'run', 'In repo ' .. repo .. ': ' .. query}, {detach = true}) +end + +vim.keymap.set('n', 'oa', function() run_opencode_query('Analyze current file: ' .. vim.fn.expand('%')) end, { desc = '[O]pencode [A]nalyze file' }) +vim.keymap.set('v', 'oe', function() run_opencode_query('Explain: ' .. vim.fn.getreg('*')) end, { desc = '[O]pencode [E]xplain selection' }) +vim.keymap.set('n', 'or', function() run_opencode_query('Refactor suggestions for repo') end, { desc = '[O]pencode [R]epo refactor' }) -- [[ Basic Autocommands ]] -- See `:help lua-guide-autocommands` @@ -227,7 +228,9 @@ vim.keymap.set('n', '', '', { desc = 'Move focus to the upper win vim.api.nvim_create_autocmd('TextYankPost', { desc = 'Highlight when yanking (copying) text', group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }), - callback = function() vim.hl.on_yank() end, + callback = function() + vim.hl.on_yank() + end, }) -- [[ Install `lazy.nvim` plugin manager ]] @@ -236,7 +239,9 @@ 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' local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath } - if vim.v.shell_error ~= 0 then error('Error cloning lazy.nvim:\n' .. out) end + if vim.v.shell_error ~= 0 then + error('Error cloning lazy.nvim:\n' .. out) + end end ---@type vim.Option @@ -255,8 +260,15 @@ rtp:prepend(lazypath) -- -- NOTE: Here is where you install your plugins. require('lazy').setup({ - -- NOTE: Plugins can be added via a link or github org/name. To run setup automatically, use `opts = {}` - { 'NMAC427/guess-indent.nvim', opts = {} }, + -- NOTE: Plugins can be added with a link (or for a github repo: 'owner/repo' link). + 'NMAC427/guess-indent.nvim', -- Detect tabstop and shiftwidth automatically + + -- NOTE: Plugins can also be added by using a table, + -- with the first argument being the link and the following + -- keys can be used to configure plugin behavior/loading/etc. + -- + -- Use `opts = {}` to automatically pass options to a plugin's `setup()` function, forcing the plugin to be loaded. + -- -- Alternatively, use `config = function() ... end` for full control over the configuration. -- If you prefer to call `setup` explicitly, use: @@ -302,15 +314,51 @@ require('lazy').setup({ { -- Useful plugin to show you pending keybinds. 'folke/which-key.nvim', - event = 'VimEnter', + event = 'VimEnter', -- Sets the loading event to 'VimEnter' opts = { -- delay between pressing a key and opening which-key (milliseconds) + -- this setting is independent of vim.o.timeoutlen delay = 0, - icons = { mappings = vim.g.have_nerd_font }, + icons = { + -- set icon mappings to true if you have a Nerd Font + mappings = vim.g.have_nerd_font, + -- If you are using a Nerd Font: set icons.keys to an empty table which will use the + -- default which-key.nvim defined Nerd Font icons, otherwise define a string table + keys = vim.g.have_nerd_font and {} or { + Up = ' ', + Down = ' ', + Left = ' ', + Right = ' ', + C = ' ', + M = ' ', + D = ' ', + S = ' ', + CR = ' ', + Esc = ' ', + ScrollWheelDown = ' ', + ScrollWheelUp = ' ', + NL = ' ', + BS = ' ', + Space = ' ', + Tab = ' ', + F1 = '', + F2 = '', + F3 = '', + F4 = '', + F5 = '', + F6 = '', + F7 = '', + F8 = '', + F9 = '', + F10 = '', + F11 = '', + F12 = '', + }, + }, -- Document existing key chains spec = { - { 's', group = '[S]earch', mode = { 'n', 'v' } }, + { 's', group = '[S]earch' }, { 't', group = '[T]oggle' }, { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, }, @@ -326,16 +374,6 @@ require('lazy').setup({ { -- Fuzzy Finder (files, lsp, etc) 'nvim-telescope/telescope.nvim', - -- By default, Telescope is included and acts as your picker for everything. - - -- If you would like to switch to a different picker (like snacks, or fzf-lua) - -- you can disable the Telescope plugin by setting enabled to false and enable - -- your replacement picker by requiring it explicitly (e.g. 'custom.plugins.snacks') - - -- Note: If you customize your config for yourself, - -- it’s best to remove the Telescope plugin config entirely - -- instead of just disabling it here, to keep your config clean. - enabled = true, event = 'VimEnter', dependencies = { 'nvim-lua/plenary.nvim', @@ -348,7 +386,9 @@ require('lazy').setup({ -- `cond` is a condition used to determine whether this plugin should be -- installed and loaded. - cond = function() return vim.fn.executable 'make' == 1 end, + cond = function() + return vim.fn.executable 'make' == 1 + end, }, { 'nvim-telescope/telescope-ui-select.nvim' }, @@ -388,7 +428,9 @@ require('lazy').setup({ -- }, -- pickers = {} extensions = { - ['ui-select'] = { require('telescope.themes').get_dropdown() }, + ['ui-select'] = { + require('telescope.themes').get_dropdown(), + }, }, } @@ -402,49 +444,14 @@ require('lazy').setup({ vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) vim.keymap.set('n', 'ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) - vim.keymap.set({ 'n', 'v' }, 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) + vim.keymap.set('n', 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) vim.keymap.set('n', 's.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' }) - vim.keymap.set('n', 'sc', builtin.commands, { desc = '[S]earch [C]ommands' }) vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) - -- This runs on LSP attach per buffer (see main LSP attach function in 'neovim/nvim-lspconfig' config for more info, - -- it is better explained there). This allows easily switching between pickers if you prefer using something else! - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup('telescope-lsp-attach', { clear = true }), - callback = function(event) - local buf = event.buf - - -- Find references for the word under your cursor. - vim.keymap.set('n', 'grr', builtin.lsp_references, { buffer = buf, desc = '[G]oto [R]eferences' }) - - -- Jump to the implementation of the word under your cursor. - -- Useful when your language has ways of declaring types without an actual implementation. - vim.keymap.set('n', 'gri', builtin.lsp_implementations, { buffer = buf, desc = '[G]oto [I]mplementation' }) - - -- Jump to the definition of the word under your cursor. - -- This is where a variable was first declared, or where a function is defined, etc. - -- To jump back, press . - vim.keymap.set('n', 'grd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' }) - - -- Fuzzy find all the symbols in your current document. - -- Symbols are things like variables, functions, types, etc. - vim.keymap.set('n', 'gO', builtin.lsp_document_symbols, { buffer = buf, desc = 'Open Document Symbols' }) - - -- Fuzzy find all the symbols in your current workspace. - -- Similar to document symbols, except searches over your entire project. - vim.keymap.set('n', 'gW', builtin.lsp_dynamic_workspace_symbols, { buffer = buf, desc = 'Open Workspace Symbols' }) - - -- Jump to the type of the word under your cursor. - -- Useful when you're not sure what type a variable is and you want to see - -- the definition of its *type*, not where it was *defined*. - vim.keymap.set('n', 'grt', builtin.lsp_type_definitions, { buffer = buf, desc = '[G]oto [T]ype Definition' }) - end, - }) - - -- Override default behavior and theme when searching + -- Slightly advanced example of overriding default behavior and theme vim.keymap.set('n', '/', function() -- You can pass additional configuration to Telescope to change the theme, layout, etc. builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { @@ -455,24 +462,33 @@ require('lazy').setup({ -- It's also possible to pass additional configuration options. -- See `:help telescope.builtin.live_grep()` for information about particular keys - vim.keymap.set( - 'n', - 's/', - function() - builtin.live_grep { - grep_open_files = true, - prompt_title = 'Live Grep in Open Files', - } - end, - { desc = '[S]earch [/] in Open Files' } - ) + vim.keymap.set('n', 's/', function() + builtin.live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } + end, { desc = '[S]earch [/] in Open Files' }) -- Shortcut for searching your Neovim configuration files - vim.keymap.set('n', 'sn', function() builtin.find_files { cwd = vim.fn.stdpath 'config' } end, { desc = '[S]earch [N]eovim files' }) + vim.keymap.set('n', 'sn', function() + builtin.find_files { cwd = vim.fn.stdpath 'config' } + end, { desc = '[S]earch [N]eovim files' }) end, }, -- LSP Plugins + { + -- `lazydev` configures Lua LSP for your Neovim config, runtime and plugins + -- used for completion, annotations and signatures of Neovim apis + 'folke/lazydev.nvim', + ft = 'lua', + opts = { + library = { + -- Load luvit types when the `vim.uv` word is found + { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, + }, + }, + }, { -- Main LSP Configuration 'neovim/nvim-lspconfig', @@ -481,6 +497,7 @@ require('lazy').setup({ -- Mason must be loaded before its dependents so we need to set it up here. -- NOTE: `opts = {}` is the same as calling `require('mason').setup({})` { 'mason-org/mason.nvim', opts = {} }, + 'mason-org/mason-lspconfig.nvim', 'WhoIsSethDaniel/mason-tool-installer.nvim', -- Useful status updates for LSP. @@ -540,17 +557,55 @@ require('lazy').setup({ -- or a suggestion from your LSP for this to activate. map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' }) + -- Find references for the word under your cursor. + map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') + + -- Jump to the implementation of the word under your cursor. + -- Useful when your language has ways of declaring types without an actual implementation. + map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') + + -- Jump to the definition of the word under your cursor. + -- This is where a variable was first declared, or where a function is defined, etc. + -- To jump back, press . + map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') + -- WARN: This is not Goto Definition, this is Goto Declaration. -- For example, in C this would take you to the header. map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + -- Fuzzy find all the symbols in your current document. + -- Symbols are things like variables, functions, types, etc. + map('gO', require('telescope.builtin').lsp_document_symbols, 'Open Document Symbols') + + -- Fuzzy find all the symbols in your current workspace. + -- Similar to document symbols, except searches over your entire project. + map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Open Workspace Symbols') + + -- Jump to the type of the word under your cursor. + -- Useful when you're not sure what type a variable is and you want to see + -- the definition of its *type*, not where it was *defined*. + map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition') + + -- This function resolves a difference between neovim nightly (version 0.11) and stable (version 0.10) + ---@param client vim.lsp.Client + ---@param method vim.lsp.protocol.Method + ---@param bufnr? integer some lsp support methods only in specific files + ---@return boolean + local function client_supports_method(client, method, bufnr) + if vim.fn.has 'nvim-0.11' == 1 then + return client:supports_method(method, bufnr) + else + return client.supports_method(method, { bufnr = bufnr }) + end + end + -- The following two autocommands are used to highlight references of the -- word under your cursor when your cursor rests there for a little while. -- See `:help CursorHold` for information about when this is executed -- -- When you move your cursor, the highlights will be cleared (the second autocommand). local client = vim.lsp.get_client_by_id(event.data.client_id) - if client and client:supports_method('textDocument/documentHighlight', event.buf) then + if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { buffer = event.buf, @@ -577,12 +632,43 @@ require('lazy').setup({ -- code, if the language server you are using supports them -- -- This may be unwanted, since they displace some of your code - if client and client:supports_method('textDocument/inlayHint', event.buf) then - map('th', function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) end, '[T]oggle Inlay [H]ints') + if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then + map('th', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) + end, '[T]oggle Inlay [H]ints') end end, }) + -- Diagnostic Config + -- See :help vim.diagnostic.Opts + vim.diagnostic.config { + severity_sort = true, + float = { border = 'rounded', source = 'if_many' }, + underline = { severity = vim.diagnostic.severity.ERROR }, + signs = vim.g.have_nerd_font and { + text = { + [vim.diagnostic.severity.ERROR] = '󰅚 ', + [vim.diagnostic.severity.WARN] = '󰀪 ', + [vim.diagnostic.severity.INFO] = '󰋽 ', + [vim.diagnostic.severity.HINT] = '󰌶 ', + }, + } or {}, + virtual_text = { + source = 'if_many', + spacing = 2, + format = function(diagnostic) + local diagnostic_message = { + [vim.diagnostic.severity.ERROR] = diagnostic.message, + [vim.diagnostic.severity.WARN] = diagnostic.message, + [vim.diagnostic.severity.INFO] = diagnostic.message, + [vim.diagnostic.severity.HINT] = diagnostic.message, + } + return diagnostic_message[diagnostic.severity] + end, + }, + } + -- LSP servers and clients are able to communicate to each other what features they support. -- By default, Neovim doesn't support everything that is in the LSP specification. -- When you add blink.cmp, luasnip, etc. Neovim now has *more* capabilities. @@ -591,18 +677,41 @@ require('lazy').setup({ -- Enable the following language servers -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. - -- See `:help lsp-config` for information about keys and how to configure + -- + -- Add any additional override configuration in the following tables. Available keys are: + -- - cmd (table): Override the default command used to start the server + -- - filetypes (table): Override the default list of associated filetypes for the server + -- - capabilities (table): Override fields in capabilities. Can be used to disable certain LSP features. + -- - settings (table): Override the default settings passed when initializing the server. + -- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/ local servers = { -- clangd = {}, -- gopls = {}, -- pyright = {}, -- rust_analyzer = {}, + -- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs -- -- Some languages (like typescript) have entire language plugins that can be useful: -- https://github.com/pmizio/typescript-tools.nvim -- -- But for many setups, the LSP (`ts_ls`) will work just fine -- ts_ls = {}, + -- + + lua_ls = { + -- cmd = { ... }, + -- filetypes = { ... }, + -- capabilities = {}, + settings = { + Lua = { + completion = { + callSnippet = 'Replace', + }, + -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings + -- diagnostics = { disable = { 'missing-fields' } }, + }, + }, + }, } -- Ensure the servers and tools above are installed @@ -612,47 +721,32 @@ require('lazy').setup({ -- :Mason -- -- You can press `g?` for help in this menu. + -- + -- `mason` had to be setup earlier: to configure its options see the + -- `dependencies` table for `nvim-lspconfig` above. + -- + -- You can add other tools here that you want Mason to install + -- for you, so that they are available from within Neovim. local ensure_installed = vim.tbl_keys(servers or {}) vim.list_extend(ensure_installed, { - 'lua_ls', -- Lua Language server 'stylua', -- Used to format Lua code - -- You can add other tools here that you want Mason to install }) - require('mason-tool-installer').setup { ensure_installed = ensure_installed } - for name, server in pairs(servers) do - server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) - vim.lsp.config(name, server) - vim.lsp.enable(name) - end - - -- Special Lua Config, as recommended by neovim help docs - vim.lsp.config('lua_ls', { - on_init = function(client) - if client.workspace_folders then - local path = client.workspace_folders[1].name - if path ~= vim.fn.stdpath 'config' and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc')) then return end - end - - client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { - runtime = { - version = 'LuaJIT', - path = { 'lua/?.lua', 'lua/?/init.lua' }, - }, - workspace = { - checkThirdParty = false, - -- NOTE: this is a lot slower and will cause issues when working on your own configuration. - -- See https://github.com/neovim/nvim-lspconfig/issues/3189 - library = vim.api.nvim_get_runtime_file('', true), - }, - }) - end, - settings = { - Lua = {}, + require('mason-lspconfig').setup { + ensure_installed = {}, -- explicitly set to an empty table (Kickstart populates installs via mason-tool-installer) + automatic_installation = false, + handlers = { + function(server_name) + local server = servers[server_name] or {} + -- This handles overriding only values explicitly passed + -- by the server configuration above. Useful when disabling + -- certain features of an LSP (for example, turning off formatting for ts_ls) + server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) + require('lspconfig')[server_name].setup(server) + end, }, - }) - vim.lsp.enable 'lua_ls' + } end, }, @@ -663,7 +757,9 @@ require('lazy').setup({ keys = { { 'f', - function() require('conform').format { async = true, lsp_format = 'fallback' } end, + function() + require('conform').format { async = true, lsp_format = 'fallback' } + end, mode = '', desc = '[F]ormat buffer', }, @@ -708,7 +804,9 @@ require('lazy').setup({ -- Build Step is needed for regex support in snippets. -- This step is not supported in many windows environments. -- Remove the below condition to re-enable on windows. - if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then return end + if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then + return + end return 'make install_jsregexp' end)(), dependencies = { @@ -724,6 +822,7 @@ require('lazy').setup({ }, opts = {}, }, + 'folke/lazydev.nvim', }, --- @module 'blink.cmp' --- @type blink.cmp.Config @@ -769,7 +868,10 @@ require('lazy').setup({ }, sources = { - default = { 'lsp', 'path', 'snippets' }, + default = { 'lsp', 'path', 'snippets', 'lazydev' }, + providers = { + lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 }, + }, }, snippets = { preset = 'luasnip' }, @@ -814,7 +916,7 @@ require('lazy').setup({ { 'folke/todo-comments.nvim', event = 'VimEnter', dependencies = { 'nvim-lua/plenary.nvim' }, opts = { signs = false } }, { -- Collection of various small independent plugins/modules - 'nvim-mini/mini.nvim', + 'echasnovski/mini.nvim', config = function() -- Better Around/Inside textobjects -- @@ -842,23 +944,38 @@ require('lazy').setup({ -- default behavior. For example, here we set the section for -- cursor location to LINE:COLUMN ---@diagnostic disable-next-line: duplicate-set-field - statusline.section_location = function() return '%2l:%-2v' end + statusline.section_location = function() + return '%2l:%-2v' + end -- ... and there is more! - -- Check out: https://github.com/nvim-mini/mini.nvim + -- Check out: https://github.com/echasnovski/mini.nvim end, }, - { -- Highlight, edit, and navigate code 'nvim-treesitter/nvim-treesitter', - config = function() - local filetypes = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } - require('nvim-treesitter').install(filetypes) - vim.api.nvim_create_autocmd('FileType', { - pattern = filetypes, - callback = function() vim.treesitter.start() end, - }) - end, + build = ':TSUpdate', + main = 'nvim-treesitter.configs', -- Sets main module to use for opts + -- [[ Configure Treesitter ]] See `:help nvim-treesitter` + opts = { + ensure_installed = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' }, + -- Autoinstall languages that are not installed + auto_install = true, + highlight = { + enable = true, + -- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules. + -- If you are experiencing weird indenting issues, add the language to + -- the list of additional_vim_regex_highlighting and disabled languages for indent. + additional_vim_regex_highlighting = { 'ruby' }, + }, + indent = { enable = true, disable = { 'ruby' } }, + }, + -- There are additional nvim-treesitter modules that you can use to interact + -- with nvim-treesitter. You should go explore a few and see what interests you: + -- + -- - Incremental selection: Included, see `:help nvim-treesitter-incremental-selection-mod` + -- - Show your current context: https://github.com/nvim-treesitter/nvim-treesitter-context + -- - Treesitter + textobjects: https://github.com/nvim-treesitter/nvim-treesitter-textobjects }, -- The following comments only work if you have downloaded the kickstart repo, not just copy pasted the diff --git a/lua/autocommands.lua b/lua/autocommands.lua new file mode 100644 index 00000000000..458419fd355 --- /dev/null +++ b/lua/autocommands.lua @@ -0,0 +1,40 @@ +-- [[ Autocommands ]] +-- See `:help lua-guide-autocommands` +-- Definitions + +-- Highlight when yanking (copying) text +-- Try it with `yap` in normal mode +-- See `:help vim.highlight.on_yank()` +vim.api.nvim_create_autocmd('TextYankPost', { + desc = 'Highlight when yanking (copying) text', + group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }), + callback = function() vim.hl.on_yank() end, +}) + +-- Resize splits if window got resized +local function augroup(name) + return vim.api.nvim_create_augroup('lazyvim_' .. name, { clear = true }) +end + +Autocmd({ 'VimResized' }, { + group = augroup 'resize_splits', + callback = function() + vim.cmd 'tabdo wincmd =' + end, +}) + +-- Remove auto comment next line +Autocmd({ 'BufEnter' }, { + group = augroup 'remove_auto_comment', + callback = function() + vim.cmd 'setlocal formatoptions-=c formatoptions-=r formatoptions-=o' + end, +}) + +-- Set cursorline only in focused window +Autocmd({ 'WinEnter', 'WinLeave' }, { + group = augroup 'cursorline', + callback = function() + vim.wo.cursorline = vim.fn.win_getid() == vim.fn.win_getid() + end, +}) diff --git a/lua/keymaps.lua b/lua/keymaps.lua new file mode 100644 index 00000000000..67599529663 --- /dev/null +++ b/lua/keymaps.lua @@ -0,0 +1,102 @@ +-- [[ Basic Keymaps ]] +-- NOTE: See `:help vim.keymap.set()` +-- vim.keymap.set( required, required, required, not required) + +-- Set highlight on search, but clear on pressing in normal mode +vim.keymap.set('n', '', 'nohlsearch', { desc = 'Remove higlight after search is done' }) + +-- Diagnostic keymaps +vim.keymap.set('n', '[d', function() vim.diagnostic.goto({ direction = 'prev', float = false }) end, { desc = 'Go to previous [D]iagnostic message' }) +vim.keymap.set('n', ']d', function() vim.diagnostic.goto({ direction = 'next', float = false }) end, { desc = 'Go to next [D]iagnostic message' }) +vim.keymap.set('n', 'e', vim.diagnostic.open_float, { desc = 'Show diagnostic [E]rror messages' }) +vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) + +-- netrw remaps +vim.keymap.set('n', 'pv', vim.cmd.Ex, { desc = 'Open netrw' }) -- open netrw + +-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier +-- for people to discover. Otherwise, you normally need to press , which +-- is not what someone will guess without a bit more experience. +-- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping +-- or just use to exit terminal mode +vim.keymap.set('t', '', '', { desc = 'Exit terminal mode' }) + + -- TIP: Disable arrow keys in normal mode, i don use them +vim.keymap.set('n', '', 'echo "Use h to move!!"') +vim.keymap.set('n', '', 'echo "Use l to move!!"') +vim.keymap.set('n', '', 'echo "Use k to move!!"') +vim.keymap.set('n', '', 'echo "Use j to move!!"') + +-- Keybinds to make split navigation easier. +-- NOTE: Use CTRL+ to switch between windows +-- See `:help wincmd` for a list of all window commands +vim.keymap.set('n', '', '', { desc = 'Move focus to the left window' }) +vim.keymap.set('n', '', '', { desc = 'Move focus to the right window' }) +vim.keymap.set('n', '', '', { desc = 'Move focus to the lower window' }) +vim.keymap.set('n', '', '', { desc = 'Move focus to the upper window' }) + +-- NOTE: Some terminals have colliding keymaps or are not able to send distinct keycodes +vim.keymap.set("n", "", "H", { desc = "Move window to the left" }) +vim.keymap.set("n", "", "L", { desc = "Move window to the right" }) +vim.keymap.set("n", "", "J", { desc = "Move window to the lower" }) +vim.keymap.set("n", "", "K", { desc = "Move window to the upper" }) + +-- copy pasting +vim.keymap.set('n', 'Y', 'y$', { desc = 'Yank till the end of the line' }) +vim.keymap.set('n', 'J', 'mzJ`z', { desc = 'Marks the point (mz), joins the lines (J) and gets back to the marked place (`z)' }) +vim.keymap.set({ 'n', 'v' }, 'y', '"+y', { desc = 'Prefix y with leader to send to system clipboard' }) +vim.keymap.set({ 'n', 'v' }, 'Y', '"+Y', { desc = 'Prefix Y with leader to send to system clipboard' }) +vim.keymap.set('x', 'p', '"+p', { desc = 'Paste from clipboard over the selection, without chaging the clipboard registry("+).' }) +vim.keymap.set('x', 'P', '"_dP', { desc = 'Deletes to void registry("_) to avoid changing registry("0) content, and then pastes from clipboard' }) + +-- Search remaps +vim.keymap.set('n', 'n', 'nzzzv', { desc = 'n = next search, zz = center cursor on screen, zv = open fold if exist' }) +vim.keymap.set('n', 'N', 'Nzzzv', { desc = 'N = previous search, zz = center cursor on screen, zv = open fold if exist' }) + +-- Add additional undo breakpoints on these simbols, makes undo more granular +vim.keymap.set('i', ',', ',u', { desc = 'Add undo breakpoint on a ,' }) +vim.keymap.set('i', '.', '.u', { desc = 'Add undo breakpoint on a .' }) +vim.keymap.set('i', '!', '!u', { desc = 'Add undo breakpoint on a !' }) +vim.keymap.set('i', '?', '?u', { desc = 'Add undo breakpoint on a ?' }) + +-- Moving text around +vim.keymap.set('v', 'J', ":m '>+1gv=gv", { desc = 'Move selection down in visual mode' }) +vim.keymap.set('v', 'K', ":m '<-2gv=gv", { desc = 'Move selection up in visual mode' }) +vim.keymap.set('i', '', ':m .-2==', { desc = 'Move line up in insert mode' }) +vim.keymap.set('i', '', ':m .+1==', { desc = 'Move line down in insert mode' }) +vim.keymap.set('n', 'j', ':m .+1==', { desc = 'Move line up in in normal mode' }) +vim.keymap.set('n', 'k', ':m .-2==', { desc = 'Move line down in in normal mode' }) + +-- Window management +vim.keymap.set('n', '', '', { desc = 'Close window with ctrl+c' }) + +-- Save file +vim.keymap.set({ 'i', 'v', 'n', 's' }, '', 'w', { desc = 'Save file' }) + +-- Function and remap to toggle relative numbers. +vim.keymap.set('n', 'nr', function() vim.o.nu = false vim.opt.relativenumber = false end, { desc = 'Disable number and relative number' }) +vim.keymap.set('n', 'rn', function() vim.o.nu = true vim.opt.relativenumber = true end, { desc = 'Enable number and relative number' }) + +-- Clean up +vim.keymap.set('n', 'dw', ':%s/\\s\\+$//e', { desc = 'Clean trailing whitespace in the document' }) +vim.keymap.set('n', 'dn', ':%s/\\n\\+\\%$//e', { desc = 'Clean trailing newlines in the document' }) +vim.keymap.set('n', 'ds', ':%s/\\^\\[\\+\\%$//e', { desc = 'Clean trailing escape sequences in the document' }) + +-- Code runner keymaps +vim.keymap.set('n', 'rr', ':RunCode', { noremap = true, silent = false, desc = 'Run code based on file type.' }) +vim.keymap.set('n', 'rf', ':RunFile', { noremap = true, silent = false, desc = 'Run code in current file.' }) +vim.keymap.set('n', 'rft', ':RunFile tab', { noremap = true, silent = false, desc = 'Run code in current file on a tab.' }) +vim.keymap.set('n', 'rp', ':RunProject', { noremap = true, silent = false, desc = 'Run code in project.' }) +vim.keymap.set('n', 'rc', ':RunClose', { noremap = true, silent = false, desc = 'Close runner.' }) +vim.keymap.set('n', 'crf', ':CRFiletype', { noremap = true, silent = false, desc = 'Open json with supported files.' }) +vim.keymap.set('n', 'crp', ':CRProjects', { noremap = true, silent = false, desc = 'Open json with list of projects.' }) + +-- Testing remaps and functions + +-- better indenting +-- vim.keymap.set('v', '<', '', '>gv') + +-- Markdown preview haven't setup this plugin +-- vim.keymap.set('n', 'mp', ':Glow', { desc = 'Remap glow to show markdown preview' }) +-- vim.keymap.set('n', 'mq', ':Glow!', { desc = 'Remap glow to close markdown preview' }) diff --git a/lua/kickstart/plugins/gitsigns.lua b/lua/kickstart/plugins/gitsigns.lua deleted file mode 100644 index 777e470a0c9..00000000000 --- a/lua/kickstart/plugins/gitsigns.lua +++ /dev/null @@ -1,55 +0,0 @@ --- Adds git related signs to the gutter, as well as utilities for managing changes --- NOTE: gitsigns is already included in init.lua but contains only the base --- config. This will add also the recommended keymaps. - -return { - { - 'lewis6991/gitsigns.nvim', - opts = { - on_attach = function(bufnr) - local gitsigns = require 'gitsigns' - - local function map(mode, l, r, opts) - opts = opts or {} - opts.buffer = bufnr - vim.keymap.set(mode, l, r, opts) - end - - -- Navigation - map('n', ']c', function() - if vim.wo.diff then - vim.cmd.normal { ']c', bang = true } - else - gitsigns.nav_hunk 'next' - end - end, { desc = 'Jump to next git [c]hange' }) - - map('n', '[c', function() - if vim.wo.diff then - vim.cmd.normal { '[c', bang = true } - else - gitsigns.nav_hunk 'prev' - end - end, { desc = 'Jump to previous git [c]hange' }) - - -- Actions - -- visual mode - map('v', 'hs', function() gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [s]tage hunk' }) - map('v', 'hr', function() gitsigns.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [r]eset hunk' }) - -- normal mode - map('n', 'hs', gitsigns.stage_hunk, { desc = 'git [s]tage hunk' }) - map('n', 'hr', gitsigns.reset_hunk, { desc = 'git [r]eset hunk' }) - map('n', 'hS', gitsigns.stage_buffer, { desc = 'git [S]tage buffer' }) - map('n', 'hu', gitsigns.stage_hunk, { desc = 'git [u]ndo stage hunk' }) - map('n', 'hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' }) - map('n', 'hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' }) - map('n', 'hb', gitsigns.blame_line, { desc = 'git [b]lame line' }) - map('n', 'hd', gitsigns.diffthis, { desc = 'git [d]iff against index' }) - map('n', 'hD', function() gitsigns.diffthis '@' end, { desc = 'git [D]iff against last commit' }) - -- Toggles - map('n', 'tb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' }) - map('n', 'tD', gitsigns.preview_hunk_inline, { desc = '[T]oggle git show [D]eleted' }) - end, - }, - }, -} diff --git a/lua/lazy-config.lua b/lua/lazy-config.lua new file mode 100644 index 00000000000..caf7e9c1c1d --- /dev/null +++ b/lua/lazy-config.lua @@ -0,0 +1,128 @@ +--[[ Configure and install plugins ]] +-- To check the current status of your plugins, run +-- :Lazy +-- +-- You can press `?` in this menu for help. Use `:q` to close the window +-- +-- To update plugins you can run +-- :Lazy update +-- +-- NOTE: Here is where you install your plugins. +require('lazy').setup({ + + -- Plugins with custom values + require 'plugins_config/lsp', -- Multilanguage lsp config + require 'plugins_config/which-key', -- Show created key bindings + require 'plugins_config/gitsigns', -- Manage git signs, blame + require 'plugins_config/vim-fugitive', -- Manage git in nvim + require 'plugins_config/telescope', -- Manage searches nicely + require 'plugins_config/worktree', -- Manage worktrees from nvim + require 'plugins_config/conform', -- Autoformat files using lsp on save + require 'plugins_config/autocomplete', -- Autocompletion + require 'plugins_config/colortheme', -- Color theme for the editor + require 'plugins_config/mini', -- Collections of useful mini plugins, like around/surround + require 'plugins_config/tree-sitter', -- manage lint, indentation and some othe language related tasks + require 'plugins_config/harpoon', -- Improve workflow for multiple files + require 'plugins_config/code_runner', -- Code runner + require 'plugins_config/indent_line', -- Indentation visualizer + require 'plugins_config/lint', -- Linter config + + -- NOTE: Plugins can be added with a link (or for a github repo: 'owner/repo' link). + -- Plugins with default values + 'NMAC427/guess-indent.nvim', -- Detect tabstop and shiftwidth automatically + 'numToStr/Comment.nvim', -- "gc" to comment visual regions/lines + 'github/copilot.vim', -- Copilot + -- keeping comments for annotation + -- NOTE: Plugins can also be added by using a table, + -- with the first argument being the link and the following + -- keys can be used to configure plugin behavior/loading/etc. + -- Use `opts = {}` to automatically pass options to a plugin's `setup()` function, forcing the plugin to be loaded. + -- Alternatively, use `config = function() ... end` for full control over the configuration. + -- If you prefer to call `setup` explicitly, use: + -- { + -- 'lewis6991/gitsigns.nvim', + -- config = function() + -- require('gitsigns').setup({ + -- -- Your gitsigns configuration here + -- }) + -- end, + -- NOTE: Plugins can also be configured to run Lua code when they are loaded. + -- + -- This is often very useful to both group configuration, as well as handle + -- lazy loading plugins that don't need to be loaded immediately at startup. + -- + -- For example, in the following configuration, we use: + -- event = 'VimEnter' + -- + -- which loads which-key before all the UI elements are loaded. Events can be + -- normal autocommands events (`:help autocmd-events`). + -- + -- Then, because we use the `opts` key (recommended), the configuration runs + -- after the plugin has been loaded as `require(MODULE).setup(opts)`. + + -- NOTE: Plugins can specify dependencies. + -- + -- The dependencies are proper plugin specifications as well - anything + -- you do for a plugin at the top level, you can do for a dependency. + -- + -- Use the `dependencies` key to specify the dependencies of a particular plugin + + -- The following two comments only work if you have downloaded the kickstart repo, not just copy pasted the + -- init.lua. If you want these files, they are in the repository, so you can just download them and + -- place them in the correct locations. + + -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` + -- This is the easiest way to modularize your config. + -- + -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. + -- For additional information, see `:help lazy.nvim-lazy.nvim-structuring-your-plugins` + -- { import = 'custom.plugins' }, + -- } + + -- One liners + -- Highlight todo, notes, etc in comments + { 'folke/todo-comments.nvim', event = 'VimEnter', dependencies = { 'nvim-lua/plenary.nvim' }, opts = { signs = false } }, + + -- Broken configs/Testing config + + -- NOTE: Plugins can also be added by using a table, + -- with the first argument being the link and the following + -- keys can be used to configure plugin behavior/loading/etc. + -- + -- Use `opts = {}` to force a plugin to be loaded. + -- + -- This is equivalent to: + -- require('Comment').setup({}) + + -- "gc" to comment visual regions/lines + -- { 'numToStr/Comment.nvim', opts = {} }, -- optional notation + + -- Here is a more advanced example where we pass configuration + -- options to `gitsigns.nvim`. This is equivalent to the following Lua: + -- require('gitsigns').setup({ ... }) + -- + -- See `:help gitsigns` to understand what the configuration keys do +}, { + ui = { + -- If you are using a Nerd Font: set icons to an empty table which will use the + -- default lazy.nvim defined Nerd Font icons, otherwise define a unicode icons table + icons = vim.g.have_nerd_font and {} or { + cmd = '⌘', + config = '🛠', + event = '📅', + ft = '📂', + init = '⚙', + keys = '🗝', + plugin = '🔌', + runtime = '💻', + require = '🌙', + source = '📄', + start = '🚀', + task = '📌', + lazy = '💤 ', + }, + }, +}) + +-- The line beneath this is called `modeline`. See `:help modeline` +-- vim: ts=2 sts=2 sw=2 et diff --git a/lua/lazy-install.lua b/lua/lazy-install.lua new file mode 100644 index 00000000000..521eff76910 --- /dev/null +++ b/lua/lazy-install.lua @@ -0,0 +1,13 @@ +-- [[ Install `lazy.nvim` plugin manager ]] +-- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info +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' + local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath } + if vim.v.shell_error ~= 0 then + error('Error cloning lazy.nvim:\n' .. out) + end +end ---@diagnostic disable-next-line: undefined-field +---@type vim.Option +local rtp = vim.opt.rtp +rtp:prepend(lazypath) diff --git a/lua/options.lua b/lua/options.lua new file mode 100644 index 00000000000..a579f87d6a1 --- /dev/null +++ b/lua/options.lua @@ -0,0 +1,84 @@ +-- [[ options ]] +-- See `:help vim.o` +-- NOTE: You can change these oions as you wish! +-- For more oions, you can see `:help option-list` + +-- Set numbers and relativenumber +vim.o.number = true +vim.o.relativenumber = true + +-- Enable mouse mode, can be useful for resizing splits for example! +vim.o.mouse = 'a' + +-- Don't show the mode, since it's already in the status line +vim.o.showmode = false + +-- Sync clipboard between OS and Neovim. +-- Schedule the setting after `UiEnter` because it can increase startup-time. +-- Remove this option if you want your OS clipboard to remain independent. +-- See `:help 'clipboard'` +-- vim.schedule(function() +-- vim.o.clipboard = 'unnamedplus' +-- end) + +-- Set indent currently managed by a plugin. +-- vim.o.tabstop = 4 +-- vim.o.softtabstop = 4 +-- vim.o.shiftwidth = 4 +vim.o.wrap = true -- wrap text after textwidth is reached +vim.o.breakindent = true -- keeps text indented after wrap line +vim.o.expandtab = true -- put the amount of spaces each time tab is used +vim.o.smartindent = true -- autodetect indent when starting a newline + +-- Save undo history and specify path to it. +vim.o.undofile = true +vim.o.undodir = os.getenv 'HOME' .. '/.nvim/undodir' + +-- Don't create swap or backup, we have undo for it +vim.o.swapfile = false +vim.o.backup = false + +-- Set highlight and navigation +vim.o.hlsearch = true -- Highlight partial search +vim.o.incsearch = true -- Incremental search to highlight partial matches +-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term +vim.o.ignorecase = true +vim.o.smartcase = true +vim.o.signcolumn = 'yes' -- Keep signcolumn on by default +vim.o.inccommand = 'split' -- Preview substitutions live, as you type! + +-- Minimal number of screen lines to keep above and below the cursor. +vim.o.scrolloff = 20 + +-- Decrease update time +vim.o.updatetime = 250 + +-- Decrease mapped sequence wait time +-- Displays which-key popup sooner +vim.o.timeoutlen = 300 + +-- Configure how new splits should be opened +vim.o.splitright = true +vim.o.splitbelow = true + +-- Sets how neovim will display certain whitespace characters in the editor. +-- See `:help 'list'` +-- and `:help 'listchars'` +vim.o.list = true +vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } + +-- Show which line your cursor is on +vim.o.cursorline = true + +-- if performing an operation that would fail due to unsaved changes in the buffer (like `:q`), +-- instead raise a dialog asking if you wish to save the current file(s) +-- See `:help 'confirm'` +vim.o.confirm = true + +-- set netrw config +vim.g.netrw_banner = 0 -- Remove banner at the top +vim.g.netrw_liststyle = 3 -- Default directory view. Cycle with i +vim.g.netrw_altv = 1 -- Files are opened to the right of netrw +vim.g.netrw_chgwin = -1 -- Files are opened in the netrw window +vim.g.netrw_winsize = 25 -- Window size +vim.g.netrw_list_hide = '.*.swp$, *.pyc$, *.log$, *.o$, *.xmi$, *.swp$, *.bak$, *.pyc$, *.class$, *.jar$, *.war$, *__pycache__*' -- Hide files with this extensions diff --git a/lua/plugins_config/autocomplete.lua b/lua/plugins_config/autocomplete.lua new file mode 100644 index 00000000000..806719f674a --- /dev/null +++ b/lua/plugins_config/autocomplete.lua @@ -0,0 +1,109 @@ +return { -- Autocompletion + 'hrsh7th/nvim-cmp', + event = 'InsertEnter', + dependencies = { + -- Snippet Engine & its associated nvim-cmp source + { + 'L3MON4D3/LuaSnip', + build = (function() + -- Build Step is needed for regex support in snippets. + -- This step is not supported in many windows environments. + -- Remove the below condition to re-enable on windows. + if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then + return + end + return 'make install_jsregexp' + end)(), + dependencies = { + -- `friendly-snippets` contains a variety of premade snippets. + -- See the README about individual language/framework/plugin snippets: + -- https://github.com/rafamadriz/friendly-snippets + -- { + -- 'rafamadriz/friendly-snippets', + -- config = function() + -- require('luasnip.loaders.from_vscode').lazy_load() + -- end, + -- }, + }, + }, + 'saadparwaiz1/cmp_luasnip', + + -- Adds other completion capabilities. + -- nvim-cmp does not ship with all sources by default. They are split + -- into multiple repos for maintenance purposes. + 'hrsh7th/cmp-nvim-lsp', + 'hrsh7th/cmp-path', + }, + config = function() + -- See `:help cmp` + local cmp = require 'cmp' + local luasnip = require 'luasnip' + luasnip.config.setup {} + + cmp.setup { + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + completion = { completeopt = 'menu,menuone,noinsert' }, + + -- For an understanding of why these mappings were + -- chosen, you will need to read `:help ins-completion` + -- + -- No, but seriously. Please read `:help ins-completion`, it is really good! + mapping = cmp.mapping.preset.insert { + -- Select the [n]ext item + [''] = cmp.mapping.select_next_item(), + -- Select the [p]revious item + [''] = cmp.mapping.select_prev_item(), + -- Accept ([y]es) the completion. + -- This will auto-import if your LSP supports it. + -- This will expand snippets if the LSP sent a snippet. + [''] = cmp.mapping.confirm { select = true }, + + -- Scroll the documentation window [b]ack / [f]orward + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + + -- If you prefer more traditional completion keymaps, + -- you can uncomment the following lines + --[''] = cmp.mapping.confirm { select = true }, + --[''] = cmp.mapping.select_next_item(), + --[''] = cmp.mapping.select_prev_item(), + + -- Manually trigger a completion from nvim-cmp. + -- Generally you don't need this, because nvim-cmp will display + -- completions whenever it has completion options available. + [''] = cmp.mapping.complete {}, + + -- Think of as moving to the right of your snippet expansion. + -- So if you have a snippet that's like: + -- function $name($args) + -- $body + -- end + -- + -- will move you to the right of each of the expansion locations. + -- is similar, except moving you backwards. + [''] = cmp.mapping(function() + if luasnip.expand_or_locally_jumpable() then + luasnip.expand_or_jump() + end + end, { 'i', 's' }), + [''] = cmp.mapping(function() + if luasnip.locally_jumpable(-1) then + luasnip.jump(-1) + end + end, { 'i', 's' }), + + -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: + -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps + }, + sources = { + { name = 'nvim_lsp' }, + { name = 'luasnip' }, + { name = 'path' }, + }, + } + end, +} diff --git a/lua/plugins_config/code_runner.lua b/lua/plugins_config/code_runner.lua new file mode 100644 index 00000000000..103cc93850c --- /dev/null +++ b/lua/plugins_config/code_runner.lua @@ -0,0 +1,18 @@ +return { + 'CRAG666/code_runner.nvim', + config = function() + require('code_runner').setup { + filetype = { + python = 'python3 -u', + javascript = 'node $file', + typescript = 'ts-node $file', + rust = { + 'cd $dir &&', + 'rustc $fileName &&', + '$dir/$fileNameWithoutExt', + }, + }, + } + end, + event = 'VeryLazy', -- or "BufEnter" if we want to load sooner. +} diff --git a/lua/plugins_config/colortheme.lua b/lua/plugins_config/colortheme.lua new file mode 100644 index 00000000000..cc191ade886 --- /dev/null +++ b/lua/plugins_config/colortheme.lua @@ -0,0 +1,20 @@ +return { -- You can easily change to a different colorscheme. + -- Change the name of the colorscheme plugin below, and then + -- change the command in the config to whatever the name of that colorscheme is. + -- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme`. + 'folke/tokyonight.nvim', + priority = 1000, -- Make sure to load this before all the other start plugins. + config = function() + ---@diagnostic disable-next-line: missing-fields + require('tokyonight').setup { + styles = { + comments = { italic = false }, -- Disable italics in comments + }, + } + + -- Load the colorscheme here. + -- Like many other themes, this one has different styles, and you could load + -- any other, such as 'tokyonight-storm', 'tokyonight-moon', or 'tokyonight-day'. + vim.cmd.colorscheme 'tokyonight-night' + end, + } diff --git a/lua/plugins_config/conform.lua b/lua/plugins_config/conform.lua new file mode 100644 index 00000000000..683789c04db --- /dev/null +++ b/lua/plugins_config/conform.lua @@ -0,0 +1,51 @@ +return { -- Autoformat + 'stevearc/conform.nvim', + event = { 'BufWritePre' }, + cmd = { 'ConformInfo' }, + lazy = false, + keys = { + { + 'f', + function() + require('conform').format { async = true, lsp_format = 'fallback' } + end, + mode = '', + desc = '[F]ormat buffer', + }, + }, + opts = { + notify_on_error = false, + format_on_save = function(bufnr) + -- Disable "format_on_save lsp_fallback" for languages that don't + -- have a well standardized coding style. You can add additional + -- languages here or re-enable it for the disabled ones. + local disable_filetypes = { c = true, cpp = true } + if disable_filetypes[vim.bo[bufnr].filetype] then + return nil + else + return { + timeout_ms = 500, + lsp_format = 'fallback', + } + end + end, + formatters_by_ft = { + lua = { 'stylua' }, + -- Conform can also run multiple formatters sequentially + python = { 'isort', 'black' }, + yaml = { 'yamlfix' }, + go = { 'gofmt' }, + rust = { 'rustfmt' }, + toml = { 'taplo' }, + jinja2 = { 'djlint' }, + javascript = { 'prettierd', 'prettier' }, + bash = { 'beautysh', 'shellcheck' }, + terraform = { 'terraform_fmt' }, + ansible = { 'ansible-lint' }, + hcl = { 'hcl' }, + markdown = { 'markdownlint' }, + -- You can use a sub-list to tell conform to run *until* a formatter + -- is found. + }, + }, +} diff --git a/lua/kickstart/plugins/autopairs.lua b/lua/plugins_config/disabled/autopairs.lua similarity index 100% rename from lua/kickstart/plugins/autopairs.lua rename to lua/plugins_config/disabled/autopairs.lua diff --git a/lua/kickstart/plugins/debug.lua b/lua/plugins_config/disabled/debug.lua similarity index 100% rename from lua/kickstart/plugins/debug.lua rename to lua/plugins_config/disabled/debug.lua diff --git a/lua/kickstart/plugins/neo-tree.lua b/lua/plugins_config/disabled/neo-tree.lua similarity index 100% rename from lua/kickstart/plugins/neo-tree.lua rename to lua/plugins_config/disabled/neo-tree.lua diff --git a/lua/plugins_config/gitsigns.lua b/lua/plugins_config/gitsigns.lua new file mode 100644 index 00000000000..bbd91a0f552 --- /dev/null +++ b/lua/plugins_config/gitsigns.lua @@ -0,0 +1,62 @@ +return { + 'lewis6991/gitsigns.nvim', + opts = { + signs = { + add = { text = '+' }, + change = { text = '~' }, + delete = { text = '_' }, + topdelete = { text = '‾' }, + changedelete = { text = '~' }, + }, + on_attach = function(bufnr) + local gitsigns = require 'gitsigns' + + local function map(mode, l, r, opts) + opts = opts or {} + opts.buffer = bufnr + vim.keymap.set(mode, l, r, opts) + end + + -- Navigation + map('n', ']c', function() + if vim.wo.diff then + vim.cmd.normal { ']c', bang = true } + else + gitsigns.nav_hunk 'next' + end + end, { desc = 'Jump to next git [c]hange' }) + + map('n', '[c', function() + if vim.wo.diff then + vim.cmd.normal { '[c', bang = true } + else + gitsigns.nav_hunk 'prev' + end + end, { desc = 'Jump to previous git [c]hange' }) + + -- Actions + -- visual mode + map('v', 'hs', function() + gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } + end, { desc = 'stage git hunk' }) + map('v', 'hr', function() + gitsigns.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } + end, { desc = 'reset git hunk' }) + -- normal mode + map('n', 'hs', gitsigns.stage_hunk, { desc = 'git [s]tage hunk' }) + map('n', 'hr', gitsigns.reset_hunk, { desc = 'git [r]eset hunk' }) + map('n', 'hS', gitsigns.stage_buffer, { desc = 'git [S]tage buffer' }) + map('n', 'hu', gitsigns.stage_hunk, { desc = 'git [u]ndo stage hunk' }) + map('n', 'hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' }) + map('n', 'hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' }) + map('n', 'hb', gitsigns.blame_line, { desc = 'git [b]lame line' }) + map('n', 'hd', gitsigns.diffthis, { desc = 'git [d]iff against index' }) + map('n', 'hD', function() + gitsigns.diffthis '@' + end, { desc = 'git [D]iff against last commit' }) + -- Toggles + map('n', 'tb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' }) + map('n', 'tD', gitsigns.preview_hunk_inline, { desc = '[T]oggle git show [D]eleted' }) + end, + }, +} diff --git a/lua/plugins_config/harpoon.lua b/lua/plugins_config/harpoon.lua new file mode 100644 index 00000000000..fbbbc14fc55 --- /dev/null +++ b/lua/plugins_config/harpoon.lua @@ -0,0 +1,27 @@ +return { + 'ThePrimeagen/harpoon', + dependencies = { + 'nvim-lua/plenary.nvim', + }, + config = function() + require('harpoon').setup {} + local mark = require 'harpoon.mark' + local ui = require 'harpoon.ui' + -- + vim.keymap.set('n', 'a', mark.add_file, { desc = 'Mark a file to be used in harpoon' }) + vim.keymap.set('n', '', ui.toggle_quick_menu, { desc = 'Toogle harpoon quick menu' }) + -- + vim.keymap.set('n', '', function() + ui.nav_file(1) + end, { desc = 'Navigate to first marked file' }) + vim.keymap.set('n', '', function() + ui.nav_file(2) + end, { desc = 'Navigate to first marked file' }) + vim.keymap.set('n', '', function() + ui.nav_file(3) + end, { desc = 'Navigate to first marked file' }) + vim.keymap.set('n', '', function() + ui.nav_file(4) + end, { desc = 'Navigate to first marked file' }) + end, +} diff --git a/lua/kickstart/health.lua b/lua/plugins_config/health.lua similarity index 100% rename from lua/kickstart/health.lua rename to lua/plugins_config/health.lua diff --git a/lua/kickstart/plugins/indent_line.lua b/lua/plugins_config/indent_line.lua similarity index 100% rename from lua/kickstart/plugins/indent_line.lua rename to lua/plugins_config/indent_line.lua diff --git a/lua/kickstart/plugins/lint.lua b/lua/plugins_config/lint.lua similarity index 100% rename from lua/kickstart/plugins/lint.lua rename to lua/plugins_config/lint.lua diff --git a/lua/plugins_config/lsp.lua b/lua/plugins_config/lsp.lua new file mode 100644 index 00000000000..1b33a9db19a --- /dev/null +++ b/lua/plugins_config/lsp.lua @@ -0,0 +1,438 @@ +return { + -- Lazy dev config + { + -- `lazydev` configures Lua LSP for your Neovim config, runtime and plugins + -- used for completion, annotations and signatures of Neovim apis + 'folke/lazydev.nvim', + ft = 'lua', + opts = { + library = { + -- Load luvit types when the `vim.uv` word is found + { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, + }, + }, + }, + + -- LSP config + { + 'neovim/nvim-lspconfig', + dependencies = { + -- Automatically install LSPs and related tools to stdpath for Neovim + -- NOTE: Must be loaded before dependants + { 'mason-org/mason.nvim', opts = {} }, + 'mason-org/mason-lspconfig.nvim', + 'WhoIsSethDaniel/mason-tool-installer.nvim', + + -- Useful status updates for LSP. + -- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})` + { 'j-hui/fidget.nvim', opts = {} }, + + -- Allows extra capabilities provided by blink.cmp + 'saghen/blink.cmp', + }, + config = function() + -- Brief aside: **What is LSP?** + -- + -- LSP is an initialism you've probably heard, but might not understand what it is. + -- + -- LSP stands for Language Server Protocol. It's a protocol that helps editors + -- and language tooling communicate in a standardized fashion. + -- + -- In general, you have a "server" which is some tool built to understand a particular + -- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers + -- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone + -- processes that communicate with some "client" - in this case, Neovim! + -- + -- LSP provides Neovim with features like: + -- - Go to definition + -- - Find references + -- - Autocompletion + -- - Symbol Search + -- - and more! + -- + -- Thus, Language Servers are external tools that must be installed separately from + -- Neovim. This is where `mason` and related plugins come into play. + -- + -- If you're wondering about lsp vs treesitter, you can check out the wonderfully + -- and elegantly composed help section, `:help lsp-vs-treesitter` + + -- This function gets run when an LSP attaches to a particular buffer. + -- That is to say, every time a new file is opened that is associated with + -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this + -- function will be executed to configure the current buffer + Autocmd('LspAttach', { + group = Augroup('lsp-attach', { clear = true }), + callback = function(event) + -- NOTE: Remember that Lua is a real programming language, and as such it is possible + -- to define small helper and utility functions so you don't have to repeat yourself. + -- + -- In this case, we create a function that lets us more easily define mappings specific + -- for LSP related items. It sets the mode, buffer and description for us each time. + local map = function(keys, func, desc, mode) + mode = mode or 'n' + vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) + end + -- Most Language Servers support renaming across files, etc. + map('grn', vim.lsp.buf.rename, '[R]e[n]ame') + + -- Execute a code action, usually your cursor needs to be on top of an error + -- or a suggestion from your LSP for this to activate. + map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' }) + + -- Find references for the word under your cursor. + map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') + + -- Jump to the implementation of the word under your cursor. + -- Useful when your language has ways of declaring types without an actual implementation. + map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') + + -- Jump to the definition of the word under your cursor. + -- This is where a variable was first declared, or where a function is defined, etc. + -- To jump back, press . + map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') + + -- WARN: This is not Goto Definition, this is Goto Declaration. + -- For example, in C this would take you to the header. + map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + + -- Fuzzy find all the symbols in your current document. + -- Symbols are things like variables, functions, types, etc. + map('gO', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') + + -- Fuzzy find all the symbols in your current workspace. + -- Similar to document symbols, except searches over your entire project. + map('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') + + -- Jump to the type of the word under your cursor. + -- Useful when you're not sure what type a variable is and you want to see + -- the definition of its *type*, not where it was *defined*. + map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition') + + -- Opens a popup that displays documentation about the word under your cursor + -- See `:help K` for why this keymap. + map('K', vim.lsp.buf.hover, 'Hover Documentation') + + -- WARN: This is not Goto Definition, this is Goto Declaration. + -- For example, in C this would take you to the header. + map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + + -- The following two autocommands are used to highlight references of the + -- word under your cursor when your cursor rests there for a little while. + -- See `:help CursorHold` for information about when this is executed + -- + + -- This function resolves a difference between neovim nightly (version 0.11) and stable (version 0.10) + ---@param client vim.lsp.Client + ---@param method vim.lsp.protocol.Method + ---@param bufnr? integer some lsp support methods only in specific files + ---@return boolean + local function client_supports_method(client, method, bufnr) + if vim.fn.has 'nvim-0.11' == 1 then + return client:supports_method(method, bufnr) + else + return client.supports_method(method, { bufnr = bufnr }) + end + end + -- When you move your cursor, the highlights will be cleared (the second autocommand). + local client = vim.lsp.get_client_by_id(event.data.client_id) + if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then + local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) + vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.document_highlight, + }) + + vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.clear_references, + }) + + vim.api.nvim_create_autocmd('LspDetach', { + group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), + callback = function(event2) + vim.lsp.buf.clear_references() + vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } + end, + }) + end + + -- The following code creates a keymap to toggle inlay hints in your + -- code, if the language server you are using supports them + -- + -- This may be unwanted, since they displace some of your code + if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then + map('th', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) + end, '[T]oggle Inlay [H]ints') + end + end, + }) + + -- Diagnostic Config + -- See :help vim.diagnostic.Opts + vim.diagnostic.config { + update_in_insert = false, + severity_sort = true, + float = { border = 'rounded', source = 'if_many' }, + underline = { severity = vim.diagnostic.severity.ERROR }, + -- Can switch between these as you prefer + virtual_text = true, -- Text shows up at the end of the line + virtual_lines = false, -- Teest shows up underneath the line, with virtual lines + + -- Auto open the float, so you can easily read the errors when jumping with `[d` and `]d` + jump = { float = true }, + signs = vim.g.have_nerd_font and { + text = { + [vim.diagnostic.severity.ERROR] = '󰅚 ', + [vim.diagnostic.severity.WARN] = '󰀪 ', + [vim.diagnostic.severity.INFO] = '󰋽 ', + [vim.diagnostic.severity.HINT] = '󰌶 ', + }, + } or {}, + virtual_text = { + source = 'if_many', + spacing = 2, + format = function(diagnostic) + local diagnostic_message = { + [vim.diagnostic.severity.ERROR] = diagnostic.message, + [vim.diagnostic.severity.WARN] = diagnostic.message, + [vim.diagnostic.severity.INFO] = diagnostic.message, + [vim.diagnostic.severity.HINT] = diagnostic.message, + } + return diagnostic_message[diagnostic.severity] + end, + }, + } + -- LSP servers and clients are able to communicate to each other what features they support. + -- By default, Neovim doesn't support everything that is in the LSP specification. + -- When you add blink.cmp, luasnip, etc. Neovim now has *more* capabilities. + -- So, we create new capabilities with blink.cmp, and then broadcast that to the servers. + local capabilities = require('blink.cmp').get_lsp_capabilities() + + -- Enable the following language servers + -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. + -- + -- Add any additional override configuration in the following tables. Available keys are: + -- - cmd (table): Override the default command used to start the server + -- - filetypes (table): Override the default list of associated filetypes for the server + -- - capabilities (table): Override fields in capabilities. Can be used to disable certain LSP features. + -- - settings (table): Override the default settings passed when initializing the server. + -- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/ + local servers = { + -- clangd = {}, + ansiblels = {}, + bashls = {}, + gh_actions_ls = {}, + jinja_lsp = {}, + markdown_oxide = {}, + terraformls = {}, + yamlls = {}, + gopls = {}, + pyright = {}, + rust_analyzer = {}, + ts_ls = {}, + -- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs + -- Some languages (like typescript) have entire language plugins that can be useful: + -- https://github.com/pmizio/typescript-tools.nvim + -- But for many setups, the LSP (`ts_ls`) will work just fine + + lua_ls = { + -- cmd = {...}, + -- filetypes = { ...}, + -- capabilities = {}, + settings = { + Lua = { + completion = { + callSnippet = 'Replace', + }, + -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings + -- diagnostics = { disable = { 'missing-fields' } }, + }, + }, + }, + } + + -- Ensure the servers and tools above are installed + -- To check the current status of installed tools and/or manually install + -- other tools, you can run + -- :Mason + -- + -- You can press `g?` for help in this menu. + -- You can add other tools here that you want Mason to install + -- for you, so that they are available from within Neovim. + local ensure_installed = vim.tbl_keys(servers or {}) + vim.list_extend(ensure_installed, { + 'rustfmt', -- Rust formatter + 'prettier', -- JS/MD formatter + 'black', -- Python formatter + 'isort', + 'shellcheck', + 'markdownlint', + }) + require('mason-tool-installer').setup { ensure_installed = ensure_installed, auto_update = false } + for name, server in pairs(servers) do + server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) + vim.lsp.config(name, server) + vim.lsp.enable(name) + end + + -- Special Lua Config, as recommended by neovim help docs + vim.lsp.config('lua_ls', { + on_init = function(client) + if client.workspace_folders then + local path = client.workspace_folders[1].name + if path ~= vim.fn.stdpath 'config' and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc')) then return end + end + + client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { + runtime = { + version = 'LuaJIT', + path = { 'lua/?.lua', 'lua/?/init.lua' }, + }, + workspace = { + checkThirdParty = false, + -- NOTE: this is a lot slower and will cause issues when working on your own configuration. + -- See https://github.com/neovim/nvim-lspconfig/issues/3189 + library = vim.api.nvim_get_runtime_file('', true), + }, + }) + end, + settings = { + Lua = {}, + }, + }) + vim.lsp.enable 'lua_ls' + end, + }, + -- Linters + { + "nvimtools/none-ls.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + config = function() + local null_ls = require("null-ls") + + null_ls.setup({ + sources = { + -- Only diagnostics/linters here (NOT formatting) + -- Shell + null_ls.builtins.diagnostics.shellcheck, + -- Ansible + null_ls.builtins.diagnostics.ansiblelint, + -- YAML + null_ls.builtins.diagnostics.yamllint, + -- Terraform + null_ls.builtins.diagnostics.terraform_validate, + -- Python (ruff or pylint) + null_ls.builtins.diagnostics.ruff, + -- Go (staticcheck) + null_ls.builtins.diagnostics.staticcheck, + -- Markdown + null_ls.builtins.diagnostics.markdownlint, + }, + }) + end, + }, + + -- Autocompletion + { + 'saghen/blink.cmp', + build = 'cargo +nightly build --release', + event = 'VimEnter', + version = '1.*', + dependencies = { + -- Snippet Engine + { + 'L3MON4D3/LuaSnip', + version = '2.*', + build = (function() + -- Build Step is needed for regex support in snippets. + -- This step is not supported in many windows environments. + -- Remove the below condition to re-enable on windows. + if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then + return + end + return 'make install_jsregexp' + end)(), + dependencies = { + -- `friendly-snippets` contains a variety of premade snippets. + -- See the README about individual language/framework/plugin snippets: + -- https://github.com/rafamadriz/friendly-snippets + -- { + -- 'rafamadriz/friendly-snippets', + -- config = function() + -- require('luasnip.loaders.from_vscode').lazy_load() + -- end, + -- }, + }, + opts = {}, + }, + 'folke/lazydev.nvim', + }, + --- @module 'blink.cmp' + --- @type blink.cmp.Config + opts = { + keymap = { + -- 'default' (recommended) for mappings similar to built-in completions + -- to accept ([y]es) the completion. + -- This will auto-import if your LSP supports it. + -- This will expand snippets if the LSP sent a snippet. + -- 'super-tab' for tab to accept + -- 'enter' for enter to accept + -- 'none' for no mappings + -- + -- For an understanding of why the 'default' preset is recommended, + -- you will need to read `:help ins-completion` + -- + -- No, but seriously. Please read `:help ins-completion`, it is really good! + -- + -- All presets have the following mappings: + -- /: move to right/left of your snippet expansion + -- : Open menu or open docs if already open + -- / or /: Select next/previous item + -- : Hide menu + -- : Toggle signature help + -- + -- See :h blink-cmp-config-keymap for defining your own keymap + preset = 'default', + + -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: + -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps + }, + + appearance = { + -- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font' + -- Adjusts spacing to ensure icons are aligned + nerd_font_variant = 'mono', + }, + + completion = { + -- By default, you may press `` to show the documentation. + -- Optionally, set `auto_show = true` to show the documentation after a delay. + documentation = { auto_show = false, auto_show_delay_ms = 500 }, + }, + + sources = { + default = { 'lsp', 'path', 'snippets', 'lazydev' }, + providers = { + lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 }, + }, + }, + + snippets = { preset = 'luasnip' }, + + -- Blink.cmp includes an optional, recommended rust fuzzy matcher, + -- which automatically downloads a prebuilt binary when enabled. + -- + -- By default, we use the Lua implementation instead, but you may enable + -- the rust implementation via `'prefer_rust_with_warning'` + -- + -- See :h blink-cmp-config-fuzzy for more information + fuzzy = { implementation = 'prefer_rust_with_warning' }, + + -- Shows a signature help window while you type arguments for a function + signature = { enabled = true }, + }, + }, +} diff --git a/lua/plugins_config/mini.lua b/lua/plugins_config/mini.lua new file mode 100644 index 00000000000..5e7f743d661 --- /dev/null +++ b/lua/plugins_config/mini.lua @@ -0,0 +1,37 @@ +return { -- Collection of various small independent plugins/modules + 'echasnovski/mini.nvim', + config = function() + -- Better Around/Inside textobjects + -- + -- Examples: + -- - va) - [V]isually select [A]round [)]paren + -- - yinq - [Y]ank [I]nside [N]ext [']quote + -- - ci' - [C]hange [I]nside [']quote + require('mini.ai').setup { n_lines = 500 } + + -- Add/delete/replace surroundings (brackets, quotes, etc.) + -- + -- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren + -- - sd' - [S]urround [D]elete [']quotes + -- - sr)' - [S]urround [R]eplace [)] ['] + require('mini.surround').setup() + + -- Simple and easy statusline. + -- You could remove this setup call if you don't like it, + -- and try some other statusline plugin + local statusline = require 'mini.statusline' + -- set use_icons to true if you have a Nerd Font + statusline.setup { use_icons = vim.g.have_nerd_font } + + -- You can configure sections in the statusline by overriding their + -- default behavior. For example, here we set the section for + -- cursor location to LINE:COLUMN + ---@diagnostic disable-next-line: duplicate-set-field + statusline.section_location = function() + return '%2l:%-2v' + end + + -- ... and there is more! + -- Check out: https://github.com/echasnovski/mini.nvim + end, +} diff --git a/lua/plugins_config/telescope.lua b/lua/plugins_config/telescope.lua new file mode 100644 index 00000000000..8f0849c678d --- /dev/null +++ b/lua/plugins_config/telescope.lua @@ -0,0 +1,141 @@ +return { -- Fuzzy Finder (files, lsp, etc) + 'nvim-telescope/telescope.nvim', + event = 'VimEnter', + dependencies = { + 'nvim-lua/plenary.nvim', + { -- If encountering errors, see telescope-fzf-native README for installation instructions + 'nvim-telescope/telescope-fzf-native.nvim', + + -- `build` is used to run some command when the plugin is installed/updated. + -- This is only run then, not every time Neovim starts up. + build = 'make', + + -- `cond` is a condition used to determine whether this plugin should be + -- installed and loaded. + cond = function() + return vim.fn.executable 'make' == 1 + end, + }, + { 'nvim-telescope/telescope-ui-select.nvim' }, + + -- Useful for getting pretty icons, but requires a Nerd Font. + { 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font }, + }, + config = function() + -- Telescope is a fuzzy finder that comes with a lot of different things that + -- it can fuzzy find! It's more than just a "file finder", it can search + -- many different aspects of Neovim, your workspace, LSP, and more! + -- + -- The easiest way to use Telescope, is to start by doing something like: + -- :Telescope help_tags + -- + -- After running this command, a window will open up and you're able to + -- type in the prompt window. You'll see a list of `help_tags` options and + -- a corresponding preview of the help. + -- + -- Two important keymaps to use while in Telescope are: + -- - Insert mode: + -- - Normal mode: ? + -- + -- This opens a window that shows you all of the keymaps for the current + -- Telescope picker. This is really useful to discover what Telescope can + -- do as well as how to actually do it! + + -- [[ Configure Telescope ]] + -- See `:help telescope` and `:help telescope.setup()` + require('telescope').setup { + -- You can put your default mappings / updates / etc. in here + -- All the info you're looking for is in `:help telescope.setup()` + -- + -- defaults = { + -- mappings = { + -- i = { [''] = 'to_fuzzy_refine' }, + -- }, + -- }, + -- pickers = {} + extensions = { + ['ui-select'] = { + require('telescope.themes').get_dropdown(), + }, + }, + } + + -- Enable Telescope extensions if they are installed + pcall(require('telescope').load_extension, 'fzf') + pcall(require('telescope').load_extension, 'ui-select') + + -- See `:help telescope.builtin` + local builtin = require 'telescope.builtin' + vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) + vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) + vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) + vim.keymap.set('n', 'ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) + vim.keymap.set({'n', 'v'}, 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) + vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) + vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) + vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) + vim.keymap.set('n', 's.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' }) + vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) + vim.keymap.set('n', 'sc', builtin.commands, { desc = '[S]earch [C]ommands' }) + vim.keymap.set('n', 'wm', function() + require('telescope').extensions.git_worktree.git_worktrees() -- manage worktrees on telescope + end) + vim.keymap.set('n', 'wc', function() + require('telescope').extensions.git_worktree.create_git_worktree() -- create worktree + end) + -- This runs on LSP attach per buffer (see main LSP attach function in 'neovim/nvim-lspconfig' config for more info, + -- it is better explained there). This allows easily switching between pickers if you prefer using something else! + vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('telescope-lsp-attach', { clear = true }), + callback = function(event) + local buf = event.buf + + -- Find references for the word under your cursor. + vim.keymap.set('n', 'grr', builtin.lsp_references, { buffer = buf, desc = '[G]oto [R]eferences' }) + + -- Jump to the implementation of the word under your cursor. + -- Useful when your language has ways of declaring types without an actual implementation. + vim.keymap.set('n', 'gri', builtin.lsp_implementations, { buffer = buf, desc = '[G]oto [I]mplementation' }) + + -- Jump to the definition of the word under your cursor. + -- This is where a variable was first declared, or where a function is defined, etc. + -- To jump back, press . + vim.keymap.set('n', 'grd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' }) + + -- Fuzzy find all the symbols in your current document. + -- Symbols are things like variables, functions, types, etc. + vim.keymap.set('n', 'gO', builtin.lsp_document_symbols, { buffer = buf, desc = 'Open Document Symbols' }) + + -- Fuzzy find all the symbols in your current workspace. + -- Similar to document symbols, except searches over your entire project. + vim.keymap.set('n', 'gW', builtin.lsp_dynamic_workspace_symbols, { buffer = buf, desc = 'Open Workspace Symbols' }) + + -- Jump to the type of the word under your cursor. + -- Useful when you're not sure what type a variable is and you want to see + -- the definition of its *type*, not where it was *defined*. + vim.keymap.set('n', 'grt', builtin.lsp_type_definitions, { buffer = buf, desc = '[G]oto [T]ype Definition' }) + end, + }) + + -- Slightly advanced example of overriding default behavior and theme + vim.keymap.set('n', '/', function() + -- You can pass additional configuration to Telescope to change the theme, layout, etc. + builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + winblend = 30, + previewer = true, + }) + end, { desc = '[/] Fuzzily search in current buffer' }) + + -- It's also possible to pass additional configuration options. + -- See `:help telescope.builtin.live_grep()` for information about particular keys + vim.keymap.set('n', 's/', function() + builtin.live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } + end, { desc = '[S]earch [/] in Open Files' }) + + -- Shortcut for searching your Neovim configuration files + vim.keymap.set('n', 'sn', function() builtin.find_files { cwd = vim.fn.stdpath 'config' } end, { desc = '[S]earch [N]eovim files' }) + end, +} diff --git a/lua/plugins_config/tree-sitter.lua b/lua/plugins_config/tree-sitter.lua new file mode 100644 index 00000000000..ceb7bbae078 --- /dev/null +++ b/lua/plugins_config/tree-sitter.lua @@ -0,0 +1,43 @@ +return { -- Highlight, edit, and navigate code + 'nvim-treesitter/nvim-treesitter', + build = ':TSUpdate', + main = 'nvim-treesitter.configs', -- Sets main module to use for opts + -- [[ Configure Treesitter ]] See `:help nvim-treesitter` + opts = { + ensure_installed = { 'lua', 'luadoc', 'rust', 'toml', 'bash', 'dockerfile', 'go', 'json', 'make', 'markdown', 'python', 'regex', 'yaml', 'vim', 'vimdoc', 'diff', 'typescript', 'javascript' }, + -- Install parsers synchronously (only applied to `ensure_installed`) + sync_install = false, + + -- Autoinstall languages that are not installed + auto_install = true, + highlight = { + enable = true, + -- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules. + -- If you are experiencing weird indenting issues, add the language to + -- the list of additional_vim_regex_highlighting and disabled languages for indent. + additional_vim_regex_highlighting = false, + }, + indent = { enable = true, disable = { 'ruby' } }, + }, + config = function(_, opts) + -- [[ Configure Treesitter ]] See `:help nvim-treesitter` + + -- Prefer git instead of curl in order to improve connectivity in some environments + require('nvim-treesitter.install').prefer_git = true + ---@diagnostic disable-next-line: missing-fields + require('nvim-treesitter.configs').setup(opts) + config = function() + local filetypes = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } + require('nvim-treesitter').install(filetypes) + vim.api.nvim_create_autocmd('FileType', { + pattern = filetypes, + callback = function() vim.treesitter.start() end, + }) + -- There are additional nvim-treesitter modules that you can use to interact + -- with nvim-treesitter. You should go explore a few and see what interests you: + -- + -- - Incremental selection: Included, see `:help nvim-treesitter-incremental-selection-mod` + -- - Show your current context: https://github.com/nvim-treesitter/nvim-treesitter-context + -- - Treesitter + textobjects: https://github.com/nvim-treesitter/nvim-treesitter-textobjects + end, +} diff --git a/lua/plugins_config/vim-fugitive.lua b/lua/plugins_config/vim-fugitive.lua new file mode 100644 index 00000000000..23368a174df --- /dev/null +++ b/lua/plugins_config/vim-fugitive.lua @@ -0,0 +1,42 @@ +return { + 'tpope/vim-fugitive', + + -- set git status remap + vim.keymap.set('n', 'gs', vim.cmd.Git, { desc = 'Start git buffer and check status' }), + vim.keymap.set('n', 'dv', ':Gvdiffsplit!', { desc = 'Diff split against HEAD vertical' }), + vim.keymap.set('n', 'dh', ':Gdiffsplit!', { desc = 'Diff split against HEAD horizontal' }), + vim.keymap.set('n', 'dt', ':windo diffthis', { desc = 'Diff files in all windows' }), + vim.keymap.set('n', 'dm', ':Gdiff!', { desc = 'On conflicted file opens a 3-way diff' }), + vim.keymap.set('n', '2', ':diffget //2 | diffupdate', { desc = 'On the middle file get the diff from Head' }), + vim.keymap.set('n', '3', ':diffget //3 | diffupdate', { desc = 'On the middle file get the diff from the other branch' }), + vim.keymap.set('n', 'do', ':diffo!', { desc = 'Turn off diff mode' }), + + -- + Autocmd('BufWinEnter', { + group = Fugitive, + pattern = '*', + callback = function() + if vim.bo.ft ~= 'fugitive' then + return + end + + local bufnr = vim.api.nvim_get_current_buf() + local opts = { buffer = bufnr, remap = false } + vim.keymap.set('n', 'gc', function() + vim.cmd.Git 'commit' + end) + vim.keymap.set('n', 'p', function() + vim.cmd.Git 'push' + end, opts) + + -- rebase always + vim.keymap.set('n', 'P', function() + vim.cmd.Git { 'pull', '--rebase' } + end, opts) + + -- NOTE: It allows me to easily set the branch i am pushing and any tracking + -- needed if i did not set the branch up correctly + vim.keymap.set('n', 't', ':Git push -u origin ', opts) + end, + }), +} diff --git a/lua/plugins_config/which-key.lua b/lua/plugins_config/which-key.lua new file mode 100644 index 00000000000..f9ceac8e3b1 --- /dev/null +++ b/lua/plugins_config/which-key.lua @@ -0,0 +1,68 @@ +return { -- Useful plugin to show you pending keybinds. + 'folke/which-key.nvim', + event = 'VimEnter', -- Sets the loading event to 'VimEnter' + opts = { + -- delay between pressing a key and opening which-key (milliseconds) + -- this setting is independent of vim.opt.timeoutlen + delay = 0, + icons = { + -- set icon mappings to true if you have a Nerd Font + mappings = vim.g.have_nerd_font, + -- If you are using a Nerd Font: set icons.keys to an empty table which will use the + -- default which-key.nvim defined Nerd Font icons, otherwise define a string table + keys = vim.g.have_nerd_font and {} or { + Up = ' ', + Down = ' ', + Left = ' ', + Right = ' ', + C = ' ', + M = ' ', + D = ' ', + S = ' ', + CR = ' ', + Esc = ' ', + ScrollWheelDown = ' ', + ScrollWheelUp = ' ', + NL = ' ', + BS = ' ', + Space = ' ', + Tab = ' ', + F1 = '', + F2 = '', + F3 = '', + F4 = '', + F5 = '', + F6 = '', + F7 = '', + F8 = '', + F9 = '', + F10 = '', + F11 = '', + F12 = '', + }, + }, + + -- Document existing key chains + spec = { + { 's', group = '[S]earch' }, + { 't', group = '[T]oggle' }, + { 'c', group = '[C]ode' }, + { 'c_', hidden = true }, + { 'd', group = '[D]ocument' }, + { 'd_', hidden = true }, + { 'h', group = 'Git [H]unk' }, + { 'h_', hidden = true }, + { 'r', group = '[R]un code' }, + { 'r_', hidden = true }, + { 'R', group = '[R]e[n]ame' }, + { 'R_', hidden = true }, + { 's', group = '[S]earch' }, + { 's_', hidden = true }, + { 't', group = '[T]oggle' }, + { 't_', hidden = true }, + { 'w', group = '[W]orkspace' }, + { 'w_', hidden = true }, + { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, + }, + }, +} diff --git a/lua/plugins_config/worktree.lua b/lua/plugins_config/worktree.lua new file mode 100644 index 00000000000..b85660e27f4 --- /dev/null +++ b/lua/plugins_config/worktree.lua @@ -0,0 +1,7 @@ +return { + 'ThePrimeagen/git-worktree.nvim', -- Manage worktrees from nvim + opts = { + change_directory_command = 'tcd', -- command to change directory (e.g. lcd for NvimTree) + autopush = true, + }, +}