494 lines
14 KiB
Lua
494 lines
14 KiB
Lua
-- ============================================================================
|
|
-- Modern Neovim Configuration (lazy.nvim)
|
|
-- ============================================================================
|
|
|
|
-- Bootstrap lazy.nvim
|
|
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
|
if not vim.loop.fs_stat(lazypath) then
|
|
vim.fn.system({
|
|
"git",
|
|
"clone",
|
|
"--filter=blob:none",
|
|
"https://github.com/folke/lazy.nvim.git",
|
|
"--branch=stable",
|
|
lazypath,
|
|
})
|
|
end
|
|
vim.opt.rtp:prepend(lazypath)
|
|
|
|
-- ============================================================================
|
|
-- Plugin Specifications
|
|
-- ============================================================================
|
|
require("lazy").setup({
|
|
-- File tree
|
|
{
|
|
'scrooloose/nerdtree',
|
|
cmd = 'NERDTreeToggle',
|
|
},
|
|
|
|
-- Build/async tools
|
|
'tpope/vim-dispatch',
|
|
|
|
-- Git integration
|
|
'tpope/vim-fugitive',
|
|
|
|
-- Text manipulation
|
|
'tpope/vim-abolish',
|
|
|
|
-- Large file handling
|
|
{
|
|
'LunarVim/bigfile.nvim',
|
|
config = function()
|
|
require('bigfile').setup()
|
|
end,
|
|
},
|
|
|
|
-- FZF
|
|
{ 'junegunn/fzf' },
|
|
{
|
|
'ibhagwan/fzf-lua',
|
|
branch = 'main',
|
|
config = function()
|
|
require('fzf-lua').setup({
|
|
winopts = {
|
|
height = 0.95,
|
|
width = 0.95
|
|
}
|
|
})
|
|
end,
|
|
},
|
|
'nvim-tree/nvim-web-devicons',
|
|
|
|
-- Alignment
|
|
{
|
|
'junegunn/vim-easy-align',
|
|
init = function()
|
|
vim.g.easy_align_delimiters = {
|
|
['>'] = { pattern = '>>\\|=>\\|>' },
|
|
['/'] = {
|
|
pattern = '//\\+\\|/\\*\\|\\*/',
|
|
delimiter_align = 'l',
|
|
ignore_groups = {'!Comment'}
|
|
},
|
|
[']'] = {
|
|
pattern = '[[\\]]',
|
|
left_margin = 0,
|
|
right_margin = 0,
|
|
stick_to_left = 0
|
|
},
|
|
[')'] = {
|
|
pattern = '[)]',
|
|
left_margin = 0,
|
|
right_margin = 0,
|
|
stick_to_left = 0
|
|
},
|
|
['('] = {
|
|
pattern = '[(]',
|
|
left_margin = 0,
|
|
right_margin = 0,
|
|
stick_to_left = 0
|
|
},
|
|
}
|
|
end,
|
|
},
|
|
|
|
-- File picker
|
|
{
|
|
'dmtrKovalenko/fff.nvim',
|
|
build = function()
|
|
-- this will download prebuild binary or try to use existing rustup toolchain to build from source
|
|
-- (if you are using lazy you can use gb for rebuilding a plugin if needed)
|
|
require("fff.download").download_or_build_binary()
|
|
end,
|
|
-- No need to lazy-load with lazy.nvim.
|
|
-- This plugin initializes itself lazily.
|
|
lazy = false,
|
|
keys = {
|
|
{
|
|
"<leader>f",
|
|
function() require('fff').find_files() end,
|
|
desc = 'FFFind files',
|
|
},
|
|
{
|
|
"<leader>r",
|
|
function() require('fff').live_grep() end,
|
|
desc = 'LiFFFe grep',
|
|
},
|
|
{
|
|
"fz",
|
|
function() require('fff').live_grep({
|
|
grep = {
|
|
modes = { 'fuzzy', 'plain' }
|
|
}
|
|
}) end,
|
|
desc = 'Live fffuzy grep',
|
|
},
|
|
{
|
|
"<leader>R",
|
|
function() require('fff').live_grep({ query = vim.fn.expand("<cword>") }) end,
|
|
desc = 'Search current word',
|
|
},
|
|
}
|
|
},
|
|
|
|
-- C++ syntax highlighting
|
|
{
|
|
'bfrg/vim-cpp-modern',
|
|
init = function()
|
|
vim.g.cpp_function_highlight = 1
|
|
vim.g.cpp_attributes_highlight = 1
|
|
vim.g.cpp_member_highlight = 0
|
|
vim.g.cpp_simple_highlight = 1
|
|
end,
|
|
},
|
|
|
|
-- Motion
|
|
{
|
|
url = 'https://codeberg.org/andyg/leap.nvim',
|
|
lazy = false,
|
|
config = function()
|
|
vim.keymap.set({'n', 'x', 'o'}, '<tab>', '<Plug>(leap)')
|
|
vim.keymap.set({'n', 'x', 'o'}, '<S-tab>', '<Plug>(leap-from-window)')
|
|
-- Highly recommended: define a preview filter to reduce visual noise
|
|
-- and the blinking effect after the first keypress
|
|
-- (see `:h leap.opts.preview`).
|
|
-- For example, skip preview if the first character of the match is
|
|
-- whitespace or is in the middle of an alphabetic word:
|
|
require('leap').opts.preview = function(ch0, ch1, ch2)
|
|
return not (
|
|
ch1:match('%s')
|
|
or (ch0:match('%a') and ch1:match('%a') and ch2:match('%a'))
|
|
)
|
|
end
|
|
|
|
-- Define equivalence classes for brackets and quotes, in addition to
|
|
-- the default whitespace group:
|
|
require('leap').opts.equivalence_classes = { ' \t\r\n', '([{', ')]}', '\'"`' }
|
|
|
|
-- Use the traversal keys to repeat the previous motion without
|
|
-- explicitly invoking Leap:
|
|
require('leap.user').set_repeat_keys('<enter>', '<backspace>')
|
|
|
|
-- Automatic paste after remote yank operations:
|
|
vim.api.nvim_create_autocmd('User', {
|
|
pattern = 'RemoteOperationDone',
|
|
group = vim.api.nvim_create_augroup('LeapRemote', {}),
|
|
callback = function(event)
|
|
if vim.v.operator == 'y' and event.data.register == '"' then
|
|
vim.cmd('normal! p')
|
|
end
|
|
end,
|
|
})
|
|
end
|
|
},
|
|
|
|
-- Theme
|
|
{
|
|
'sainnhe/gruvbox-material',
|
|
priority = 1000,
|
|
init = function()
|
|
vim.g.gruvbox_material_background = 'hard'
|
|
vim.g.gruvbox_material_foreground = 'mix'
|
|
vim.g.gruvbox_material_disable_italic_comment = 1
|
|
vim.g.gruvbox_material_enable_italic = 0
|
|
vim.g.gruvbox_material_enable_bold = 0
|
|
vim.g.gruvbox_material_diagnostic_virtual_text = 'colored'
|
|
vim.g.gruvbox_material_better_performance = 1
|
|
end,
|
|
config = function()
|
|
vim.cmd('colorscheme gruvbox-material')
|
|
end,
|
|
},
|
|
|
|
-- Odin syntax
|
|
'Tetralux/odin.vim',
|
|
|
|
-- Treesitter
|
|
{
|
|
'nvim-treesitter/nvim-treesitter',
|
|
build = ':TSUpdate',
|
|
},
|
|
|
|
-- LSP
|
|
{
|
|
'williamboman/mason.nvim',
|
|
config = function()
|
|
require('mason').setup({})
|
|
end,
|
|
},
|
|
{
|
|
'williamboman/mason-lspconfig.nvim',
|
|
config = function()
|
|
require('mason-lspconfig').setup({
|
|
ensure_installed = { "clangd" },
|
|
automatic_enable = true,
|
|
})
|
|
end,
|
|
},
|
|
'neovim/nvim-lspconfig',
|
|
|
|
-- Completion
|
|
{
|
|
'hrsh7th/nvim-cmp',
|
|
dependencies = {
|
|
'hrsh7th/cmp-nvim-lsp',
|
|
'hrsh7th/cmp-buffer',
|
|
'hrsh7th/cmp-path',
|
|
'L3MON4D3/LuaSnip',
|
|
},
|
|
config = function()
|
|
local cmp = require('cmp')
|
|
cmp.setup({
|
|
sources = {
|
|
{ name = 'nvim_lsp' },
|
|
{ name = 'buffer' },
|
|
{ name = 'path' },
|
|
},
|
|
mapping = cmp.mapping.preset.insert({
|
|
['<CR>'] = cmp.mapping.confirm({ select = false }),
|
|
['<Tab>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
|
|
['<S-Tab>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
|
|
}),
|
|
snippet = {
|
|
expand = function(args)
|
|
require('luasnip').lsp_expand(args.body)
|
|
end,
|
|
},
|
|
})
|
|
end,
|
|
},
|
|
'hrsh7th/cmp-nvim-lsp',
|
|
'hrsh7th/cmp-buffer',
|
|
'hrsh7th/cmp-path',
|
|
'L3MON4D3/LuaSnip',
|
|
|
|
-- Utilities
|
|
'nvim-lua/plenary.nvim',
|
|
}, {
|
|
install = {
|
|
colorscheme = { "gruvbox-material" },
|
|
},
|
|
checker = {
|
|
enabled = false,
|
|
},
|
|
})
|
|
|
|
-- ============================================================================
|
|
-- Options
|
|
-- ============================================================================
|
|
vim.opt.autowrite = true
|
|
vim.opt.colorcolumn = { 80, 100 }
|
|
vim.opt.completeopt = { 'menu', 'menuone', 'noselect' }
|
|
vim.opt.cpoptions:append('$')
|
|
vim.opt.cursorline = true
|
|
vim.opt.expandtab = true
|
|
vim.opt.guifont = 'JetBrains_Mono,Consolas:h9'
|
|
vim.opt.hlsearch = false
|
|
vim.opt.ignorecase = true
|
|
vim.opt.linebreak = true
|
|
vim.opt.list = true
|
|
vim.opt.listchars:append('tab:>-,trail:■,extends:»,precedes:«')
|
|
vim.opt.number = true
|
|
vim.opt.relativenumber = true
|
|
vim.opt.shiftwidth = 4
|
|
vim.opt.splitright = true
|
|
vim.opt.swapfile = false
|
|
vim.opt.textwidth = 80
|
|
vim.opt.visualbell = true
|
|
vim.opt.wrap = false
|
|
vim.opt.signcolumn = 'no'
|
|
|
|
-- Setup undo and backup directories
|
|
vim.opt.undofile = true
|
|
vim.opt.undodir = vim.fn.stdpath('config') .. '/undo'
|
|
vim.opt.backupdir = vim.fn.stdpath('config') .. '/backup'
|
|
|
|
-- Status line
|
|
vim.opt.statusline = '%<%F%h%m%r [%{&ff}] (%{strftime("%H:%M %d/%m/%Y",getftime(expand("%:p")))})%=%l,%c%V %P'
|
|
|
|
-- Wild ignore
|
|
vim.opt.wildignore:append('*.class,*.o,*\\tmp\\*,*.swp,*.zip,*.exe,*.obj,*.vcxproj,*.pdb,*.idb')
|
|
|
|
-- Mouse support
|
|
vim.opt.mouse = 'a'
|
|
|
|
-- Spelling
|
|
vim.opt.spell = true
|
|
|
|
-- ============================================================================
|
|
-- LSP Configuration
|
|
-- ============================================================================
|
|
local opts = { noremap = true, silent = true }
|
|
vim.keymap.set("n", "<F2>", vim.lsp.buf.rename, opts)
|
|
vim.keymap.set("n", "<F4>", vim.lsp.buf.code_action, opts)
|
|
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
|
|
vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
|
|
|
|
-- Diagnostic configuration
|
|
vim.diagnostic.config({
|
|
signs = false,
|
|
virtual_text = true,
|
|
})
|
|
|
|
-- Spelling highlight
|
|
vim.api.nvim_create_autocmd("LspAttach", {
|
|
callback = function()
|
|
vim.cmd("highlight SpellBad gui=underline guifg=#d3869b")
|
|
end,
|
|
})
|
|
|
|
-- ============================================================================
|
|
-- Vim Dispatch Configuration
|
|
-- ============================================================================
|
|
if vim.fn.has('win64') == 1 or vim.fn.has('win32') == 1 or vim.fn.has('win16') == 1 then
|
|
if os.getenv('SHELL') ~= nil then
|
|
vim.o.shellcmdflag = '-c'
|
|
vim.o.makeprg = "./build.sh"
|
|
else
|
|
vim.o.makeprg = "build.bat"
|
|
end
|
|
else
|
|
vim.o.makeprg = "./build.sh"
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Autocommands
|
|
-- ============================================================================
|
|
|
|
-- Automatically scroll to bottom of quickfix window when opened
|
|
vim.api.nvim_create_autocmd("FileType", {
|
|
pattern = "qf",
|
|
callback = function()
|
|
vim.cmd('normal! G')
|
|
end,
|
|
})
|
|
|
|
-- Per-Project Bindings - load project file on buffer enter
|
|
vim.api.nvim_create_autocmd("BufEnter", {
|
|
callback = function()
|
|
local project_file = vim.fn.getcwd() .. '/project_nvim.lua'
|
|
if vim.fn.filereadable(project_file) == 1 then
|
|
vim.cmd('luafile ' .. vim.fn.fnameescape(project_file))
|
|
end
|
|
end,
|
|
})
|
|
|
|
-- Formatting options
|
|
vim.api.nvim_create_augroup("persistent_settings", { clear = true })
|
|
vim.api.nvim_create_autocmd("BufEnter", {
|
|
group = "persistent_settings",
|
|
pattern = "*",
|
|
command = "set formatoptions=q1j",
|
|
})
|
|
|
|
-- ============================================================================
|
|
-- Functions
|
|
-- ============================================================================
|
|
local function raddbg_open_file()
|
|
local filepath = vim.fn.expand("%:p"):gsub('\\', '/')
|
|
vim.fn.system("dev raddbg --ipc open " .. filepath)
|
|
vim.fn.system("dev raddbg --ipc goto_line " .. vim.fn.line("."))
|
|
vim.fn.system("powershell -Command Add-Type -AssemblyName Microsoft.VisualBasic; [Microsoft.VisualBasic.Interaction]::AppActivate('The RAD Debugger')")
|
|
end
|
|
|
|
local function raddbg_start_debugging()
|
|
vim.fn.system("dev raddbg --ipc run")
|
|
end
|
|
|
|
local function raddbg_stop_debugging()
|
|
vim.fn.system("dev raddbg --ipc kill_all")
|
|
end
|
|
|
|
local function raddbg_run_to_cursor()
|
|
local filepath = vim.fn.expand("%:p"):gsub('\\', '/')
|
|
vim.fn.system("dev raddbg --ipc open " .. filepath)
|
|
vim.fn.system("dev raddbg --ipc goto_line " .. vim.fn.line("."))
|
|
vim.fn.system("dev raddbg --ipc run_to_cursor " .. filepath .. ":" .. vim.fn.line("."))
|
|
vim.fn.system("powershell -Command Add-Type -AssemblyName Microsoft.VisualBasic; [Microsoft.VisualBasic.Interaction]::AppActivate('The RAD Debugger')")
|
|
end
|
|
|
|
local function raddbg_add_breakpoint()
|
|
local filepath = vim.fn.expand("%:p"):gsub('\\', '/')
|
|
vim.fn.system("dev raddbg --ipc open " .. filepath)
|
|
vim.fn.system("dev raddbg --ipc goto_line " .. vim.fn.line("."))
|
|
vim.fn.system("dev raddbg --ipc toggle_breakpoint " .. filepath .. ":" .. vim.fn.line("."))
|
|
vim.fn.system("powershell -Command Add-Type -AssemblyName Microsoft.VisualBasic; [Microsoft.VisualBasic.Interaction]::AppActivate('The RAD Debugger')")
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Keymaps
|
|
-- ============================================================================
|
|
|
|
local function adjust_fontsize(amount)
|
|
-- Get current font and size
|
|
local current_font = vim.opt.guifont:get()[1] or "Consolas"
|
|
local current_size = tonumber(current_font:match(":h(%d+)")) or 12
|
|
|
|
-- Extract font name (everything before :h)
|
|
local font_name = current_font:match("^(.+):h%d+") or current_font
|
|
|
|
-- Calculate new size
|
|
local new_size = math.max(6, current_size + amount) -- Minimum size of 6
|
|
|
|
-- Apply new font setting
|
|
if vim.g.neovide then
|
|
vim.opt.guifont = font_name .. ":h" .. new_size
|
|
else
|
|
vim.cmd("GuiFont! " .. font_name .. ":h" .. new_size)
|
|
end
|
|
end
|
|
|
|
-- Numpad mappings
|
|
vim.keymap.set('n', '<C-=>', function() adjust_fontsize(1) end)
|
|
vim.keymap.set('n', '<C-->', function() adjust_fontsize(-1) end)
|
|
|
|
-- FZF Bindings
|
|
vim.keymap.set('n', '<leader>h', '<cmd>FzfLua oldfiles<cr>')
|
|
vim.keymap.set('n', '<leader>t', '<cmd>FzfLua lsp_live_workspace_symbols<cr>')
|
|
vim.keymap.set('n', '<leader>T', '<cmd>FzfLua lsp_finder<cr>')
|
|
vim.keymap.set('n', '<leader>b', '<cmd>FzfLua buffers<cr>')
|
|
vim.keymap.set('n', '<leader><leader>', '<cmd>FzfLua<cr>')
|
|
|
|
-- Window navigation
|
|
vim.keymap.set('n', '<C-h>', '<C-w>h', { silent = true })
|
|
vim.keymap.set('n', '<C-j>', '<C-w>j', { silent = true })
|
|
vim.keymap.set('n', '<C-k>', '<C-w>k', { silent = true })
|
|
vim.keymap.set('n', '<C-l>', '<C-w>l', { silent = true })
|
|
|
|
-- Move by wrapped lines
|
|
vim.keymap.set('n', 'j', 'gj')
|
|
vim.keymap.set('n', 'k', 'gk')
|
|
vim.keymap.set('n', 'gj', 'j')
|
|
vim.keymap.set('n', 'gk', 'k')
|
|
|
|
-- NERDTree
|
|
vim.keymap.set('n', '<C-n>', ':NERDTreeToggle<CR>')
|
|
|
|
-- Change to current buffer's directory
|
|
vim.keymap.set('n', 'cd', function()
|
|
vim.cmd('cd ' .. vim.fn.expand('%:p:h'))
|
|
end)
|
|
|
|
-- Buffer splitting
|
|
vim.keymap.set('n', '<leader>s', ':vs<CR>')
|
|
|
|
-- Quickfix navigation
|
|
vim.keymap.set('n', '<A-j>', ':cn<CR>')
|
|
vim.keymap.set('n', '<A-k>', ':cp<CR>')
|
|
|
|
-- Terminal escape
|
|
vim.keymap.set('t', '<Esc>', '<C-\\><C-n>')
|
|
|
|
-- Make (Vim Dispatch)
|
|
vim.keymap.set('n', '<C-b>', ':Make<CR>', { noremap = true })
|
|
|
|
-- Easy-Align
|
|
vim.keymap.set('x', '<leader>a', '<Plug>(LiveEasyAlign)')
|
|
|
|
-- RAD Debugger
|
|
vim.keymap.set('n', '<F6>', function() raddbg_open_file() end, { silent = true })
|
|
vim.keymap.set('n', '<F5>', function() raddbg_start_debugging() end, { silent = true })
|
|
vim.keymap.set('n', '<S-F5>', function() raddbg_stop_debugging() end, { silent = true })
|
|
vim.keymap.set('n', '<F9>', function() raddbg_add_breakpoint() end, { silent = true })
|
|
vim.keymap.set('n', '<C-F10>', function() raddbg_run_to_cursor() end, { silent = true })
|