feat/pack (#1)

Reviewed-on: #1
Co-authored-by: Tomas Mirchev <contact@tomastm.com>
Co-committed-by: Tomas Mirchev <contact@tomastm.com>
This commit was merged in pull request #1.
This commit is contained in:
2025-10-26 04:18:14 +00:00
committed by Tomas Mirchev
parent 2b1b3ebbf0
commit 3075a218b8
24 changed files with 735 additions and 513 deletions

109
lua/core/events.lua Normal file
View File

@@ -0,0 +1,109 @@
local api = vim.api
local au = api.nvim_create_autocmd
local group = api.nvim_create_augroup('core.events', { clear = true })
-- Automatically create a scratch buffer if Neovim starts with no files
au('VimEnter', {
group = group,
callback = function()
-- Only trigger if no file arguments are passed
if vim.fn.argc() == 0 then
vim.cmd('enew')
vim.bo.buftype = 'nofile'
vim.bo.bufhidden = 'wipe'
vim.bo.swapfile = false
end
end,
})
-- Highlight when yanking (copying) text
au('TextYankPost', {
group = group,
callback = function()
vim.highlight.on_yank({ timeout = 200 })
end,
})
-- Disable comment continuation only when using 'o'/'O', but keep it for <Enter>
au('FileType', {
group = group,
pattern = '*',
callback = function()
vim.opt_local.formatoptions:remove('o')
end,
})
-- Show cursor line only in active window
au({ 'WinEnter', 'InsertLeave' }, {
group = group,
callback = function()
if vim.w.auto_cursorline then
vim.wo.cursorline = true
vim.w.auto_cursorline = nil
end
end,
})
au({ 'WinLeave', 'InsertEnter' }, {
group = group,
callback = function()
-- Keep it on NvimTree to show current file
if vim.bo.filetype == 'NvimTree' then
return
end
if vim.wo.cursorline then
vim.w.auto_cursorline = true
vim.wo.cursorline = false
end
end,
})
-- Autocompletion
au('LspAttach', {
group = group,
callback = function(event)
local client = vim.lsp.get_client_by_id(event.data.client_id)
if not client then
return
end
-- Enable native completion
if client:supports_method('textDocument/completion') then
vim.lsp.completion.enable(true, client.id, event.buf, { autotrigger = true })
end
end,
})
vim.lsp.handlers['textDocument/completion'] = function(err, result, ctx, config)
if err or not result then
return
end
for _, item in ipairs(result.items or result) do
if item.kind then
local kind = vim.lsp.protocol.CompletionItemKind[item.kind] or ''
item.menu = '[' .. kind .. ']'
end
end
return vim.lsp.completion._on_completion_result(err, result, ctx, config)
end
au('InsertEnter', {
group = group,
once = true,
callback = function()
require('nvim-ts-autotag').setup()
require('nvim-autopairs').setup()
end,
})
require('modules.theme')
au('UIEnter', {
group = group,
once = true,
callback = function()
vim.schedule(function()
require('modules.navigation')
require('plugins.language-manager').setup()
require('modules.diagnostics')
end)
end,
})

88
lua/core/keymaps.lua Normal file
View File

@@ -0,0 +1,88 @@
-- Helper functions
local function map(mode, lhs, rhs)
vim.keymap.set(mode, lhs, rhs, { silent = true })
end
local function cmd(str)
return '<cmd>' .. str .. '<CR>'
end
-- QOL
map('i', 'jk', '<Esc>')
map('i', '<C-c>', '<Esc>')
map('n', '<Esc>', cmd('nohlsearch'))
map('n', 'q:', '<nop>')
vim.keymap.set('n', 'J', 'mzJ`z')
vim.keymap.set('n', 'n', 'nzzzv')
vim.keymap.set('n', 'N', 'Nzzzv')
vim.keymap.set('x', 'J', ":m '>+1<CR>gv=gv")
vim.keymap.set('x', 'K', ":m '<-2<CR>gv=gv")
vim.keymap.set('n', '<leader>s', [[:%s/\<<C-r><C-w>\>/<C-r><C-w>/g<Left><Left><Left>]])
-- Easy to use registers
map('x', '<leader>p', '"_dP')
map({ 'n', 'x' }, '<leader>y', '"+y')
map('n', '<leader>Y', '"+y$')
map({ 'n', 'x' }, '<leader>d', '"_d')
map({ 'n', 'x' }, 'x', '"_x')
-- Window navigation
map('n', '<C-h>', '<C-w>h')
map('n', '<C-l>', '<C-w>l')
map('n', '<C-j>', '<C-w>j')
map('n', '<C-k>', '<C-w>k')
-- Tab management
map('n', ']t', cmd('tabnext'))
map('n', '[t', cmd('tabprevious'))
map('n', '<leader>tt', cmd('tabnew'))
map('n', '<leader>tn', cmd('tabnew'))
map('n', '<leader>tc', cmd('tabclose'))
map('n', '<Leader>tl', cmd('tabmove +1'))
map('n', '<Leader>th', cmd('tabmove -1'))
for i = 1, 9 do
map('n', string.format('<Leader>t%d', i), string.format('%dgt', i))
end
-- Buffer management
map('n', ']b', cmd('bnext'))
map('n', '[b', cmd('bprevious'))
map('n', '<leader>bl', cmd('ls'))
map('n', '<leader>bd', cmd(':bp | bd #'))
map('n', '<leader>bo', cmd('%bd|e#')) -- close all except current
map('n', '<leader>bb', '<C-^>') -- toggle between buffers
-- Terminal
map('n', '<leader>xx', cmd('TermDefault'))
map('n', '<leader>xr', cmd('TermRelative'))
map('n', '<leader>xs', cmd('TermSplit'))
map('n', '<leader>xv', cmd('TermVSplit'))
map('t', '<Esc>', '<C-\\><C-n>')
map('t', '<C-w>h', [[<C-\><C-n><C-w>h]])
map('t', '<C-w>j', [[<C-\><C-n><C-w>j]])
map('t', '<C-w>k', [[<C-\><C-n><C-w>k]])
map('t', '<C-w>l', [[<C-\><C-n><C-w>l]])
map('t', '<C-w>c', [[<C-\><C-n><cmd>bd!<CR>]])
map('t', '<C-w><C-w>', [[<C-\><C-n><C-w>w]])
-- File explorer
map('n', '<leader>e', cmd('NvimTreeToggle'))
map('n', '<leader>E', cmd('NvimTreeOpen'))
-- Diagnostics
map('n', ']d', function()
vim.diagnostic.jump({ count = 1, float = true })
end)
map('n', '[d', function()
vim.diagnostic.jump({ count = -1, float = true })
end)
map('n', '<leader>q', vim.diagnostic.setloclist)
map('n', '<leader>d', vim.diagnostic.open_float)
map('n', 'K', vim.lsp.buf.hover)
map('n', 'gd', vim.lsp.buf.definition)
map('n', 'gr', vim.lsp.buf.references)
map('n', '<C-s>', vim.lsp.buf.signature_help)

108
lua/core/options.lua Normal file
View File

@@ -0,0 +1,108 @@
-- Map Leader
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
-- Disable built-in plugins
vim.loader.enable()
vim.g.loaded_gzip = 1
vim.g.loaded_tar = 1
vim.g.loaded_tarPlugin = 1
vim.g.loaded_zip = 1
vim.g.loaded_zipPlugin = 1
vim.g.loaded_getscript = 1
vim.g.loaded_getscriptPlugin = 1
vim.g.loaded_vimball = 1
vim.g.loaded_vimballPlugin = 1
vim.g.loaded_matchit = 1
vim.g.loaded_2html_plugin = 1
vim.g.loaded_rrhelper = 1
vim.g.loaded_tutor_mode_plugin = 1
vim.g.loaded_spellfile_plugin = 1
vim.g.loaded_logipat = 1
vim.g.loaded_rplugin = 1
vim.g.loaded_netrw = 1 -- use nvim-tree instead
vim.g.loaded_netrwPlugin = 1
-- UI
vim.g.have_nerd_font = true
vim.opt.termguicolors = false
vim.opt.textwidth = 100
vim.opt.colorcolumn = '+0'
vim.opt.signcolumn = 'no'
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.cursorline = true
vim.opt.ruler = false
vim.opt.winborder = 'rounded'
vim.opt.guicursor = 'n-v-i-c:block'
vim.opt.laststatus = 3
vim.opt.statusline = '── %f %h%w%m%r %= [%l,%c-%L] ──'
vim.opt.fillchars = {
stl = '',
stlnc = '',
horiz = '',
horizdown = '',
horizup = '',
vert = '',
vertleft = '',
vertright = '',
verthoriz = '',
}
-- Wrap
vim.opt.wrap = false
vim.opt.linebreak = true
vim.opt.breakindent = true
-- Indent
vim.opt.shiftwidth = 2 -- Number of spaces to use for (auto)indent
vim.opt.tabstop = 2 -- Number of spaces that a <Tab> in file counts for
vim.opt.softtabstop = 2 -- Number of spaces when pressing <Tab> in insert mode
vim.opt.expandtab = true -- Use spaces instead of literal tab characters
vim.opt.autoindent = true -- Copy indent from the current line when starting a new one
vim.opt.smartindent = true -- Automatically inserts indents in code blocks (for C-like languages)
-- Scroll and mouse
vim.opt.scrolloff = 10
vim.opt.sidescrolloff = 5
vim.opt.mousescroll = 'hor:1,ver:5'
vim.opt.mouse = 'a' -- Enable mouse support
-- Search
vim.opt.ignorecase = true
vim.opt.smartcase = true -- Override ignorecase if search contains upper case chars
vim.opt.inccommand = 'split' -- Live substitution preview
vim.opt.completeopt = { 'fuzzy', 'menuone', 'popup', 'noselect' }
-- Splits
vim.opt.splitright = true
vim.opt.splitbelow = true
-- Persistence
vim.opt.undofile = true
vim.opt.swapfile = false
-- Tweaks
vim.opt.updatetime = 50
vim.opt.timeout = true
vim.opt.ttimeout = true
vim.opt.timeoutlen = 500
vim.opt.ttimeoutlen = 10
-- Clipboard
if vim.env.CONTAINER then
vim.g.clipboard = {
name = 'osc52',
copy = {
['+'] = require('vim.ui.clipboard.osc52').copy('+'),
['*'] = require('vim.ui.clipboard.osc52').copy('*'),
},
paste = {
['+'] = require('vim.ui.clipboard.osc52').paste('+'),
['*'] = require('vim.ui.clipboard.osc52').paste('*'),
},
}
end