diff --git a/.gitignore b/.gitignore index b6a61f0..4639fe0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ autoload plugged .netrwhist +bin diff --git a/colors/anticuus.vim b/colors/anticuus.vim index 81c555c..0652d44 100644 --- a/colors/anticuus.vim +++ b/colors/anticuus.vim @@ -1,6 +1,5 @@ " anticuus.vim -" Pitch-black minimalist theme — port of nvim anticuus + custom syntax extensions. -" Requires `set termguicolors`. +" Pitch-black minimalist theme with 256-color terminal fallbacks. hi clear if exists('syntax_on') @@ -10,133 +9,156 @@ endif let g:colors_name = 'anticuus' set background=dark +function! s:hi(group, guifg, guibg, ctermfg, ctermbg, gui, cterm) + let l:cmd = 'highlight ' . a:group + if a:guifg !=# '' + let l:cmd .= ' guifg=' . a:guifg + endif + if a:guibg !=# '' + let l:cmd .= ' guibg=' . a:guibg + endif + if a:ctermfg !=# '' + let l:cmd .= ' ctermfg=' . a:ctermfg + endif + if a:ctermbg !=# '' + let l:cmd .= ' ctermbg=' . a:ctermbg + endif + if a:gui !=# '' + let l:cmd .= ' gui=' . a:gui + endif + if a:cterm !=# '' + let l:cmd .= ' cterm=' . a:cterm + endif + execute l:cmd +endfunction + " === Base === -highlight Normal guifg=#dadada guibg=#000000 -highlight NormalNC guifg=#dadada guibg=#000000 -highlight NonText guifg=#3a3a3a guibg=NONE -highlight EndOfBuffer guifg=#000000 guibg=NONE -highlight Whitespace guifg=#3a3a3a -highlight SpecialKey guifg=#3a3a3a +call s:hi('Normal', '#dadada', '#000000', '253', '16', '', '') +call s:hi('NormalNC', '#dadada', '#000000', '253', '16', '', '') +call s:hi('NonText', '#3a3a3a', 'NONE', '237', 'NONE', '', '') +call s:hi('EndOfBuffer', '#000000', 'NONE', '16', 'NONE', '', '') +call s:hi('Whitespace', '#3a3a3a', '', '237', '', '', '') +call s:hi('SpecialKey', '#3a3a3a', '', '237', '', '', '') " === Syntax: comments dim italic, strings green === -highlight Comment guifg=#5a5a5a gui=italic cterm=italic -highlight SpecialComment guifg=#5a5a5a gui=italic cterm=italic -highlight String guifg=#00b300 -highlight Character guifg=#5a5a5a gui=italic cterm=italic +call s:hi('Comment', '#5a5a5a', '', '240', '', 'italic', 'italic') +call s:hi('SpecialComment', '#5a5a5a', '', '240', '', 'italic', 'italic') +call s:hi('String', '#00b300', '', '34', '', '', '') +call s:hi('Character', '#5a5a5a', '', '240', '', 'italic', 'italic') " === Literals: purple === -highlight Number guifg=#c490d0 -highlight Float guifg=#c490d0 -highlight Boolean guifg=#c490d0 -highlight Constant guifg=#c490d0 +call s:hi('Number', '#c490d0', '', '176', '', '', '') +call s:hi('Float', '#c490d0', '', '176', '', '', '') +call s:hi('Boolean', '#c490d0', '', '176', '', '', '') +call s:hi('Constant', '#c490d0', '', '176', '', '', '') " === Identifiers / functions: white baseline, functions teal === -highlight Identifier guifg=#dadada -highlight Function guifg=#88ddcc +call s:hi('Identifier', '#dadada', '', '253', '', '', '') +call s:hi('Function', '#88ddcc', '', '116', '', '', '') " === Statements: yellow keywords, red exception/return === -highlight Statement guifg=#ffcc00 -highlight Conditional guifg=#ffcc00 -highlight Repeat guifg=#dadada -highlight Keyword guifg=#ffcc00 -highlight Operator guifg=#dadada -highlight Label guifg=#ffcc00 -highlight Exception guifg=#ff6b6b +call s:hi('Statement', '#ffcc00', '', '220', '', '', '') +call s:hi('Conditional', '#ffcc00', '', '220', '', '', '') +call s:hi('Repeat', '#dadada', '', '253', '', '', '') +call s:hi('Keyword', '#ffcc00', '', '220', '', '', '') +call s:hi('Operator', '#dadada', '', '253', '', '', '') +call s:hi('Label', '#ffcc00', '', '220', '', '', '') +call s:hi('Exception', '#ff6b6b', '', '203', '', '', '') " === PreProc family: green === -highlight PreProc guifg=#00b300 -highlight Include guifg=#00b300 -highlight Define guifg=#00b300 -highlight Macro guifg=#00b300 -highlight PreCondit guifg=#00b300 +call s:hi('PreProc', '#00b300', '', '34', '', '', '') +call s:hi('Include', '#00b300', '', '34', '', '', '') +call s:hi('Define', '#00b300', '', '34', '', '', '') +call s:hi('Macro', '#00b300', '', '34', '', '', '') +call s:hi('PreCondit', '#00b300', '', '34', '', '', '') " === Types: amber === -highlight Type guifg=#e8a060 -highlight StorageClass guifg=#e8a060 -highlight Structure guifg=#e8a060 -highlight Typedef guifg=#e8a060 +call s:hi('Type', '#e8a060', '', '215', '', '', '') +call s:hi('StorageClass', '#e8a060', '', '215', '', '', '') +call s:hi('Structure', '#e8a060', '', '215', '', '', '') +call s:hi('Typedef', '#e8a060', '', '215', '', '', '') " === Special: green for special chars, red for tags === -highlight Special guifg=#00b300 -highlight SpecialChar guifg=#00b300 -highlight Tag guifg=#ff6b6b -highlight Delimiter guifg=#dadada +call s:hi('Special', '#00b300', '', '34', '', '', '') +call s:hi('SpecialChar', '#00b300', '', '34', '', '', '') +call s:hi('Tag', '#ff6b6b', '', '203', '', '', '') +call s:hi('Delimiter', '#dadada', '', '253', '', '', '') " === Errors / Todo === -highlight Error guifg=#ff6b6b -highlight Todo guifg=#ffcc00 gui=bold cterm=bold +call s:hi('Error', '#ff6b6b', '', '203', '', '', '') +call s:hi('Todo', '#ffcc00', '', '220', '', 'bold', 'bold') " === Line numbers / cursor / columns === -highlight LineNr guifg=#dadada guibg=NONE -highlight CursorLineNr guifg=#dadada guibg=#282828 gui=bold cterm=bold -highlight CursorLine guibg=#121212 -highlight CursorColumn guibg=#121212 -highlight ColorColumn guibg=#1a1a1a -highlight SignColumn guifg=#00b300 guibg=#000000 +call s:hi('LineNr', '#dadada', 'NONE', '253', 'NONE', '', '') +call s:hi('CursorLineNr', '#dadada', '#282828', '253', '235', 'bold', 'bold') +call s:hi('CursorLine', '', '#121212', '', '233', 'NONE', 'NONE') +call s:hi('CursorColumn', '', '#121212', '', '233', '', '') +call s:hi('ColorColumn', '', '#1a1a1a', '', '234', '', '') +call s:hi('SignColumn', '#00b300', '#000000', '34', '16', '', '') " === Splits / status / winbar === -highlight VertSplit guifg=#3a3a3a guibg=NONE -highlight WinSeparator guifg=#3a3a3a guibg=NONE -highlight StatusLine guifg=#dadada guibg=#000000 -highlight StatusLineNC guifg=#dadada guibg=#000000 -highlight WinBar guifg=#dadada gui=bold cterm=bold -highlight WinBarNC guifg=#888888 +call s:hi('VertSplit', '#3a3a3a', 'NONE', '237', 'NONE', '', '') +call s:hi('WinSeparator', '#3a3a3a', 'NONE', '237', 'NONE', '', '') +call s:hi('StatusLine', '#dadada', '#000000', '253', '16', '', '') +call s:hi('StatusLineNC', '#dadada', '#000000', '253', '16', '', '') +call s:hi('WinBar', '#dadada', '', '253', '', 'bold', 'bold') +call s:hi('WinBarNC', '#888888', '', '245', '', '', '') " === Visual / search === -highlight Visual guibg=#3a3a3a -highlight VisualNOS guibg=#3a3a3a -highlight Search guifg=#000000 guibg=#ffcc00 -highlight IncSearch guifg=#000000 guibg=#88ddcc -highlight CurSearch guifg=#000000 guibg=#c490d0 +call s:hi('Visual', '', '#3a3a3a', '', '237', '', '') +call s:hi('VisualNOS', '', '#3a3a3a', '', '237', '', '') +call s:hi('Search', '#000000', '#ffcc00', '16', '220', '', '') +call s:hi('IncSearch', '#000000', '#88ddcc', '16', '116', '', '') +call s:hi('CurSearch', '#000000', '#c490d0', '16', '176', '', '') " === Brackets === -highlight MatchParen guifg=#c490d0 gui=bold,underline cterm=bold,underline +call s:hi('MatchParen', '#c490d0', '', '176', '', 'bold,underline', 'bold,underline') " === Popup menu (completion / fzf overlay) === -highlight Pmenu guifg=#dadada guibg=#181818 -highlight PmenuSel guifg=#000000 guibg=#ffcc00 -highlight PmenuSbar guibg=#181818 -highlight PmenuThumb guibg=#3a3a3a +call s:hi('Pmenu', '#dadada', '#181818', '253', '234', '', '') +call s:hi('PmenuSel', '#000000', '#ffcc00', '16', '220', '', '') +call s:hi('PmenuSbar', '', '#181818', '', '234', '', '') +call s:hi('PmenuThumb', '', '#3a3a3a', '', '237', '', '') " === Folds / titles / directories === -highlight Folded guifg=#888888 gui=italic cterm=italic -highlight FoldColumn guifg=#888888 guibg=NONE -highlight Title guifg=#88ddcc gui=bold cterm=bold -highlight Directory guifg=#88ddcc +call s:hi('Folded', '#888888', '', '245', '', 'italic', 'italic') +call s:hi('FoldColumn', '#888888', 'NONE', '245', 'NONE', '', '') +call s:hi('Title', '#88ddcc', '', '116', '', 'bold', 'bold') +call s:hi('Directory', '#88ddcc', '', '116', '', '', '') " === Diff === -highlight DiffAdd guifg=#a5d6a7 guibg=#0a2010 -highlight DiffChange guifg=#e8a060 guibg=#201a0a -highlight DiffDelete guifg=#ff6b6b guibg=#200a0a -highlight DiffText guifg=#ffcc00 guibg=#3a2000 gui=bold cterm=bold +call s:hi('DiffAdd', '#a5d6a7', '#0a2010', '151', '22', '','') +call s:hi('DiffChange', '#e8a060', '#201a0a', '215', '58', '','') +call s:hi('DiffDelete', '#ff6b6b', '#200a0a', '203', '52', '','') +call s:hi('DiffText', '#ffcc00', '#3a2000', '220', '94', 'bold', 'bold') " === Spell === highlight SpellBad guisp=#ff6b6b gui=undercurl cterm=underline highlight SpellCap guisp=#ffcc00 gui=undercurl cterm=underline highlight SpellRare guisp=#c490d0 gui=undercurl cterm=underline -highlight SpellLocal guisp=#88ddcc gui=undercurl cterm=undercurl +highlight SpellLocal guisp=#88ddcc gui=undercurl cterm=underline " === Markdown (vim's built-in syntax) === -highlight markdownH1 guifg=#00b300 gui=bold cterm=bold -highlight markdownH2 guifg=#00b300 gui=bold cterm=bold -highlight markdownH3 guifg=#00b300 gui=bold cterm=bold -highlight markdownH4 guifg=#00b300 gui=bold cterm=bold -highlight markdownH5 guifg=#00b300 gui=bold cterm=bold -highlight markdownH6 guifg=#00b300 gui=bold cterm=bold -highlight markdownHeadingDelimiter guifg=#00b300 gui=bold cterm=bold -highlight markdownLinkText guifg=#88ddcc gui=underline cterm=underline -highlight markdownUrl guifg=#5a5a5a gui=italic cterm=italic -highlight markdownCode guifg=#e8a060 -highlight markdownCodeBlock guifg=#e8a060 +call s:hi('markdownH1', '#00b300', '', '34', '', 'bold', 'bold') +call s:hi('markdownH2', '#00b300', '', '34', '', 'bold', 'bold') +call s:hi('markdownH3', '#00b300', '', '34', '', 'bold', 'bold') +call s:hi('markdownH4', '#00b300', '', '34', '', 'bold', 'bold') +call s:hi('markdownH5', '#00b300', '', '34', '', 'bold', 'bold') +call s:hi('markdownH6', '#00b300', '', '34', '', 'bold', 'bold') +call s:hi('markdownHeadingDelimiter', '#00b300', '', '34', '', 'bold', 'bold') +call s:hi('markdownLinkText', '#88ddcc', '', '116', '', 'underline', 'underline') +call s:hi('markdownUrl', '#5a5a5a', '', '240', '', 'italic', 'italic') +call s:hi('markdownCode', '#e8a060', '', '215', '', '', '') +call s:hi('markdownCodeBlock', '#e8a060', '', '215', '', '', '') " === Diagnostic groups (for plugins like ALE/CoC) === -highlight DiagnosticError guifg=#ff6b6b -highlight DiagnosticWarn guifg=#ffcc00 -highlight DiagnosticInfo guifg=#00b300 -highlight DiagnosticHint guifg=#dadada +call s:hi('DiagnosticError', '#ff6b6b', '', '203', '', '', '') +call s:hi('DiagnosticWarn', '#ffcc00', '', '220', '', '', '') +call s:hi('DiagnosticInfo', '#00b300', '', '34', '', '', '') +call s:hi('DiagnosticHint', '#dadada', '', '253', '', '', '') highlight link ALEErrorSign DiagnosticError highlight link ALEWarningSign DiagnosticWarn highlight link ALEInfoSign DiagnosticInfo " === vim-highlightedyank === -highlight HighlightedyankRegion guifg=#000000 guibg=#ffcc00 +call s:hi('HighlightedyankRegion', '#000000', '#ffcc00', '16', '220', '', '') diff --git a/vimrc b/vimrc index 696936a..b6aefd5 100644 --- a/vimrc +++ b/vimrc @@ -1,24 +1,42 @@ -let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim' +let data_dir = '~/.vim' +if executable(expand('~/.vim/bin/rg')) + let $PATH = expand('~/.vim/bin') . ':' . $PATH +endif + if empty(glob(data_dir . '/autoload/plug.vim')) silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' endif -autocmd VimEnter * if len(filter(values(g:plugs), '!isdirectory(v:val.dir)')) - \| PlugInstall --sync | source $MYVIMRC - \| endif +augroup vimrc_plug_install + autocmd! + autocmd VimEnter * if exists('g:plugs') && len(filter(values(g:plugs), '!isdirectory(v:val.dir)')) + \| PlugInstall --sync | source $MYVIMRC + \| endif +augroup END call plug#begin('~/.vim/plugged') Plug 'tpope/vim-surround' Plug 'jiangmiao/auto-pairs' - Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } - Plug 'junegunn/fzf.vim' + Plug 'junegunn/fzf', { 'do': './install --all' } + if v:version < 800 + Plug 'junegunn/fzf.vim', { 'commit': '5ab282c2f4a597fa655f39f36e7ee8e97bf51650' } + else + Plug 'junegunn/fzf.vim' + endif Plug 'mtdl9/vim-log-highlighting' - Plug 'machakann/vim-highlightedyank' Plug 'osyo-manga/vim-anzu' + if v:version < 800 && has('timers') + Plug 'machakann/vim-highlightedyank', { 'commit': '03fe057c5836a3f3897a943dc96bdfe3f087890e' } + elseif v:version >= 800 + Plug 'machakann/vim-highlightedyank' + endif call plug#end() let mapleader = "\" set background=dark +if !has('gui_running') && &t_Co < 256 + set t_Co=256 +endif if has('termguicolors') set termguicolors endif @@ -26,8 +44,8 @@ silent! colorscheme anticuus highlight Normal ctermbg=NONE guibg=NONE ctermfg=White guifg=#FFFFFF highlight NonText ctermbg=NONE guibg=NONE -highlight CursorLine ctermbg=NONE guibg=NONE -highlight CursorLineNr ctermfg=Yellow guifg=#E5C07B ctermbg=NONE guibg=NONE cterm=bold gui=bold +highlight CursorLine term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE +highlight CursorLineNr term=bold ctermfg=Yellow guifg=#E5C07B ctermbg=NONE guibg=NONE cterm=bold gui=bold highlight HighlightedyankRegion ctermfg=Black guifg=#000000 ctermbg=Yellow guibg=yellow highlight NormalNC ctermbg=NONE guibg=NONE highlight Search ctermfg=Black guifg=#000000 ctermbg=Yellow guibg=#FFCC66 @@ -35,6 +53,11 @@ highlight LineNr ctermbg=NONE guibg=NONE highlight Visual ctermbg=Gray guibg=Gray ctermfg=Black guifg=Black let g:highlightedyank_highlight_duration = 140 +if v:version < 800 && has('timers') + nmap y (highlightedyank) + xmap y (highlightedyank) + omap y (highlightedyank) +endif let $FZF_DEFAULT_OPTS = '--bind=tab:up,shift-tab:down' let g:fzf_layout = { 'window': 'enew' } @@ -46,10 +69,21 @@ let g:netrw_liststyle = 3 let g:netrw_browse_split = 4 let g:netrw_altv = 1 -autocmd FileType netrw nnoremap :wincmd l -autocmd FileType netrw nnoremap :wincmd h -autocmd FileType netrw nnoremap :wincmd j -autocmd FileType netrw nnoremap :wincmd k +augroup vimrc_netrw + autocmd! + autocmd FileType,BufEnter,BufWinEnter * call HideNetrwBuffer() + autocmd FileType netrw nnoremap :wincmd l + autocmd FileType netrw nnoremap :wincmd h + autocmd FileType netrw nnoremap :wincmd j + autocmd FileType netrw nnoremap :wincmd k +augroup END + +augroup vimrc_quickfix + autocmd! + autocmd FileType qf nnoremap j + autocmd FileType qf nnoremap k + autocmd FileType qf nnoremap :cclose +augroup END set laststatus=2 @@ -65,8 +99,12 @@ set smartcase set clipboard=unnamedplus set noswapfile set nobackup -set undofile -set undodir=~/.vim/undodir +if exists('&undofile') + set undofile + if exists('&undodir') + set undodir=~/.vim/undodir + endif +endif set hidden @@ -75,7 +113,9 @@ set shiftwidth=2 set softtabstop=2 set expandtab set smartindent -set fillchars=eob:\ +if v:version >= 800 + set fillchars=eob:\ +endif set statusline=%{exists('*anzu#search_status')?anzu#search_status():''} @@ -89,35 +129,63 @@ function! NetrwToggle() endif endfor let g:netrw_return_win = winnr() - Lexplore + if exists(':Lexplore') == 2 + Lexplore + else + execute 'topleft vertical ' . g:netrw_winsize . 'new' + Explore + endif endfunction function! SafeWincmd(dir) - let target = winnr(a:dir) - if target == winnr() - return - endif - if getbufvar(winbufnr(target), '&filetype') ==# 'netrw' - return - endif + let l:current = winnr() execute 'wincmd ' . a:dir + if winnr() == l:current + return + endif + if &filetype ==# 'netrw' + execute l:current . 'wincmd w' + endif endfunction function! GitRoot() - let l:root = systemlist('git rev-parse --show-toplevel') - if v:shell_error == 0 && !empty(l:root) && !empty(l:root[0]) - return l:root[0] + let l:root = substitute(system('git rev-parse --show-toplevel'), '\n\+$', '', '') + if v:shell_error == 0 && !empty(l:root) + return l:root endif return getcwd() endfunction +function! FzfRg() + if exists(':Rg') != 2 && exists(':grep') != 2 + echohl WarningMsg | echom 'No project search command is available' | echohl None + return + endif + execute 'lcd ' . fnameescape(GitRoot()) + if executable('rg') && exists(':Rg') == 2 + Rg + else + let l:query = input('Search: ') + if empty(l:query) + return + endif + let l:results = system('grep -RIn -e ' . shellescape(l:query) . ' . 2>/dev/null') + if empty(l:results) + echohl WarningMsg | echom 'No matches found' | echohl None + return + endif + cgetexpr split(l:results, "\n") + copen + endif +endfunction + function! SafeBdelete() if &filetype ==# 'netrw' echohl WarningMsg | echom 'Cannot delete buffer from netrw' | echohl None return endif - let l:buflisted = getbufinfo({'buflisted': 1}) + let l:buflisted = filter(range(1, bufnr('$')), 'buflisted(v:val)') if len(l:buflisted) <= 1 echohl WarningMsg | echom 'Cannot delete last buffer' | echohl None return @@ -128,6 +196,46 @@ function! SafeBdelete() execute 'bdelete ' . l:buf endfunction +function! IsNetrwBuffer(buf) + let l:name = bufname(a:buf) + return getbufvar(a:buf, '&filetype') =~# '^netrw' + \ || fnamemodify(l:name, ':t') ==# 'NetrwTreeListing' + \ || (!empty(l:name) && isdirectory(l:name)) +endfunction + +function! HideNetrwBuffer() + if IsNetrwBuffer(bufnr('%')) + setlocal nobuflisted + endif +endfunction + +function! ListedFileBuffers() + return filter(range(1, bufnr('$')), 'buflisted(v:val) && !IsNetrwBuffer(v:val)') +endfunction + +function! SafeBnext(dir) + let l:buffers = ListedFileBuffers() + if empty(l:buffers) + return + endif + + let l:current = bufnr('%') + let l:index = index(l:buffers, l:current) + if l:index < 0 + let l:index = 0 + elseif a:dir > 0 + let l:index = (l:index + 1) % len(l:buffers) + else + let l:index = (l:index - 1 + len(l:buffers)) % len(l:buffers) + endif + + execute 'buffer ' . l:buffers[l:index] +endfunction + +if exists(':Buffers') == 2 + command! -bar -bang -nargs=? -complete=buffer Buffers call fzf#vim#buffers(, ListedFileBuffers(), fzf#vim#with_preview({ 'placeholder': '{1}' }), 0) +endif + " --- Plugin management --- nnoremap pu :PlugUpdate nnoremap pd :PlugUpgrade @@ -150,13 +258,14 @@ vnoremap > >gv nnoremap zz nnoremap zz -" --- Window navigation (matches nvim , skips netrw) --- -nnoremap :call SafeWincmd('h') -nnoremap :call SafeWincmd('j') -nnoremap :call SafeWincmd('k') -nnoremap :call SafeWincmd('l') +" --- Window navigation (skips netrw) --- +nnoremap :call SafeWincmd('h') +nnoremap :call SafeWincmd('h') +nnoremap :call SafeWincmd('j') +nnoremap :call SafeWincmd('k') +nnoremap :call SafeWincmd('l') -" --- Window resize (matches nvim ) --- +" --- Window resize --- nnoremap :vertical resize +10 nnoremap :vertical resize -10 nnoremap :resize +10 @@ -172,7 +281,7 @@ nnoremap wW :wincmd W " --- File explorer & search --- nnoremap e :call NetrwToggle() -nnoremap / :execute 'lcd ' . fnameescape(GitRoot()) Rg +nnoremap / :call FzfRg() nnoremap ff :execute 'lcd ' . fnameescape(GitRoot()) Files nnoremap fp :History nnoremap fb :Buffers @@ -180,11 +289,13 @@ nnoremap ? :History: " --- Buffers --- nnoremap bd :call SafeBdelete() -nnoremap H :bprevious -nnoremap L :bnext +nnoremap H :call SafeBnext(-1) +nnoremap L :call SafeBnext(1) " --- Terminal --- -nnoremap t :below terminal ++rows=10 +if exists(':terminal') == 2 + nnoremap t :below terminal ++rows=10 +endif " --- Misc --- nnoremap ts :execute "normal! a" . strftime('[%b %d %H:%M:%S - BR]')