@ -37,13 +37,14 @@ I hope you enjoy your Neovim journey,
P.S . You can delete this when you ' re done too. It ' s your config now : )
--]]
-- Set <space> as the leader key
-- See `:help mapleader`
-- NOTE: Must happen before plugins are required (otherwise wrong leader will be used)
vim.g . mapleader = ' '
vim.g . maplocalleader = ' '
-- Install package manager
-- [[ Install `lazy.nvim` plugin manager ]]
-- https://github.com/folke/lazy.nvim
-- `:help lazy.nvim.txt` for more info
local lazypath = vim.fn . stdpath ' data ' .. ' /lazy/lazy.nvim '
@ -59,6 +60,7 @@ if not vim.loop.fs_stat(lazypath) then
end
vim.opt . rtp : prepend ( lazypath )
-- [[ Configure plugins ]]
-- NOTE: Here is where you install your plugins.
-- You can configure plugins using the `config` key.
--
@ -81,12 +83,12 @@ require('lazy').setup({
' neovim/nvim-lspconfig ' ,
dependencies = {
-- Automatically install LSPs to stdpath for neovim
{ ' williamboman/mason.nvim ' , config = true } ,
' williamboman/mason.nvim ' ,
' williamboman/mason-lspconfig.nvim ' ,
-- Useful status updates for LSP
-- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})`
{ ' j-hui/fidget.nvim ' , tag = ' legacy ' , opts = { } } ,
{ ' j-hui/fidget.nvim ' , opts = { } } ,
-- Additional lua configuration, makes nvim stuff amazing!
' folke/neodev.nvim ' ,
@ -124,20 +126,64 @@ require('lazy').setup({
changedelete = { text = ' ~ ' } ,
} ,
on_attach = function ( bufnr )
vim.keymap . set ( ' n ' , ' <leader>hp ' , require ( ' gitsigns ' ) . preview_hunk , { buffer = bufnr , desc = ' Preview git hunk ' } )
-- don't override the built-in and fugitive keymaps
local gs = package.loaded . gitsigns
vim.keymap . set ( { ' n ' , ' v ' } , ' ]c ' , function ( )
if vim.wo . diff then return ' ]c ' end
vim.schedule ( function ( ) gs.next_hunk ( ) end )
local function map ( mode , l , r , opts )
opts = opts or { }
opts.buffer = bufnr
vim.keymap . set ( mode , l , r , opts )
end
-- Navigation
map ( { ' n ' , ' v ' } , ' ]c ' , function ( )
if vim.wo . diff then
return ' ]c '
end
vim.schedule ( function ( )
gs.next_hunk ( )
end )
return ' <Ignore> '
end , { expr = true , buffer = bufnr , desc = " Jump to next hunk " } )
vim.keymap . set ( { ' n ' , ' v ' } , ' [c ' , function ( )
if vim.wo . diff then return ' [c ' end
vim.schedule ( function ( ) gs.prev_hunk ( ) end )
end , { expr = true , desc = ' Jump to next hunk ' } )
map ( { ' n ' , ' v ' } , ' [c ' , function ( )
if vim.wo . diff then
return ' [c '
end
vim.schedule ( function ( )
gs.prev_hunk ( )
end )
return ' <Ignore> '
end , { expr = true , buffer = bufnr , desc = " Jump to previous hunk " } )
end , { expr = true , desc = ' Jump to previous hunk ' } )
-- Actions
-- visual mode
map ( ' v ' , ' <leader>hs ' , function ( )
gs.stage_hunk { vim.fn . line ' . ' , vim.fn . line ' v ' }
end , { desc = ' stage git hunk ' } )
map ( ' v ' , ' <leader>hr ' , function ( )
gs.reset_hunk { vim.fn . line ' . ' , vim.fn . line ' v ' }
end , { desc = ' reset git hunk ' } )
-- normal mode
map ( ' n ' , ' <leader>hs ' , gs.stage_hunk , { desc = ' git stage hunk ' } )
map ( ' n ' , ' <leader>hr ' , gs.reset_hunk , { desc = ' git reset hunk ' } )
map ( ' n ' , ' <leader>hS ' , gs.stage_buffer , { desc = ' git Stage buffer ' } )
map ( ' n ' , ' <leader>hu ' , gs.undo_stage_hunk , { desc = ' undo stage hunk ' } )
map ( ' n ' , ' <leader>hR ' , gs.reset_buffer , { desc = ' git Reset buffer ' } )
map ( ' n ' , ' <leader>hp ' , gs.preview_hunk , { desc = ' preview git hunk ' } )
map ( ' n ' , ' <leader>hb ' , function ( )
gs.blame_line { full = false }
end , { desc = ' git blame line ' } )
map ( ' n ' , ' <leader>hd ' , gs.diffthis , { desc = ' git diff against index ' } )
map ( ' n ' , ' <leader>hD ' , function ( )
gs.diffthis ' ~ '
end , { desc = ' git diff against last commit ' } )
-- Toggles
map ( ' n ' , ' <leader>tb ' , gs.toggle_current_line_blame , { desc = ' toggle git blame line ' } )
map ( ' n ' , ' <leader>td ' , gs.toggle_deleted , { desc = ' toggle git show deleted ' } )
-- Text object
map ( { ' o ' , ' x ' } , ' ih ' , ' :<C-U>Gitsigns select_hunk<CR> ' , { desc = ' select git hunk ' } )
end ,
} ,
} ,
@ -169,12 +215,9 @@ require('lazy').setup({
-- Add indentation guides even on blank lines
' lukas-reineke/indent-blankline.nvim ' ,
-- Enable `lukas-reineke/indent-blankline.nvim`
-- See `:help indent_blankline.txt`
version = ' 2.20.8 ' ,
opts = {
char = ' ┊ ' ,
show_trailing_blankline_indent = false ,
} ,
-- See `:help ibl`
main = ' ibl ' ,
opts = { } ,
} ,
-- "gc" to comment visual regions/lines
@ -276,6 +319,12 @@ vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
vim.keymap . set ( ' n ' , ' k ' , " v:count == 0 ? 'gk' : 'k' " , { expr = true , silent = true } )
vim.keymap . set ( ' n ' , ' j ' , " v:count == 0 ? 'gj' : 'j' " , { expr = true , silent = true } )
-- Diagnostic keymaps
vim.keymap . set ( ' n ' , ' [d ' , vim.diagnostic . goto_prev , { desc = ' Go to previous diagnostic message ' } )
vim.keymap . set ( ' n ' , ' ]d ' , vim.diagnostic . goto_next , { desc = ' Go to next diagnostic message ' } )
vim.keymap . set ( ' n ' , ' <leader>e ' , vim.diagnostic . open_float , { desc = ' Open floating diagnostic message ' } )
vim.keymap . set ( ' n ' , ' <leader>q ' , vim.diagnostic . setloclist , { desc = ' Open diagnostics list ' } )
-- [[ Highlight on yank ]]
-- See `:help vim.highlight.on_yank()`
local highlight_group = vim.api . nvim_create_augroup ( ' YankHighlight ' , { clear = true } )
@ -303,6 +352,42 @@ require('telescope').setup {
-- Enable telescope fzf native, if installed
pcall ( require ( ' telescope ' ) . load_extension , ' fzf ' )
-- Telescope live_grep in git root
-- Function to find the git root directory based on the current buffer's path
local function find_git_root ( )
-- Use the current buffer's path as the starting point for the git search
local current_file = vim.api . nvim_buf_get_name ( 0 )
local current_dir
local cwd = vim.fn . getcwd ( )
-- If the buffer is not associated with a file, return nil
if current_file == ' ' then
current_dir = cwd
else
-- Extract the directory from the current file's path
current_dir = vim.fn . fnamemodify ( current_file , ' :h ' )
end
-- Find the Git root directory from the current file's path
local git_root = vim.fn . systemlist ( ' git -C ' .. vim.fn . escape ( current_dir , ' ' ) .. ' rev-parse --show-toplevel ' ) [ 1 ]
if vim.v . shell_error ~= 0 then
print ' Not a git repository. Searching on current working directory '
return cwd
end
return git_root
end
-- Custom live_grep function to search in git root
local function live_grep_git_root ( )
local git_root = find_git_root ( )
if git_root then
require ( ' telescope.builtin ' ) . live_grep {
search_dirs = { git_root } ,
}
end
end
vim.api . nvim_create_user_command ( ' LiveGrepGitRoot ' , live_grep_git_root , { } )
-- See `:help telescope.builtin`
vim.keymap . set ( ' n ' , ' <leader>? ' , require ( ' telescope.builtin ' ) . oldfiles , { desc = ' [?] Find recently opened files ' } )
vim.keymap . set ( ' n ' , ' <leader><space> ' , require ( ' telescope.builtin ' ) . buffers , { desc = ' [ ] Find existing buffers ' } )
@ -314,85 +399,91 @@ vim.keymap.set('n', '<leader>/', function()
} )
end , { desc = ' [/] Fuzzily search in current buffer ' } )
local function telescope_live_grep_open_files ( )
require ( ' telescope.builtin ' ) . live_grep {
grep_open_files = true ,
prompt_title = ' Live Grep in Open Files ' ,
}
end
vim.keymap . set ( ' n ' , ' <leader>s/ ' , telescope_live_grep_open_files , { desc = ' [S]earch [/] in Open Files ' } )
vim.keymap . set ( ' n ' , ' <leader>ss ' , require ( ' telescope.builtin ' ) . builtin , { desc = ' [S]earch [S]elect Telescope ' } )
vim.keymap . set ( ' n ' , ' <leader>gf ' , require ( ' telescope.builtin ' ) . git_files , { desc = ' Search [G]it [F]iles ' } )
vim.keymap . set ( ' n ' , ' <leader>sf ' , require ( ' telescope.builtin ' ) . find_files , { desc = ' [S]earch [F]iles ' } )
vim.keymap . set ( ' n ' , ' <leader>sh ' , require ( ' telescope.builtin ' ) . help_tags , { desc = ' [S]earch [H]elp ' } )
vim.keymap . set ( ' n ' , ' <leader>sw ' , require ( ' telescope.builtin ' ) . grep_string , { desc = ' [S]earch current [W]ord ' } )
vim.keymap . set ( ' n ' , ' <leader>sg ' , require ( ' telescope.builtin ' ) . live_grep , { desc = ' [S]earch by [G]rep ' } )
vim.keymap . set ( ' n ' , ' <leader>sG ' , ' :LiveGrepGitRoot<cr> ' , { desc = ' [S]earch by [G]rep on Git Root ' } )
vim.keymap . set ( ' n ' , ' <leader>sd ' , require ( ' telescope.builtin ' ) . diagnostics , { desc = ' [S]earch [D]iagnostics ' } )
vim.keymap . set ( ' n ' , ' <leader>sr ' , require ( ' telescope.builtin ' ) . resume , { desc = ' [S]earch [R]esume ' } )
-- [[ Configure Treesitter ]]
-- See `:help nvim-treesitter`
require ( ' nvim-treesitter.configs ' ) . setup {
-- Add languages to be installed here that you want installed for treesitter
ensure_installed = { ' c ' , ' cpp ' , ' go ' , ' lua ' , ' python ' , ' rust ' , ' tsx ' , ' javascript ' , ' typescript ' , ' vimdoc ' , ' vim ' } ,
-- Autoinstall languages that are not installed. Defaults to false (but you can change for yourself!)
auto_install = false ,
highlight = { enable = true } ,
indent = { enable = true } ,
incremental_selection = {
enable = true ,
keymaps = {
init_selection = ' <c-space> ' ,
node_incremental = ' <c-space> ' ,
scope_incremental = ' <c-s> ' ,
node_decremental = ' <M-space> ' ,
} ,
} ,
textobjects = {
select = {
-- Defer Treesitter setup after first render to improve startup time of 'nvim {filename}'
vim.defer_fn ( function ( )
require ( ' nvim-treesitter.configs ' ) . setup {
-- Add languages to be installed here that you want installed for treesitter
ensure_installed = { ' c ' , ' cpp ' , ' go ' , ' lua ' , ' python ' , ' rust ' , ' tsx ' , ' javascript ' , ' typescript ' , ' vimdoc ' , ' vim ' , ' bash ' } ,
-- Autoinstall languages that are not installed. Defaults to false (but you can change for yourself!)
auto_install = false ,
highlight = { enable = true } ,
indent = { enable = true } ,
incremental_selection = {
enable = true ,
lookahead = true , -- Automatically jump forward to textobj, similar to targets.vim
keymaps = {
-- You can use the capture groups defined in textobjects.scm
[ ' aa ' ] = ' @parameter.outer ' ,
[ ' ia ' ] = ' @parameter.inner ' ,
[ ' af ' ] = ' @function.outer ' ,
[ ' if ' ] = ' @function.inner ' ,
[ ' ac ' ] = ' @class.outer ' ,
[ ' ic ' ] = ' @class.inner ' ,
init_selection = ' <c-space> ' ,
node_incremental = ' <c-space> ' ,
scope_incremental = ' <c-s> ' ,
node_decremental = ' <M-space> ' ,
} ,
} ,
move = {
enable = true ,
set_jumps = true , -- whether to set jumps in the jumplist
goto_next_start = {
[ ' ]m ' ] = ' @function.outer ' ,
[ ' ]] ' ] = ' @class.outer ' ,
textobjects = {
select = {
enable = true ,
lookahead = true , -- Automatically jump forward to textobj, similar to targets.vim
keymaps = {
-- You can use the capture groups defined in textobjects.scm
[ ' aa ' ] = ' @parameter.outer ' ,
[ ' ia ' ] = ' @parameter.inner ' ,
[ ' af ' ] = ' @function.outer ' ,
[ ' if ' ] = ' @function.inner ' ,
[ ' ac ' ] = ' @class.outer ' ,
[ ' ic ' ] = ' @class.inner ' ,
} ,
} ,
goto_next_end = {
[ ' ]M ' ] = ' @function.outer ' ,
[ ' ][ ' ] = ' @class.outer ' ,
move = {
enable = true ,
set_jumps = true , -- whether to set jumps in the jumplist
goto_next_start = {
[ ' ]m ' ] = ' @function.outer ' ,
[ ' ]] ' ] = ' @class.outer ' ,
} ,
goto_next_end = {
[ ' ]M ' ] = ' @function.outer ' ,
[ ' ][ ' ] = ' @class.outer ' ,
} ,
goto_previous_start = {
[ ' [m ' ] = ' @function.outer ' ,
[ ' [[ ' ] = ' @class.outer ' ,
} ,
goto_previous_end = {
[ ' [M ' ] = ' @function.outer ' ,
[ ' [] ' ] = ' @class.outer ' ,
} ,
} ,
goto_previous_start = {
[ ' [m ' ] = ' @function.outer ' ,
[ ' [[ ' ] = ' @class.outer ' ,
} ,
goto_previous_end = {
[ ' [M ' ] = ' @function.outer ' ,
[ ' [] ' ] = ' @class.outer ' ,
swap = {
enable = true ,
swap_next = {
[ ' <leader>a ' ] = ' @parameter.inner ' ,
} ,
swap_previous = {
[ ' <leader>A ' ] = ' @parameter.inner ' ,
} ,
} ,
} ,
swap = {
enable = true ,
swap_next = {
[ ' <leader>a ' ] = ' @parameter.inner ' ,
} ,
swap_previous = {
[ ' <leader>A ' ] = ' @parameter.inner ' ,
} ,
} ,
} ,
}
-- Diagnostic keymaps
vim.keymap . set ( ' n ' , ' [d ' , vim.diagnostic . goto_prev , { desc = ' Go to previous diagnostic message ' } )
vim.keymap . set ( ' n ' , ' ]d ' , vim.diagnostic . goto_next , { desc = ' Go to next diagnostic message ' } )
vim.keymap . set ( ' n ' , ' <leader>e ' , vim.diagnostic . open_float , { desc = ' Open floating diagnostic message ' } )
vim.keymap . set ( ' n ' , ' <leader>q ' , vim.diagnostic . setloclist , { desc = ' Open diagnostics list ' } )
}
end , 0 )
-- [[ Configure LSP ]]
-- This function gets run when an LSP connects to a particular buffer.
@ -414,10 +505,10 @@ local on_attach = function(_, bufnr)
nmap ( ' <leader>rn ' , vim.lsp . buf.rename , ' [R]e[n]ame ' )
nmap ( ' <leader>ca ' , vim.lsp . buf.code_action , ' [C]ode [A]ction ' )
nmap ( ' gd ' , vim.lsp. buf.definition , ' [G]oto [D]efinition ' )
nmap ( ' gd ' , require( ' telescope.builtin ' ) . lsp_definitions , ' [G]oto [D]efinition ' )
nmap ( ' gr ' , require ( ' telescope.builtin ' ) . lsp_references , ' [G]oto [R]eferences ' )
nmap ( ' gI ' , require ( ' telescope.builtin ' ) . lsp_implementations , ' [G]oto [I]mplementation ' )
nmap ( ' <leader>D ' , vim.lsp. buf.type_definition , ' Type [D]efinition ' )
nmap ( ' <leader>D ' , require( ' telescope.builtin ' ) . lsp_type_definitions , ' Type [D]efinition ' )
nmap ( ' <leader>ds ' , require ( ' telescope.builtin ' ) . lsp_document_symbols , ' [D]ocument [S]ymbols ' )
nmap ( ' <leader>ws ' , require ( ' telescope.builtin ' ) . lsp_dynamic_workspace_symbols , ' [W]orkspace [S]ymbols ' )
@ -439,6 +530,29 @@ local on_attach = function(_, bufnr)
end , { desc = ' Format current buffer with LSP ' } )
end
-- document existing key chains
require ( ' which-key ' ) . register {
[ ' <leader>c ' ] = { name = ' [C]ode ' , _ = ' which_key_ignore ' } ,
[ ' <leader>d ' ] = { name = ' [D]ocument ' , _ = ' which_key_ignore ' } ,
[ ' <leader>g ' ] = { name = ' [G]it ' , _ = ' which_key_ignore ' } ,
[ ' <leader>h ' ] = { name = ' Git [H]unk ' , _ = ' which_key_ignore ' } ,
[ ' <leader>r ' ] = { name = ' [R]ename ' , _ = ' which_key_ignore ' } ,
[ ' <leader>s ' ] = { name = ' [S]earch ' , _ = ' which_key_ignore ' } ,
[ ' <leader>t ' ] = { name = ' [T]oggle ' , _ = ' which_key_ignore ' } ,
[ ' <leader>w ' ] = { name = ' [W]orkspace ' , _ = ' which_key_ignore ' } ,
}
-- register which-key VISUAL mode
-- required for visual <leader>hs (hunk stage) to work
require ( ' which-key ' ) . register ( {
[ ' <leader> ' ] = { name = ' VISUAL <leader> ' } ,
[ ' <leader>h ' ] = { ' Git [H]unk ' } ,
} , { mode = ' v ' } )
-- mason-lspconfig requires that these setup functions are called in this order
-- before setting up the servers.
require ( ' mason ' ) . setup ( )
require ( ' mason-lspconfig ' ) . setup ( )
-- Enable the following language servers
-- Feel free to add/remove any LSPs that you want here. They will automatically be installed.
--
@ -459,6 +573,8 @@ local servers = {
Lua = {
workspace = { checkThirdParty = false } ,
telemetry = { enable = false } ,
-- NOTE: toggle below to ignore Lua_LS's noisy `missing-fields` warnings
-- diagnostics = { disable = { 'missing-fields' } },
} ,
} ,
}
@ -485,7 +601,7 @@ mason_lspconfig.setup_handlers {
settings = servers [ server_name ] ,
filetypes = ( servers [ server_name ] or { } ) . filetypes ,
}
end
end ,
}
-- [[ Configure nvim-cmp ]]
@ -501,6 +617,9 @@ cmp.setup {
luasnip.lsp_expand ( args.body )
end ,
} ,
completion = {
completeopt = ' menu,menuone,noinsert ' ,
} ,
mapping = cmp.mapping . preset.insert {
[ ' <C-n> ' ] = cmp.mapping . select_next_item ( ) ,
[ ' <C-p> ' ] = cmp.mapping . select_prev_item ( ) ,