kickstart.nvim/init.lua

531 lines
19 KiB
Lua

--[[
=====================================================================
==================== READ THIS BEFORE CONTINUING ====================
=====================================================================
======== .-----. ========
======== .----------------------. | === | ========
======== |.-""""""""""""""""""-.| |-----| ========
======== || || | === | ========
======== || KICKSTART.NVIM || |-----| ========
======== || || | === | ========
======== || || |-----| ========
======== ||:Tutor || |:::::| ========
======== |'-..................-'| |____o| ========
======== `"")----------------(""` ___________ ========
======== /::::::::::| |::::::::::\ \ no mouse \ ========
======== /:::========| |==hjkl==:::\ \ required \ ========
======== '""""""""""""' '""""""""""""' '""""""""""' ========
======== ========
=====================================================================
=====================================================================
-- [[ Setting options ]]
-- See `:help vim.o`
-- Set to true if you have a Nerd Font installed and selected in the terminal
vim.g.have_nerd_font = true
-- Key mappings
vim.g.mapleader = ' ' -- Set leader key to space
vim.g.maplocalleader = ' ' -- Set local leader key (NEW)
-- Make background transparent
vim.api.nvim_set_hl(0, 'Normal', { bg = 'none' })
vim.api.nvim_set_hl(0, 'NormalNC', { bg = 'none' })
vim.api.nvim_set_hl(0, 'EndOfBuffer', { bg = 'none' })
vim.api.nvim_set_hl(0, 'SignColumn', { bg = 'none' }) -- Make sign column transparent
vim.opt.number = true -- Line numbers
-- Basic settings
vim.opt.relativenumber = true -- Relative line numbers
vim.opt.cursorline = true -- Highlight current line
vim.opt.wrap = false -- Don't wrap lines
vim.opt.scrolloff = 10 -- Keep 10 lines above/below cursor
vim.opt.sidescrolloff = 8 -- Keep 8 columns left/right of cursor
-- Indentation
vim.opt.tabstop = 2 -- Tab width
vim.opt.shiftwidth = 2 -- Indent width
vim.opt.softtabstop = 2 -- Soft tab stop
vim.opt.expandtab = true -- Use spaces instead of tabs
vim.opt.smartindent = true -- Smart auto-indenting
vim.opt.autoindent = true -- Copy indent from current line
vim.o.breakindent = true
-- Search settings
vim.opt.ignorecase = true -- Case insensitive search
vim.opt.smartcase = true -- Case sensitive if uppercase in search
vim.opt.hlsearch = false -- Don't highlight search results
vim.opt.incsearch = true -- Show matches as you type
-- Visual settings
vim.opt.termguicolors = true -- Enable 24-bit colors
vim.opt.signcolumn = 'yes' -- Always show sign column
vim.opt.showmatch = true -- Highlight matching brackets
vim.opt.matchtime = 2 -- How long to show matching bracket
vim.opt.cmdheight = 1 -- Command line height
vim.opt.completeopt = 'menuone,noinsert,noselect' -- Completion options
vim.opt.showmode = false -- Don't show mode in command line
vim.opt.pumheight = 10 -- Popup menu height
vim.opt.pumblend = 10 -- Popup menu transparency
vim.opt.winblend = 0 -- Floating window transparency
vim.opt.concealcursor = '' -- Don't hide cursor line markup
vim.opt.conceallevel = 0 -- Don't hide markup
-- vim.opt.lazyredraw = true -- Don't redraw during macros
vim.opt.synmaxcol = 300 -- Syntax highlighting limit
vim.o.winborder = 'rounded' -- Make floating windows have a rounded border
vim.o.list = true
vim.opt.listchars = { tab = ' ', trail = '·', nbsp = '' } -- Sets how whitespace chars will be displayed
-- Folding settings
vim.opt.foldmethod = 'expr' -- Use expression for folding
-- vim.wo.vim.foldexpr = 'v:lua.vim.treesitter.foldexpr()' -- Use treesitter for folding
vim.opt.foldlevel = 99 -- Start with all folds open
-- File handling
vim.opt.backup = false -- Don't create backup files
vim.opt.writebackup = false -- Don't create backup before writing
vim.opt.swapfile = false -- Don't create swap files
vim.opt.undofile = true -- Persistent undo
vim.o.undofile = true -- Save undo history
vim.opt.undodir = vim.fn.expand '~/.vim/undodir' -- Undo directory
vim.opt.updatetime = 250 -- Faster completion
vim.opt.timeoutlen = 500 -- Key timeout duration
vim.opt.ttimeoutlen = 0 -- Key code timeout
vim.opt.autoread = true -- Auto reload files changed outside vim
vim.opt.autowrite = false -- Don't auto save
-- Behavior settings
vim.opt.hidden = true -- Allow hidden buffers
vim.opt.errorbells = false -- No error bells
vim.opt.backspace = 'indent,eol,start' -- Better backspace behavior
vim.opt.autochdir = false -- Don't auto change directory
vim.opt.iskeyword:append '-' -- Treat dash as part of word
vim.opt.path:append '**' -- include subdirectories in search
vim.opt.selection = 'exclusive' -- Selection behavior
vim.opt.mouse = 'a' -- Enable mouse support
vim.opt.clipboard:append 'unnamedplus' -- Use system clipboard
vim.opt.modifiable = true -- Allow buffer modifications
vim.opt.encoding = 'UTF-8' -- Set encoding
vim.opt.splitbelow = true -- Horizontal splits go below
vim.opt.splitright = true -- Vertical splits go right
vim.o.inccommand = 'split'
vim.o.confirm = true -- Ask before closing (unsaved changes)
-- 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)
-- [[ Basic Keymaps ]]
vim.keymap.set('n', '<leader>Ss', '<cmd>SessionSave<CR>', { desc = 'Save session' })
vim.keymap.set('n', '<leader>Sl', '<cmd>SessionLoad<CR>', { desc = 'Load session' })
vim.keymap.set('n', '<C-s>', '<cmd>w<CR>', { desc = 'Save file' })
-- Clear highlights on search when pressing <Esc> in normal mode
vim.keymap.set('n', '<C-c>', '<cmd>nohlsearch<CR>', { desc = 'Clear search highlights' })
vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>', { desc = 'Clear search highlights' })
-- Diagnostic keymaps
-- vim.keymap.set('n', '<leader>dq', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' })
-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier
-- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping
-- or just use <C-\><C-n> to exit terminal mode
vim.keymap.set('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Exit terminal mode' })
-- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows
--
-- See `:help wincmd` for a list of all window commands
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' })
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' })
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' })
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move focus to the upper window' })
-- Splitting & Resizing
vim.keymap.set('n', '<leader>w|', '<cmd>vsplit<CR>', { desc = 'Split window vertically' })
vim.keymap.set('n', '<leader>w-', '<cmd>split<CR>', { desc = 'Split window horizontally' })
vim.keymap.set('n', '<C-A-k>', '<cmd>resize +2<CR>', { desc = 'Increase window height' })
vim.keymap.set('n', '<C-A-j>', '<cmd>resize -2<CR>', { desc = 'Decrease window height' })
vim.keymap.set('n', '<C-A-h>', '<cmd>vertical resize +2<CR>', { desc = 'Increase window width' })
vim.keymap.set('n', '<C-A-l>', '<cmd>vertical resize -2<CR>', { desc = 'Decrease window width' })
-- Ctrl-Shift-letter doesnt work with my setup -> Fixed by using xxd and using litteral input str
vim.keymap.set('n', '^[[1;9h', '<C-w>H', { desc = 'Move window to the left' })
vim.keymap.set('n', '^[[1;9l', '<C-w>L', { desc = 'Move window to the right' })
vim.keymap.set('n', '^[[1;9j', '<C-w>J', { desc = 'Move window to the lower' })
vim.keymap.set('n', '^[[1;9k', '<C-w>K', { desc = 'Move window to the upper' })
-- [[ Basic Autocommands ]]
-- See `:help lua-guide-autocommands`
-- Center screen when jumping
vim.keymap.set('n', 'n', 'nzzzv', { desc = 'Next search result (centered)' })
vim.keymap.set('n', 'N', 'Nzzzv', { desc = 'Previous search result (centered)' })
vim.keymap.set('n', '<C-d>', '<C-d>zz', { desc = 'Half page down (centered)' })
vim.keymap.set('n', '<C-u>', '<C-u>zz', { desc = 'Half page up (centered)' })
-- Delete without yanking
vim.keymap.set({ 'n', 'v' }, 'D', '"_d', { desc = 'Delete without yanking' })
-- Paste without yanking
vim.keymap.set('x', 'p', [["_dP]], { desc = 'Paste without yanking' })
-- Buffer navigation
vim.keymap.set('n', '<leader>bn', '<cmd>bnext<CR>', { desc = 'Next buffer' })
vim.keymap.set('n', '<leader>bp', '<cmd>bprevious<CR>', { desc = 'Previous buffer' })
-- Move lines up/down
vim.keymap.set('n', '<A-j>', '<cmd>m .+1<CR>==', { desc = 'Move line down' })
vim.keymap.set('n', '<A-k>', '<cmd>m .-2<CR>==', { desc = 'Move line up' })
vim.keymap.set('v', '<A-j>', "<cmd>m '>+1<CR>gv=gv", { desc = 'Move selection down' })
vim.keymap.set('v', '<A-k>', "<cmd>m '<-2<CR>gv=gv", { desc = 'Move selection up' })
-- Better indenting in visual mode
vim.keymap.set('v', '<', '<gv', { desc = 'Indent left and reselect' })
vim.keymap.set('v', '>', '>gv', { desc = 'Indent right and reselect' })
-- Better J behavior
vim.keymap.set('n', 'J', 'mzJ`z', { desc = 'Join lines and keep cursor position' })
-- ============================================================================
-- USEFUL FUNCTIONS
-- ============================================================================
-- Copy Full File-Path
vim.keymap.set('n', '<leader>yp', function()
local path = vim.fn.expand '%:p'
vim.fn.setreg('+', path)
print('file:', path)
end)
-- Basic autocommands
local augroup = vim.api.nvim_create_augroup('UserConfig', {})
-- Highlight yanked text
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,
})
-- Return to last edit position when opening files
vim.api.nvim_create_autocmd('BufReadPost', {
group = augroup,
callback = function()
local mark = vim.api.nvim_buf_get_mark(0, '"')
local lcount = vim.api.nvim_buf_line_count(0)
if mark[1] > 0 and mark[1] <= lcount then
pcall(vim.api.nvim_win_set_cursor, 0, mark)
end
end,
})
-- Set filetype-specific settings
vim.api.nvim_create_autocmd('FileType', {
group = augroup,
pattern = { 'lua', 'python' },
callback = function()
vim.opt_local.tabstop = 4
vim.opt_local.shiftwidth = 4
end,
})
vim.api.nvim_create_autocmd('FileType', {
group = augroup,
pattern = { 'javascript', 'typescript', 'javascriptreact', 'typescriptreact', 'json', 'html', 'css', 'go' },
callback = function()
vim.opt_local.tabstop = 2
vim.opt_local.shiftwidth = 2
end,
})
-- Auto-close terminal when process exits
vim.api.nvim_create_autocmd('TermClose', {
group = augroup,
callback = function()
if vim.v.event.status == 0 then
vim.api.nvim_buf_delete(0, {})
end
end,
})
-- Disable line numbers in terminal
vim.api.nvim_create_autocmd('TermOpen', {
group = augroup,
callback = function()
vim.opt_local.number = false
vim.opt_local.relativenumber = false
vim.opt_local.signcolumn = 'no'
end,
})
-- Auto-resize splits when window is resized
vim.api.nvim_create_autocmd('VimResized', {
group = augroup,
callback = function()
vim.cmd 'tabdo wincmd ='
end,
})
-- Create directories when saving files
vim.api.nvim_create_autocmd('BufWritePre', {
callback = function()
local filepath = vim.fn.expand '<afile>:p:h'
if filepath:match '^oil://' or vim.uv.fs_realpath(filepath) == nil then
return
end
if vim.fn.isdirectory(filepath) == 0 then
vim.fn.mkdir(filepath, 'p')
end
end,
})
-- Command-line completion
vim.opt.wildmenu = true
vim.opt.wildmode = 'longest:full,full'
vim.opt.wildignore:append { '*.o', '*.obj', '*.pyc', '*.class', '*.jar' }
-- Better diff options
vim.opt.diffopt:append 'linematch:60'
-- Performance improvements
vim.opt.redrawtime = 10000
vim.opt.maxmempattern = 20000
-- Create undo directory if it doesn't exist
local undodir = vim.fn.expand '~/.vim/undodir'
if vim.fn.isdirectory(undodir) == 0 then
vim.fn.mkdir(undodir, 'p')
end
-- ============================================================================
-- FLOATING TERMINAL
-- ============================================================================
-- terminal
local terminal_state = {
buf = nil,
win = nil,
is_open = false,
}
local function FloatingTerminal()
-- If terminal is already open, close it (toggle behavior)
if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then
vim.api.nvim_win_close(terminal_state.win, false)
terminal_state.is_open = false
return
end
-- Create buffer if it doesn't exist or is invalid
if not terminal_state.buf or not vim.api.nvim_buf_is_valid(terminal_state.buf) then
terminal_state.buf = vim.api.nvim_create_buf(false, true)
-- Set buffer options for better terminal experience
vim.api.nvim_buf_set_option(terminal_state.buf, 'bufhidden', 'hide')
end
-- Calculate window dimensions
local width = math.floor(vim.o.columns * 0.8)
local height = math.floor(vim.o.lines * 0.8)
local row = math.floor((vim.o.lines - height) / 2)
local col = math.floor((vim.o.columns - width) / 2)
-- Create the floating window
terminal_state.win = vim.api.nvim_open_win(terminal_state.buf, true, {
relative = 'editor',
width = width,
height = height,
row = row,
col = col,
style = 'minimal',
border = 'rounded',
})
-- Set transparency for the floating window
vim.api.nvim_win_set_option(terminal_state.win, 'winblend', 0)
-- Set transparent background for the window
vim.api.nvim_win_set_option(terminal_state.win, 'winhighlight', 'Normal:FloatingTermNormal,FloatBorder:FloatingTermBorder')
-- Define highlight groups for transparency
vim.api.nvim_set_hl(0, 'FloatingTermNormal', { bg = 'none' })
vim.api.nvim_set_hl(0, 'FloatingTermBorder', { bg = 'none' })
-- Start terminal if not already running
local has_terminal = false
local lines = vim.api.nvim_buf_get_lines(terminal_state.buf, 0, -1, false)
for _, line in ipairs(lines) do
if line ~= '' then
has_terminal = true
break
end
end
if not has_terminal then
vim.fn.termopen(os.getenv 'SHELL')
end
terminal_state.is_open = true
vim.cmd 'startinsert'
-- Set up auto-close on buffer leave
vim.api.nvim_create_autocmd('BufLeave', {
buffer = terminal_state.buf,
callback = function()
if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then
vim.api.nvim_win_close(terminal_state.win, false)
terminal_state.is_open = false
end
end,
once = true,
})
end
-- Function to explicitly close the terminal
local function CloseFloatingTerminal()
if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then
vim.api.nvim_win_close(terminal_state.win, false)
terminal_state.is_open = false
end
end
-- Key mappings
vim.keymap.set('n', '<leader>tft', FloatingTerminal, { noremap = true, silent = true, desc = 'Toggle floating terminal' })
vim.keymap.set('n', '<leader>tt', '<cmd>horizontal terminal<CR>', { noremap = true, silent = true, desc = 'Toggle terminal' })
vim.keymap.set('t', '<Esc>', function()
if terminal_state.is_open then
vim.api.nvim_win_close(terminal_state.win, false)
terminal_state.is_open = false
end
end, { noremap = true, silent = true, desc = 'Close floating terminal from terminal mode' })
-- ============================================================================
-- TABS
-- ============================================================================
-- Tab display settings
vim.opt.showtabline = 1 -- Always show tabline (0=never, 1=when multiple tabs, 2=always)
vim.opt.tabline = '' -- Use default tabline (empty string uses built-in)
-- Transparent tabline appearance
vim.cmd [[
hi TabLineFill guibg=NONE ctermfg=242 ctermbg=NONE
]]
-- Alternative navigation (more intuitive)
vim.keymap.set('n', '<leader>tn', '<cmd>tabnew<CR>', { desc = 'New tab' })
vim.keymap.set('n', '<leader>tx', '<cmd>tabclose<CR>', { desc = 'Close tab' })
-- Tab moving
vim.keymap.set('n', '<leader>tm', '<cmd>tabmove<CR>', { desc = 'Move tab' })
vim.keymap.set('n', '<leader>t>', '<cmd>tabmove +1<CR>', { desc = 'Move tab right' })
vim.keymap.set('n', '<leader>t<', '<cmd>tabmove -1<CR>', { desc = 'Move tab left' })
-- Function to open file in new tab
local function open_file_in_tab()
vim.ui.input({ prompt = 'File to open in new tab: ', completion = 'file' }, function(input)
if input and input ~= '' then
vim.cmd('tabnew ' .. input)
end
end)
end
-- Function to duplicate current tab
local function duplicate_tab()
local current_file = vim.fn.expand '%:p'
if current_file ~= '' then
vim.cmd('tabnew ' .. current_file)
else
vim.cmd 'tabnew'
end
end
-- Function to close tabs to the right
local function close_tabs_right()
local current_tab = vim.fn.tabpagenr()
local last_tab = vim.fn.tabpagenr '$'
for i = last_tab, current_tab + 1, -1 do
vim.cmd(i .. 'tabclose')
end
end
-- Function to close tabs to the left
local function close_tabs_left()
local current_tab = vim.fn.tabpagenr()
for i = current_tab - 1, 1, -1 do
vim.cmd '1tabclose'
end
end
-- Enhanced keybindings
vim.keymap.set('n', '<leader>tO', open_file_in_tab, { desc = 'Open file in new tab' })
vim.keymap.set('n', '<leader>td', duplicate_tab, { desc = 'Duplicate current tab' })
vim.keymap.set('n', '<leader>tr', close_tabs_right, { desc = 'Close tabs to the right' })
vim.keymap.set('n', '<leader>tL', close_tabs_left, { desc = 'Close tabs to the left' })
vim.keymap.set('n', '<leader>x', '<cmd>q<CR>', { desc = 'Smart close buffer/tab' })
-- [[ 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 ]]
require('lazy').setup({
{ import = 'kickstart.plugins' },
{ import = 'kickstart.plugins.lsp' },
{ import = 'custom.plugins' },
--
-- In normal mode type `<space>sh` then write `lazy.nvim-plugin`
-- you can continue same window with `<space>sr` which resumes last telescope search
}, {
ui = {
-- If you are using a Nerd Font: set icons to an empty table which will use the
-- default lazy.nvim defined Nerd Font icons, otherwise define a unicode icons table
icons = vim.g.have_nerd_font and {} or {
cmd = '',
config = '🛠',
event = '📅',
ft = '📂',
init = '',
keys = '🗝',
plugin = '🔌',
runtime = '💻',
require = '🌙',
source = '📄',
start = '🚀',
task = '📌',
lazy = '💤 ',
},
},
})
-- The line beneath this is called `modeline`. See `:help modeline`
-- vim: ts=2 sts=2 sw=2 et