"====================================================================== " " Only for key mapping " " COMMON_MAPPING " MANAGE_VIMRC " MOVING_WITH_READLINE " INSERT_SURROUNDING " JUMP_TO_TABS_WITH_ALT " MANAGE_TABS " MANAGE_BUFFERS " MANAGE_WINDOWS " FOLDING " SURROURD_WITH_CHAR " REDIRECTION_WITH_BUFFER " QUICK_SUBSTITUTE " GIT_TIG " 终端支持 " 编译运行 " "====================================================================== " vim: set ts=4 sw=4 tw=78 noet : "---------------------------------------------------------------------- " COMMON_MAPPING "---------------------------------------------------------------------- " Space for searching map / " j/k will move virtual lines (lines that wrap) noremap j (v:count == 0 ? 'gj' : 'j') noremap k (v:count == 0 ? 'gk' : 'k') " Search for selected test vnoremap * y/\V=escape(@",'/\') " set buflisted noremap st :set " Disable highlight when is pressed map :noh " Quick move in a line noremap 30h noremap 30l " Paste register 0 nnoremap "0p " Fast saving nmap w :w! " Fast quit with error nmap q :q " Fast quit with error nmap cq :cq " Switch wrap nmap W :set wrap! " :W sudo saves the file " (useful for handling the permission-denied error) command! W execute 'w !sudo -S tee %' edit! " Enter to open file nnoremap gf nnoremap gF :e " Remap in Quickfix, Cmdwin Location list augroup vimrc_CRfix au! autocmd BufReadPost quickfix nnoremap autocmd CmdwinEnter * nnoremap autocmd CmdwinEnter * nnoremap augroup END " Open terminal " nnoremap , :terminal ++noclose vnoremap , :terminal " Toggle paste mode on and off map pp :setlocal paste! " Switch CWD to the directory of the open buffer nnoremap cd :cd %:p:h:pwd " Switch CWD to root git directory nnoremap cdg :execute 'cd' fnameescape(fnamemodify(finddir('.git', escape(expand('%:p:h'), ' ') . ';'), ':h')):pwd " alias for cd nnoremap cdd :cd nnoremap cd.. :cd .. :pwd nnoremap cd... :cd ../.. :pwd " Move one line up and down nnoremap ddp nnoremap ddkP " In case ALT key is not working " execute "set =\e1" " execute "set =\e2" " execute "set =\e3" " execute "set =\e4" " execute "set =\e5" " execute "set =\e6" " execute "set =\e7" " execute "set =\e8" " execute "set =\e9" " execute "set =\e0" " execute "set =\ef" " execute "set =\eb" " execute "set =\ed" " execute "set =\el" " execute "set =\eh" " Copy from system clipboard nnoremap P :r !xsel -ob vnoremap Y :w !xsel -ib " Spell nnoremap ts :set spell! nnoremap ss ]s nnoremap S [s " Show full path by default nnoremap 1 " Translate by Google API vnoremap Tz :!trans -t zh-TW -b vnoremap Te :!trans -t en-US -b " source .vimrc nnoremap so V:so nnoremap so :source ~/.vimrc vnoremap so :source "---------------------------------------------------------------------- " MANAGE_VIMRC "---------------------------------------------------------------------- nnoremap e :scriptnames nnoremap ee :edit $MYVIMRC autocmd! BUFWRITEPOST $MYVIMRC source $MYVIMRC "---------------------------------------------------------------------- " MOVING_WITH_READLINE "---------------------------------------------------------------------- inoremap inoremap inoremap 0 inoremap $ inoremap inoremap inoremap inoremap inoremap inoremap set cedit= cnoremap cnoremap cnoremap cnoremap cnoremap cnoremap cnoremap " cnoremap cnoremap cnoremap cnoremap cnoremap d$ cnoremap de " Moving with wrap noremap gj noremap gk inoremap gj inoremap gk "---------------------------------------------------------------------- " INSERT_SURROUNDING "---------------------------------------------------------------------- inoremap ' '' inoremap " "" inoremap ( () inoremap [ [] inoremap { {} "---------------------------------------------------------------------- " JUMP_TO_TABS_WITH_ALT "---------------------------------------------------------------------- noremap :tabn 1 noremap :tabn 2 noremap :tabn 3 noremap :tabn 4 noremap :tabn 5 noremap :tabn 6 noremap :tabn 7 noremap :tabn 8 noremap :tablast inoremap :tabn 1 inoremap :tabn 2 inoremap :tabn 3 inoremap :tabn 4 inoremap :tabn 5 inoremap :tabn 6 inoremap :tabn 7 inoremap :tabn 8 inoremap :tablast "---------------------------------------------------------------------- " MANAGE_TABS "---------------------------------------------------------------------- " Useful mappings for managing tabs map tn :tabnew map tc :tabclose map tm :tabmove map to :tabonly noremap :call Tab_MoveLeft() noremap :call Tab_MoveRight() " Let tl toggle between this and the last accessed tab let g:lasttab = 1 nmap tl :exe "tabn ".g:lasttab autocmd TabLeave * let g:lasttab = tabpagenr() " Opens a new tab with the current buffer's path " Super useful when editing files in the same directory map te :tabedit =expand("%:p:h") " Tab move functions function! Tab_MoveLeft() let l:tabnr = tabpagenr() - 2 if l:tabnr >= 0 exec 'tabmove '.l:tabnr endif endfunc function! Tab_MoveRight() let l:tabnr = tabpagenr() + 1 if l:tabnr <= tabpagenr('$') exec 'tabmove '.l:tabnr endif endfunc "---------------------------------------------------------------------- " MANAGE_BUFFERS "---------------------------------------------------------------------- " Open a new buffer nmap b :enew nmap B :enew nmap O :e /tmp/buffer " Next buffer noremap l :exe "buffer ".g:lastbuffer " noremap :exe 'buffer '.g:lastbuffer " set filetype noremap ft :e'set filetype='..&filetype " Let l toggle between this and the last accessed buffer augroup SaveLastBuffer let g:lastbuffer = 1 au BufLeave * let g:lastbuffer = bufnr() augroup END " Uset d to toggle Diff mode function! s:SwitchDiff() if &diff windo | if &buftype == "nofile" | bdelete | endif else DiffOrig wincmd p | set nobuflisted | wincmd p endif endfunction com! SwitchDiff call s:SwitchDiff() nnoremap d silent! SwitchDiff function! s:SwitchDiffForGitHEAD() nmap cdg if &diff windo | if &buftype == "nofile" | bdelete | endif else vert new | set buftype=nofile nobuflisted read !git show HEAD:# 0d_ | diffthis | wincmd p | diffthis endif endfunction com! SwitchDiffForGitHEAD call s:SwitchDiffForGitHEAD() nnoremap D silent! SwitchDiffForGitHEAD "---------------------------------------------------------------------- " MANAGE_WINDOWS "---------------------------------------------------------------------- nnoremap sb :windo set scrollbind! "---------------------------------------------------------------------- " FOLDING "---------------------------------------------------------------------- " Set foldmethod noremap fm :e'set foldmethod='..&foldmethod " Show fold level when it changes nnoremap zm zm:set foldlevel nnoremap zr zr:set foldlevel " Use l to open fold nnoremap l foldclosed('.') == -1 ? 'l' : 'zo' " Open fold in next line nnoremap zo foldclosed('.') == -1 ? 'zjzo' : 'zo' nnoremap zO foldclosed('.') == -1 ? 'zjzO' : 'zO' "---------------------------------------------------------------------- " SURROURD_WITH_CHAR "---------------------------------------------------------------------- vnoremap S sa vnoremap ' ``>la' vnoremap q ``>la" vnoremap ( ``>la) vnoremap [ ``>la] vnoremap { ``>la} vnoremap ` ``>la` vnoremap ``>la vnoremap Q ``>la」 "---------------------------------------------------------------------- " REDIRECTION_WITH_BUFFER "---------------------------------------------------------------------- " 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! 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 enew let w:scratch = 1 " setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile setlocal buftype=nofile noswapfile call setline(1, split(output, "\n")) endfunction command! -nargs=1 -complete=command Redir silent call Redir() nnoremap rr :Redir "---------------------------------------------------------------------- " QUICK_SUBSTITUTE " Press n times for area, and for substitute "---------------------------------------------------------------------- " substitute across file vnoremap s y:%s//0/g let g:search_not_in_register = 1 " When leaving visual mode, resume search_not_in_register autocmd Modechanged [vV\x16]*:* let g:search_not_in_register = 1 function! ExpandSelectionBySearch(sep) if g:search_not_in_register " Save current selection to register, and keep selection execute 'norm ygv' let g:search_not_in_register = 0 endif " Use register s to go to next search, counts/total is displayed in " statusline call feedkeys(a:sep.."\0"..a:sep.."e\") endfunction function! SubstituteBySearch() " Apply current search for default substitute text call feedkeys(":s//\0/g\\") endfunction vnoremap call ExpandSelectionBySearch('/') vnoremap call ExpandSelectionBySearch('?') vnoremap call SubstituteBySearch() "---------------------------------------------------------------------- " GIT_TIG "---------------------------------------------------------------------- let g:tig_explorer_keymap_commit_split = '' let g:tig_explorer_keymap_commit_vsplit = '' nnoremap Tig nnoremap s TigStatus nnoremap b TigBlame nnoremap d :vertical TigOpenFileWithCommit + % 0 "---------------------------------------------------------------------- " Markdown items (temproray solution) "---------------------------------------------------------------------- " Toggle list item in markdown: "- [ ] XXX" -> "XXX" -> "- XXX" -> "- [ ] XXX" " autocmd FileType markdown nnoremap i V:!sed -E '/^ *- \[.\]/ { s/^( *)- \[.\] */\1/; q; }; /^ *[^[:space:]-]/ { s/^( *)/\1- /; q; }; /^ *- / { s/^( *)- /\1- [ ] /; q; }' " autocmd FileType markdown nnoremap I V:!sed -E 's/^( *)/\1- [ ] /' " Toggle task status: "- [ ] " -> "- [x]" -> "- [.] " -> "- [ ] " " nnoremap x V:!sed -E '/^ *- \[ \]/ { s/^( *)- \[ \]/\1- [x]/; q; }; /^ *- \[\x\]/ { s/^( *)- \[\x\]/\1- [.]/; q; }; /^ *- \[\.\]/ { s/^( *)- \[\.\]/\1- [ ]/; q; }' "---------------------------------------------------------------------- " Common command "---------------------------------------------------------------------- " Show date selector nnoremap dd :r !sh -c 'LANG=en zenity --calendar --date-format="\%Y.\%m.\%d" 2>/dev/null' nnoremap dD :r !sh -c 'LANG=en zenity --calendar --date-format="\%a \%b \%d" 2>/dev/null' nnoremap dt :r !date +\%H:\%mA "---------------------------------------------------------------------- " 窗口切换:ALT+SHIFT+hjkl " 传统的 CTRL+hjkl 移动窗口不适用于 vim 8.1 的终端模式,CTRL+hjkl 在 " bash/zsh 及带文本界面的程序中都是重要键位需要保留,不能 tnoremap 的 "---------------------------------------------------------------------- noremap h noremap l noremap j noremap k inoremap h inoremap l inoremap j inoremap k if has('terminal') && exists(':terminal') == 2 && has('patch-8.1.1') " vim 8.1 支持 termwinkey ,不需要把 terminal 切换成 normal 模式 " 设置 termwinkey 为 CTRL 加减号(GVIM),有些终端下是 CTRL+? " 后面四个键位是搭配 termwinkey 的,如果 termwinkey 更改,也要改 set termwinkey= tnoremap h tnoremap l tnoremap j tnoremap k tnoremap elseif has('nvim') " neovim 没有 termwinkey 支持,必须把 terminal 切换回 normal 模式 tnoremap h tnoremap l tnoremap j tnoremap k tnoremap endif "---------------------------------------------------------------------- " 编译运行 C/C++ 项目 " 详细见:http://www.skywind.me/blog/archives/2084 "---------------------------------------------------------------------- " 自动打开 quickfix window ,高度为 6 let g:asyncrun_open = 6 " 任务结束时候响铃提醒 let g:asyncrun_bell = 1 " 设置 F10 打开/关闭 Quickfix 窗口 nnoremap :call asyncrun#quickfix_toggle(6) " F9 编译 C/C++ 文件 nnoremap :AsyncRun gcc -Wall -O2 "$(VIM_FILEPATH)" -o "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" " F5 运行文件 nnoremap :call ExecuteFile() " F7 编译项目 nnoremap :AsyncRun -cwd= make " F8 运行项目 nnoremap :AsyncRun -cwd= -raw make run " F6 测试项目 nnoremap :AsyncRun -cwd= -raw make test " 更新 cmake nnoremap :AsyncRun -cwd= cmake . " Windows 下支持直接打开新 cmd 窗口运行 if has('win32') || has('win64') nnoremap :AsyncRun -cwd= -mode=4 make run endif "---------------------------------------------------------------------- " F5 运行当前文件:根据文件类型判断方法,并且输出到 quickfix 窗口 "---------------------------------------------------------------------- function! ExecuteFile() let cmd = '' if index(['c', 'cpp', 'rs', 'go'], &ft) >= 0 " native 语言,把当前文件名去掉扩展名后作为可执行运行 " 写全路径名是因为后面 -cwd=? 会改变运行时的当前路径,所以写全路径 " 加双引号是为了避免路径中包含空格 let cmd = '"$(VIM_FILEDIR)/$(VIM_FILENOEXT)"' elseif &ft == 'python' let $PYTHONUNBUFFERED=1 " 关闭 python 缓存,实时看到输出 let cmd = 'python "$(VIM_FILEPATH)"' elseif &ft == 'javascript' let cmd = 'node "$(VIM_FILEPATH)"' elseif &ft == 'perl' let cmd = 'perl "$(VIM_FILEPATH)"' elseif &ft == 'ruby' let cmd = 'ruby "$(VIM_FILEPATH)"' elseif &ft == 'php' let cmd = 'php "$(VIM_FILEPATH)"' elseif &ft == 'lua' let cmd = 'lua "$(VIM_FILEPATH)"' elseif &ft == 'zsh' let cmd = 'zsh "$(VIM_FILEPATH)"' elseif &ft == 'ps1' let cmd = 'powershell -file "$(VIM_FILEPATH)"' elseif &ft == 'vbs' let cmd = 'cscript -nologo "$(VIM_FILEPATH)"' elseif &ft == 'sh' let cmd = 'bash "$(VIM_FILEPATH)"' else return endif " Windows 下打开新的窗口 (-mode=4) 运行程序,其他系统在 quickfix 运行 " -raw: 输出内容直接显示到 quickfix window 不匹配 errorformat " -save=2: 保存所有改动过的文件 " -cwd=$(VIM_FILEDIR): 运行初始化目录为文件所在目录 if has('win32') || has('win64') exec 'AsyncRun -cwd=$(VIM_FILEDIR) -raw -save=2 -mode=4 '. cmd else exec 'AsyncRun -cwd=$(VIM_FILEDIR) -raw -save=2 -mode=0 '. cmd endif endfunc "---------------------------------------------------------------------- " F2 在项目目录下 Grep 光标下单词,默认 C/C++/Py/Js ,扩展名自己扩充 " 支持 rg/grep/findstr ,其他类型可以自己扩充 " 不是在当前目录 grep,而是会去到当前文件所属的项目目录 project root " 下面进行 grep,这样能方便的对相关项目进行搜索 "---------------------------------------------------------------------- if executable('rg') noremap :AsyncRun! -cwd= rg -n --no-heading \ --color never -g *.h -g *.c* -g *.py -g *.js -g *.vim \ "" elseif has('win32') || has('win64') noremap :AsyncRun! -cwd= findstr /n /s /C:"" \ "\%CD\%\*.h" "\%CD\%\*.c*" "\%CD\%\*.py" "\%CD\%\*.js" \ "\%CD\%\*.vim" \ else noremap :AsyncRun! -cwd= grep -n -s -R \ --include='*.h' --include='*.c*' --include='*.py' \ --include='*.js' --include='*.vim' \ '' endif