diff --git a/.stylua.toml b/.stylua.toml index edfa5067106..78c5507c326 100644 --- a/.stylua.toml +++ b/.stylua.toml @@ -1,7 +1,6 @@ -column_width = 160 +column_width = 120 line_endings = "Unix" indent_type = "Spaces" indent_width = 2 quote_style = "AutoPreferSingle" call_parentheses = "None" -collapse_simple_statement = "Always" diff --git a/after/lsp/lua_ls.lua b/after/lsp/lua_ls.lua new file mode 100644 index 00000000000..12e6d0f4139 --- /dev/null +++ b/after/lsp/lua_ls.lua @@ -0,0 +1,43 @@ +return { + on_init = function(client) + client.server_capabilities.documentFormattingProvider = false -- Disable formatting (formatting is done by stylua) + + 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, + library = { + vim.env.VIMRUNTIME, + }, + -- -- 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.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), { + -- '${3rd}/luv/library', + -- '${3rd}/busted/library', + -- }), + }, + }) + end, + ---@type lspconfig.settings.lua_ls + settings = { + Lua = { + format = { enable = false }, -- Disable formatting (formatting is done by stylua) + }, + }, +} diff --git a/init.lua b/init.lua index 8d1f19a10d4..95fab1589f1 100644 --- a/init.lua +++ b/init.lua @@ -84,907 +84,7 @@ I hope you enjoy your Neovim journey, P.S. You can delete this when you're done too. It's your config now! :) --]] --- Set as the leader key --- See `:help mapleader` --- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) -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 - --- [[ Setting options ]] --- See `:help vim.o` --- NOTE: You can change these options as you wish! --- For more options, you can see `:help option-list` - --- Make line numbers default -vim.o.number = true --- You can also add relative line numbers, to help with jumping. --- Experiment for yourself to see if you like it! --- 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) - --- Enable break indent -vim.o.breakindent = true - --- Enable undo/redo changes even after closing and reopening a file -vim.o.undofile = true - --- Case-insensitive searching UNLESS \C or one or more capital letters in the search term -vim.o.ignorecase = true -vim.o.smartcase = true - --- Keep signcolumn on by default -vim.o.signcolumn = 'yes' - --- Decrease update time -vim.o.updatetime = 250 - --- Decrease mapped sequence wait time -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'` --- --- 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` -vim.o.list = true -vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } - --- Preview substitutions live, as you type! -vim.o.inccommand = 'split' - --- Show which line your cursor is on -vim.o.cursorline = true - --- Minimal number of screen lines to keep above and below the cursor. -vim.o.scrolloff = 10 - --- 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 - --- [[ Basic Keymaps ]] --- See `:help vim.keymap.set()` - --- Clear highlights on search when pressing in normal mode --- 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 = { min = vim.diagnostic.severity.WARN } }, - - -- Can switch between these as you prefer - virtual_text = true, -- Text shows up at the end of the line - virtual_lines = false, -- Text 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 }, -} - -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 --- 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 --- 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. --- 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" }) - --- [[ Basic Autocommands ]] --- See `:help lua-guide-autocommands` - --- Highlight when yanking (copying) text --- Try it with `yap` in normal mode --- See `:help vim.hl.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, -}) - --- [[ 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 - ----@type vim.Option -local rtp = vim.opt.rtp -rtp:prepend(lazypath) - --- [[ 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({ - -- NOTE: Plugins can be added via a link or github org/name. To run setup automatically, use `opts = {}` - { 'NMAC427/guess-indent.nvim', opts = {} }, - - -- 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, - -- } - -- - -- Here is a more advanced example where we pass configuration - -- options to `gitsigns.nvim`. - -- - -- See `:help gitsigns` to understand what the configuration keys do - { -- Adds git related signs to the gutter, as well as utilities for managing changes - 'lewis6991/gitsigns.nvim', - ---@module 'gitsigns' - ---@type Gitsigns.Config - ---@diagnostic disable-next-line: missing-fields - opts = { - signs = { - add = { text = '+' }, ---@diagnostic disable-line: missing-fields - change = { text = '~' }, ---@diagnostic disable-line: missing-fields - delete = { text = '_' }, ---@diagnostic disable-line: missing-fields - topdelete = { text = '‾' }, ---@diagnostic disable-line: missing-fields - changedelete = { text = '~' }, ---@diagnostic disable-line: missing-fields - }, - }, - }, - - -- 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)`. - - { -- Useful plugin to show you pending keybinds. - 'folke/which-key.nvim', - event = 'VimEnter', - ---@module 'which-key' - ---@type wk.Opts - ---@diagnostic disable-next-line: missing-fields - opts = { - -- delay between pressing a key and opening which-key (milliseconds) - delay = 0, - icons = { mappings = vim.g.have_nerd_font }, - - -- Document existing key chains - spec = { - { 's', group = '[S]earch', mode = { 'n', 'v' } }, - { 't', group = '[T]oggle' }, - { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, -- Enable gitsigns recommended keymaps first - { 'gr', group = 'LSP Actions', mode = { 'n' } }, - }, - }, - }, - - -- 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 - - { -- 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', - { -- 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', '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 - 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 = 10, - previewer = false, - }) - 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, - }, - - -- LSP Plugins - { - -- Main LSP Configuration - 'neovim/nvim-lspconfig', - dependencies = { - -- Automatically install LSPs and related tools to stdpath for Neovim - -- 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', - ---@module 'mason.settings' - ---@type MasonSettings - ---@diagnostic disable-next-line: missing-fields - opts = {}, - }, - -- Maps LSP server names between nvim-lspconfig and Mason package names. - 'mason-org/mason-lspconfig.nvim', - 'WhoIsSethDaniel/mason-tool-installer.nvim', - - -- Useful status updates for LSP. - { 'j-hui/fidget.nvim', opts = {} }, - }, - 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 - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup('kickstart-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 - - -- Rename the variable under your cursor. - -- 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' }) - - -- 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') - - -- 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 - 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('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, - }) - - -- 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 - ---@type table - local servers = { - -- clangd = {}, - -- gopls = {}, - -- pyright = {}, - -- rust_analyzer = {}, - -- - -- 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 = {}, - - stylua = {}, -- Used to format Lua code - - -- Special Lua Config, as recommended by neovim help docs - lua_ls = { - on_init = function(client) - client.server_capabilities.documentFormattingProvider = false -- Disable formatting (formatting is done by stylua) - - 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.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), { - '${3rd}/luv/library', - '${3rd}/busted/library', - }), - }, - }) - end, - ---@type lspconfig.settings.lua_ls - settings = { - Lua = { - format = { enable = false }, -- Disable formatting (formatting is done by stylua) - }, - }, - }, - } - - -- 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. - local ensure_installed = vim.tbl_keys(servers or {}) - vim.list_extend(ensure_installed, { - -- 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 - vim.lsp.config(name, server) - vim.lsp.enable(name) - end - end, - }, - - { -- Autoformat - 'stevearc/conform.nvim', - event = { 'BufWritePre' }, - cmd = { 'ConformInfo' }, - keys = { - { - 'f', - function() require('conform').format { async = true } end, - mode = '', - desc = '[F]ormat buffer', - }, - }, - ---@module 'conform' - ---@type conform.setupOpts - opts = { - notify_on_error = false, - format_on_save = function(bufnr) - -- You can specify filetypes to autoformat on save here: - local enabled_filetypes = { - -- lua = true, - -- python = true, - } - if enabled_filetypes[vim.bo[bufnr].filetype] then - return { timeout_ms = 500 } - else - return nil - end - end, - default_format_opts = { - lsp_format = 'fallback', -- Use external formatters if configured below, otherwise use LSP formatting. Set to `false` to disable LSP formatting entirely. - }, - -- You can also specify external formatters in here. - formatters_by_ft = { - -- rust = { 'rustfmt' }, - -- Conform can also run multiple formatters sequentially - -- python = { "isort", "black" }, - -- - -- You can use 'stop_after_first' to run the first available formatter from the list - -- javascript = { "prettierd", "prettier", stop_after_first = true }, - }, - }, - }, - - { -- Autocompletion - 'saghen/blink.cmp', - 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 = {}, - }, - }, - ---@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' }, - }, - - 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 = 'lua' }, - - -- Shows a signature help window while you type arguments for a function - signature = { enabled = true }, - }, - }, - - { -- 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, - }, - - -- Highlight todo, notes, etc in comments - { - 'folke/todo-comments.nvim', - event = 'VimEnter', - dependencies = { 'nvim-lua/plenary.nvim' }, - ---@module 'todo-comments' - ---@type TodoOptions - ---@diagnostic disable-next-line: missing-fields - opts = { signs = false }, - }, - - { -- Collection of various small independent plugins/modules - 'nvim-mini/mini.nvim', - config = function() - -- Better Around/Inside textobjects - -- - -- Examples: - -- - va) - [V]isually select [A]round [)]paren - -- - yiiq - [Y]ank [I]nside [I]+1 [Q]uote - -- - ci' - [C]hange [I]nside [']quote - require('mini.ai').setup { - -- NOTE: Avoid conflicts with the built-in incremental selection mappings on Neovim>=0.12 (see `:help treesitter-incremental-selection`) - mappings = { - around_next = 'aa', - inside_next = 'ii', - }, - 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/nvim-mini/mini.nvim - end, - }, - - { -- Highlight, edit, and navigate code - 'nvim-treesitter/nvim-treesitter', - lazy = false, - build = ':TSUpdate', - branch = 'main', - -- [[ Configure Treesitter ]] See `:help nvim-treesitter-intro` - config = function() - -- ensure basic parser are installed - local parsers = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } - require('nvim-treesitter').install(parsers) - - ---@param buf integer - ---@param language string - local function treesitter_try_attach(buf, language) - -- check if parser exists and load it - if not vim.treesitter.language.add(language) then return end - -- enables syntax highlighting and other treesitter features - vim.treesitter.start(buf, language) - - -- enables treesitter based folds - -- for more info on folds see `:help folds` - -- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' - -- vim.wo.foldmethod = 'expr' - - -- check if treesitter indentation is available for this language, and if so enable it - -- in case there is no indent query, the indentexpr will fallback to the vim's built in one - local has_indent_query = vim.treesitter.query.get(language, 'indents') ~= nil - - -- enables treesitter based indentation - if has_indent_query then vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" end - end - - local available_parsers = require('nvim-treesitter').get_available() - vim.api.nvim_create_autocmd('FileType', { - callback = function(args) - local buf, filetype = args.buf, args.match - - local language = vim.treesitter.language.get_lang(filetype) - if not language then return end - - local installed_parsers = require('nvim-treesitter').get_installed 'parsers' - - if vim.tbl_contains(installed_parsers, language) then - -- enable the parser if it is installed - treesitter_try_attach(buf, language) - elseif vim.tbl_contains(available_parsers, language) then - -- if a parser is available in `nvim-treesitter` auto install it, and enable it after the installation is done - require('nvim-treesitter').install(language):await(function() treesitter_try_attach(buf, language) end) - else - -- try to enable treesitter features in case the parser exists but is not available from `nvim-treesitter` - treesitter_try_attach(buf, language) - end - end, - }) - end, - }, - - -- The following 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: Next step on your Neovim journey: Add/Configure additional plugins for Kickstart - -- - -- Here are some example plugins that I've included in the Kickstart repository. - -- Uncomment any of the lines below to enable them (you will need to restart nvim). - -- - -- require 'kickstart.plugins.debug', - -- require 'kickstart.plugins.indent_line', - -- require 'kickstart.plugins.lint', - -- require 'kickstart.plugins.autopairs', - -- require 'kickstart.plugins.neo-tree', - -- require 'kickstart.plugins.gitsigns', -- adds gitsigns recommended keymaps - - -- 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. - -- { import = 'custom.plugins' }, - -- - -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` - -- Or use telescope! - -- In normal mode type `sh` then write `lazy.nvim-plugin` - -- you can continue same window with `sr` which resumes last telescope search -}, { ---@diagnostic disable-line: missing-fields - 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 = '💤 ', - }, - }, -}) +require 'core' -- The line beneath this is called `modeline`. See `:help modeline` -- vim: ts=2 sts=2 sw=2 et diff --git a/lua/core/autocommands.lua b/lua/core/autocommands.lua new file mode 100644 index 00000000000..13689c782c1 --- /dev/null +++ b/lua/core/autocommands.lua @@ -0,0 +1,32 @@ +-- [[ Basic Autocommands ]] +-- See `:help lua-guide-autocommands` + +-- Highlight when yanking (copying) text +-- Try it with `yap` in normal mode +-- See `:help vim.hl.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, +}) + +vim.api.nvim_create_autocmd('ColorScheme', { + desc = 'Reset colors for some elements after changing the colorscheme.', + group = vim.api.nvim_create_augroup('ElementsColorReset', { clear = true }), + callback = function() + vim.api.nvim_set_hl(0, 'WinSeparator', vim.api.nvim_get_hl(0, { name = 'CursorLineNr' })) + vim.api.nvim_set_hl(0, 'EndOfBuffer', vim.api.nvim_get_hl(0, { name = 'CursorLineNr' })) + end, +}) + +vim.api.nvim_create_autocmd('TermOpen', { + desc = 'Rename terminal buffer', + group = vim.api.nvim_create_augroup('RenameTerminalBufer', { clear = true }), + callback = function(ev) + local pid, cmd = ev.file:match '//(%d-:)(.+)' + cmd = vim.fs.basename(cmd) + vim.api.nvim_buf_set_name(ev.buf, 'term://' .. pid .. cmd) + end, +}) diff --git a/lua/core/globals.lua b/lua/core/globals.lua new file mode 100644 index 00000000000..9061875b805 --- /dev/null +++ b/lua/core/globals.lua @@ -0,0 +1,179 @@ +-- [[ Global Configs ]] +-- Set as the leader key +-- See `:help mapleader` +-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) +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 = true + +-- Configs for Programming Languages +-- like LSPs, Tree-sitters, Linters, Fromatters, Debuggers, etc. +Langs = { + lsp = { + 'bashls', + 'clangd', + 'elmls', + 'gopls', + 'harper_ls', + 'html', + 'intelephense', + 'just', + 'laravel_ls', + 'lua_ls', + 'markdown_oxide', + 'marksman', + 'omnisharp', + 'phpactor', + 'pyrefly', + 'roslyn_ls', + 'stylua', + 'superhtml', + 'svelte', + 'tailwindcss', + 'ts_ls', + 'zls', + -- 'fsautocomplete', + }, + + treesitter = { + 'bash', + 'c', + 'c_sharp', + 'css', + 'diff', + 'go', + 'html', + 'lua', + 'luadoc', + 'markdown', + 'markdown_inline', + 'php', + 'python', + 'query', + 'vim', + 'vimdoc', + 'zig', + }, + + linter = { + markdown = { 'mado' }, -- or rumdl + python = { 'ruff' }, + }, + + fmt = { + -- lua = { 'stylua' }, -- see [Use stylua as an lsp formatter instead of an external formatter · nvim-lua/kickstart.nvim@459b868](https://github.com/nvim-lua/kickstart.nvim/commit/459b86865e9e81235c9db3be553d107adac5f72f) + sh = { 'shfmt' }, + bash = { 'shfmt' }, + python = { 'ruff_format' }, + blade = { 'blade-formatter' }, + markdown = { 'mdformat' }, + }, + + fmt_cmd = { + shfmt = { + prepend_args = { '-i', '4' }, + -- The base args are { "-filename", "$FILENAME" } so the final args will be + -- { "-filename", "$FILENAME", "-i", "2" } + }, + ['blade-formatter'] = { + prepend_args = { '-i', '2' }, + }, + }, +} + +-- My set of defined icons, I still don't know if its inclusive or not. +-- I named it Glyphs to avoid misinterpreting it with something else. +Glyphs = { + ui = { + prompt = '', + }, + lazy = { + cmd = ' ', + config = '', + debug = '● ', + event = ' ', + favorite = ' ', + ft = ' ', + init = ' ', + import = ' ', + keys = ' ', + lazy = '󰒲 ', + loaded = '●', + not_loaded = '○', + plugin = ' ', + runtime = ' ', + require = ' ', + source = ' ', + start = ' ', + task = ' ', + list = { '●', '○', '◆', '◇' }, + }, + snacksPicker = { + lsp = { + unavailable = '', + enabled = '', + disabled = '', + attached = '', + }, + }, + diagnostics = { + error = '', + warn = '', + hint = '', + info = '', + }, + dev_kit = { + lsp = '', + fmt = '󰉿', + lint = '', + }, + file_status = { + modified = '󰏫', + unmodifiable = '󰏯', + readOnly = '󰌾', + preview = '󰈈', + }, + kinds = { + -- taken from: + -- - [Completion.Kind (LSP APIs)](https://bits.netbeans.org/29/javadoc/org-netbeans-api-lsp/org/netbeans/api/lsp/Completion.Kind.html) + -- - [StructureElement.Kind (LSP APIs)](https://bits.netbeans.org/29/javadoc/org-netbeans-api-lsp/org/netbeans/api/lsp/StructureElement.Kind.html) + Array = '', + Boolean = '', + Class = '󰒕', + Color = '󰏘', + Constant = '󰏿', + Constructor = '󱌣', + Copilot = '', -- for AI indication + Enum = '', -- or   + EnumMember = '', -- or   + Event = '', + Field = '󰿨', + File = '󰈙', + Folder = '󰉋', + Function = '󰊕', + Interface = '󰩦', -- or 󱖡 + Key = '', + Keyword = '', + Method = 'ɱ', -- or ꬺ, I can't decide + Module = '󰅩', + Namespace = '󰦮', + Null = '∅', + Number = '󰎠', + Object = '󰮄', --  would more appropriate + Operator = '', + Package = '󰏗', + Property = '󰆦', + Reference = '󰬲', + Snippet = '󱄽', + String = '󱀍', -- or  󰀬 + Struct = '󰓸', -- or 󰙅 󰆩 + Text = '󰉿', + TypeParameter = '', + Unit = '󰑭', + Unknown = '', -- for Unknown values + Value = '󰼢', + Variable = '󰀫', + }, +} diff --git a/lua/core/init.lua b/lua/core/init.lua new file mode 100644 index 00000000000..a96dd049291 --- /dev/null +++ b/lua/core/init.lua @@ -0,0 +1,6 @@ +require 'core.globals' +require 'core.options' +require 'core.keymaps' +require 'core.autocommands' +require 'core.lazy-nvim' +require 'core.ui' diff --git a/lua/core/keymaps.lua b/lua/core/keymaps.lua new file mode 100644 index 00000000000..8953f157e47 --- /dev/null +++ b/lua/core/keymaps.lua @@ -0,0 +1,91 @@ +-- [[ Basic Keymaps ]] +-- See `:help vim.keymap.set()` + +-- Clear highlights on search when pressing in normal mode +-- See `:help hlsearch` +vim.keymap.set('n', '', 'nohlsearch') + +-- 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 +-- 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. +-- 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" }) + +vim.keymap.set('n', 'n', 'nzz') +vim.keymap.set('n', 'N', 'Nzz') +vim.keymap.set('n', '*', '*zz') +vim.keymap.set('n', '#', '#zz') +-- vim.keymap.set('n', 'g*', '*zz') +-- vim.keymap.set('n', 'g#', '#zz') +vim.keymap.set('n', '{', '{zt') +vim.keymap.set('n', '}', '}zt') +vim.keymap.set('n', '(', '(zt') +vim.keymap.set('n', ')', ')zt') + +vim.keymap.set('n', 'tl', 'Lazy', { desc = '[T]oggle [L]azy' }) +vim.keymap.set('n', 'tm', 'Mason', { desc = '[T]oggle [M]ason' }) +vim.keymap.set('n', 'ta', 'set arabic!', { desc = '[T]oggle [A]rabic' }) +vim.keymap.set('n', 'tw', 'set wrap!', { noremap = true, silent = true, desc = '[T]oggle [W]rap' }) + +vim.keymap.set('n', 'w', 'w', { desc = '[w]rite buffer' }) +vim.keymap.set('n', 'y', '%y', { desc = '[y]ank buffer' }) +vim.keymap.set('n', 'q', 'q', { desc = '[q]uit buffer' }) +vim.keymap.set('n', 'c', 'bdelete', { desc = '[c]lose file' }) + +-- terminal keymaps +vim.keymap.set('n', ';;', function() + vim.cmd.term() +end, { desc = 'New termianl proc - current buf' }) +vim.keymap.set('n', ';s', function() + vim.cmd.new() -- or vim.cmd.vnew(); vim.cmd.wincmd 'J' + vim.cmd.term() + vim.api.nvim_win_set_height(0, 10) +end, { desc = 'New termianl proc - horizontal' }) +vim.keymap.set('n', ';v', function() + vim.cmd.vnew() + vim.cmd.term() +end, { desc = 'New termianl proc - vertical' }) +vim.keymap.set('n', ';t', function() + vim.cmd.tabnew() + vim.cmd.term() +end, { desc = 'New termianl proc - tab' }) +vim.keymap.set('n', ';o', function() + vim.cmd.tabnew() + vim.cmd.term 'opencode' +end, { desc = 'New opencode proc' }) +vim.keymap.set('n', ';l', function() + vim.cmd.tabnew() + vim.cmd.term 'lazygit' +end, { desc = 'New lazygit proc' }) + +-- Add a keymap for delete while on insert-mode +-- this works well with , , +vim.keymap.set('i', '', '') + +-- [[ Keymap Deletion ]] + +-- this would be remapped to `grs` so I don't want to keep it. +vim.keymap.del('n', 'gO') diff --git a/lua/core/lazy-nvim.lua b/lua/core/lazy-nvim.lua new file mode 100644 index 00000000000..7d55d7c0bf7 --- /dev/null +++ b/lua/core/lazy-nvim.lua @@ -0,0 +1,90 @@ +-- [[ 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 + +---@type vim.Option +local rtp = vim.opt.rtp +rtp:prepend(lazypath) + +-- [[ 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({ + -- NOTE: Plugins can be added via a link or github org/name. To run setup automatically, use `opts = {}` + + -- 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, + -- } + -- + -- Here is a more advanced example where we pass configuration + -- options to `gitsigns.nvim`. + -- + -- See `:help gitsigns` to understand what the configuration keys do + + -- 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 + + -- NOTE: Next step on your Neovim journey: Add/Configure additional plugins for Kickstart + -- + -- You can do that by requiring each file as: + -- + -- require 'plugins.gitsigns' + -- + -- Or by using lazy.nvim special `import` field to automatically import your + -- own plugins, configuration, etc from `lua/custom/plugins/*.lua` + -- + -- This is the easiest way to modularize your config. + -- + { import = 'plugins' }, + + -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` + -- Or use telescope! + -- In normal mode type `sh` then write `lazy.nvim-plugin` + -- you can continue same window with `sr` which resumes last telescope search +}, { ---@diagnostic disable-line: missing-fields + 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 = Glyphs.lazy, + }, +}) diff --git a/lua/core/options.lua b/lua/core/options.lua new file mode 100644 index 00000000000..b16963f27d4 --- /dev/null +++ b/lua/core/options.lua @@ -0,0 +1,89 @@ +-- [[ Setting Options ]] +-- See `:help vim.o` +-- NOTE: You can change these options as you wish! +-- For more options, you can see `:help option-list` + +-- Make line numbers default +vim.o.number = true +-- You can also add relative line numbers, to help with jumping. +-- Experiment for yourself to see if you like it! +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) + +-- Enable break indent +vim.o.breakindent = true + +-- Enable undo/redo changes even after closing and reopening a file +vim.o.undofile = true + +-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term +vim.o.ignorecase = true +vim.o.smartcase = true + +-- Keep signcolumn on by default +vim.o.signcolumn = 'yes' + +-- Decrease update time +vim.o.updatetime = 250 + +-- Decrease mapped sequence wait time +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'` +-- +-- 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` +vim.o.list = true +vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } + +-- Preview substitutions live, as you type! +vim.o.inccommand = 'split' + +-- Show which line your cursor is on +vim.o.cursorline = true + +-- Minimal number of screen lines to keep above and below the cursor. +vim.o.scrolloff = 5 + +-- 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 linebreak to true to break lines according to word-boundary rather than last character +vim.o.linebreak = true + +-- set tabs +-- A tab character looks like 4 spaces +vim.o.tabstop = 4 +-- Size of an indent +vim.o.shiftwidth = 4 +-- Number of spaces tabs count for a while performing editing operations +vim.o.softtabstop = 4 +-- Turn tabs into spaces +vim.o.expandtab = true + +-- set spellchecking +vim.o.spell = true +vim.o.spelllang = 'en_us' diff --git a/lua/core/ui.lua b/lua/core/ui.lua new file mode 100644 index 00000000000..607e2927b44 --- /dev/null +++ b/lua/core/ui.lua @@ -0,0 +1,10 @@ +-- [[ UI Configs ]] +-- set transparency +vim.api.nvim_set_hl(0, 'Normal', { bg = 'none', ctermbg = 'none' }) +vim.api.nvim_set_hl(0, 'NonText', { bg = 'none', ctermbg = 'none' }) +vim.api.nvim_set_hl(0, 'SignColumn', { bg = 'none', ctermbg = 'none' }) +vim.api.nvim_set_hl(0, 'FoldColumn', { bg = 'none', ctermbg = 'none' }) + +-- set WinSeparator & EndOfBuffer to match the highlight on cursor-line-number +vim.api.nvim_set_hl(0, 'WinSeparator', vim.api.nvim_get_hl(0, { name = 'CursorLineNr' })) +vim.api.nvim_set_hl(0, 'EndOfBuffer', vim.api.nvim_get_hl(0, { name = 'CursorLineNr' })) diff --git a/lua/custom/plugins/init.lua b/lua/custom/plugins/init.lua deleted file mode 100644 index b3ddcfdd3aa..00000000000 --- a/lua/custom/plugins/init.lua +++ /dev/null @@ -1,8 +0,0 @@ --- You can add your own plugins here or in other files in this directory! --- I promise not to create any merge conflicts in this directory :) --- --- See the kickstart.nvim README for more information - ----@module 'lazy' ----@type LazySpec -return {} diff --git a/lua/kickstart/health.lua b/lua/health.lua similarity index 100% rename from lua/kickstart/health.lua rename to lua/health.lua diff --git a/lua/kickstart/plugins/neo-tree.lua b/lua/kickstart/plugins/neo-tree.lua deleted file mode 100644 index af8d4495650..00000000000 --- a/lua/kickstart/plugins/neo-tree.lua +++ /dev/null @@ -1,29 +0,0 @@ --- Neo-tree is a Neovim plugin to browse the file system --- https://github.com/nvim-neo-tree/neo-tree.nvim - ----@module 'lazy' ----@type LazySpec -return { - 'nvim-neo-tree/neo-tree.nvim', - version = '*', - dependencies = { - 'nvim-lua/plenary.nvim', - 'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended - 'MunifTanjim/nui.nvim', - }, - lazy = false, - keys = { - { '\\', ':Neotree reveal', desc = 'NeoTree reveal', silent = true }, - }, - ---@module 'neo-tree' - ---@type neotree.Config - opts = { - filesystem = { - window = { - mappings = { - ['\\'] = 'close_window', - }, - }, - }, - }, -} diff --git a/lua/plugins/blade-nav.lua b/lua/plugins/blade-nav.lua new file mode 100644 index 00000000000..43f8789baaa --- /dev/null +++ b/lua/plugins/blade-nav.lua @@ -0,0 +1,11 @@ +return { + 'ricardoramirezr/blade-nav.nvim', + dependencies = { + 'saghen/blink.cmp', + }, + ft = { 'blade', 'php' }, -- optional, improves startup time + opts = { + -- This applies for nvim-cmp and coq, for blink refer to the configuration of this plugin + close_tag_on_complete = true, -- default: true + }, +} diff --git a/lua/plugins/blink.lua b/lua/plugins/blink.lua new file mode 100644 index 00000000000..1a3909de546 --- /dev/null +++ b/lua/plugins/blink.lua @@ -0,0 +1,179 @@ +-- Autocompletion +return { + 'saghen/blink.cmp', + 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 = {}, + }, + }, + init = function() + -- set autocommand for blink-menu-sourcename. + vim.api.nvim_create_autocmd('ColorScheme', { + desc = 'set italic to BlinkCmpSource, and try to change fg', + group = vim.api.nvim_create_augroup('blink.cmp-source-hl', { clear = true }), + callback = function() + local hl = { + default = true, + italic = true, + } + + -- if the hl-group for the Menu-Selection has reverse property, + -- then don't bother setting fg & bg, because it would be messed up anyway. + if not vim.api.nvim_get_hl(0, { name = 'PmenuSel' }).reverse then + hl.fg = vim.api.nvim_get_hl(0, { name = 'LspCodeLens' }).fg + or vim.api.nvim_get_hl(0, { name = 'BlinkCmpGhostText' }).fg + or vim.api.nvim_get_hl(0, { name = 'NonText' }).fg + end + + vim.api.nvim_set_hl(0, 'BlinkCmpSource', hl) + end, + }) + end, + + ---@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', + -- + -- I have my own keymaps now + [''] = { 'show_documentation', 'hide_documentation' }, + [''] = { 'hide', 'fallback' }, + [''] = { 'select_and_accept', 'fallback' }, + + [''] = { 'select_prev', 'fallback' }, + [''] = { 'select_next', 'fallback' }, + [''] = { 'select_prev', 'fallback_to_mappings' }, + [''] = { 'show', 'select_next', 'fallback_to_mappings' }, + + [''] = { 'scroll_documentation_up', 'fallback' }, + [''] = { 'scroll_documentation_down', 'fallback' }, + + [''] = { 'snippet_forward', 'fallback_to_mappings' }, + [''] = { 'snippet_backward', 'fallback_to_mappings' }, + + [''] = { 'show_signature', 'hide_signature', 'fallback' }, + + -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: + -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps + }, + + cmdline = { + keymap = { preset = 'inherit' }, + completion = { menu = { auto_show = true } }, + }, + + term = { + keymap = { preset = 'inherit' }, + completion = { menu = { auto_show = true } }, + }, + + appearance = { + -- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font' + -- Adjusts spacing to ensure icons are aligned + nerd_font_variant = 'mono', + kind_icons = Glyphs.kinds, + }, + + 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 = true, auto_show_delay_ms = 1500 }, + + menu = { + draw = { + columns = { + -- The following two components are from the default config + { 'kind_icon' }, + { 'label', 'label_description', gap = 1 }, + -- Add `source_name` to parse it and get lsp-provider name + { 'source_name' }, + }, + components = { + source_name = { + width = { fill = true }, + text = function(ctx) + -- either get the client_name aka lsp-provider "like lua_ls" + -- or get the source name from blink's list of sources, see below. + return ctx.item.client_name or ctx.source_name + end, + highlight = 'BlinkCmpSource', + }, + }, + }, + }, + }, + + sources = { + default = { 'lsp', 'path', 'snippets', 'blade-nav' }, + providers = { + ['blade-nav'] = { + module = 'blade-nav.blink', + opts = { + close_tag_on_complete = true, --default: true + }, + }, + }, + }, + + 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/conform.lua b/lua/plugins/conform.lua new file mode 100644 index 00000000000..9a6a28947ec --- /dev/null +++ b/lua/plugins/conform.lua @@ -0,0 +1,50 @@ +-- Autoformat +return { + 'stevearc/conform.nvim', + event = { 'BufWritePre' }, + cmd = { 'ConformInfo' }, + keys = { + { + 'F', + function() + require('conform').format { async = true } + end, + mode = '', + desc = '[F]ormat buffer', + }, + }, + ---@module 'conform' + ---@type conform.setupOpts + opts = { + notify_on_error = true, + format_on_save = function(bufnr) + -- NOTE: + -- See: + -- - [Change format_on_save to a whitelist instead of a blacklist · nvim-lua/kickstart.nvim@ce353a9](https://github.com/nvim-lua/kickstart.nvim/commit/ce353a9b0e3c47d27784509217200818f522329e) + -- - [please disable autoformat on save in default configuration · Issue #1819 · nvim-lua/kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim/issues/1819) + + -- You can specify filetypes to autoformat on save here: + local enabled_filetypes = { + lua = true, + -- python = true, + } + if enabled_filetypes[vim.bo[bufnr].filetype] then + return { timeout_ms = 500 } + end + return nil + end, + default_format_opts = { + lsp_format = 'fallback', -- Use external formatters if configured below, otherwise use LSP formatting. Set to `false` to disable LSP formatting entirely. + }, + -- You can also specify external formatters in here. + formatters_by_ft = Langs.fmt, + -- Example + -- rust = { 'rustfmt' }, + -- Conform can also run multiple formatters sequentially + -- python = { "isort", "black" }, + -- + -- You can use 'stop_after_first' to run the first available formatter from the list + -- javascript = { "prettierd", "prettier", stop_after_first = true }, + formatters = Langs.fmt_cmd, + }, +} diff --git a/lua/plugins/demicolon-nvim.lua b/lua/plugins/demicolon-nvim.lua new file mode 100644 index 00000000000..a9a729c42ad --- /dev/null +++ b/lua/plugins/demicolon-nvim.lua @@ -0,0 +1,12 @@ +return { + 'mawkler/demicolon.nvim', + dependencies = { + 'nvim-treesitter/nvim-treesitter', + 'nvim-treesitter/nvim-treesitter-textobjects', + }, + opts = { + keymaps = { + repeat_motions = 'stateful', + }, + }, +} diff --git a/lua/plugins/fzf-lua.lua b/lua/plugins/fzf-lua.lua new file mode 100644 index 00000000000..e77e016c1de --- /dev/null +++ b/lua/plugins/fzf-lua.lua @@ -0,0 +1,157 @@ +return { + 'ibhagwan/fzf-lua', + -- optional for icon support + dependencies = { + 'nvim-mini/mini.nvim', -- for mini.icons + 'nvim-treesitter/nvim-treesitter', + }, + config = function() + local fl = require 'fzf-lua' + fl.setup { + lsp = { + symbols = { + symbol_icons = Glyphs.kinds, + }, + }, + } + + -- fuzzy-find specific + vim.keymap.set('n', 'fl', fl.blines, { desc = 'Find line - current buf' }) + vim.keymap.set('n', 'fL', fl.lines, { desc = 'Find line - open buffers' }) + vim.keymap.set('n', 'ff', fl.files, { desc = 'Find files' }) + vim.keymap.set('n', 'o', fl.buffers, { desc = '[O]pen buffers' }) + vim.keymap.set('n', 'fR', fl.history, { desc = 'Recent files & buffers' }) + vim.keymap.set('n', 'fr', fl.oldfiles, { desc = 'Recent files' }) + vim.keymap.set('n', 'ft', fl.treesitter, { desc = 'Treesiter objects' }) + vim.keymap.set('n', 'fn', function() + fl.files { cwd = vim.fn.stdpath 'config' } + end, { desc = 'Neovim config files' }) + vim.keymap.set('n', 'fN', function() + fl.files { cwd = vim.fn.stdpath 'data' .. '/lazy/' } + end, { desc = 'Neovim plugins src' }) + + -- grep specific + vim.keymap.set('n', 'gb', fl.grep_curbuf, { desc = 'Grep current buffer' }) + vim.keymap.set('n', 'gG', fl.grep_project, { desc = 'Grep project' }) + vim.keymap.set('n', 'gg', fl.live_grep, { desc = 'Grep a pattern' }) + vim.keymap.set({ 'n', 'v' }, 'gv', fl.grep_visual, { desc = 'Grep with visual selection' }) + vim.keymap.set('n', 'gw', fl.grep_cword, { desc = 'Grep word under cursor' }) + vim.keymap.set('n', 'gW', fl.grep_cWORD, { desc = 'Grep WORD under cursor' }) + vim.keymap.set('n', 'g.', function() + fl.grep { resume = true } + end, { desc = 'Resume last grep' }) + vim.keymap.set('n', 'gn', function() + fl.live_grep { cwd = '$VIMRUNTIME/doc' } + end, { desc = 'Grep Neovim docs' }) + vim.keymap.set('n', 'gN', function() + fl.live_grep { cwd = vim.fn.stdpath 'data' .. '/lazy/' } + end, { desc = 'Grep Neovim plugins src' }) + + -- -- Git specific + -- vim.keymap.set('n', 'GC', fl.git_bcommits, { desc = 'Git: commits - current buf' }) + -- vim.keymap.set('n', 'GS', fl.git_stash, { desc = 'Git: stash' }) + -- vim.keymap.set('n', 'Gb', fl.git_branches, { desc = 'Git: branches' }) + -- vim.keymap.set('n', 'Gc', fl.git_commits, { desc = 'Git: commits' }) + -- vim.keymap.set('n', 'Gd', fl.git_diff, { desc = 'Git: diff' }) + -- vim.keymap.set('n', 'Gf', fl.git_files, { desc = 'Git: files' }) + -- vim.keymap.set('n', 'Gh', fl.git_hunks, { desc = 'Git: hunks' }) + -- vim.keymap.set('n', 'Gs', fl.git_status, { desc = 'Git: status' }) + -- vim.keymap.set('n', 'Gw', fl.git_worktrees, { desc = 'Git: worktrees' }) + -- vim.keymap.set('n', 'vh', fl.git_hunks, { desc = 'Git: hunks' }) + -- vim.keymap.set('n', 'vw', fl.git_worktrees, { desc = 'Git: worktrees' }) + + -- LSP specific + vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('fzflua-lsp-attach', { clear = true }), + callback = function(event) + local buf = event.buf + + -- `gr` keymap style + vim.keymap.set({ 'n', 'v' }, 'gra', fl.lsp_code_actions, { buffer = buf, desc = 'LSP: code actions' }) + vim.keymap.set({ 'n', 'v' }, 'grD', fl.lsp_declarations, { buffer = buf, desc = 'LSP: declaration' }) + vim.keymap.set({ 'n', 'v' }, 'grd', fl.lsp_definitions, { buffer = buf, desc = 'LSP: definition' }) + vim.keymap.set({ 'n', 'v' }, 'gri', fl.lsp_implementations, { buffer = buf, desc = 'LSP: implementations' }) + vim.keymap.set({ 'n', 'v' }, 'grI', fl.lsp_incoming_calls, { buffer = buf, desc = 'LSP: incoming calls' }) + vim.keymap.set({ 'n', 'v' }, 'grO', fl.lsp_outgoing_calls, { buffer = buf, desc = 'LSP: outgoing calls' }) + vim.keymap.set({ 'n', 'v' }, 'grr', fl.lsp_references, { buffer = buf, desc = 'LSP: references' }) + vim.keymap.set('n', 'grs', fl.lsp_document_symbols, { buffer = buf, desc = 'LSP: symbols - current buf' }) + vim.keymap.set('n', 'grw', fl.lsp_workspace_symbols, { buffer = buf, desc = 'LSP: symbols - workspace' }) + vim.keymap.set({ 'n', 'v' }, 'grt', fl.lsp_typedefs, { buffer = buf, desc = 'LSP: type definition' }) + + -- my style + vim.keymap.set({ 'n', 'v' }, 'la', fl.lsp_code_actions, { buffer = buf, desc = 'LSP: code actions' }) + vim.keymap.set({ 'n', 'v' }, 'lD', fl.lsp_declarations, { buffer = buf, desc = 'LSP: declaration' }) + vim.keymap.set({ 'n', 'v' }, 'ld', fl.lsp_definitions, { buffer = buf, desc = 'LSP: definition' }) + vim.keymap.set( + { 'n', 'v' }, + 'li', + fl.lsp_implementations, + { buffer = buf, desc = 'LSP: implementations' } + ) + vim.keymap.set( + { 'n', 'v' }, + 'lI', + fl.lsp_incoming_calls, + { buffer = buf, desc = 'LSP: incoming calls' } + ) + vim.keymap.set( + { 'n', 'v' }, + 'lO', + fl.lsp_outgoing_calls, + { buffer = buf, desc = 'LSP: outgoing calls' } + ) + vim.keymap.set({ 'n', 'v' }, 'lr', fl.lsp_references, { buffer = buf, desc = 'LSP: references' }) + vim.keymap.set( + 'n', + 'ls', + fl.lsp_document_symbols, + { buffer = buf, desc = 'LSP: symbols - current buf' } + ) + vim.keymap.set('n', 'lw', fl.lsp_workspace_symbols, { buffer = buf, desc = 'LSP: symbols - workspace' }) + vim.keymap.set({ 'n', 'v' }, 'lt', fl.lsp_typedefs, { buffer = buf, desc = 'LSP: type definition' }) + end, + }) + + -- Diagnostic specific + vim.keymap.set('n', 'dd', fl.diagnostics_document, { desc = 'List diagnostics - current buf' }) + vim.keymap.set('n', 'dw', fl.diagnostics_workspace, { desc = 'List diagnostics - workspace' }) + vim.keymap.set('n', 'dz', fl.spellcheck, { desc = 'Spelling mistakes' }) + + -- misc specific + vim.keymap.set('n', "f'", fl.marks, { desc = 'Marks' }) + vim.keymap.set('n', 'f:', fl.command_history, { desc = 'Command history' }) + vim.keymap.set('n', 'f"', fl.registers, { desc = 'Registers' }) + vim.keymap.set('n', 'f/', fl.search_history, { desc = 'Search history' }) + vim.keymap.set('n', 'f;', fl.jumps, { desc = 'Jump list' }) + vim.keymap.set('n', 'f.', fl.resume, { desc = 'Resume last command/query' }) -- conflict + vim.keymap.set('n', 'fh', fl.helptags, { desc = 'Help-Pages' }) + vim.keymap.set('n', 'fk', fl.keymaps, { desc = 'Keymaps' }) + vim.keymap.set('n', 'fm', fl.manpages, { desc = 'Man-Pages' }) + vim.keymap.set('n', 'fb', fl.builtin, { desc = 'Builtin pickers' }) + -- TODO: I should implement _clipboard history_ in fzf-lua + -- vim.keymap.set('n', 'fy', _I need to implement it_, { desc = 'Clipboard history' }) + + -- use fzf-lua for spelling suggestion + vim.keymap.set('i', '', function() + fl.spell_suggest { + winopts = { + height = 0.4, + width = 30, + relative = 'cursor', + }, + } + end, { desc = 'Spelling suggestions' }) + vim.keymap.set('n', 'z=', function() + fl.spell_suggest { + winopts = { + height = 0.4, + width = 30, + relative = 'cursor', + }, + } + end, { desc = 'Spelling suggestions' }) + + -- application specific + vim.keymap.set('n', 'fZ', fl.zoxide, { desc = 'Zoxide directories' }) + end, +} diff --git a/lua/kickstart/plugins/gitsigns.lua b/lua/plugins/gitsigns.lua similarity index 63% rename from lua/kickstart/plugins/gitsigns.lua rename to lua/plugins/gitsigns.lua index 500ea6c4085..48d19ad7456 100644 --- a/lua/kickstart/plugins/gitsigns.lua +++ b/lua/plugins/gitsigns.lua @@ -1,6 +1,4 @@ -- 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. ---@module 'lazy' ---@type LazySpec @@ -10,6 +8,13 @@ return { ---@type Gitsigns.Config ---@diagnostic disable-next-line: missing-fields opts = { + signs = { + add = { text = '+' }, ---@diagnostic disable-line: missing-fields + change = { text = '~' }, ---@diagnostic disable-line: missing-fields + delete = { text = '_' }, ---@diagnostic disable-line: missing-fields + topdelete = { text = '‾' }, ---@diagnostic disable-line: missing-fields + changedelete = { text = '~' }, ---@diagnostic disable-line: missing-fields + }, on_attach = function(bufnr) local gitsigns = require 'gitsigns' @@ -38,8 +43,12 @@ return { -- 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' }) + 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' }) @@ -47,14 +56,20 @@ return { map('n', 'hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' }) map('n', 'hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' }) map('n', 'hi', gitsigns.preview_hunk_inline, { desc = 'git preview hunk [i]nline' }) - map('n', 'hb', function() gitsigns.blame_line { full = true } end, { desc = 'git [b]lame line' }) + map('n', 'hb', function() + gitsigns.blame_line { full = true } + end, { 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' }) - map('n', 'hQ', function() gitsigns.setqflist 'all' end, { desc = 'git hunk [Q]uickfix list (all files in repo)' }) + map('n', 'hD', function() + gitsigns.diffthis '@' + end, { desc = 'git [D]iff against last commit' }) + map('n', 'hQ', function() + gitsigns.setqflist 'all' + end, { desc = 'git hunk [Q]uickfix list (all files in repo)' }) map('n', 'hq', gitsigns.setqflist, { desc = 'git hunk [q]uickfix list (all changes in this file)' }) -- Toggles map('n', 'tb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' }) - map('n', 'tw', gitsigns.toggle_word_diff, { desc = '[T]oggle git intra-line [w]ord diff' }) + map('n', 'tW', gitsigns.toggle_word_diff, { desc = '[T]oggle git intra-line [w]ord diff' }) -- Text object map({ 'o', 'x' }, 'ih', gitsigns.select_hunk) diff --git a/lua/plugins/guess-indent.lua b/lua/plugins/guess-indent.lua new file mode 100644 index 00000000000..49b15d4e680 --- /dev/null +++ b/lua/plugins/guess-indent.lua @@ -0,0 +1,5 @@ +-- Automatic indentation style detection +return { + 'NMAC427/guess-indent.nvim', + opts = {}, +} diff --git a/lua/kickstart/plugins/indent_line.lua b/lua/plugins/indent-blankline.lua similarity index 100% rename from lua/kickstart/plugins/indent_line.lua rename to lua/plugins/indent-blankline.lua diff --git a/lua/plugins/ionide-vim.lua b/lua/plugins/ionide-vim.lua new file mode 100644 index 00000000000..94617fc8253 --- /dev/null +++ b/lua/plugins/ionide-vim.lua @@ -0,0 +1,4 @@ +return { + 'ionide/Ionide-vim', + ft = { 'fsharp', 'fsharp_project' }, +} diff --git a/lua/plugins/lualine.lua b/lua/plugins/lualine.lua new file mode 100644 index 00000000000..4eb077d4fae --- /dev/null +++ b/lua/plugins/lualine.lua @@ -0,0 +1,299 @@ +local col_mark_80 = 80 +local col_mark_120 = 120 +local col_mark_180 = 180 + +---@class Section +local S = {} + +--- Create a new `lualine` section +---@param t table a table with 'section-name' +---@return Section +function S:new(t) + self.__index = self + return setmetatable(t or {}, self) +end + +--- Set bold for `lualine` section, if it supports it +---@return Section +function S:set_bold() + self.color = self.color or {} + self.color.gui = 'bold' + return self +end + +--- Set symbols for `lualine` section, if it supports it +---@param symbols table key: name of the option, value: the icon +---@return Section +function S:set_symbols(symbols) + self.symbols = self.symbols or {} + self.symbols = symbols + return self +end + +--- Set format function to act on a `lualine` section +---@param fmt_func fun(str: string): string a function that takes the string that will be rendered and format it +---@return Section +function S:set_fmt(fmt_func) + if self.fmt ~= nil then + vim.defer_fn(function() + vim.notify('lualine section (' .. self[1] .. '): already has fmt function', vim.log.levels.WARN) + end, 1000) + return self + end + + self.fmt = fmt_func + return self +end + +--- Set responsive _autohide_ width for `lualine` section by providing a fmt function +--- Setting this will affect other implementation of fmt_func +---@see Section.set_fmt +---@param onColumn integer? The column number where the section will be hidden when the buffer's width is less than +---@return Section +function S:set_autohide_fmt(onColumn) + onColumn = onColumn or col_mark_120 + + if self.fmt ~= nil then + vim.defer_fn(function() + vim.notify('lualine section (' .. self[1] .. '): already has fmt function', vim.log.levels.WARN) + end, 1000) + return self + end + + self.fmt = function(str) + if vim.api.nvim_win_get_width(0) > onColumn then + return str + end + return '' + end + return self +end + +local devKit_icons = Glyphs.dev_kit +local fs_icons = Glyphs.file_status +local diag_icons = {} +for key, val in pairs(Glyphs.diagnostics) do + diag_icons[key] = val .. ' ' +end + +return { + 'nvim-lualine/lualine.nvim', + dependencies = { + 'nvim-mini/mini.nvim', -- for mini.icons, and maybe only needed for filetype component + }, + config = function() + require('lualine').setup { + options = { + icons_enabled = true, + theme = 'auto', + component_separators = { left = '|', right = '|' }, + section_separators = { left = '', right = '' }, + disabled_filetypes = { + statusline = {}, + winbar = {}, + }, + ignore_focus = {}, + always_divide_middle = true, + always_show_tabline = false, + globalstatus = false, + refresh = { + statusline = 1000, + tabline = 1000, + winbar = 1000, + refresh_time = 16, -- ~60fps + events = { + 'WinEnter', + 'BufEnter', + 'BufWritePost', + 'SessionLoadPost', + 'FileChangedShellPost', + 'VimResized', + 'Filetype', + 'CursorMoved', + 'CursorMovedI', + 'ModeChanged', + }, + }, + }, + sections = { + lualine_a = { + S:new({ 'mode' }) + :set_fmt( -- trim to initials using kebab-case + function(str) + if vim.api.nvim_win_get_width(0) > col_mark_120 then + return str + end + if str:match '-' then + -- matches V-L/INE and V-B/LOCK + return str:sub(1, 3) + end + -- just the first char + return str:sub(1, 1) + end + ) + :set_bold(), + }, + + lualine_b = { + S:new({ 'branch', icon = '' }) + :set_fmt( -- trim to first char + function(str) + if vim.api.nvim_win_get_width(0) > col_mark_120 then + return str + end + -- just the first char + return str:sub(1, 1) + end + ) + :set_bold(), + S:new({ 'diff' }):set_bold():set_autohide_fmt(), + S:new({ 'diagnostics' }):set_symbols(diag_icons):set_autohide_fmt(80), + }, + + lualine_c = { + { + function() + -- do some evaluation + local buff_width = vim.api.nvim_win_get_width(0) + local proto_prefix = vim.fn.expand('%'):match '(.-://).+' or '' + + local filename_parts = {} + + -- handle special case before setting default + if proto_prefix == 'oil://' then + filename_parts[1] = (buff_width > col_mark_80 and '%F') + or proto_prefix .. '.../' .. vim.fs.basename(vim.fn.fnamemodify(vim.fn.getcwd(), '%:p')) .. '/' + elseif proto_prefix == 'term://' then + filename_parts[1] = proto_prefix .. '%t' + else + -- responsive file-path-name + filename_parts[1] = (buff_width > col_mark_180 and '%F') -- full path + or (buff_width > col_mark_120 and '%f') -- relative path + or proto_prefix .. '%t' -- file name only + end + + -- modifiable indicator + filename_parts[#filename_parts + 1] = vim.bo.modified and fs_icons.modified + or not vim.bo.modifiable and fs_icons.unmodifiable + or nil + -- read-only indicator + filename_parts[#filename_parts + 1] = (vim.bo.readonly and fs_icons.readOnly) or nil + + -- preview indicator + filename_parts[#filename_parts + 1] = (vim.wo.previewwindow and fs_icons.preview) or nil + + return '%<' .. table.concat(filename_parts, ' ') + end, + }, + }, + + lualine_x = { + S:new({ + -- A formatters section + function() + local ok, conform = pcall(require, 'conform') + if not ok then + return '' + end + + local formatters = conform.list_formatters_to_run(0) + if #formatters == 0 then + return '' + end + + local formatter_names = {} + for _, formatter in ipairs(formatters) do + table.insert(formatter_names, formatter.name) + end + + return devKit_icons.fmt .. ' ' .. table.concat(formatter_names, ' ') + end, + }):set_autohide_fmt(), + S:new({ + -- A formatters section + function() + local ok, lint = pcall(require, 'lint') + if not ok then + return '' + end + + local filetype = vim.bo.filetype + local linters = lint.linters_by_ft[filetype] + + if not linters then + return '' + end + + return devKit_icons.lint .. ' ' .. table.concat(linters, ' ') + end, + }):set_autohide_fmt(), + { + 'lsp_status', + icon = devKit_icons.lsp, + }, + }, + + lualine_y = { + S:new({ 'encoding' }):set_bold():set_autohide_fmt(), + S:new({ 'fileformat' }):set_bold():set_autohide_fmt(), + S:new({ 'filetype' }):set_bold(), + }, + + lualine_z = { + S:new({ 'progress' }):set_bold():set_autohide_fmt(), + S:new({ + -- A location section, row:col + function() + if vim.api.nvim_win_get_width(0) > col_mark_120 then + -- padding with two char + return '%2l:%-2v' + end + return '%l:%v' + end, + }):set_bold(), + }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { { 'filename', path = 3 } }, + lualine_x = { 'location' }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = { + lualine_a = { + { + 'tabs', + max_length = vim.o.columns, -- Maximum width of tabs component. + mode = 2, -- Shows tab_nr + tab_name + + -- Automatically updates active tab color to match color of other components (will be overidden if buffers_color is set) + use_mode_colors = true, + + show_modified_status = false, -- I don't need this option, because I handle it in another place + + fmt = function(name, context) + -- match buffers similar to 'term://', 'oil://' + local buffer_protocol = context.file:match '(.-://).+' + if buffer_protocol then + name = buffer_protocol .. name + end + + -- Show + if buffer is modified in tab + local buflist = vim.fn.tabpagebuflist(context.tabnr) + local winnr = vim.fn.tabpagewinnr(context.tabnr) + local bufnr = buflist[winnr] + local mod = vim.fn.getbufvar(bufnr, '&mod') + + return name .. (mod == 1 and ' ' .. Glyphs.file_status.modified or '') + end, + }, + }, + }, + winbar = {}, + inactive_winbar = {}, + extensions = {}, + } + end, +} diff --git a/lua/plugins/mini.lua b/lua/plugins/mini.lua new file mode 100644 index 00000000000..702ee667aa2 --- /dev/null +++ b/lua/plugins/mini.lua @@ -0,0 +1,54 @@ +-- Collection of various small independent plugins/modules +return { + 'nvim-mini/mini.nvim', + config = function() + -- Better Around/Inside textobjects + -- + -- Examples: + -- - va) - [V]isually select [A]round [)]paren + -- - yiiq - [Y]ank [I]nside [I]next [Q]uote + -- - ci' - [C]hange [I]nside [']quote + require('mini.ai').setup { + -- NOTE: Avoid conflicts with the built-in incremental selection mappings on Neovim>=0.12 (see `:help treesitter-incremental-selection`) + mappings = { + around_next = 'aa', + inside_next = 'ii', + }, + 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 + + -- general icon provider. Several categories (file, directory, OS, LSP, etc.) + -- with better styles, colorscheme blending, and more + require('mini.icons').setup() + require('mini.icons').mock_nvim_web_devicons() + + -- plugin to split and join arguments + -- - gS - Toggle [S]plit/join arguments + require('mini.splitjoin').setup() + + -- ... and there is more! + -- Check out: https://github.com/nvim-mini/mini.nvim + end, +} diff --git a/lua/kickstart/plugins/autopairs.lua b/lua/plugins/nvim-autopairs.lua similarity index 100% rename from lua/kickstart/plugins/autopairs.lua rename to lua/plugins/nvim-autopairs.lua diff --git a/lua/kickstart/plugins/debug.lua b/lua/plugins/nvim-dap.lua similarity index 79% rename from lua/kickstart/plugins/debug.lua rename to lua/plugins/nvim-dap.lua index 7e58905e830..481c6fbbb55 100644 --- a/lua/kickstart/plugins/debug.lua +++ b/lua/plugins/nvim-dap.lua @@ -28,14 +28,56 @@ return { }, keys = { -- Basic debugging keymaps, feel free to change to your liking! - { '', function() require('dap').continue() end, desc = 'Debug: Start/Continue' }, - { '', function() require('dap').step_into() end, desc = 'Debug: Step Into' }, - { '', function() require('dap').step_over() end, desc = 'Debug: Step Over' }, - { '', function() require('dap').step_out() end, desc = 'Debug: Step Out' }, - { 'b', function() require('dap').toggle_breakpoint() end, desc = 'Debug: Toggle Breakpoint' }, - { 'B', function() require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ') end, desc = 'Debug: Set Breakpoint' }, + { + '', + function() + require('dap').continue() + end, + desc = 'Debug: Start/Continue', + }, + { + '', + function() + require('dap').step_into() + end, + desc = 'Debug: Step Into', + }, + { + '', + function() + require('dap').step_over() + end, + desc = 'Debug: Step Over', + }, + { + '', + function() + require('dap').step_out() + end, + desc = 'Debug: Step Out', + }, + { + 'b', + function() + require('dap').toggle_breakpoint() + end, + desc = 'Debug: Toggle Breakpoint', + }, + { + 'B', + function() + require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ') + end, + desc = 'Debug: Set Breakpoint', + }, -- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception. - { '', function() require('dapui').toggle() end, desc = 'Debug: See last session result.' }, + { + '', + function() + require('dapui').toggle() + end, + desc = 'Debug: See last session result.', + }, }, config = function() local dap = require 'dap' diff --git a/lua/plugins/nvim-highlight-colors.lua b/lua/plugins/nvim-highlight-colors.lua new file mode 100644 index 00000000000..26273101cb7 --- /dev/null +++ b/lua/plugins/nvim-highlight-colors.lua @@ -0,0 +1,75 @@ +return { + 'brenoprata10/nvim-highlight-colors', + config = function() + require('nvim-highlight-colors').setup { + -- # default config + + -- ---Render style + -- ---@usage 'background'|'foreground'|'virtual' + -- render = 'background', + -- + -- ---Set virtual symbol (requires render to be set to 'virtual') + -- virtual_symbol = '■', + -- + -- ---Set virtual symbol suffix (defaults to '') + -- virtual_symbol_prefix = '', + -- + -- ---Set virtual symbol suffix (defaults to ' ') + -- virtual_symbol_suffix = ' ', + -- + -- ---Set virtual symbol position() + -- ---@usage 'inline'|'eol'|'eow' + -- ---inline mimics VS Code style + -- ---eol stands for `end of column` - Recommended to set `virtual_symbol_suffix = ''` when used. + -- ---eow stands for `end of word` - Recommended to set `virtual_symbol_prefix = ' ' and virtual_symbol_suffix = ''` when used. + -- virtual_symbol_position = 'inline', + -- + -- ---Highlight hex colors, e.g. '#FFFFFF' + -- enable_hex = true, + -- + -- ---Highlight short hex colors e.g. '#fff' + -- enable_short_hex = true, + -- + -- ---Highlight rgb colors, e.g. 'rgb(0 0 0)' + -- enable_rgb = true, + -- + -- ---Highlight hsl colors, e.g. 'hsl(150deg 30% 40%)' + -- enable_hsl = true, + -- + -- ---Highlight ansi colors, e.g '\033[0;34m' + -- enable_ansi = true, + -- + -- ---Highlight xterm 256 (8bit) colors, e.g '\033[38;5;118m' + -- enable_xterm256 = true, + -- + -- ---Highlight xterm True Color (24bit) colors, e.g '\033[38;2;118;64;90m' + -- enable_xtermTrueColor = true, + -- + -- -- Highlight hsl colors without function, e.g. '--foreground: 0 69% 69%;' + -- enable_hsl_without_function = true, + -- + -- ---Highlight CSS variables, e.g. 'var(--testing-color)' + -- enable_var_usage = true, + -- + -- ---Highlight named colors, e.g. 'green' + -- enable_named_colors = true, + -- + -- ---Highlight tailwind colors, e.g. 'bg-blue-500' + -- enable_tailwind = false, + -- + -- ---Set custom colors + -- ---Label must be properly escaped with '%' to adhere to `string.gmatch` + -- --- :help string.gmatch + -- custom_colors = { + -- { label = '%-%-theme%-primary%-color', color = '#0f1219' }, + -- { label = '%-%-theme%-secondary%-color', color = '#5a5d64' }, + -- }, + -- + -- -- Exclude filetypes or buftypes from highlighting e.g. 'exclude_buftypes = {'text'}' + -- exclude_filetypes = {}, + -- exclude_buftypes = {}, + -- -- Exclude buffer from highlighting e.g. 'exclude_buffer = function(bufnr) return vim.fn.getfsize(vim.api.nvim_buf_get_name(bufnr)) > 1000000 end' + -- exclude_buffer = function(bufnr) end, + } + end, +} diff --git a/lua/kickstart/plugins/lint.lua b/lua/plugins/nvim-lint.lua similarity index 91% rename from lua/kickstart/plugins/lint.lua rename to lua/plugins/nvim-lint.lua index 556f3178811..6e46f0be8f4 100644 --- a/lua/kickstart/plugins/lint.lua +++ b/lua/plugins/nvim-lint.lua @@ -7,9 +7,7 @@ return { event = { 'BufReadPre', 'BufNewFile' }, config = function() local lint = require 'lint' - lint.linters_by_ft = { - markdown = { 'markdownlint' }, -- Make sure to install `markdownlint` via mason / npm - } + lint.linters_by_ft = Langs.linter -- To allow other plugins to add linters to require('lint').linters_by_ft, -- instead set linters_by_ft like this: @@ -52,7 +50,9 @@ return { -- Only run the linter in buffers that you can modify in order to -- avoid superfluous noise, notably within the handy LSP pop-ups that -- describe the hovered symbol using Markdown. - if vim.bo.modifiable then lint.try_lint() end + if vim.bo.modifiable then + lint.try_lint() + end end, }) end, diff --git a/lua/plugins/nvim-lspconfig.lua b/lua/plugins/nvim-lspconfig.lua new file mode 100644 index 00000000000..18760807421 --- /dev/null +++ b/lua/plugins/nvim-lspconfig.lua @@ -0,0 +1,175 @@ +-- LSP Plugins +return { + -- Main LSP Configuration + 'neovim/nvim-lspconfig', + dependencies = { + -- Automatically install LSPs and related tools to stdpath for Neovim + -- 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', + ---@module 'mason.settings' + ---@type MasonSettings + ---@diagnostic disable-next-line: missing-fields + opts = { + registries = { + 'github:Crashdummyy/mason-registry', + 'github:mason-org/mason-registry', + }, + }, + }, + -- Maps LSP server names between nvim-lspconfig and Mason package names. + 'mason-org/mason-lspconfig.nvim', + 'WhoIsSethDaniel/mason-tool-installer.nvim', + + -- Useful status updates for LSP. + { 'j-hui/fidget.nvim', opts = {} }, + }, + 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 + vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('kickstart-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 + + -- Rename the variable under your cursor. + -- 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' }) + + -- 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') + + -- 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 + 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('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, + }) + + -- 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 + ---@type table + -- local servers = { + -- -- clangd = {}, + -- -- gopls = {}, + -- -- pyright = {}, + -- -- rust_analyzer = {}, + -- -- + -- -- 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 = {}, + -- + -- stylua = {}, -- Used to format Lua code + -- + -- -- Special Lua Config, as recommended by neovim help docs + -- lua_ls = {}, + -- } + + local servers = Langs.lsp + + -- -- NOTE: I won't be using `mason-tool-installer` to auto-install tools for now. + -- -- + -- -- 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. + -- local ensure_installed = vim.tbl_keys(servers or {}) + -- vim.list_extend(ensure_installed, { + -- -- 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 + if string.match(name, '^%d+$') then + -- name is actually an index, and the server doesn't provide any additional config. + vim.lsp.enable(server) + else + -- name is an actual name, and the server provides additional config. + vim.lsp.config(name, server) + vim.lsp.enable(name) + end + end + end, +} diff --git a/lua/plugins/nvim-treesitter-textobjects.lua b/lua/plugins/nvim-treesitter-textobjects.lua new file mode 100644 index 00000000000..c91a78eea8e --- /dev/null +++ b/lua/plugins/nvim-treesitter-textobjects.lua @@ -0,0 +1,103 @@ +return { + 'nvim-treesitter/nvim-treesitter-textobjects', + branch = 'main', + dependencies = { + { + 'ABDsheikho/nvim-keysitter', + -- dir = '~/Repos/nvim-keysitter/', + -- name = 'keysitter', + config = function() + local keysitter = require 'keysitter' + local tsto = keysitter.new('treesitter-textobjects', { group_prefix = 'o' }) + + -- a setup function + tsto.setup({ 'FileType', 'BufEnter' }, 'keysitter', function() + -- tsto:set('f', 'function'):around():inner():next():prev() + + for k, v in pairs { + -- ['b'] = 'block', -- or b for brace-less languages like python + ['f'] = 'function', + ['i'] = 'conditional', + ['l'] = 'loop', + ['r'] = 'return', + ['t'] = 'attribute', + ['x'] = 'regex', + } do + tsto:set(k, v):around():inner():next():prev() + end + + tsto:set('/', 'comment'):around():inner():goto_start() + tsto:set('{', 'block'):around():inner():goto_start():goto_end { key = '}' } + tsto:set('(', 'call'):around():inner():goto_start():goto_end { key = ')' } + tsto:set(',', 'parameter'):around():inner():goto_start():goto_end { key = '.' } + tsto:set(';', 'statement'):around():inner({ attribute = 'outer' }):goto_start():goto_end { key = ':' } + + tsto + :set('=', 'assignment') + :around() + :inner({ attribute = 'rhs' }) + :goto_start({ attribute = 'lhs' }) + :next_start({ attribute = 'rhs', key = '-' }, { desc = 'next assignment rhs' }) + :previous_start({ attribute = 'rhs', key = '-' }, { desc = 'previous assignment rhs' }) + + tsto + :set('c', 'class') + :around() + :inner() + :next_start({ motion = ']', group_prefix = '', key = ']' }) + :next_end({ motion = ']', group_prefix = '', key = '[' }) + :previous_start({ motion = '[', group_prefix = '', key = '[' }) + :previous_end { motion = '[', group_prefix = '', key = ']' } + end, { desc = 'Set keysitter keymaps for nvim-treesitter-textobjects' }) + end, + }, + }, + init = function() + -- Disable entire built-in ftplugin mappings to avoid conflicts. + -- See https://github.com/neovim/neovim/tree/master/runtime/ftplugin for built-in ftplugins. + vim.g.no_plugin_maps = true + + -- Or, disable per filetype (add as you like) + -- vim.g.no_python_maps = true + -- vim.g.no_ruby_maps = true + -- vim.g.no_rust_maps = true + -- vim.g.no_go_maps = true + end, + config = function() + -- put your config here + -- configuration + require('nvim-treesitter-textobjects').setup { + select = { + -- Automatically jump forward to textobj, similar to targets.vim + lookahead = true, + -- You can choose the select mode (default is charwise 'v') + -- + -- Can also be a function which gets passed a table with the keys + -- * query_string: eg '@function.inner' + -- * method: eg 'v' or 'o' + -- and should return the mode ('v', 'V', or '') or a table + -- mapping query_strings to modes. + selection_modes = { + ['@parameter.outer'] = 'v', -- charwise + -- ['@function.outer'] = 'V', -- linewise + -- ['@class.outer'] = '', -- blockwise + }, + -- If you set this to `true` (default is `false`) then any textobject is + -- extended to include preceding or succeeding whitespace. Succeeding + -- whitespace has priority in order to act similarly to eg the built-in + -- `ap`. + -- + -- Can also be a function which gets passed a table with the keys + -- * query_string: eg '@function.inner' + -- * selection_mode: eg 'v' + -- and should return true of false + include_surrounding_whitespace = false, + }, + + move = { + -- whether to set jumps in the jumplist + set_jumps = true, + }, + } + end, +} diff --git a/lua/plugins/nvim-treesitter.lua b/lua/plugins/nvim-treesitter.lua new file mode 100644 index 00000000000..a1bba6a78a9 --- /dev/null +++ b/lua/plugins/nvim-treesitter.lua @@ -0,0 +1,63 @@ +-- Highlight, edit, and navigate code +return { + 'nvim-treesitter/nvim-treesitter', + lazy = false, + build = ':TSUpdate', + branch = 'main', + -- [[ Configure Treesitter ]] See `:help nvim-treesitter-intro` + config = function() + require('nvim-treesitter').install(Langs.treesitter) + + ---@param buf integer + ---@param language string + local function treesitter_try_attach(buf, language) + -- check if parser exists and load it + if not vim.treesitter.language.add(language) then + return + end + -- enables syntax highlighting and other treesitter features + vim.treesitter.start(buf, language) + + -- enables treesitter based folds + -- for more info on folds see `:help folds` + -- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' + -- vim.wo.foldmethod = 'expr' + + -- check if treesitter indentation is available for this language, and if so enable it + -- in case there is no indent query, the indentexpr will fallback to the vim's built in one + local has_indent_query = vim.treesitter.query.get(language, 'indents') ~= nil + + -- enables treesitter based indentation + if has_indent_query then + vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + end + end + + local available_parsers = require('nvim-treesitter').get_available() + vim.api.nvim_create_autocmd('FileType', { + callback = function(args) + local buf, filetype = args.buf, args.match + + local language = vim.treesitter.language.get_lang(filetype) + if not language then + return + end + + local installed_parsers = require('nvim-treesitter').get_installed 'parsers' + + if vim.tbl_contains(installed_parsers, language) then + -- enable the parser if it is installed + treesitter_try_attach(buf, language) + elseif vim.tbl_contains(available_parsers, language) then + -- if a parser is available in `nvim-treesitter` auto install it, and enable it after the installation is done + require('nvim-treesitter').install(language):await(function() + treesitter_try_attach(buf, language) + end) + else + -- try to enable treesitter features in case the parser exists but is not available from `nvim-treesitter` + treesitter_try_attach(buf, language) + end + end, + }) + end, +} diff --git a/lua/plugins/oil-git-status.lua b/lua/plugins/oil-git-status.lua new file mode 100644 index 00000000000..9075f8bbeb1 --- /dev/null +++ b/lua/plugins/oil-git-status.lua @@ -0,0 +1,9 @@ +return { + 'refractalize/oil-git-status.nvim', + + dependencies = { + 'stevearc/oil.nvim', + }, + + config = true, +} diff --git a/lua/plugins/oil.lua b/lua/plugins/oil.lua new file mode 100644 index 00000000000..0ea176efe41 --- /dev/null +++ b/lua/plugins/oil.lua @@ -0,0 +1,284 @@ +-- Declare a global function to retrieve the current directory +-- check out https://github.com/stevearc/oil.nvim/blob/master/doc/recipes.md#show-cwd-in-the-winbar +function _G.get_oil_winbar() + local bufnr = vim.api.nvim_win_get_buf(vim.g.statusline_winid) + local dir = require('oil').get_current_dir(bufnr) + if dir then + return vim.fn.fnamemodify(dir, ':~') + else + -- If there is no current directory (e.g. over ssh), just show the buffer name + return vim.api.nvim_buf_get_name(0) + end +end + +return { + 'stevearc/oil.nvim', + ---@module 'oil' + ---@type oil.SetupOpts + opts = {}, + -- Optional dependencies + dependencies = { + { 'nvim-mini/mini.nvim', opts = {} }, -- only for mini.icons + }, + -- Lazy loading is not recommended because it is very tricky to make it work correctly in all situations. + lazy = false, + keys = { + { + 'tf', + 'Oil', + desc = '[T]oggle Oil [F]ile manager', + }, + -- { + -- 'tF', + -- function() + -- require('oil').toggle_float(nil, { preview = { split = 'belowright' } }) + -- end, + -- desc = '[T]oggle Oil [F]ile manager, float-mode', + -- }, + }, + config = function() + require('oil').isDetailed = true + require('oil').setup { + -- Oil will take over directory buffers (e.g. `vim .` or `:e src/`) + -- Set to false if you want some other plugin (e.g. netrw) to open when you edit directories. + default_file_explorer = true, + -- Id is automatically added at the beginning, and name at the end + -- See :help oil-columns + columns = { + 'permissions', + 'size', + 'mtime', + 'icon', + }, + -- Buffer-local options to use for oil buffers + buf_options = { + buflisted = false, + bufhidden = 'hide', + }, + -- Window-local options to use for oil buffers + win_options = { + wrap = false, + signcolumn = 'yes:2', + cursorcolumn = false, + foldcolumn = '0', + spell = false, + list = false, + conceallevel = 3, + concealcursor = 'nvic', + winbar = '%!v:lua.get_oil_winbar()', + }, + -- Send deleted files to the trash instead of permanently deleting them (:help oil-trash) + delete_to_trash = false, + -- Skip the confirmation popup for simple operations (:help oil.skip_confirm_for_simple_edits) + skip_confirm_for_simple_edits = false, + -- Selecting a new/moved/renamed file or directory will prompt you to save changes first + -- (:help prompt_save_on_select_new_entry) + prompt_save_on_select_new_entry = true, + -- Oil will automatically delete hidden buffers after this delay + -- You can set the delay to false to disable cleanup entirely + -- Note that the cleanup process only starts when none of the oil buffers are currently displayed + cleanup_delay_ms = 2000, + lsp_file_methods = { + -- Enable or disable LSP file operations + enabled = true, + -- Time to wait for LSP file operations to complete before skipping + timeout_ms = 1000, + -- Set to true to autosave buffers that are updated with LSP willRenameFiles + -- Set to "unmodified" to only save unmodified buffers + autosave_changes = false, + }, + -- Constrain the cursor to the editable parts of the oil buffer + -- Set to `false` to disable, or "name" to keep it on the file names + constrain_cursor = 'editable', + -- Set to true to watch the filesystem for changes and reload oil + watch_for_changes = false, + -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap + -- options with a `callback` (e.g. { callback = function() ... end, desc = "", mode = "n" }) + -- Additionally, if it is a string that matches "actions.", + -- it will use the mapping at require("oil.actions"). + -- Set to `false` to remove a keymap + -- See :help oil-actions for a list of all available actions + keymaps = { + ['g?'] = { mode = 'n', 'actions.show_help' }, + ['go'] = { mode = 'n', 'actions.select' }, + [''] = { mode = 'n', 'actions.select' }, + ['gv'] = { mode = 'n', 'actions.select', opts = { vertical = true } }, + ['gh'] = { mode = 'n', 'actions.select', opts = { horizontal = true } }, + ['gb'] = { mode = 'n', 'actions.select', opts = { tab = true } }, + ['gp'] = { + mode = 'n', + callback = function() + -- require('oil').open_preview { vertical = false, horizontal = true, split = 'belowright' } + local v = vim.api.nvim_win_get_width(0) > 150 + require('oil.actions').preview.callback { vertical = v, horizontal = not v, split = 'belowright' } + end, + desc = 'Toggle/Untoggle preview window', + }, + ['gc'] = { mode = 'n', 'actions.close' }, + ['gl'] = { mode = 'n', 'actions.refresh' }, + ['-'] = { mode = 'n', 'actions.parent' }, + [''] = { mode = 'n', 'actions.parent' }, + ['_'] = { mode = 'n', 'actions.open_cwd' }, + ['gw'] = { mode = 'n', 'actions.open_cwd' }, + ['`'] = { mode = 'n', 'actions.cd' }, + ['~'] = { mode = 'n', 'actions.cd', opts = { scope = 'tab' } }, + ['gd'] = { + mode = 'n', + callback = function() + local oil = require 'oil' + if oil.isDetailed then + oil.set_columns { 'icon' } + else + oil.set_columns { 'permissions', 'size', 'mtime', 'icon' } + end + oil.isDetailed = not oil.isDetailed + end, + desc = 'Toggle/Untoggle detailed view', + }, + ['gs'] = { mode = 'n', 'actions.change_sort' }, + ['gx'] = { mode = 'n', 'actions.open_external' }, + ['g.'] = { + mode = 'n', + callback = 'actions.toggle_hidden', + desc = 'Toggle/Untoggle hidden files and directories', + }, + ['g\\'] = { mode = 'n', 'actions.toggle_trash' }, + ['gq'] = { mode = 'n', 'actions.close' }, + + -- keymaps to scrolle preview window + ['H'] = { mode = 'n', 'actions.preview_scroll_left' }, + ['J'] = { mode = 'n', 'actions.preview_scroll_down' }, + ['K'] = { mode = 'n', 'actions.preview_scroll_up' }, + ['L'] = { mode = 'n', 'actions.preview_scroll_right' }, + }, + -- Set to false to disable all of the above keymaps + use_default_keymaps = false, + view_options = { + -- Show files and directories that start with "." + show_hidden = true, + -- This function defines what is considered a "hidden" file + is_hidden_file = function(name, bufnr) + local m = name:match '^%.' + return m ~= nil + end, + -- This function defines what will never be shown, even when `show_hidden` is set + is_always_hidden = function(name, bufnr) + return false + end, + -- Sort file names with numbers in a more intuitive order for humans. + -- Can be "fast", true, or false. "fast" will turn it off for large directories. + natural_order = 'fast', + -- Sort file and directory names case insensitive + case_insensitive = false, + sort = { + -- sort order can be "asc" or "desc" + -- see :help oil-columns to see which columns are sortable + { 'type', 'asc' }, + { 'name', 'asc' }, + }, + -- Customize the highlight group for the file name + highlight_filename = function(entry, is_hidden, is_link_target, is_link_orphan) + return nil + end, + }, + -- Extra arguments to pass to SCP when moving/copying files over SSH + extra_scp_args = {}, + -- Extra arguments to pass to aws s3 when creating/deleting/moving/copying files using aws s3 + extra_s3_args = {}, + -- EXPERIMENTAL support for performing file operations with git + git = { + -- Return true to automatically git add/mv/rm files + add = function(path) + return false + end, + mv = function(src_path, dest_path) + return false + end, + rm = function(path) + return false + end, + }, + -- Configuration for the floating window in oil.open_float + float = { + -- Padding around the floating window + padding = 2, + -- max_width and max_height can be integers or a float between 0 and 1 (e.g. 0.4 for 40%) + max_width = 0, + max_height = 0, + border = 'rounded', + win_options = { + winblend = 0, + }, + -- optionally override the oil buffers window title with custom function: fun(winid: integer): string + get_win_title = nil, + -- preview_split: Split direction: "auto", "left", "right", "above", "below". + preview_split = 'auto', + -- This is the config that will be passed to nvim_open_win. + -- Change values here to customize the layout + override = function(conf) + return conf + end, + }, + -- Configuration for the file preview window + preview_win = { + -- Whether the preview window is automatically updated when the cursor is moved + update_on_cursor_moved = true, + -- How to open the preview window "load"|"scratch"|"fast_scratch" + preview_method = 'fast_scratch', + -- A function that returns true to disable preview on a file e.g. to avoid lag + disable_preview = function(filename) + return false + end, + -- Window-local options to use for preview window buffers + win_options = { + wrap = false, + }, + }, + -- Configuration for the floating action confirmation window + confirmation = { + -- Width dimensions can be integers or a float between 0 and 1 (e.g. 0.4 for 40%) + -- min_width and max_width can be a single value or a list of mixed integer/float types. + -- max_width = {100, 0.8} means "the lesser of 100 columns or 80% of total" + max_width = 0.9, + -- min_width = {40, 0.4} means "the greater of 40 columns or 40% of total" + min_width = { 40, 0.4 }, + -- optionally define an integer/float for the exact width of the preview window + width = nil, + -- Height dimensions can be integers or a float between 0 and 1 (e.g. 0.4 for 40%) + -- min_height and max_height can be a single value or a list of mixed integer/float types. + -- max_height = {80, 0.9} means "the lesser of 80 columns or 90% of total" + max_height = 0.9, + -- min_height = {5, 0.1} means "the greater of 5 columns or 10% of total" + min_height = { 5, 0.1 }, + -- optionally define an integer/float for the exact height of the preview window + height = nil, + border = 'rounded', + win_options = { + winblend = 0, + }, + }, + -- Configuration for the floating progress window + progress = { + max_width = 0.9, + min_width = { 40, 0.4 }, + width = nil, + max_height = { 10, 0.9 }, + min_height = { 5, 0.1 }, + height = nil, + border = 'rounded', + minimized_border = 'none', + win_options = { + winblend = 0, + }, + }, + -- Configuration for the floating SSH window + ssh = { + border = 'rounded', + }, + -- Configuration for the floating keymaps help window + keymaps_help = { + border = 'rounded', + }, + } + end, +} diff --git a/lua/plugins/render-markdown.lua b/lua/plugins/render-markdown.lua new file mode 100644 index 00000000000..bb51103ec2e --- /dev/null +++ b/lua/plugins/render-markdown.lua @@ -0,0 +1,25 @@ +return { + 'MeanderingProgrammer/render-markdown.nvim', + dependencies = { + 'nvim-treesitter/nvim-treesitter', + 'nvim-mini/mini.nvim', -- for mini.icons, to use icons during render + }, + ---@module 'render-markdown' + ---@type render.md.UserConfig + ft = { 'markdown', 'quarto' }, + keys = { + { + 'tr', + function() + require('render-markdown').toggle() + end, + desc = '[T]oggle [R]enderMarkdown', + }, + }, + opts = { + -- for more info read https://github.com/MeanderingProgrammer/render-markdown.nvim/wiki + enabled = false, + render_modes = { 'n', 'c', 't', 'v', 'V', '\22' }, + completions = { lsp = { enabled = true } }, + }, +} diff --git a/lua/plugins/roslyn.lua b/lua/plugins/roslyn.lua new file mode 100644 index 00000000000..b50b93a53ac --- /dev/null +++ b/lua/plugins/roslyn.lua @@ -0,0 +1,9 @@ +return { + 'seblyng/roslyn.nvim', + ---@module 'roslyn.config' + ---@type RoslynNvimConfig + ft = { 'csharp' }, + opts = { + -- your configuration comes here; leave empty for default settings + }, +} diff --git a/lua/plugins/snacks.lua b/lua/plugins/snacks.lua new file mode 100644 index 00000000000..f4360bd4b1c --- /dev/null +++ b/lua/plugins/snacks.lua @@ -0,0 +1,314 @@ +return { + 'folke/snacks.nvim', + config = function() + Snacks = require 'snacks' + Snacks.setup { + picker = { + prompt = Glyphs.ui.prompt .. ' ', + sources = {}, + focus = 'input', + show_delay = 5000, + limit_live = 10000, + layout = { + cycle = true, + --- Use the default layout or vertical if the window is too narrow + preset = function() + return vim.o.columns >= 120 and 'default' or 'vertical' + end, + }, + layouts = { + default = { + layout = { + box = 'horizontal', + width = 0.8, + min_width = 120, + height = 0.8, + { + box = 'vertical', + border = true, + title = '{title} {live} {flags}', + { win = 'input', height = 1, border = 'bottom' }, + { win = 'list', border = 'none' }, + }, + { win = 'preview', title = '{preview}', border = true, width = 0.6 }, + }, + }, + vertical = { + layout = { + backdrop = false, + width = 0.5, + min_width = 80, + height = 0.8, + min_height = 30, + box = 'vertical', + border = true, + title = '{title} {live} {flags}', + title_pos = 'center', + { win = 'input', height = 1, border = 'bottom' }, + { win = 'list', border = 'none' }, + { win = 'preview', title = '{preview}', height = 0.6, border = 'top' }, + }, + }, + }, + ---@class snacks.picker.matcher.Config + matcher = { + fuzzy = true, -- use fuzzy matching + smartcase = true, -- use smartcase + ignorecase = true, -- use ignorecase + sort_empty = false, -- sort results when the search string is empty + filename_bonus = true, -- give bonus for matching file names (last part of the path) + file_pos = true, -- support patterns like `file:line:col` and `file:line` + -- the bonusses below, possibly require string concatenation and path normalization, + -- so this can have a performance impact for large lists and increase memory usage + cwd_bonus = false, -- give bonus for matching files in the cwd + frecency = false, -- frecency bonus + history_bonus = false, -- give more weight to chronological order + }, + sort = { + -- default sort is by score, text length and index + fields = { 'score:desc', '#text', 'idx' }, + }, + ui_select = true, -- replace `vim.ui.select` with the snacks picker + ---@class snacks.picker.formatters.Config + formatters = { + text = { + ft = nil, ---@type string? filetype for highlighting + }, + file = { + filename_first = false, -- display filename before the file path + --- * left: truncate the beginning of the path + --- * center: truncate the middle of the path + --- * right: truncate the end of the path + ---@type "left"|"center"|"right" + truncate = 'center', + min_width = 40, -- minimum length of the truncated path + filename_only = false, -- only show the filename + icon_width = 2, -- width of the icon (in characters) + git_status_hl = true, -- use the git status highlight group for the filename + }, + selected = { + show_always = false, -- only show the selected column when there are multiple selections + unselected = true, -- use the unselected icon for unselected items + }, + severity = { + icons = true, -- show severity icons + level = false, -- show severity level + ---@type "left"|"right" + pos = 'left', -- position of the diagnostics + }, + }, + ---@class snacks.picker.previewers.Config + previewers = { + diff = { + -- fancy: Snacks fancy diff (borders, multi-column line numbers, syntax highlighting) + -- syntax: Neovim's built-in diff syntax highlighting + -- terminal: external command (git's pager for git commands, `cmd` for other diffs) + style = 'fancy', ---@type "fancy"|"syntax"|"terminal" + cmd = { 'delta' }, -- example for using `delta` as the external diff command + ---@type vim.wo?|{} window options for the fancy diff preview window + wo = { + breakindent = true, + wrap = true, + linebreak = true, + showbreak = '', + }, + }, + git = { + args = {}, -- additional arguments passed to the git command. Useful to set pager options usin `-c ...` + }, + file = { + max_size = 1024 * 1024, -- 1MB + max_line_length = 500, -- max line length + ft = nil, ---@type string? filetype for highlighting. Use `nil` for auto detect + }, + man_pager = nil, ---@type string? MANPAGER env to use for `man` preview + }, + ---@class snacks.picker.jump.Config + jump = { + jumplist = true, -- save the current position in the jumplist + tagstack = false, -- save the current position in the tagstack + reuse_win = false, -- reuse an existing window if the buffer is already open + close = true, -- close the picker when jumping/editing to a location (defaults to true) + match = false, -- jump to the first match position. (useful for `lines`) + }, + toggles = { + follow = 'f', + hidden = 'h', + ignored = 'i', + modified = 'm', + regex = { icon = 'R', value = false }, + }, + win = { + -- input window + input = { + keys = { + -- to close the picker on ESC instead of going to normal mode, + -- add the following keymap to your config + -- [""] = { "close", mode = { "n", "i" } }, + ['/'] = 'toggle_focus', + [''] = { 'history_forward', mode = { 'i', 'n' } }, + [''] = { 'history_back', mode = { 'i', 'n' } }, + [''] = { 'cancel', mode = 'i' }, + [''] = { '', mode = { 'i' }, expr = true, desc = 'delete word' }, + [''] = { 'confirm', mode = { 'n', 'i' } }, + [''] = { 'list_down', mode = { 'i', 'n' } }, + [''] = 'cancel', + [''] = { { 'pick_win', 'jump' }, mode = { 'n', 'i' } }, + [''] = { 'select_and_prev', mode = { 'i', 'n' } }, + [''] = { 'select_and_next', mode = { 'i', 'n' } }, + [''] = { 'list_up', mode = { 'i', 'n' } }, + [''] = { 'inspect', mode = { 'n', 'i' } }, + [''] = { 'toggle_follow', mode = { 'i', 'n' } }, + [''] = { 'toggle_hidden', mode = { 'i', 'n' } }, + [''] = { 'toggle_ignored', mode = { 'i', 'n' } }, + [''] = { 'toggle_regex', mode = { 'i', 'n' } }, + [''] = { 'toggle_maximize', mode = { 'i', 'n' } }, + [''] = { 'toggle_preview', mode = { 'i', 'n' } }, + [''] = { 'cycle_win', mode = { 'i', 'n' } }, + [''] = { 'select_all', mode = { 'n', 'i' } }, + [''] = { 'preview_scroll_up', mode = { 'i', 'n' } }, + [''] = { 'list_scroll_down', mode = { 'i', 'n' } }, + [''] = { 'preview_scroll_down', mode = { 'i', 'n' } }, + [''] = { 'toggle_live', mode = { 'i', 'n' } }, + [''] = { 'list_down', mode = { 'i', 'n' } }, + [''] = { 'list_up', mode = { 'i', 'n' } }, + [''] = { 'list_down', mode = { 'i', 'n' } }, + [''] = { 'list_up', mode = { 'i', 'n' } }, + [''] = { 'qflist', mode = { 'i', 'n' } }, + [''] = { 'edit_split', mode = { 'i', 'n' } }, + [''] = { 'tab', mode = { 'n', 'i' } }, + [''] = { 'list_scroll_up', mode = { 'i', 'n' } }, + [''] = { 'edit_vsplit', mode = { 'i', 'n' } }, + ['#'] = { 'insert_alt', mode = 'i' }, + ['%'] = { 'insert_filename', mode = 'i' }, + [''] = { 'insert_cWORD', mode = 'i' }, + [''] = { 'insert_file', mode = 'i' }, + [''] = { 'insert_line', mode = 'i' }, + [''] = { 'insert_file_full', mode = 'i' }, + [''] = { 'insert_cword', mode = 'i' }, + ['H'] = 'layout_left', + ['J'] = 'layout_bottom', + ['K'] = 'layout_top', + ['L'] = 'layout_right', + ['?'] = 'toggle_help_input', + ['G'] = 'list_bottom', + ['gg'] = 'list_top', + ['j'] = 'list_down', + ['k'] = 'list_up', + ['q'] = 'cancel', + }, + b = { + minipairs_disable = true, + }, + }, + -- result list window + list = { + keys = { + ['/'] = 'toggle_focus', + ['<2-LeftMouse>'] = 'confirm', + [''] = 'confirm', + [''] = 'list_down', + [''] = 'cancel', + [''] = { { 'pick_win', 'jump' } }, + [''] = { 'select_and_prev', mode = { 'n', 'x' } }, + [''] = { 'select_and_next', mode = { 'n', 'x' } }, + [''] = 'list_up', + [''] = 'inspect', + [''] = 'toggle_follow', + [''] = 'toggle_hidden', + [''] = 'toggle_ignored', + [''] = 'toggle_maximize', + [''] = 'toggle_preview', + [''] = 'cycle_win', + [''] = 'select_all', + [''] = 'preview_scroll_up', + [''] = 'list_scroll_down', + [''] = 'preview_scroll_down', + [''] = 'list_down', + [''] = 'list_up', + [''] = 'list_down', + [''] = 'list_up', + [''] = 'qflist', + [''] = 'print_path', + [''] = 'edit_split', + [''] = 'tab', + [''] = 'list_scroll_up', + [''] = 'edit_vsplit', + ['H'] = 'layout_left', + ['J'] = 'layout_bottom', + ['K'] = 'layout_top', + ['L'] = 'layout_right', + ['?'] = 'toggle_help_list', + ['G'] = 'list_bottom', + ['gg'] = 'list_top', + ['i'] = 'focus_input', + ['j'] = 'list_down', + ['k'] = 'list_up', + ['q'] = 'cancel', + ['zb'] = 'list_scroll_bottom', + ['zt'] = 'list_scroll_top', + ['zz'] = 'list_scroll_center', + }, + wo = { + conceallevel = 2, + concealcursor = 'nvc', + }, + }, + -- preview window + preview = { + keys = { + [''] = 'cancel', + ['q'] = 'cancel', + ['i'] = 'focus_input', + [''] = 'cycle_win', + }, + }, + }, + ---@class snacks.picker.icons + icons = Glyphs.snacksPicker, + + ---@class snacks.picker.db.Config + db = { + -- path to the sqlite3 library + -- If not set, it will try to load the library by name. + -- On Windows it will download the library from the internet. + sqlite3_path = nil, ---@type string? + }, + ---@class snacks.picker.debug + debug = { + scores = false, -- show scores in the list + leaks = false, -- show when pickers don't get garbage collected + explorer = false, -- show explorer debug info + files = false, -- show file debug info + grep = false, -- show file debug info + proc = false, -- show proc debug info + extmarks = false, -- show extmarks errors + }, + }, + } + + vim.keymap.set('n', 'fy', Snacks.picker.cliphist, { desc = 'Clipboard history' }) + + vim.api.nvim_create_autocmd({ 'VimEnter', 'DirChanged' }, { + group = vim.api.nvim_create_augroup('snacksPicker-git-attach', { clear = true }), + callback = function(event) + -- check if the workspace is a git repo + local code = vim.system({ 'git', 'rev-parse', '--is-inside-work-tree' }, {}, nil):wait().code + if code ~= 0 then + return + end + + vim.keymap.set('n', 'vC', Snacks.picker.git_log_file, { desc = 'Git: commits - current buf' }) + vim.keymap.set('n', 'vS', Snacks.picker.git_stash, { desc = 'Git: stash' }) + vim.keymap.set('n', 'vb', Snacks.picker.git_branches, { desc = 'Git: branches' }) + vim.keymap.set('n', 'vc', Snacks.picker.git_log, { desc = 'Git: commits' }) + vim.keymap.set('n', 'vd', Snacks.picker.git_diff, { desc = 'Git: diff' }) + vim.keymap.set('n', 'vf', Snacks.picker.git_files, { desc = 'Git: files' }) + vim.keymap.set('n', 'vl', Snacks.picker.git_log_line, { desc = 'Git: commits - current line' }) + vim.keymap.set('n', 'vs', Snacks.picker.git_status, { desc = 'Git: status' }) + end, + }) + + vim.keymap.set('n', 'lc', Snacks.picker.lsp_config, { desc = 'LSP: lsp-config info' }) + end, +} diff --git a/lua/plugins/telescope-undo.lua b/lua/plugins/telescope-undo.lua new file mode 100644 index 00000000000..96758d56fe1 --- /dev/null +++ b/lua/plugins/telescope-undo.lua @@ -0,0 +1,67 @@ +return { + 'debugloop/telescope-undo.nvim', + dependencies = { + { + 'nvim-telescope/telescope.nvim', + dependencies = { 'nvim-lua/plenary.nvim' }, + }, + }, + -- lazy = true, + keys = { + { -- lazy style key map + 'fu', + function() + require('telescope').extensions.undo.undo() + end, + desc = 'Undo history', + }, + }, + opts = { + extensions = { + undo = { + -- side_by_side = true, + -- layout_strategy = 'flex', + mappings = { + i = { + [''] = function(buff) + return require('telescope-undo.actions').yank_additions(buff) + end, + [''] = false, + [''] = false, + -- alternative defaults, for users whose terminals do questionable things with modified + [''] = function(buff) + return require('telescope-undo.actions').yank_additions(buff) + end, + [''] = function(buff) + return require('telescope-undo.actions').yank_additions(buff) + end, + [''] = function(buff) + return require('telescope-undo.actions').yank_deletions(buff) + end, + [''] = function(buff) + return require('telescope-undo.actions').restore(buff) + end, + }, + n = { + ['y'] = function(buff) + return require('telescope-undo.actions').yank_additions(buff) + end, + ['Y'] = function(buff) + return require('telescope-undo.actions').yank_deletions(buff) + end, + ['u'] = function(buff) + return require('telescope-undo.actions').restore(buff) + end, + }, + }, + }, + }, + }, + config = function(_, opts) + -- Calling telescope's setup from multiple specs does not hurt, it will happily merge the + -- configs for us. We won't use data, as everything is in it's own namespace (telescope + -- defaults, as well as each extension). + require('telescope').setup(opts) + require('telescope').load_extension 'undo' + end, +} diff --git a/lua/plugins/telescope.lua b/lua/plugins/telescope.lua new file mode 100644 index 00000000000..99909f9e4e9 --- /dev/null +++ b/lua/plugins/telescope.lua @@ -0,0 +1,179 @@ +-- Fuzzy Finder (files, lsp, etc) +return { + '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', + lazy = true, + 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-mini/mini.nvim' }, -- for mini.icons + }, + 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 = { + prompt_prefix = Glyphs.ui.prompt .. ' ', + selection_caret = Glyphs.ui.prompt .. ' ', + sorting_strategy = 'ascending', + layout_strategy = 'flex', + layout_config = { + prompt_position = 'top', + horizontal = { + preview_width = 0.6, + }, + vertical = { + preview_height = 0.6, + mirror = true, + }, + }, + mappings = { + i = { + [''] = 'to_fuzzy_refine', -- this allows to multiple layers of filtering the search list + [''] = { + require('telescope.actions').move_selection_next, + type = 'action', + opts = { nowait = true, silent = true }, + }, + [''] = { + require('telescope.actions').move_selection_previous, + type = 'action', + opts = { nowait = true, silent = true }, + }, + }, + }, + }, + -- 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', '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 + -- 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 = 10, + -- previewer = false, + -- }) + -- 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/tiny-inline-diagnostic.lua b/lua/plugins/tiny-inline-diagnostic.lua new file mode 100644 index 00000000000..1338314db4c --- /dev/null +++ b/lua/plugins/tiny-inline-diagnostic.lua @@ -0,0 +1,145 @@ +return { + 'rachartier/tiny-inline-diagnostic.nvim', + event = 'LspAttach', + priority = 1000, + init = function() + -- Disable Neovim's default virtual text diagnostics + -- and other diagnostic related configs + vim.diagnostic.config { + virtual_text = false, + severity_sort = true, -- I don't think this field is needed with tiny-inline, but I'll leave it. + underline = { severity = { min = vim.diagnostic.severity.WARN } }, + } + + vim.keymap.set('n', 'dq', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) + end, + + opts = { + -- Choose a preset style for diagnostic appearance + -- Available: "modern", "classic", "minimal", "powerline", "ghost", "simple", "nonerdfont", "amongus" + preset = 'powerline', + + -- Make diagnostic background transparent + transparent_bg = false, + + -- Make cursorline background transparent for diagnostics + transparent_cursorline = true, + + -- Customize highlight groups for colors + -- Use Neovim highlight group names or hex colors like "#RRGGBB" + hi = { + error = 'DiagnosticError', -- Highlight for error diagnostics + warn = 'DiagnosticWarn', -- Highlight for warning diagnostics + info = 'DiagnosticInfo', -- Highlight for info diagnostics + hint = 'DiagnosticHint', -- Highlight for hint diagnostics + arrow = 'NonText', -- Highlight for the arrow pointing to diagnostic + background = 'CursorLine', -- Background highlight for diagnostics + mixing_color = 'Normal', -- Color to blend background with (or "None") + }, + + -- List of filetypes to disable the plugin for + disabled_ft = {}, + + options = { + -- Display the source of diagnostics (e.g., "lua_ls", "pyright") + show_source = { + enabled = true, -- Enable showing source names + if_many = false, -- Only show source if multiple sources exist for the same diagnostic + }, + + -- Display the diagnostic code of diagnostics (e.g., "F401", "no-dupe-args") + show_code = true, + + -- Use icons from vim.diagnostic.config instead of preset icons + use_icons_from_diagnostic = false, + + -- Color the arrow to match the severity of the first diagnostic + set_arrow_to_diag_color = false, + + -- Throttle update frequency in milliseconds to improve performance + -- Higher values reduce CPU usage but may feel less responsive + -- Set to 0 for immediate updates (may cause lag on slow systems) + throttle = 20, + + -- Minimum number of characters before wrapping long messages + softwrap = 30, + + -- Control how diagnostic messages are displayed + -- NOTE: When using display_count = true, you need to enable multiline diagnostics with multilines.enabled = true + -- If you want them to always be displayed, you can also set multilines.always_show = true. + add_messages = { + messages = true, -- Show full diagnostic messages + display_count = false, -- Show diagnostic count instead of messages when cursor not on line + use_max_severity = false, -- When counting, only show the most severe diagnostic + show_multiple_glyphs = true, -- Show multiple icons for multiple diagnostics of same severity + }, + + -- Settings for multiline diagnostics + multilines = { + enabled = false, -- Enable support for multiline diagnostic messages + always_show = false, -- Always show messages on all lines of multiline diagnostics + trim_whitespaces = false, -- Remove leading/trailing whitespace from each line + tabstop = 4, -- Number of spaces per tab when expanding tabs + severity = nil, -- Filter multiline diagnostics by severity (e.g., { vim.diagnostic.severity.ERROR }) + }, + + -- Show all diagnostics on the current cursor line, not just those under the cursor + show_all_diags_on_cursorline = false, + + -- Only show diagnostics when the cursor is directly over them, no fallback to line diagnostics + show_diags_only_under_cursor = false, + + -- Display related diagnostics from LSP relatedInformation + show_related = { + enabled = true, -- Enable displaying related diagnostics + max_count = 3, -- Maximum number of related diagnostics to show per diagnostic + }, + + -- Enable diagnostics display in insert mode + -- May cause visual artifacts; consider setting throttle to 0 if enabled + enable_on_insert = false, + + -- Enable diagnostics display in select mode (e.g., during auto-completion) + enable_on_select = false, + + -- Handle messages that exceed the window width + overflow = { + mode = 'wrap', -- "wrap": split into lines, "none": no truncation, "oneline": keep single line + padding = 0, -- Extra characters to trigger wrapping earlier + }, + + -- Break long messages into separate lines + break_line = { + enabled = false, -- Enable automatic line breaking + after = 30, -- Number of characters before inserting a line break + }, + + -- Custom function to format diagnostic messages + -- Receives diagnostic object, returns formatted string + -- Example: function(diag) return diag.message .. " [" .. diag.source .. "]" end + format = nil, + + -- Virtual text display priority + -- Higher values appear above other plugins (e.g., GitBlame) + virt_texts = { + priority = 2048, + }, + + -- Filter diagnostics by severity levels + -- Remove severities you don't want to display + severity = { + vim.diagnostic.severity.ERROR, + vim.diagnostic.severity.WARN, + vim.diagnostic.severity.INFO, + vim.diagnostic.severity.HINT, + }, + + -- Events that trigger attaching diagnostics to buffers + -- Default is {"LspAttach"}; change only if plugin doesn't work with your LSP setup + overwrite_events = nil, + + -- Automatically disable diagnostics when opening diagnostic float windows + override_open_float = false, + }, + }, +} diff --git a/lua/plugins/todo-comments.lua b/lua/plugins/todo-comments.lua new file mode 100644 index 00000000000..7443dfea4a2 --- /dev/null +++ b/lua/plugins/todo-comments.lua @@ -0,0 +1,10 @@ +-- Highlight todo, notes, etc in comments +return { + 'folke/todo-comments.nvim', + event = 'VimEnter', + dependencies = { 'nvim-lua/plenary.nvim' }, + ---@module 'todo-comments' + ---@type TodoOptions + ---@diagnostic disable-next-line: missing-fields + opts = { signs = false }, +} diff --git a/lua/plugins/tokyonight.lua b/lua/plugins/tokyonight.lua new file mode 100644 index 00000000000..4e7d696555a --- /dev/null +++ b/lua/plugins/tokyonight.lua @@ -0,0 +1,23 @@ +-- Add colorscheme +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/undotree.lua b/lua/plugins/undotree.lua new file mode 100644 index 00000000000..3b04e16e209 --- /dev/null +++ b/lua/plugins/undotree.lua @@ -0,0 +1,15 @@ +return { + 'jiaoshijie/undotree', + dependencies = 'nvim-lua/plenary.nvim', + config = true, + keys = { + { + 'tu', + function() + -- load the plugin only when using it's keybinding + require('undotree').toggle() + end, + desc = '[T]oggle [U]ndotree', + }, + }, +} diff --git a/lua/plugins/virt-column.lua b/lua/plugins/virt-column.lua new file mode 100644 index 00000000000..e8e7902cddb --- /dev/null +++ b/lua/plugins/virt-column.lua @@ -0,0 +1,12 @@ +-- Display a character as the colorcolumn +return { + 'lukas-reineke/virt-column.nvim', + opts = { + char = '▕', -- This line is the whole idea of using virt-column + virtcolumn = '80,100', + highlight = 'CursorLineNr', -- match CursorLineNr highlight + exclude = { + filetypes = { 'oil' }, + }, + }, +} diff --git a/lua/plugins/which-key.lua b/lua/plugins/which-key.lua new file mode 100644 index 00000000000..50721e2d925 --- /dev/null +++ b/lua/plugins/which-key.lua @@ -0,0 +1,39 @@ +-- Useful plugin to show you pending keybinds. +return { + 'folke/which-key.nvim', + event = 'VimEnter', + ---@module 'which-key' + ---@type wk.Opts + ---@diagnostic disable-next-line: missing-fields + opts = { + -- set which-key layout to look like 'helix' + preset = 'helix', + -- delay between pressing a key and opening which-key (milliseconds) + delay = 0, + icons = { mappings = false }, + sort = { 'local', 'order', 'group', 'desc', 'case', 'alphanum', 'mod' }, + + plugins = { + spelling = { enabled = false }, + }, + + -- Document existing key chains + spec = { + { 's', group = '[S]earch', mode = { 'n', 'v' } }, + { 'f', group = '[F]uzzy-find', mode = { 'n', 'v' } }, + { 'g', group = '[G]rep', mode = { 'n', 'v' } }, + { 'G', group = '[G]it', mode = { 'n', 'v' } }, + { 'v', group = '[V]ersion control', mode = { 'n', 'v' } }, + { 'l', group = '[L]SP', mode = { 'n', 'v' } }, + { 't', group = '[T]oggle' }, + { 'd', group = '[D]iagnostic' }, + { ';', group = '[;]terminal' }, + { 'ao', group = 'TS text[O]bject', mode = { 'v', 'o' } }, + { 'io', group = 'TS text[O]bject', mode = { 'v', 'o' } }, + { '[o', group = 'TS text[O]bject', mode = { 'n', 'v', 'o' } }, + { ']o', group = 'TS text[O]bject', mode = { 'n', 'v', 'o' } }, + { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, + { 'gr', group = 'LSP Actions', mode = { 'n' } }, + }, + }, +}