" =============================================================================
" ~/.vim/vimrc
" Vim config — no plugins, ported from Neovim config.
" Symlink: ln -sf ~/.local/share/Panama/config/dot/vim/vimrc ~/.vim/vimrc
" =============================================================================


" =============================================================================
" GENERAL / COMPATIBILITY
" =============================================================================

" Disable Vi compatibility. Must be first.
set nocompatible

" Enable filetype detection, plugins, and indent files.
filetype plugin indent on

" Enable syntax highlighting.
syntax enable


" =============================================================================
" LEADER KEY
" =============================================================================

" Must be set before any <leader> mappings.
let mapleader = ' '
let maplocalleader = '\'


" =============================================================================
" LINE NUMBERS
" =============================================================================

set number          " Absolute line number on current line
set relativenumber  " Relative line numbers on all other lines


" =============================================================================
" INDENTATION
" =============================================================================

set tabstop=2       " A <Tab> displays as 2 columns
set softtabstop=2   " <Tab> in insert mode inserts 2 spaces
set shiftwidth=2    " >> and << shift by 2 spaces
set expandtab       " Use spaces instead of tab characters
set smartindent     " Auto-indent new lines based on context


" =============================================================================
" SWAP / UNDO
" =============================================================================

set noswapfile

" Persistent undo — ~/.vim/undodir must exist (it already does on this machine).
set undodir=~/.vim/undodir
set undofile


" =============================================================================
" SEARCH
" =============================================================================

set hlsearch    " Highlight all matches
set incsearch   " Show matches as you type
set ignorecase  " Case-insensitive by default...
set smartcase   " ...unless the query has uppercase


" =============================================================================
" APPEARANCE
" =============================================================================

" 24-bit color — requires a true-color terminal (kitty, ghostty, etc.).
set termguicolors

" Keep 4 lines visible above/below cursor when scrolling.
set scrolloff=4

" Always show the sign column to prevent layout shifts.
set signcolumn=yes

" Reduce delay before CursorHold fires.
set updatetime=50

" Show invisible characters: trailing spaces and non-breaking spaces as ⋅,
" tabs as two spaces so they are visible but not distracting.
set list
set listchars=trail:⋅,nbsp:⋅,tab:\ \

" Always show statusline even with a single window.
set laststatus=2

" habamax is a good built-in dark theme in Vim 9+; fall back to slate.
if v:version >= 900
  colorscheme habamax
else
  colorscheme slate
endif

" Transparent statusline background (mirrors the Neovim setup).
highlight StatusLine   guibg=NONE ctermbg=NONE
highlight StatusLineNC guibg=NONE ctermbg=NONE


" =============================================================================
" STATUS LINE
" =============================================================================
" Mirrors lualine layout: mode | filepath [+][RO]  ... filetype | enc | line:col | %

set statusline=
set statusline+=\ %{toupper(mode())}
set statusline+=\ \|\ %f\ %m%r
set statusline+=%=
set statusline+=%y\ \|\ %{&fileencoding?&fileencoding:&encoding}
set statusline+=\ \|\ %l:%c\ \|\ %p%%\


" =============================================================================
" MISCELLANEOUS
" =============================================================================

set ttyfast                      " Assume a fast terminal connection
set backspace=indent,eol,start   " Backspace over everything in insert mode
set nowrap                       " Don't wrap long lines
set showcmd                      " Show partial commands in last line
set showmatch                    " Briefly jump to matching bracket on insert


" =============================================================================
" KEYMAPS — WINDOW NAVIGATION
" =============================================================================

nnoremap <leader>h <C-w>h
nnoremap <leader>j <C-w>j
nnoremap <leader>k <C-w>k
nnoremap <leader>l <C-w>l
vnoremap <leader>h <C-w>h
vnoremap <leader>j <C-w>j
vnoremap <leader>k <C-w>k
vnoremap <leader>l <C-w>l


" =============================================================================
" KEYMAPS — FILE OPERATIONS
" =============================================================================

nnoremap <leader>w :write<CR>
nnoremap <leader>q :quit<CR>

" Source the vimrc (mirrors <leader><leader>s in Neovim).
nnoremap <leader><leader>s :update<CR>:source $MYVIMRC<CR>

" Make the current file executable.
nnoremap <silent> <leader><leader>x :!chmod +x %<CR>


" =============================================================================
" KEYMAPS — LINE MANIPULATION
" =============================================================================

" Move selected lines down / up in visual mode.
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv

" Join lines in normal mode while keeping the cursor position fixed.
nnoremap J mzJ`z


" =============================================================================
" KEYMAPS — SCROLL AND SEARCH WITH RECENTERING
" =============================================================================

nnoremap <C-d> <C-d>zz
nnoremap <C-u> <C-u>zz

" Next / previous search result: center view and open any fold.
nnoremap n nzzzv
nnoremap N Nzzzv


" =============================================================================
" KEYMAPS — CLIPBOARD (SYSTEM)
" =============================================================================
" Requires Vim compiled with +clipboard.
" On Fedora, install vim-X11 if needed: sudo dnf install vim-X11
" Verify with :version — look for +clipboard.

nnoremap <leader>p "+p
nnoremap <leader>P "+P
vnoremap <leader>p "+p
vnoremap <leader>P "+P

nnoremap <leader>y  "+y
vnoremap <leader>y  "+y
nnoremap <leader>yy "+yy

" Yank entire buffer to system clipboard.
nnoremap <leader>YY :%y+<CR>

" Visual: replace selection from clipboard without clobbering the clipboard.
xnoremap <leader>v "_dP


" =============================================================================
" KEYMAPS — VOID-REGISTER DELETE
" =============================================================================
" Delete without touching the unnamed register, preserving the last yank.

nnoremap <leader>d  "_d
vnoremap <leader>d  "_d
nnoremap <leader>dd "_dd


" =============================================================================
" KEYMAPS — SEARCH AND REPLACE
" =============================================================================

" Replace the word under the cursor across the whole file.
" Cursor is placed inside the replacement text for immediate editing.
nnoremap <leader>sr :%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>


" =============================================================================
" KEYMAPS — DISABLED KEYS
" =============================================================================

nnoremap Q <nop>


" =============================================================================
" KEYMAPS — COMMENT TOGGLE (<leader>c)
" =============================================================================
" Toggles `// ` comments on the current line (normal) or each line in a
" visual selection. Not filetype-aware — works for C, C++, JS, TS, Go, Rust.
" For language-aware comments a plugin like vim-commentary would be needed.

function! ToggleComment() range
  let l:first_line = getline(a:firstline)
  if l:first_line =~ '^\s*\/\/ '
    execute a:firstline . ',' . a:lastline . 's/^\(\s*\)\/\/ /\1/'
  else
    execute a:firstline . ',' . a:lastline . 's/^\(\s*\)/\1\/\/ /'
  endif
endfunction

nnoremap <silent> <leader>c :call ToggleComment()<CR>
vnoremap <silent> <leader>c :call ToggleComment()<CR>


" =============================================================================
" AUTOCOMMANDS
" =============================================================================

augroup VimRCGroup
  autocmd!

  " Strip trailing whitespace on every save.
  autocmd BufWritePre * :%s/\s\+$//e

  " Auto-source this vimrc whenever it is saved.
  autocmd BufWritePost vimrc source $MYVIMRC

augroup END


" =============================================================================
" HIGHLIGHT YANK
" =============================================================================
" Briefly highlights yanked text using IncSearch colors, then clears it.
" Implements Neovim's vim.highlight.on_yank() using matchadd + timer_start.
" Requires Vim 8.0.1422+ (for v:event) and Vim 8.0+ (for timer_start).

augroup HighlightYank
  autocmd!
  autocmd TextYankPost * call s:HighlightYank()
augroup END

function! s:HighlightYank()
  if v:event.operator !=# 'y'
    return
  endif
  let l:match_id = matchadd('IncSearch',
    \ '\%' . line("'[") . 'l\%' . col("'[") . 'c\_.*' .
    \ '\%' . line("']") . 'l\%' . col("']") . 'c')
  call timer_start(150, {-> s:ClearYankHighlight(l:match_id)})
endfunction

function! s:ClearYankHighlight(match_id)
  silent! call matchdelete(a:match_id)
endfunction
