" Author: Philipp Moers " soziflip@gmail.com " https://github.com/flipsi/dotfiles " https://philippmoers.de " " ~/.vimrc " " " Configuration file for " " __ _______ __ __ " \ \ / /_ _| \/ | " \ \ / / | | | \ / | " \ \/ / | | | |\/| | " \ / _| |_| | | | " \/ |_____|_| |_| " " " " (What vim is? The best reason not to use emacs!) " " " " " If you are reading this configuration file on whe web and want use it right " away, start vim like this: " " bash -c "vim -u <(curl https://raw.githubusercontent.com/flipsi/dotfiles/master/vim/vimrc) FILE" " " " In case you open this file in vim and don't know how to use folds: " - open/close a fold with zo/zc " - open/close all folds with zR/zM " " " """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " " " README " " " " " """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " {{{ " " " Vim becomes especially powerful with plugins. I use vim-plug to manage them. " I install vim-plug like this in neovim: " " sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' " " or like this in vim: " " curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim " " and don't have ~/.vim/bundle under version control, because this is a bad " idea. Instead, I use the install.sh script provided in this repository to " install vim configuration files let vim-plug handle the plugins. " " " I want my vimrc to be sourced without errors out of the box. " So there are two modes: " a mastery of the world mode ('mastery') with all my plugins, " a stripped mode ('stripped') without plugins. " I use the stripped mode on some other systems than home, VMs or as root. " " " This vimrc is divided in several sections. " " a PLUGIN SECTION " where plugins are listed configured. " It can contain settings and keymaps that are " specific to a particular plugin. " It is only executed in mastery mode. " an SETTINGS SECTION " that contains some options not specific to a " plugin. " Also, settings that are no options are made here " (e.g. colorscheme) " It is executed in both modes. " a FUNCTION SECTION " with some useful functions. " This often is stuff too big for one mapping or the " like and probably I shamelessly copied it. " It is executed in both modes. " a COMMAND AND KEYMAP SECTION " where commands are defined and characters are bound. " Command definitions makes it easier to find a " functionality via :FzfCommands when I can't remember " the corresponding mapping. " It is executed in both modes. " Also, it may contain fallback keymaps for plugin " specific things if we are in stripped mode. " It must be executed after the plugin section. " Mappings with the alt key should be done twice: " - with * for terminal sequences, and " - with for gvim " Leader key convention: " - general leader is space (` `) " - text edit leader is single quote (`'`) " - interface leader is space followed by y (` y`) " The leader key may set several times in this file " since the execution time of the mapping matters. " a LOCAL SECTION " where potential other vimrc files are loaded. " " " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " " " SETUP " " " " " """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " basic setup {{{ " we use vim, not vi set nocompatible " execute external commands with bash " (fish is not posix compatible and makes problems) "set shell=/usr/bin/bash let &shell=system('which bash | tr -d "\n"') " force usage of python3 " https://robertbasic.com/blog/force-python-version-in-vim/ if has('python3') endif " always search recursively (e.g. when using :find) set path+=** " edit runtimepath set runtimepath+=~/.vim/syntax " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " my mode {{{ " compute if we should use mastery of the world or stripped mode function! ComputeMyMode() if has('nvim') let l:plugin_file = '~/.local/share/nvim/site/autoload/plug.vim' else let l:plugin_file = '"~/.vim/autoload/plug.vim"' endif if filereadable(expand(l:plugin_file)) return 'mastery' else return 'stripped' endif endfunction " " ... and compute this only once let s:MyMode = ComputeMyMode() " test which mode will be used if s:MyMode == 'mastery' "echo 'Loading configuration with plugins...' else "echo 'Loading configuration without plugins...' endif " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " leader key {{{ let mapleader=' ' let maplocalleader=' ' " leader key should do nothing alone nnoremap " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " automatically source vimrc on save {{{ if !exists("*SourceMYVIMRC") function SourceMYVIMRC() echo 'Sourcing vimrc ...' source ~/.vimrc syntax enable AirlineRefresh FixHighlighting let l:win_id = win_getid() normal! mZ if exists("*RainbowToggleOn") windo RainbowToggleOn endif call win_gotoid(l:win_id) normal! `Z redraw echomsg 'vimrc sourced' . ' ✔' endfunction endif command! SourceMYVIMRC :call SourceMYVIMRC() " Reload configuration augroup reload_vimrc autocmd! autocmd BufWritePost vimrc SourceMYVIMRC augroup END " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " automatically create non-existing directories when writing files augroup Mkdir autocmd! autocmd BufWritePre * call mkdir(expand(":p:h"), "p") augroup END " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " cursor to the last line when reopening a file {{{ augroup line_jump_on_open au! au BufReadPost * \ if line("'\"") > 0 && line("'\"") <= line("$") | \ execute 'normal! g`"zvzz' | \ endif augroup END " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " automatically resize windows when terminal (or font) is resized augroup autoresize_windows autocmd! autocmd VimResized * :wincmd = augroup END """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " " " PLUGIN SECTION " " " " " """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" nnoremap pi :PlugInstall nnoremap pc :PlugClean nnoremap pu :PlugUpdate nnoremap ps :PlugStatus nnoremap pd :PlugDiff if s:MyMode == 'mastery' call plug#begin() if has('nvim') Plug 'nvim-lua/plenary.nvim' endif """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Extend gx to use it beyond just URLs! {{{ " ... e.g. vim plugin URLS, markdown URLs etc. " Plug 'stsewd/gx-extended.vim' nmap gx (gxext-normal) xmap gx (gxext-visual) " }}} """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " vim sessions {{{ " make sessions more convenient and automatically updated Plug 'tpope/vim-obsession' let g:session_file_name = '.session.vim' " start session nnoremap se :exe 'Obsession' . g:session_file_name " automatically load sessions if started without args autocmd VimEnter * nested \ if !argc() && empty(v:this_session) | \ if filereadable(g:session_file_name) | \ exe 'source' . g:session_file_name | " \ elseif | " \ exe 'Obsession' . g:session_file_name | \ endif | \ endif " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " terminal extensions {{{ Plug 'kassio/neoterm' " layout options, see SetNeoTermModeAutomatically() let g:neoterm_mode = 'automatically' let g:neoterm_default_mod = '' let g:neoterm_size_horizontally = '20' let g:neoterm_size_vertically = '' let g:neoterm_shell = 'fish' let g:neoterm_autoinsert = 1 let g:neoterm_autoscroll = 1 let g:neoterm_automap_keys = '' " don't add default mapping (,tt) " Execute some neoterm terminal command without ending up in insert mode " (this is necessary due to the 'startinsert' autocmd that I want) command! -nargs=1 ExecuteInNeoTerminal :call ExecuteInNeoTerminal() function! ExecuteInNeoTerminal(vimcommand) let g:suppress_terminal_autoinsert = 1 call SetNeoTermModeAutomatically() if index(['Tkill','Tclear'], a:vimcommand) >= 0 execute a:vimcommand else execute "T " . a:vimcommand endif sleep 50m unlet g:suppress_terminal_autoinsert endfunction " Switch how to split terminal window command! SwitchNeoTermMode :call SwitchNeoTermMode() function! SwitchNeoTermMode() let g:run_command_method = "terminal-buffer" " I don't use this function when I don't use that setting... if g:neoterm_mode == 'automatically' let g:neoterm_mode = ':botright' let g:neoterm_default_mod = ':botright' let g:neoterm_size = g:neoterm_size_horizontally echo 'Splitting terminal at the bottom' elseif g:neoterm_mode == ':botright' let g:neoterm_mode = ':vertical' let g:neoterm_default_mod = ':vertical' let g:neoterm_size = g:neoterm_size_vertically echo 'Splitting terminal vertically' else let g:neoterm_mode = 'automatically' let g:neoterm_default_mod = '' let g:neoterm_size ='' echo 'Splitting terminal based on window layout' endif endfunction " If enabled (g:neoterm_mode), set how to split terminal window (g:neoterm_default_mod) based on current window layout command! SetNeoTermModeAutomatically :call SetNeoTermModeAutomatically() function! SetNeoTermModeAutomatically() if g:neoterm_mode == 'automatically' " if winnr('$') == 1 if len(filter(range(1, winnr('$')), 'winwidth(v:val) != &columns')) == 0 let g:neoterm_default_mod = ':vertical' let g:neoterm_size = g:neoterm_size_vertically else let g:neoterm_default_mod = ':botright' let g:neoterm_size = g:neoterm_size_horizontally endif endif endfunction " " Remove stupid default mappings " augroup neoterm_remove_mappings " au! " au VimEnter * silent! nunmap ,tt " augroup END nnoremap ott :SwitchNeoTermMode nnoremap tm :echo "Use ott from now on, please!" " legacy binding nnoremap tt :call SetNeoTermModeAutomatically() Topen nnoremap tn :Tnew nnoremap t :Tclose " only hides buffer, we can still sent commands to it " nnoremap tl :Tclear " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " tmux integration {{{ " fix FocusLost and FocusGained events in tmux " Update: this plugin is now obsolete and no longer needed as both neovim and vim (since version 8.2.2345) have native support for this functionality. " Plug 'tmux-plugins/vim-tmux-focus-events' " consistent keybindings to change tmux panes and vim windows Plug 'christoomey/vim-tmux-navigator' " NOTE that this doesn't work in terminal buffers, see https://github.com/christoomey/vim-tmux-navigator/pull/172 let g:tmux_navigator_save_on_switch = 1 let g:tmux_navigator_no_mappings = 1 nnoremap :TmuxNavigateLeft nnoremap :TmuxNavigateDown nnoremap :TmuxNavigateUp nnoremap :TmuxNavigateRight "nnoremap :TmuxNavigatePrevious " run tmux commands from within vim Plug 'preservim/vimux' let g:VimuxHeight = "50" let g:VimuxOrientation = "h" let VimuxUseNearest = 1 " autocompletion from words visible in tmux panes Plug 'wellle/tmux-complete.vim' " and then or a few times " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " allow plugins to utilize . command {{{ Plug 'tpope/vim-repeat' " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " look and feel {{{ " " smooth scrolling " Plug 'psliwka/vim-smoothie' " nmap (SmoothieDownwards) " nmap (SmoothieUpwards) " make gvim colorschemes work in terminal Plug 'godlygeek/csapprox' " colorschemes Plug 'flazz/vim-colorschemes' Plug 'christophermca/meta5' Plug 'sjl/badwolf' Plug 'sonph/onehalf', {'rtp': 'vim/'} Plug 'ayu-theme/ayu-vim' Plug 'NLKNguyen/papercolor-theme' Plug 'sainnhe/gruvbox-material' " cycle through colorschemes Plug 'vim-scripts/ScrollColors' nnoremap yo :COLORSCROLL " highlight word under cursor " Plug 'RRethy/vim-illuminate' let g:Illuminate_delay = 200 let g:Illuminate_highlightUnderCursor = 0 " highlight different parentheses pairs with different colors if has('nvim') Plug 'hiphish/rainbow-delimiters.nvim' nnoremap yb :lua require('rainbow-delimiters').toggle(0) else Plug 'luochen1990/rainbow' let g:rainbow_active = 1 nnoremap yb :RainbowToggle augroup rainbow_disable_in_terminal_buffers au! " au TermOpen * echo "zack" " TODO: delete this debugging statement " TODO: FIX " au TermOpen * RainbowToggleOff " au TermOpen * if exists(":RainbowToggleOff") | RainbowToggleOff | endif augroup END augroup rainbow_disable_in_terminal_buffers_too_late_but_used_to_work au! au BufEnter term://* echo "zzzack" au BufEnter term://* RainbowToggleOff augroup END " TODO: fork plugin and disable per filetype " https://github.com/luochen1990/rainbow/issues/187 " endif " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " distraction free mode {{{ if has('nvim') Plug 'folke/zen-mode.nvim' nnoremap yz :ZenMode endif Plug 'junegunn/goyo.vim' let g:goyo_width="120" let g:goyo_height="100%" nnoremap yy :Goyo " maximize (like tmux 'zoom') current window temporarily Plug 'szw/vim-maximizer' let g:maximizer_set_default_mapping = 0 nnoremap ym :MaximizerToggle! vnoremap ym :MaximizerToggle!gv nnoremap z :MaximizerToggle! vnoremap z :MaximizerToggle! " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " status bar {{{ Plug 'vim-airline/vim-airline' Plug 'vim-airline/vim-airline-themes' let g:airline_detect_modified=1 let g:airline_detect_paste=1 let g:airline_inactive_collapse=0 let g:airline_statusline_ontop = 1 let g:airline#extensions#tabline#show_tabs = 0 let g:airline#extensions#tabline#show_tab_count = 1 let g:airline#extensions#tabline#enabled = 1 let g:airline#extensions#tabline#formatter = 'unique_tail' if has('nvim') let g:airline#extensions#lsp#enabled = 1 let g:airline#extensions#coc#enabled = 0 else let g:airline#extensions#coc#enabled = 1 endif let g:airline_section_mode_default = '%#__accent_bold#%{airline#util#wrap(airline#parts#mode(),0)}%#__restore__#%{airline#util#append(airline#parts#crypt(),0)}%{airline#util#append(airline#parts#paste(),0)}%{airline#util#append(airline#extensions#keymap#status(),0)}%{airline#util#append(airline#parts#spell(),0)}%{airline#util#append("",0)}%{airline#util#append("",0)}%{airline#util#append(airline#parts#iminsert(),0)}' let g:airline_section_my_filename = ' %{expand("%:t")}' let g:airline_section_a = g:airline_section_mode_default . g:airline_section_my_filename let g:airline_section_b = '%{airline#util#wrap(airline#extensions#hunks#get_hunks(),100)}%{airline#util#wrap(airline#extensions#branch#get_head(),80)}' if g:airline#extensions#coc#enabled == 1 let g:airline_section_c = '%{coc#status()}' else let g:airline_section_c = '%{expand("%:h")}' endif command! -nargs=1 AirlineIndicateCustomMode :call AirlineIndicateCustomMode() function! AirlineIndicateCustomMode(modename) if s:MyMode == 'mastery' " TODO use airline#section#create() ? let g:airline_section_a = '%#__accent_bold#[' . a:modename . ']% ' . g:airline_section_my_filename AirlineRefresh endif endfunction command! AirlineResetCustomMode :call AirlineResetCustomMode() function! AirlineResetCustomMode() if s:MyMode == 'mastery' let g:airline_section_a = g:airline_section_mode_default . g:airline_section_my_filename AirlineRefresh endif endfunction let g:airline_powerline_fonts=0 if !exists('g:airline_symbols') let g:airline_symbols = {} endif let g:airline_symbols.linenr = '' let g:airline_symbols.maxlinenr = '' " " airline extension: show list of buffers (like tabs) " Plug 'bling/vim-bufferline' " let g:airline#extensions#bufferline#enabled = 0 " airline extension: obsession (session plugin) let g:airline#extensions#obsession#enabled = 1 " airline extension: show columns of csv files let g:airline#extensions#csv#enabled = 1 " airline extension: hide fugitive stuff let g:airline#extensions#fugitiveline#enabled = 1 " airline extension: vim-grepper integration let g:airline#extensions#grepper#enabled = 1 " simple status bar alternative? " http://www.blaenkdenum.com/posts/a-simpler-vim-statusline/ " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " do some git from within vim {{{ Plug 'tpope/vim-fugitive' " open quickfixlist with unstaged changes nnoremap gel :Git difftool " git status " nnoremap gs :Git " nnoremap gs :Gsplit : " nnoremap gs :silent! wincmd 1w vertical Git " Note that if the working dir is different from the git dir, strangely enough `:Git` opens netrw/ranger if not in the first window. I workaround the issue with `wincmd 1w`. nnoremap gs :GitStatusTab " stage and commit nnoremap gw :Gwrite nnoremap gA :Gwrite nnoremap gU :Gread nnoremap gcc :Git commit nnoremap gca :Git commit --amend " reset nnoremap grH :Confirm Git reset --hard HEAD~1 nnoremap grh :Confirm Git reset --hard nnoremap grr :exe ':Confirm Git reset --hard ' . GitRemoteName() . '/' . GitCurrentBranchName() " stash nnoremap gta :Confirm Git stash push --include-untracked nnoremap gtp :Confirm Git stash pop " diff / resolve merge conflicts nnoremap gdd :Gdiffsplit nnoremap gdv :Gvdiffsplit!gg:FindGitConflictMarkers nnoremap gdt :GdiffsplitTabgg:FindGitConflictMarkers nnoremap gdm :exe ':Shell git diff ' . GitRepoMainOrMaster() . ' \| delta' nnoremap gdM :GitRemoteDiffMergeRequest " checkout/create/rename branches nnoremap gee :Git checkout nnoremap geo :GitCheckoutInteractively nnoremap gem :exe ':Confirm Git checkout ' . GitRepoMainOrMaster() nnoremap ge- :Confirm Git checkout - nnoremap geb :silent! exe ':Git checkout -b ' . input('Branch name: ') nnoremap gbm :silent! exe ':Confirm Git branch -m ' . input('Renaming branch to: ') " merge and rebase nnoremap gmo :GitMergeChooseBranchInteractively nnoremap gmm :exe ':Confirm Git merge ' . GitRepoMainOrMaster() nnoremap gro :GitRebaseChooseBranchInteractively nnoremap grm :exe ':Confirm Git rebase ' . GitRepoMainOrMaster() nnoremap gra :Confirm Git rebase --abort nnoremap grc :Confirm Git rebase --continue " fech, pull and push nnoremap gpl :Git pull nnoremap gfm :exe ':Confirm Git fetch ' . GitRemoteName() . ' ' . GitRepoMainOrMaster() . ':' . GitRepoMainOrMaster() nnoremap gps :GitPush nnoremap gpu :GitPush nnoremap gpf :Git push --force-with-lease nnoremap gup :Confirm Git submodule update " work with remote (Mnemonic: 'G'it Rem'o'te) Github or Gitlab nnoremap go nnoremap gow :OpenGitRepoWeb nnoremap goo :call GitWebUrl('line', 'open_in_web') vnoremap goo :call GitWebUrl('range', 'open_in_web') nnoremap goy :call GitWebUrl('line', 'yank_to_clipboard') vnoremap goy :call GitWebUrl('range', 'yank_to_clipboard') nnoremap gor :GitRemoteCreateOrViewMergeRequest nnoremap gop :GitRemoteShowPipeline " git log etc. nnoremap glh :Git log nnoremap gll :tab Git log nnoremap glf :tab Git log % nnoremap glm :exe 'Git log ' . GitRepoMainOrMaster() nnoremap gbb :Git blame command! GitStatusTab call GitStatusTab() function! GitStatusTab() let g:git_status_last_used_tabnr = tabpagenr() tab Git endfunction " switch to last used tab after closing the Git Status tab opened with GitStatusTab augroup gitstatusclose au! au BufDelete fugitive://*.git// exec 'normal! ' . g:git_status_last_used_tabnr . 'gt' au BufDelete fugitive://*.git/worktrees/*/ exec 'normal! ' . g:git_status_last_used_tabnr . 'gt' augroup END " can be replaced with `` in some cases function! GStatusGetFilenameUnderCursor() return matchstr(getline('.'), '^[A-Z?] \zs.*') endfunction command! GdiffsplitTab call GdiffsplitTab(expand("%")) function! GdiffsplitTab(filename) exe 'tabedit ' . a:filename Gdiffsplit endfunction " custom mapping in fugitive window (:Git) augroup custom_fugitive_mappings au! au FileType fugitive nnoremap k au FileType fugitive nnoremap j au FileType fugitive nnoremap h au FileType fugitive nnoremap l au FileType fugitive nmap ! X au FileType fugitive nmap w = au FileType fugitive nnoremap dt :call GdiffsplitTab(GStatusGetFilenameUnderCursor()) au FileType fugitive nmap pl :Git pull au FileType fugitive nmap ps :Git push au FileType fugitive nmap pu :GitPush au FileType fugitive nmap pf :Git push --force-with-lease au FileType fugitive nmap pr :GitRemoteCreateOrViewMergeRequest augroup END " in Gdiff view, stage/checkout easily augroup gitdiff au! au BufRead fugitive://* nnoremap g do au BufRead fugitive://* nnoremap g dp augroup END " in Git commit view (opening from git log, not commit message), don't use folds augroup gitcommit_view au! au BufRead fugitive:///*/.git//?\\\{40\} normal zR augroup END " resolve 3-way merge conflicts (diff view) nnoremap g ]c nnoremap g [c nnoremap g :diffget //3 " get changes from the right nnoremap g :diffget //2 " get changes from the left """"""""" " Resolve merge conflicts the easy way (used as `git mergetool` or with the mappings below) " [Requires fugitive] Plug 'christoomey/vim-conflicted' nnoremap gmt :Conflicted nnoremap gmn :GitNextConflict " navigate through hunks with ]c and [c let g:diffget_local_map = '' let g:diffget_upstream_map = '' """"""""" " Highlight and resolve merge conflicts in file without diff view Plug 'akinsho/git-conflict.nvim' " inspired by conflict-marker (see below) " See nvim/lua/flipsi/plugins/git-conflict.lua for mappings " nnoremap gec GitConflictListQf """"""""" " Resolve merge conflicts from within vim " (simply when conflict markers are present) " Plug 'rhysd/conflict-marker.vim' " superseded by git-conflict (see above) let g:conflict_marker_highlight_group = '' let g:conflict_marker_begin = '^<<<<<<< .*$' let g:conflict_marker_end = '^>>>>>>> .*$' highlight ConflictMarkerBegin guibg=#2f7366 highlight ConflictMarkerOurs guibg=#2e5049 highlight ConflictMarkerTheirs guibg=#344f69 highlight ConflictMarkerEnd guibg=#2f628e highlight ConflictMarkerCommonAncestorsHunk guibg=#754a81 " [x jump to next conflict marker " ]x jump to previous conflict marker " co choose ours (top) " ct choose theirs (bottom) " cb choose both (just remove conflict markers) " cn choose none (remove both versions and conflict markers) """"""""" " https://github.com/sindrets/diffview.nvim " never configured " show git status of lines on the left """"""""" " VIBE CODED MERGE CONFLICT HELPERS " rebecause I'm not happy with the plugins above) " command! HighlightGitConflictMarkers call HighlightGitConflictMarkers() function! HighlightGitConflictMarkers() highlight default GitConflictMarkerGrey ctermfg=NONE ctermbg=238 guifg=NONE guibg=#444444 syntax match GitConflictMarkerStart /^\s*<<<<<<<.*$/ syntax match GitConflictMarkerBase /^\s*|||||||.*$/ syntax match GitConflictMarkerSep /^\s*=======$/ syntax match GitConflictMarkerEnd /^\s*>>>>>>>.*$/ highlight default link GitConflictMarkerStart GitConflictMarkerGrey highlight default link GitConflictMarkerBase GitConflictMarkerGrey highlight default link GitConflictMarkerSep GitConflictMarkerGrey highlight default link GitConflictMarkerEnd GitConflictMarkerGrey endfunction " Patterns let g:GitConflictStartPat = '^\s*<<<<<<<.*' let g:GitConflictBasePat = '^\s*|||||||\s*' let g:GitConflictSepPat = '^\s*=======$' let g:GitConflictEndPat = '^\s*>>>>>>>.*' function! GitConflictNext() abort call search(g:GitConflictStartPat . '\|' . g:GitConflictSepPat . '\|' . g:GitConflictEndPat, 'W') normal! zt endfunction function! GitConflictPrev() abort call search(g:GitConflictStartPat . '\|' . g:GitConflictSepPat . '\|' . g:GitConflictEndPat, 'bW') normal! zt endfunction function! s:GitConflictLocate() abort let sp = getpos('.') let cur = sp[1] let start = getline(cur) =~# g:GitConflictStartPat ? cur : search(g:GitConflictStartPat, 'bnW') if start == 0 | let start = search(g:GitConflictStartPat, 'nW') | endif if start == 0 | call setpos('.', sp) | return {} | endif call cursor(start, 1) let eq = search(g:GitConflictSepPat, 'nW') let en = search(g:GitConflictEndPat, 'nW') if eq == 0 || en == 0 || eq <= start || en <= eq | call setpos('.', sp) | return {} | endif let base = search(g:GitConflictBasePat, 'nW') if base == 0 || base <= start || base >= eq | let base = -1 | endif if getline(cur) !~# g:GitConflictStartPat && (cur < start || cur > en) | call setpos('.', sp) | return {} | endif call setpos('.', sp) return {'start': start, 'base': base, 'eq': eq, 'end': en} endfunction function! s:GitConflictReplace(r) abort call setline(a:r.start, a:r.list) let n = len(a:r.list) let ds = a:r.start + n if a:r.end >= ds | execute ds . ',' . a:r.end . 'delete _' | endif call cursor(a:r.start + max([n - 1, 0]), 1) endfunction function! GitConflictDebug() abort let l = s:GitConflictLocate() | if empty(l) | return | endif echo l endfunction function! GitConflictKeepOurs() abort let l = s:GitConflictLocate() | if empty(l) | return | endif let s = l.start + 1 let e = (l.base > 0 ? l.base - 1 : l.eq - 1) " stop before base or ======= call s:GitConflictReplace({'start': l.start, 'end': l.end, 'list': (e >= s ? getline(s, e) : [])}) endfunction function! GitConflictKeepTheirs() abort let l = s:GitConflictLocate() | if empty(l) | return | endif let s = l.eq + 1 let e = l.end - 1 " after ======= up to before >>>>>>> call s:GitConflictReplace({'start': l.start, 'end': l.end, 'list': (e >= s ? getline(s, e) : [])}) endfunction function! GitConflictKeepBoth() abort let l = s:GitConflictLocate() | if empty(l) | return | endif let os = l.start + 1 let oe = (l.base > 0 ? l.base - 1 : l.eq - 1) " ours ends before base/======= let ts = l.eq + 1 let te = l.end - 1 " theirs excludes >>>>>>> let ours = (oe >= os ? getline(os, oe) : []) let theirs = (te >= ts ? getline(ts, te) : []) let out = copy(ours) if !empty(ours) && !empty(theirs) | call add(out, '') | endif call extend(out, theirs) call s:GitConflictReplace({'start': l.start, 'end': l.end, 'list': out}) endfunction command! GitConflictNext call GitConflictNext() command! GitConflictPrev call GitConflictPrev() command! GitConflictKeepOurs call GitConflictKeepOurs() command! GitConflictKeepTheirs call GitConflictKeepTheirs() command! GitConflictKeepBoth call GitConflictKeepBoth() command! GitConflictDebug call GitConflictDebug() command! EnableGitConflictMode :call EnableGitConflictMode() function! EnableGitConflictMode() let g:gitconflictmode = 1 AirlineIndicateCustomMode GITCONFLICT MODE HighlightGitConflictMarkers nnoremap kd :GitConflictDebug nnoremap ]c :GitConflictNext nnoremap [c :GitConflictPrev " Or use JumpUpSoToSpeak/JumpDownSoToSpeak nnoremap ko :GitConflictKeepOurs nnoremap kt :GitConflictKeepTheirs nnoremap kb :GitConflictKeepBoth endfunction command! DisableGitConflictMode :call DisableGitConflictMode() function! DisableGitConflictMode() let g:gitconflictmode = 0 AirlineResetCustomMode silent! nunmap ]c silent! nunmap [c silent! nunmap ko silent! nunmap kt silent! nunmap kb endfunction let g:gitconflictmode = 0 nnoremap gk :EnableGitConflictMode " automatically unmap (after committing is reasonable) augroup gitgutter_unmap au! au BufWipeout .git/COMMIT_EDITMSG DisableGitConflictMode augroup END """"""""" Plug 'airblade/vim-gitgutter' let g:gitgutter_max_signs = 4000 " GitGutter styling let g:gitgutter_sign_added = '|' let g:gitgutter_sign_modified = '|' let g:gitgutter_sign_removed = '|' let g:gitgutter_sign_modified_removed = '|' " do not map ic/ac text objects etc because I decide how I use them let g:gitgutter_map_keys = 0 omap ih GitGutterTextObjectInnerPending omap ah GitGutterTextObjectOuterPending xmap ih GitGutterTextObjectInnerVisual xmap ah GitGutterTextObjectOuterVisual nnoremap yG :GitGutterToggle nnoremap yg :GitGutter " redraw nnoremap gi :GitGutterPreviewHunk nnoremap gu :GitGutterUndoHunk nnoremap ga :GitGutterStageHunkGitGutterNextHunk:EnableGitGutterMode nnoremap gg gg:GitGutterNextHunkzzzv:EnableGitGutterMode nnoremap gG G:GitGutterPrevHunkzzzv:EnableGitGutterMode nnoremap g :GitGutterNextHunkzzzv:EnableGitGutterMode nnoremap g :GitGutterPrevHunkzzzv:EnableGitGutterMode nnoremap gn :GitGutterNextHunkzzzv:EnableGitGutterMode nnoremap gN :GitGutterPrevHunkzzzv:EnableGitGutterMode nnoremap gn :GitGutterNextHunkzzzv nnoremap gN :GitGutterPrevHunkzzzv command! EnableGitGutterMode :call EnableGitGutterMode() function! EnableGitGutterMode() let g:gitguttermode = 1 nnoremap :GitGutterStageHunkGitGutterNextHunk AirlineIndicateCustomMode GITGUTTER MODE endfunction command! DisableGitGutterMode :call DisableGitGutterMode() function! DisableGitGutterMode() let g:gitguttermode = 0 silent! nunmap AirlineResetCustomMode endfunction let g:gitguttermode = 0 " automatically unmap (after committing is reasonable) augroup gitgutter_unmap au! au BufWipeout .git/COMMIT_EDITMSG DisableGitGutterMode augroup END " show commit messages in a preview window Plug 'rhysd/git-messenger.vim' let g:git_messenger_no_default_mappings = v:true nmap gB (git-messenger) " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " handle unicode and digraphs easily {{{ Plug 'chrisbra/unicode.vim' " inspect character under cursor nnoremap ga :UnicodeName " complete unicode with " complete digraph with " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " amazingly move everywhere {{{ Plug 'easymotion/vim-easymotion' " prefix map (easymotion-prefix) map l (easymotion-prefix) " keys to move to target let g:EasyMotion_keys = 'asdfgh,.qwertuiocvbnmjkl' " make f and t clever (i.e. repeatable. ',' and ';' will not be needed anymore.) " Plug 'rhysd/clever-f.vim' let g:clever_f_across_no_line = 0 " let g:clever_f_ignore_case = 1 let g:clever_f_smart_case = 1 " let g:clever_f_timeout_ms = 2000 let g:clever_f_fix_key_direction = 0 let g:clever_f_repeat_last_char_inputs = ["\", "\"] let g:clever_f_chars_match_any_signs = '/' " like f but with two characters Plug 'justinmk/vim-sneak' " interactive mode like easymotion " let g:sneak#label = 1 " movement repeatable with same keystroke like clever-f " (i don't really like this, as it makes movements unpredictable) " let g:sneak#s_next = 1 " , always forwards ; always backwards " let g:sneak#absolute_dir = 1 " use smartcase; let g:sneak#use_ic_scs = 1 nmap f Sneak_s nmap F Sneak_S " nmap l Sneak_S " suitable for Moonlander, but not for other keyboards... nmap , Sneak_; nmap ; Sneak_, xmap f :call sneak#wrap(visualmode(), 2, 0, 1, 0) xmap F :call sneak#wrap(visualmode(), 2, 1, 1, 0) xmap l :call sneak#wrap(visualmode(), 2, 1, 1, 0) xmap t :call sneak#wrap(visualmode(), 2, 0, 0, 0) xmap T :call sneak#wrap(visualmode(), 2, 1, 0, 0) xmap l :call sneak#wrap(visualmode(), 2, 1, 0, 0) omap f :call sneak#wrap(v:operator, 2, 0, 1, 0) omap F :call sneak#wrap(v:operator, 2, 1, 1, 0) omap l :call sneak#wrap(v:operator, 2, 1, 1, 0) omap t :call sneak#wrap(v:operator, 2, 0, 0, 0) omap T :call sneak#wrap(v:operator, 2, 1, 0, 0) omap l :call sneak#wrap(v:operator, 2, 1, 0, 0) " make f only match interesting characters " Plug 'svermeulen/vim-NotableFt' " nmap , NotableFtRepeatSearchForward " nmap ; NotableFtRepeatSearchBackward " nmap f NotableFtSearchFForward " nmap s NotableFtSearchFBackward " nmap F NotableFtSearchFBackward " nmap t NotableFtSearchTForward " nmap T NotableFtSearchTBackward " highlight characters for f " Plug 'unblevable/quick-scope' " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " movements and text objects for parts of words {{{ " move with ,w in wordsLikeThisWord or words_like_this_word " Plug 'bkad/CamelCaseMotion' " call camelcasemotion#CreateMotionMappings(',') " DOES NOT WORK HERE " also handle dashes with this plugin (hence w should move over them) " (this breaks toggle_words for many cases) " set iskeyword+=- " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " better and custom text objects {{{ "TODO: use treesitter enhanced mini.nvim "EasyAlign -> mini.align "flash.nvim -> mini.jump "lualine -> mini.statusline "nvim-autopairs -> mini.pairs "nvim-web-devicons -> mini.icons "vim-sandwich -> mini.surround "vim-unimpaired -> mini.bracketed "see https://evantravers.com/articles/2024/09/17/making-my-nvim-act-more-like-helix-with-mini-nvim/ Plug 'wellle/targets.vim' """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Plug 'kana/vim-textobj-user' " lines with the same indent level (ai/ii) Plug 'kana/vim-textobj-indent' " quotes (aq/iq) Plug 'beloglazov/vim-textobj-quotes' " functions (af/if) Plug 'kana/vim-textobj-function' Plug 'thinca/vim-textobj-function-javascript' " function arguments (aa/ia) " (somehow required one more keystroke) Plug 'gaving/vim-textobj-argument' " lines with ( [ { pairs (ac/ic) " Plug 'Chun-Yang/vim-textobj-chunk' " css rules (ac/ic) Plug 'jasonlong/vim-textobj-css' " Plug 'stephenway/vim-textobj-css' " HTML/XML attributes (ax/ix) Plug 'whatyouhide/vim-textobj-xmlattr' " PHP Tags (aP/iP) Plug 'akiyan/vim-textobj-php' " folds (az/iz) Plug 'kana/vim-textobj-fold' " git hunks (ih) (now managed by gitgutter plugin) " Plug 'gilligan/textobj-gitgutter' " omap ah (textobj-gitgutter-i) " vmap ah (textobj-gitgutter-i) " entire buffer / 'all' (aa/ia) Plug 'kana/vim-textobj-entire' let g:textobj_entire_no_default_key_mappings = 1 omap aE (textobj-entire-a) vmap aE (textobj-entire-a) omap iE (textobj-entire-i) vmap iE (textobj-entire-i) " load dynamically with :TextobjEntireDefaultKeyMappings " note that vimtex also defines mappings ic/id/ie/i$ " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " advanced searching {{{ " Plug 'google/vim-searchindex' " Plug 'osyo-manga/vim-anzu' Plug 'haya14busa/incsearch.vim' let g:incsearch#auto_nohlsearch = 1 let g:incsearch#emacs_like_keymap = 1 let g:incsearch_cli_key_mappings = { \ "\": { \ 'key': '(buffer-complete)', \ 'noremap': 1 \ }, \ "\": { \ 'key': '(buffer-complete-prev)', \ 'noremap': 1 \ }, \ } " nnoremap / (incsearch-forward) " nnoremap ? (incsearch-backward) nnoremap / :call incsearch#call() nnoremap ? :call incsearch#call({'command': '?'}) " searching in multiple files " Plug 'mileszs/ack.vim' " command to execute let g:ackprg="ag --vimgrep --smart-case" " " type a search pattern " nnoremap ag :let g:jumplist = 'quickfixlist' " \ :Ack!"" " " search for visual selection " xnoremap ag y:let g:jumplist = 'quickfixlist' " \ :Ack! "-Q" """ " grep in vim like a pro Plug 'mhinz/vim-grepper' let g:grepper = {} " let g:grepper.tools = ['git', 'ag', 'grep', 'rg'] let g:grepper.quickfix = 1 let g:grepper.switch = 0 let g:grepper.jump = 1 let g:grepper.prompt_mapping_side = '' let g:grepper.searchreg = 1 nnoremap / :Grepper nnoremap g/ :Grepper-side nnoremap g* :Grepper-side -cword -noprompt -tool ag xnoremap g/ y:Grepper-side -noprompt -tool ag -query """ xmap g* g/ nnoremap * nnoremap ** :Grepper -cword -noprompt -tool ag nnoremap *b :Grepper -cword -noprompt -tool ag -buffer nnoremap *o :Grepper -cword -noprompt -tool ag -buffers nmap *B *b nmap *O *o nmap gs (GrepperOperator) xmap gs (GrepperOperator) xmap * y:Grepper -noprompt -tool ag -query """ command! TODO Grepper -noprompt -tool git -query -E '(TODO|FIXME|XXX|\?\?\?)' " % also matches HTML-tags/words etc Plug 'vim-scripts/matchit.zip' " hide (fold) everything except search string etc Plug 'embear/vim-foldsearch' let g:foldsearch_highlight = 0 let g:foldsearch_disable_mappings = 1 " show last search nnoremap zs :Fs nnoremap z/ :Fs nnoremap zz :Fs " show word under cursor nnoremap z* :Fw nnoremap zw :Fw " show visual selection vnoremap z y:Fp\V" " change context size (number of lines around matches) nnoremap z+ :Fi nnoremap zi :Fi nnoremap z- :Fd nnoremap zd :Fd " restore folds nnoremap ze :Fe nnoremap Z :Fe " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " fuzzy find files etc (like Sublimes 'Goto Anything') {{{ " Plug 'kien/ctrlp.vim' " let g:ctrlp_map = '#' " let g:ctrlp_cmd = 'CtrlPBuffer' nnoremap ef :CtrlPRoot nnoremap er :CtrlPMRUFiles nnoremap em :CtrlPMixed nnoremap eo :CtrlPRoot nnoremap eb :CtrlPBuffer " ignore some stuff (in addition to 'wildignore') let g:ctrlp_custom_ignore = { \ 'dir': '\v[\/]\.(git|hg|svn)$', \ 'file': '\v\.(class)$', \ } " change appearance "let g:ctrlp_match_window = 'bottom,order:btt,min:1,max:10,results:10' let g:ctrlp_match_window = 'top,order:ttb,min:1,max:8,results:8' " custom key bindings when ctrlp prompt is open let g:ctrlp_prompt_mappings = { \ 'PrtSelectMove("j")': ['', '', ''], \ 'PrtSelectMove("k")': ['', '', ''], \ 'PrtExpandDir()': [], \ 'AcceptSelection("v")': ['', '', '', ''], \ 'ToggleFocus()': [], \ 'ToggleRegex()': ['', 'r'], \ 'ToggleType(1)': ['', ''], \ 'ToggleType(-1)': ['', ''], \ 'PrtCurLeft()': ['', ''], \ 'PrtCurRight()': [''], \ } " also find hidden files let g:ctrlp_show_hidden = 1 " only cache if we're in huge projects let g:ctrlp_use_caching = 2000 " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " fzf - great fuzzy finder {{{ " (makes ctrlp and the ag plugin obsolete) " (prefixing a word with ' makes it non-fuzzy) " install 'fzf' package on the system. or: Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --bin' } Plug 'junegunn/fzf.vim' Plug 'stsewd/fzf-checkout.vim' " prefix all the command names let g:fzf_command_prefix = 'Fzf' " how/where to open fzf let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } } " extra interactive key bindings " (scroll with and let g:fzf_action = { \ 'ctrl-x': 'split', \ 'ctrl-s': 'split', \ 'ctrl-l': 'vsplit', \ 'ctrl-v': 'vsplit', \ 'ctrl-t': '$tab split', \ '!': '$tab split', \ } " \ 'ctrl-k': 'previous-history', " \ 'ctrl-j': 'next-history', " enable per-command history " (scroll through history with and ) let g:fzf_history_dir = '~/.local/share/fzf-history' " Preview window settings (disable preview window altogether with empty value) let g:fzf_preview_window = 'right:50%' " override command to only match content (not filenames) command! -bang -nargs=* FzfAg \ call fzf#vim#ag(, \ 0 ? fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'down:50%') \ : fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'right:20%:hidden', '?'), \ 0) " open files by name nnoremap fl :FzfLocate nnoremap fi :FzfFiles nnoremap ef :FzfFiles nnoremap eo :FzfGFiles nnoremap eg :FzfGFiles? nnoremap er :FzfHistory nnoremap eb :FzfBuffers nnoremap :FzfBuffers vnoremap :FzfBuffers let g:fzf_tags_command = 'ctags -R -f .tags' nnoremap et :FzfTags xnoremap et y:FzfTags " " type a search pattern nnoremap f/ :FzfAg! nnoremap ff :FzfAg! " search for word under cursor in working dir nnoremap f* :FzfAg! nnoremap fw :FzfAg! nnoremap fW :FzfAg! " search for visual selection in working dir xnoremap f* y:FzfAg! " xnoremap fw y:FzfAg! " " fuzzy search commands nnoremap : :FzfCommands " fuzzy search command history nnoremap h: :FzfHistory: " fuzzy search search history nnoremap hs :FzfHistory/ " fuzzy search helptags nnoremap hh :FzfHelptags " autocomplete lines like a boss, even across multiple files imap (fzf-complete-line) " adjust colors to colorscheme: gruvbox let g:fzf_colors = \ { 'fg': ['fg', 'Normal'], \ 'bg': ['bg', 'Normal'], \ 'hl': ['fg', 'Comment'], \ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'], \ 'bg+': ['bg', 'CursorLine', 'CursorColumn'], \ 'hl+': ['fg', 'Statement'], \ 'info': ['fg', 'PreProc'], \ 'prompt': ['fg', 'Conditional'], \ 'pointer': ['fg', 'Exception'], \ 'marker': ['fg', 'Keyword'], \ 'spinner': ['fg', 'Label'], \ 'header': ['fg', 'Comment'] } " Plug 'laher/fuzzymenu.vim' nmap ; Fzm vmap ; FzmVisual """"""""""""""""""""""""" " Plug 'yuki-yano/fzf-preview.vim', { 'branch': 'release/rpc' } " TOO SLOW! " " open files by name " nnoremap fi :FzfPreviewProjectFilesRpc " nnoremap ef :FzfPreviewProjectFilesRpc " nnoremap eo :FzfPreviewGitFilesRpc " nnoremap eb :FzfPreviewBuffersRpc " nnoremap :FzfPreviewBuffersRpc " " jump to line in current buffer " nnoremap el :FzfPreviewLinesRpc " " project grep " nnoremap / :FzfPreviewProjectGrepRpc " xnoremap / "sy:FzfPreviewProjectGrepRpc-F"=substitute(substitute(@s, '\n', '', 'g'), '/', '\\/', 'g')" " " search command history " nnoremap h: :FzfPreviewCommandPaletteRpc: " " search TODO etc. " nnoremap h: :FzfPreviewTodoCommentsRpc: " " open Github PR that introduced line " " :FzfPreviewBlamePRRpc " " [coc] jump to definitions " nnoremap ed :CocCommand fzf-preview.CocTypeDefinitions """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Telescope - another highly extendable fuzzy finder " TOO SLOW! " Neovim Nightly (0.5) is required for telescope.nvim to work. " if has('nvim') " Plug 'nvim-lua/popup.nvim' " Plug 'nvim-lua/plenary.nvim' " Plug 'nvim-telescope/telescope.nvim' lua << EOF --[[ require('telescope').setup{ defaults = { vimgrep_arguments = { 'rg', '--color=never', '--no-heading', '--with-filename', '--line-number', '--column', '--smart-case' }, prompt_prefix = ">>> ", } } --]] EOF " fzf-writer! " https://github.com/nvim-telescope/telescope-fzf-writer.nvim " cooler typ config? " https://github.com/smithbm2316/dotfiles/tree/main/nvim " nnoremap hh Telescope help_tags " nnoremap ef Telescope find_files " nnoremap j/ Telescope live_grep " nnoremap eb Telescope buffers " nnoremap Telescope buffers " endif " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " file searching and much more {{{ " http://bling.github.io/blog/2013/06/02/unite-dot-vim-the-plugin-you-didnt-know-you-need/ " TODO CONFIGURE AND TEST "Plug 'Shougo/vimproc.vim' "Plug 'Shougo/unite.vim' " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " tags (variables, functions, ...) {{{ " install 'ctags' package on the system " generate tag file manually " (fails with '–exclude=@.gitignore' when the file does not exist!) " nnoremap eT :!ctags -R -f .tags . " generate tag file automagically Plug 'craigemery/vim-autotag' let g:autotagTagsFile=".tags" Plug 'majutsushi/tagbar' " if I leave tagbar open but unfocused, q closes vim. that not what i want... " so i autoclose and autofocus tagbar, which is cooler anyway let g:tagbar_compact = 1 let g:tagbar_autoclose = 1 "let g:tagbar_map_close = 'Q' noremap tb :TagbarToggle "autocmd FileType vim nested :TagbarOpen() " jump to definitions without relying on tags Plug 'misterbuckley/vim-definitive' " Plug 'flipsi/vim-definitive' nnoremap fd :FindDefinition " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " file management {{{ " write buffer with sudo " (because the `:w !sudo tee % > /dev/null` does not work in neovim) Plug 'lambdalisue/suda.vim' cnoreabbrev w!! SudaWrite " sugar for unix shell commands like move/rename/delete/find files etc. Plug 'tpope/vim-eunuch' nnoremap rn :Rename =expand("%:t") nnoremap rm :Confirm Delete! " Plug 'scrooloose/nerdtree' let NERDTreeWinSize = 50 let NERDTreeQuitOnOpen = 1 let NERDTreeWinPos = 'right' " show nerdtree from current file " noremap tn :NERDTreeFind " show/hide nerdtree " noremap tN :NERDTreeToggle " show/hide hidden files let NERDTreeMapToggleHidden='.' " pimp netrw " Plug 'tpope/vim-vinegar' " delete a buffer in Vim without closing the window " (required by ranger.vim) if has('nvim') Plug 'rbgrouleff/bclose.vim' let g:bclose_no_plugin_maps = 1 " let g:no_plugin_maps = true endif " use ranger file manager as file chooser etc. Plug 'francoiscabrol/ranger.vim' " open ranger when vim opens a directory let g:ranger_replace_netrw = 1 " map keys explicitly let g:ranger_map_keys = 0 " open ranger in a vertical split window at the left nnoremap ir :vertical split wincmd H vertical resize 60 Ranger nnoremap iR :vertical split wincmd H vertical resize 60 RangerWorkingDirectory " close window when exiting ranger (and fix window width afterwards) augroup ranger_autoclose au! au BufWipeout term://*ranger* quit | wincmd = augroup END " ranger alternative Plug 'theniceboy/joshuto.nvim' " open ranger in a vertical split window at the left nnoremap :Joshuto nnoremap i :Joshuto " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " close all other buffers {{{ Plug 'vim-scripts/BufOnly.vim' nmap qO :BufOnly " }}} """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " static code analysis {{{ " old school synchronous linter " Plug 'scrooloose/syntastic' let g:syntastic_always_populate_loc_list = 1 let g:syntastic_auto_loc_list = 1 let g:syntastic_loc_list_height = 5 let g:syntastic_check_on_open = 0 let g:syntastic_check_on_wq = 0 let g:syntastic_mode_map = { \ "mode": "active", \ "active_filetypes": ["ruby", "php"], \ "passive_filetypes": ["python", "tex", "scala"] } " let g:syntastic_cpp_compiler = 'clang++' " let g:syntastic_cpp_compiler_options = ' -std=c++11 -stdlib=libc++' let g:syntastic_c_cppcheck_args = ' -std=c++11 -stdlib=libc++' " nnoremap sc :SyntasticCheck " nnoremap sr :SyntasticReset " nnoremap st :SyntasticToggleMode " nnoremap si :SyntasticInfo " install linters on the system: " - pylint " - jslint / jshint " - csslint (but phpcs also can do css) " - phpcs (https://github.com/squizlabs/PHP_CodeSniffer) " - fsc " - scalac " - shellcheck " - markdownlint let g:syntastic_php_checkers = ['phpcs', 'phplint', 'php'] " let g:syntastic_javascript_checkers = ['eslint', 'jshint', 'jslint'] let g:syntastic_javascript_checkers = ['eslint', 'jshint'] let g:syntastic_scala_checkers = ['fsc'] " ignore these errors/warnings let g:syntastic_quiet_messages = { "regex": [ \ '\mMissing file doc comment', \ '\mFile is being conditionally included;', \ '\mFile is being unconditionally included;', \ '\mLine indented incorrectly;.*', \ '\mMulti-line IF statement not indented correctly;.*', \ '\mEach line in a multi-line IF statement must begin with a boolean operator.*', \ '\mSpace after opening parenthesis of function call prohibited.*', \ '\mExpected 0 spaces before closing bracket; .* found.*', \ '\mExpected \\"foreach (...) {\\n\\"; found \\"foreach(...) {\\n\\".*', \ '\mExpected \\"if (...) {\\n\\"; found \\"if(...) {\\n\\".*', \ '\mExpected \\"} elseif (...) {\\n\\"; found \\"} elseif(...) {\\n\\".*', \ '\mOpening brace should be on a new line.*', \ '\mBad line breaking before .+..', \ '\mInline control structures are discouraged', \ '\mClosing parenthesis of a multi-line IF statement must be on a new line', \ '\mLine exceeds 85 characters;.*', \ '\mYou must use .* style comments.*', \ '\mDon.t use adjoining classes.', \ '\mDon.t use IDs in selectors.', \ '\mHeading (h.) should not be qualified.', \ '\mShort PHP opening tag used;', \ '\m.$. was used before it was defined.', \ '\mpossible unwanted space at "{"', \ '\mFunction name .* is prefixed with a package name but does not begin with a capital letter', \ '\m.$. was used before it was defined.' \ ] } if !has('nvim') " asynchronous alternative to syntastic Plug 'w0rp/ale' let g:ale_list_window_size = 5 let g:ale_lint_on_enter = 0 let g:ale_linters = { \ 'markdown': ['markdownlint'], \ 'clojure': ['clj-kondo'], \ 'javascript': ['eslint'], \ 'typescript': ['tsserver', 'tslint'], \ 'vue': ['eslint'] \} let g:ale_fixers = { \ 'javascript': ['eslint'], \ 'typescript': ['prettier'], \ 'vue': ['eslint'], \ 'markdown': ['prettier'], \ 'scss': ['prettier'], \ 'html': ['prettier'] \} " disable hints for certain languages, " because coc aleady provides this let g:ale_linters_ignore = {'clojure': ['clj-kondo']} " add some options let g:ale_python_pylint_options = '--rcfile $HOME/.vim/config/pylint.rc' nnoremap sc :ALELint nnoremap sn :ALENext nnoremap sN :ALEPrevious nnoremap sp :ALEPrevious nnoremap sr :ALEDisable nnoremap st :ALEToggle nnoremap si :ALEInfo else Plug 'mfussenegger/nvim-lint' " With ale we already got an asynchronous linter, why write yet another one? " Because ale also includes its own language server client. " nvim-lint instead has a more narrow scope: It spawns linters, parses their output, and reports the results via the vim.diagnostic module. endif " evaluate expression live, which is awesome " Plug 'metakirby5/codi.vim' " lookup stuff " Plug 'dbeniamine/cheat.sh-vim' let g:CheatSheetDefaultMode=0 let g:CheatSheetDoNotMap=1 " use line as query and paste result after line nnoremap