" ● if &shell =~# 'fish$' set shell=bash endif " #plugins {{{ if has('nvim') if empty(glob('~/.config/nvim/autoload/plug.vim'))"{{{ silent !curl -fLo ~/.config/nvim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim autocmd VimEnter * PlugInstall --sync | source $MYVIMRC endif "}}} call plug#begin('~/.vim/bundle') source ~/.config/vim/config/plugins.nvim.vim else if empty(glob('~/.vim/autoload/plug.vim'))"{{{ silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim autocmd VimEnter * PlugInstall --sync | source $MYVIMRC endif "}}} call plug#begin('~/.config/nvim/bundle') source ~/.config/vim/config/plugins.vim endif source ~/.config/vim/config/plugins.shared.vim call plug#end() runtime macros/matchit.vim "----------------------------------------------------------------------------}}} " #functions {{{ function! SetColor(name, fg, bg, fg_l, bg_l, style) abort"{{{ if &background ==? 'dark' if a:fg ==? 'normal' let l:guifg = ' guifg=' . g:d_normal_fg let l:ctermfg = 'ctermfg=black' " let l:termfg = 'termfg=black' elseif a:fg ==? 'none' let l:guifg = ' guifg=' . g:d_normal_bg let l:ctermfg = ' ctermfg=white' " let l:termfg = ' termfg=white' elseif a:fg ==? '' let l:guifg = '' let l:ctermfg = '' " let l:termfg = '' else let l:guifg = ' guifg=' . a:fg let l:ctermfg = ' ctermfg=black' " let l:termfg = ' termfg=black' endif if a:bg ==? 'none' let l:guibg = ' guibg=NONE' let l:ctermbg = ' ctermbg=none' " let l:termbg = ' termbg=none' elseif a:bg ==? '' let l:guibg = '' let l:ctermbg = '' " let l:termbg = '' else let l:guibg = ' guibg=' . a:bg let l:ctermbg = ' ctermbg=black' endif else " light background if a:fg_l ==? 'normal' let l:guifg = ' guifg=' . g:l_normal_fg let l:ctermfg = ' ctermfg=black' " let l:termfg = ' termfg=black' elseif a:fg_l ==? 'none' let l:guifg = ' guifg=' . g:l_normal_bg let l:ctermfg = ' ctermfg=white' " let l:termfg = ' termfg=white' elseif a:fg_l ==? '' let l:guifg = '' let l:ctermfg = '' let l:termfg = '' else let l:guifg = ' guifg=' . a:fg_l let l:ctermfg = ' ctermfg=black' " let l:termfg = ' termfg=black' endif if a:bg_l ==? 'none' let l:guibg = ' guibg=NONE' let l:ctermbg = ' ctermbg=none' " let l:termbg = ' termbg=none' elseif a:bg_l ==? '' let l:guibg = '' let l:ctermbg = '' " let l:termbg = '' else let l:guibg = ' guibg=' . a:bg_l let l:ctermbg = ' ctermbg=white' " let l:termbg = ' termbg=white' endif endif if a:style ==? '' let l:style = ' term=none cterm=none gui=NONE' else let l:style = ' term=' . a:style . ' cterm=' . a:style . ' gui=' . a:style endif let l:histring = 'hi! ' . a:name . l:guifg . l:guibg . l:style let l:histring .= l:ctermfg . l:ctermbg " let l:histring .= l:termfg . l:termbg execute 'hi clear ' . a:name execute l:histring endfunction "}}} function! GetStatusFrag(condition, colorname, conditionprefix, text) abort "{{{ " TODO better name let l:frag='%#' . a:colorname . '#' let l:frag.=a:conditionprefix let l:frag.='%{(' . a:condition . ")?'" . a:text . "':''}" return l:frag endfunction "}}} function! MyFoldText() "{{{ if !exists('g:foldtext_column') let g:foldtext_column = 80 " column to right align foldtext with endif if !exists('b:foldtext_column') let b:foldtext_column = g:foldtext_column " column to right align foldtext with endif if !exists('g:foldtext_maxcolumn') let g:foldtext_maxcolumn = 120 endif let l:linecount = v:foldend - v:foldstart " don't display foldmarker braces " put one of the braces in brackets so vim doesn't treat " it as an actual fold marker let l:line = substitute(getline(v:foldstart), '"\?{\({\){', '', '') " don't display vim comment quotation marks " TODO other comment markers let l:line = substitute(l:line, "\^\"\\s\\?", '', '') " let l:postfix = l:linecount . ' ' . substitute(v:folddashes, '-', '•', 'g') let l:postfix = l:linecount . ' ' . substitute(v:folddashes, '-', '↓', 'g') while strchars(l:postfix) < 7 let l:postfix = ' ' . l:postfix endwhile " let l:postfix = ' ↓ ' . l:postfix let l:len_line = len(l:line) let l:len_postfix = strchars(l:postfix) if l:len_line + l:len_postfix <= b:foldtext_column let l:padding = ' '[l:len_line + l:len_postfix + 0:b:foldtext_column - 1] let l:foldtext = l:line . l:padding . l:postfix else let l:sniptext = ' ⋯' let l:foldtext = l:line[:b:foldtext_column - 1 - strchars(l:sniptext) - l:len_postfix] . l:sniptext . l:postfix endif return l:foldtext endfunction "}}} function! IndentFoldTextColumn(amount) abort "{{{ if !exists('g:foldtext_column') " column to right align foldtext with let g:foldtext_column = 80 endif if !exists('b:foldtext_column') " column to right align foldtext with let b:foldtext_column = g:foldtext_column endif if a:amount == 0 let b:foldtext_column = g:foldtext_column return endif let l:newcolumn = b:foldtext_column + a:amount if l:newcolumn < 20 let l:newcolumn = 20 elseif l:newcolumn > g:foldtext_maxcolumn let l:newcolumn = g:foldtext_maxcolumn endif let b:foldtext_column = l:newcolumn endfunction nnoremap z, :call IndentFoldTextColumn(-5 * (v:count == 0 ? 1 : v:count)) nnoremap z. :call IndentFoldTextColumn(5 * (v:count == 0 ? 1 : v:count)) nnoremap z= :call IndentFoldTextColumn(0) "}}} function! SynStack()"{{{ if !exists('*synstack') return endif echo map(synstack(line('.'), col('.')), 'synIDattr(v:val,"name")') '-> ' . synIDattr(synIDtrans(synID(line('.'),col('.'),1)), 'name' ) endfunc nmap pp :call SynStack() "}}} function! s:Get_env() abort "{{{ " devdocs DD " https://gist.github.com/romainl/8d3b73428b4366f75a19be2dad2f0987#file-devdocs-vim if has('win64') || has('win32') || has('win16') return 'WINDOWS' else return toupper(substitute(system('uname'), '\n', '', '')) endif endfunction " What command to use on what system let s:cmds = {'DARWIN': 'open', 'LINUX': 'qutebrowser', 'WINDOWS': 'start'} " Build the URL stub let s:stub = s:cmds[Get_env()] . " 'http://devdocs.io/?q=" command! -nargs=* DD silent! call system(len(split(, ' ')) == 0 ? \ s:stub . &ft . ' ' . expand('') . "'" : len(split(, ' ')) == 1 ? \ s:stub . &ft . ' ' . . "'" : s:stub . . "'") "}}} if has('nvim') if !exists('*RangerExplorer') "{{{ function RangerExplorer() abort exec 'silent Ranger' endfun nnoremap ra :call RangerExplorer() endif else if !exists('*RangerExplorer') function RangerExplorer() abort exec 'silent !ranger --choosefile=/tmp/vim_ranger_current_file ' . expand('%:p:h') if filereadable('/tmp/vim_ranger_current_file') exec 'edit ' . system('cat /tmp/vim_ranger_current_file') call system('rm /tmp/vim_ranger_current_file') endif redraw! endfun nnoremap ra :call RangerExplorer() endif endif "}}} function! WinEnterColorColumn() abort"{{{ if &buftype != '' setlocal colorcolumn=0 elseif exists('b:colorcolumn_restore') execute 'setlocal colorcolumn=' . b:colorcolumn_restore endif endfunction "}}} function! WinLeaveColorColumn() abort"{{{ let b:colorcolumn_restore = &colorcolumn setlocal colorcolumn=0 endfunction "}}} function! GetLinterStatus(key) abort "{{{ let l:statuscount = 0 if exists('b:ale_linted') let l:linter = ale#statusline#Count(bufnr('')) else let l:linter = GetDiagnosticCountsFromSigns(bufnr('')) endif if has_key(l:linter, a:key) let l:statuscount = l:linter[a:key] endif return l:statuscount endfunction "}}} function! s:RunShellCommand(cmdline) abort"{{{ " Shell command " http://vim.wikia.com/wiki/VimTip1599 let l:expanded_cmdline = a:cmdline for l:part in split(a:cmdline, ' ') if l:part[0] =~ '\v[%#<]' let l:expanded_part = fnameescape(expand(l:part)) let l:expanded_cmdline = substitute(l:expanded_cmdline, l:part, l:expanded_part, '') endif endfor if g:shell_scratch_buffer_nr > -1 let l:win_nr = bufwinnr(g:shell_scratch_buffer_nr) if l:win_nr < 0 execute 'bdelete' g:shell_scratch_buffer_nr top new let g:shell_scratch_buffer_nr = bufnr('%') else execute l:win_nr. ' wincmd w' setlocal modifiable %delete _ endif else top new let g:shell_scratch_buffer_nr = bufnr('%') endif setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap nnoremap q :bdelete augroup ResetShellBufferNr autocmd! * autocmd BufUnload let g:shell_scratch_buffer_nr = -1 augroup END " call setline(1, 'You entered: ' . a:cmdline) " call setline(2, 'Expanded Form: ' .l:expanded_cmdline) " call setline(3,substitute(getline(2),'.','=','g')) execute '$read !'. l:expanded_cmdline 1 setlocal nomodifiable if !exists('b:shell_line_count') let b:shell_line_count = line('$') if b:shell_line_count > 25 let b:shell_line_count = 20 endif execute 'resize' b:shell_line_count + 1 endif wincmd p endfunction command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand() let g:shell_scratch_buffer_nr = -1 "}}} function! GetDiagnosticCountsFromSigns(buffer) abort "{{{ let l:error = 0 let l:warn = 0 let l:info = 0 let l:hint = 0 redir => l:result silent exec 'sign place buffer=' . a:buffer redir end let l:lines = split(l:result, '\n') for l:line in l:lines if l:line =~? 'Error' let l:error += 1 endif if l:line =~? 'Warning' let l:warn += 1 endif if l:line =~? 'Info' let l:info += 1 endif if l:line =~? 'Hint' let l:hint += 1 endif endfor return {'error': l:error, 'warning': l:warn, 'info': l:info, 'hint': l:hint} endfunction "}}} function! SaveAndExecute(ex_command) abort "{{{ " https://stackoverflow.com/a/40195855 " ex_command: command to run to execute file " SOURCE [reusable window]: https://github.com/fatih/vim-go/blob/master/autoload/go/ui.vim " save and reload current file silent execute 'update | edit' " get file path of current file let s:current_buffer_file_path = expand('%') let s:output_buffer_name = 'Output' let s:output_buffer_filetype = 'output' " reuse existing buffer window if it exists otherwise create a new one if !exists('c:buf_nr') || !bufexists(s:buf_nr) || bufwinnr(s:buf_nr) == -1 silent execute 'top new ' . s:output_buffer_name let s:buf_nr = bufnr('%') elseif bufwinnr(s:buf_nr) != bufwinnr('%') silent execute bufwinnr(s:buf_nr) . 'wincmd w' endif silent execute 'setlocal filetype=' . s:output_buffer_filetype setlocal bufhidden=delete setlocal buftype=nofile setlocal noswapfile setlocal nobuflisted setlocal winfixheight setlocal cursorline " make it easy to distinguish setlocal nonumber setlocal norelativenumber setlocal showbreak="" nnoremap q :bdelete!'.zz " clear the buffer setlocal noreadonly " setlocal modifiable %delete _ " add the console output silent execute '.!'. a:ex_command . ' ' . shellescape(s:current_buffer_file_path, 1) " resize window to content length " Note: This is annoying because if you print a lot of lines then your code buffer is forced to a height of one line every time you run this function. " However without this line the buffer starts off as a default size and if you resize the buffer then it keeps that custom size after repeated runs of this function. " But if you close the output buffer then it returns to using the default size when its recreated "execute 'resize' . line('$') " make the buffer non modifiable setlocal readonly " setlocal nomodifiable endfunction "}}} function! JsIncludeExpr(file)"{{{ " substitute(substitute(v:fname,'^[\\~@]\/','./',''),'^[\\~@]','./node_modules/','') return substitute(substitute(a:file,'^[\\~@]\/','./',''),'^[\\~@]','./node_modules/','') endfunction "}}} function! Redir(cmd) "{{{ for win in range(1, winnr('$')) if getwinvar(win, 'scratch') execute win . 'windo close' endif endfor if a:cmd =~ '^!' let output = system(matchstr(a:cmd, '^!\zs.*')) else redir => output execute a:cmd redir END endif vnew let w:scratch = 1 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile call setline(1, split(output, "\n")) endfunction command! -nargs=1 -complete=command Redir silent call Redir() " Usage: " :Redir hi ............. show the full output of command ':hi' in a scratch window " :Redir !ls -al ........ show the full output of command ':!ls -al' in a scratch window "}}} function! OpenNetrw() abort "{{{ Texplore setl rnu nu endfunction "}}} function! CloseNetrw(keep_buffer) abort "{{{ if a:keep_buffer == 1 let l:current_buffer = bufnr("%") tabclose tabprevious if bufexists(l:current_buffer) > 0 execute "buffer" l:current_buffer endif else tabclose tabprevious endif endfunction "}}} "}}} end #functions "----------------------------------------------------------------------------}}} "#commands{{{ " TrimWhitespace{{{ command! -range=% TrimWhitespace let b:wv = winsaveview() | \ keeppattern ,s/\s\+$// | \ call winrestview(b:wv) "}}} " Scratch, ScratchVertical{{{ command! Scratch new | setlocal buftype=nofile | setlocal bufhidden=hide | setlocal noswapfile command! ScratchVertical vnew | setlocal buftype=nofile | setlocal bufhidden=hide | setlocal noswapfile "}}} "}}} " #settings {{{ scriptencoding utf-8 syntax on set fillchars=stl:\ ,stlnc:\ ,vert:┃ set guioptions-=mTrLb set guioptions+=c if exists('+termguicolors') let &t_8f = "\[38;2;%lu;%lu;%lum" let &t_8b = "\[48;2;%lu;%lu;%lum" set termguicolors endif colorscheme monotonous-dark set updatetime=100 set timeoutlen=500 set lazyredraw " the ;/home/ray tells vim to stop searching at /home/ray set tags+=./.tags,.tags,./tags-py,.tags-py;/home/ray/ " persisitent undo file set undofile set viewoptions-=options set ignorecase set smartcase set wildmenu set wildmode=longest:full,full set wildignore+=/node_modules/,dist/ " Use ag over grep if executable('ag') set grepprg=ag\ --nogroup\ --nocolor\ --ignore\ node_modules endif set hidden set number relativenumber set hlsearch " set completeopt=menuone,preview set completeopt=menuone set nospell set spelllang=en_gb set diffopt+=vertical set tabstop=8 set softtabstop=2 set shiftwidth=2 set shiftround set expandtab set autoindent set textwidth=180 set formatoptions=cq set wrapmargin=0 set cursorline set foldcolumn=2 if has('patch-7-4-2201') set signcolumn=yes endif set colorcolumn=80,120 set iskeyword+=- set scrolloff=10 set showcmd set incsearch set laststatus=2 set shortmess=aoOT set cmdheight=3 set foldmethod=indent set foldnestmax=3 set showmode set autoindent set breakindent set showbreak=\ \ ↳\ set mouse=a set listchars=eol:¬,tab:>-,trail:~,extends:>,precedes:<,space:· set foldtext=MyFoldText() set conceallevel=0 "----------------------------------------------------------------------------}}} " #mappings {{{ let g:mapleader = ' ' " search and replace {{{ nnoremap rr :%s/\<=expand('')\>//g "}}} " miscallaneous {{{ nnoremap 0 ^ nnoremap cs :let @/="" nnoremap : :setlocal norelativenumber: nnoremap rc :so $MYVIMRC nnoremap nh (&hls && v:hlsearch ? ':nohls' : ':set hls')."\n" nnoremap sl :set invlist nnoremap aa A nnoremap a2 A nnoremap ab AB nnoremap co :!clear; nnoremap ;; A; nnoremap ;j jA; nnoremap ,, A, nnoremap ,j jA, " Focus on current fold, close the rest nnoremap zz zMzvzt " replace current word with last yanked/deleted text nnoremap rw "_diwP " replace current word with last yanked text nnoremap ry diw"0P " quick grep of visual selection vnoremap gr y:grep! -R " . " open quickfix window of TODOs nnoremap td :grep! -R 'TODO' .:botright cwindow:echo len(getqflist()) 'TODOs' " devdocs mapping nnoremap dd :DD " write and delete current buffer nnoremap bx :w\|bd " sync highlighting from start nnoremap ss :syntax sync fromstart "}}} " terminal{{{ if has('terminal') tnoremap endif "}}} " windows{{{ nnoremap :resize:vertical resize " }}} " git mappings {{{ " also see vim-fugitive plugin section nnoremap gD :!clear; echo 'git diff'; git diff nnoremap ga :!clear; git add %; git status nnoremap gA :!clear; git add .; git status nnoremap gg :!clear; git add %; git commit -m '' nnoremap gP :!clear; echo 'git push'; git push "}}} " movement/navigation{{{ nnoremap j :resize -5 nnoremap k :resize +5 nnoremap l :vertical resize +5 nnoremap h :vertical resize -5 " alias for :tjump nnoremap tj g " alias for :ptjump nnoremap tp g} "}}} " location list and quickfix mappings {{{ nnoremap lo :botright lwindow nnoremap :lprevzv nnoremap :lnextzv nnoremap lc :lclose nnoremap lh :lhistory nnoremap lp :lolder nnoremap ln :lnewer nnoremap qo :botright cwindow nnoremap :cprevzv nnoremap :cnextzv nnoremap qc :cclose nnoremap qh :chistory nnoremap qp :colder nnoremap qn :cnewer "}}} " insert mode mappings {{{ inoremap jkrg :reg inoremap :w :w inoremap [:w :w inoremap {:w :w " Chain multiple path completions with / key. Selects the first suggestion if " no current selection. Use ctrl-y to finish completion as normal. inoremap / pumvisible() \ ? len(v:completed_item) ? '' : '' \ : '/' "}}} " working_with_underscores{{{ nnoremap w f_l nnoremap b hT_ nnoremap e lt_ onoremap u t_ onoremap U f_ "}}} "----------------------------------------------------------------------------}}} " #abbreviations {{{ " spelling"{{{ iabbrev adn and iabbrev waht what iabbrev tehn then iabbrev functin function iabbrev positin position "}}} " css{{{ iabbrev pabs; position: absolute; iabbrev pfix; position: fixed; iabbrev prel; position: relative; iabbrev fdr; flex-direction: row; iabbrev fdc; flex-direction: column; iabbrev jcc; justify-content: center; iabbrev aic; align-items: center; iabbrev t0; top: 0; iabbrev b0; bottom: 0; iabbrev l0; left: 0; iabbrev r0; right: 0; iabbrev ct'' content-type: ''; "}}} "----------------------------------------------------------------------------}}} " #autocommands {{{ " persistent folds {{{ augroup AutoSaveFolds autocmd! " autocmd BufWinLeave ?* mkview autocmd BufWrite ?* mkview " autocmd BufWinEnter ?* silent loadview autocmd BufRead ?* silent! loadview augroup END " }}} " Show trailing whitepace and spaces before a tab: {{{ augroup whitespaceerrors autocmd! autocmd Syntax * syn match ExtraWhitespace /\s\+$\| \+\ze\t/ containedin=ALL augroup END " }}} " automatically reload if color scheme file written {{{ " augroup coloreload " autocmd! " autocmd BufWritePost customred256.vim so $MYVIMRC " augroup end " " }}} " line numbering {{{ augroup linenumbering autocmd! autocmd InsertEnter * :set norelativenumber autocmd InsertLeave * :set number relativenumber autocmd WinEnter * :set number relativenumber autocmd WinLeave * set norelativenumber if exists('##CmdlineEnter') autocmd CmdlineEnter * :redraw | :set norelativenumber autocmd CmdlineLeave * :set number relativenumber endif augroup END " }}} " auto_window_settings {{{ augroup auto_window_settings autocmd! autocmd WinEnter * call WinEnterColorColumn() autocmd WinEnter * set cursorline | set cursorcolumn " autocmd WinLeave * setlocal colorcolumn=0 autocmd WinLeave * call WinLeaveColorColumn() autocmd WinLeave * set nocursorline | set nocursorcolumn augroup END " }}} " Automatically reload .vimrc if changed {{{ augroup myvimrc autocmd! autocmd BufWritePost .vimrc,_vimrc,vimrc,.gvimrc,_gvimrc,gvimrc so $MYVIMRC | if has('gui_running') | so $MYGVIMRC | endif augroup END " }}} " Open qfix after grepping {{{ " augroup qfixopen " autocmd! " autocmd QuickFixCmdPost *grep* botright cwindow " augroup END " }}} " Open quickfix window{{{ augroup QuickFixAutoload autocmd! autocmd QuickFixCmdPost [^l]* nested botright cwindow autocmd QuickFixCmdPost l* nested botright lwindow augroup END " }}} "----------------------------------------------------------------------------}}} " #statusline {{{ set statusline=\ set statusline+=[%n]\ \ set statusline+=%p\ of\ %L set statusline+=%= set statusline+=%y\ set statusline+=%r\ %m\ %F set statusline+=\ "----------------------------------------------------------------------------}}} runtime vimrc-overrides "}}} " vim: set foldmethod=marker: