Last active
June 12, 2024 08:30
-
-
Save roachsinai/92f1841d2d4940be789f0a5b434b113c to your computer and use it in GitHub Desktop.
minimal vimrc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" | |
" A (not so) minimal vimrc. | |
" https://github.com/mhinz/vim-galore/blob/master/static/minimal-vimrc.vim | |
" | |
" You want Vim, not vi. When Vim finds a vimrc, 'nocompatible' is set anyway. | |
" We set it explicitely to make our position clear! | |
set nocompatible | |
filetype plugin indent on " Load plugins according to detected filetype. | |
syntax on " Enable syntax highlighting. | |
set autoindent " Indent according to previous line. | |
set pastetoggle =<F2> " https://zhuanlan.zhihu.com/p/652837014 | |
set expandtab " Use spaces instead of tabs. | |
set tabstop =4 | |
set shiftwidth =4 " >> indents by 4 spaces. | |
set softtabstop =4 | |
set shiftround " >> indents to next multiple of 'shiftwidth'. | |
set backspace =indent,eol,start " Make backspace work as you would expect. | |
set hidden " Switch between buffers without having to save first. | |
set laststatus =2 " Always show statusline. | |
set display =lastline " Show as much as possible of the last line. | |
set showmode " Show current mode in command-line. | |
set showcmd " Show already typed keys when more are expected. | |
set ttyfast " Faster redrawing. | |
set lazyredraw " Only redraw when necessary. | |
set splitbelow " Open new windows below the current window. | |
set splitright " Open new windows right of the current window. | |
set ignorecase smartcase | |
set number | |
highlight LineNr term=bold cterm=NONE ctermfg=DarkGrey ctermbg=NONE gui=NONE guifg=DarkGrey guibg=NONE | |
" set cursorline " Find the current line quickly. | |
set wrapscan " Searches wrap around end-of-file. | |
set report =0 " Always report changed lines. | |
set synmaxcol =200 " Only highlight the first 200 columns. | |
set list " Show non-printable characters. | |
if has('multi_byte') && &encoding ==# 'utf-8' | |
let &listchars = 'tab:▸ ,extends:❯,precedes:❮,nbsp:±' | |
else | |
let &listchars = 'tab:> ,extends:>,precedes:<,nbsp:.' | |
endif | |
" The fish shell is not very compatible to other shells and unexpectedly | |
" breaks things that use 'shell'. | |
if &shell =~# 'fish$' | |
set shell=/bin/bash | |
endif | |
" https://gist.github.com/meskarune/57b613907ebd1df67eb7bdb83c6e6641 | |
" status bar colors | |
au InsertEnter * hi statusline guifg=black guibg=#d7afff ctermfg=black ctermbg=magenta | |
au InsertLeave * hi statusline guifg=black guibg=#8fbfdc ctermfg=black ctermbg=cyan | |
hi statusline guifg=black guibg=#8fbfdc ctermfg=black ctermbg=cyan | |
" Status line | |
" default: set statusline=%f\ %h%w%m%r\ %=%(%l,%c%V\ %=\ %P%) | |
" Status Line Custom | |
let g:currentmode={ | |
\ 'n' : 'Normal', | |
\ 'no' : 'Normal·Operator Pending', | |
\ 'v' : 'Visual', | |
\ 'V' : 'V·Line', | |
\ '' : 'V·Block', | |
\ 's' : 'Select', | |
\ 'S' : 'S·Line', | |
\ '' : 'S·Block', | |
\ 'i' : 'Insert', | |
\ 'R' : 'Replace', | |
\ 'Rv' : 'V·Replace', | |
\ 'c' : 'Command', | |
\ 'cv' : 'Vim Ex', | |
\ 'ce' : 'Ex', | |
\ 'r' : 'Prompt', | |
\ 'rm' : 'More', | |
\ 'r?' : 'Confirm', | |
\ '!' : 'Shell', | |
\ 't' : 'Terminal' | |
\} | |
function! StatuslineGit() | |
" use tirm above vim 7.4, if not trim will show garbled code: ^[[?12;4$y | |
let l:branchname = \ | |
substitute(system('git rev-parse --abbrev-ref HEAD 2>/dev/null'), '^\s*\(.\{-}\)\s*$', '\1', '') | |
return strlen(l:branchname) > 0?' '.l:branchname.' ':'' | |
endfunction | |
function! ShrinkHome(path) | |
let home = expand('~') | |
let result = substitute(a:path, '^' . home, '~', '') | |
return result | |
endfunction | |
set laststatus=2 | |
set noshowmode | |
set statusline= | |
set statusline+=%0*\ %{toupper(g:currentmode[mode()])}\ " The current mode | |
set statusline+=%0*\ %n\ " Buffer number | |
set statusline+=%1*\ %{pathshorten(ShrinkHome(expand('%:f')))}%m%r%h%w\ " File path, modified, readonly, helpfile, preview | |
"set statusline+=%{StatuslineGit()} | |
set statusline+=%3*│ " Separator | |
set statusline+=%2*\ %Y\ " FileType | |
set statusline+=%3*│ " Separator | |
set statusline+=%2*\ %{''.(&fenc!=''?&fenc:&enc).''} " Encoding | |
set statusline+=\ (%{&ff}) " FileFormat (dos/unix..) | |
set statusline+=%= " Right Side | |
set statusline+=%2*\ col:\ %02v\ " Colomn number | |
set statusline+=%3*│ " Separator | |
set statusline+=%1*\ ln:\ %02l/%L\ (%3p%%)\ " Line number / total lines, percentage of document | |
set statusline+=%{&paste?'PASTE':''} | |
" https://stackoverflow.com/questions/5375240/a-more-useful-statusline-in-vim | |
hi User1 ctermfg=007 ctermbg=239 guibg=#4e4e4e guifg=#adadad | |
hi User2 ctermfg=007 ctermbg=236 guibg=#303030 guifg=#adadad | |
hi User3 ctermfg=236 ctermbg=236 guibg=#303030 guifg=#303030 | |
hi User4 ctermfg=239 ctermbg=239 guibg=#4e4e4e guifg=#4e4e4e | |
" https://jeffkreeftmeijer.com/vim-number/ | |
set number | |
augroup numbertoggle | |
autocmd! | |
autocmd BufEnter,FocusGained,InsertLeave,WinEnter * if &nu && mode() != "i" | set rnu | endif | |
autocmd BufLeave,FocusLost,InsertEnter,WinLeave * if &nu | set nornu | endif | |
augroup END | |
" mac os | |
" set clipboard=unnamed | |
let mapleader=" " | |
nmap <leader>q :q<CR> | |
nmap <leader>w :w<CR> | |
nmap <leader>wq :wq<CR> | |
nmap <tab>q :qall<CR> | |
xnoremap < <gv | |
xnoremap > >gv | |
nmap <leader>d "+d | |
nmap <leader>p "+p | |
vmap <leader>d "+d | |
nmap <leader>; % | |
if exists('$TMUX') | |
nmap <leader>y <Plug>OSCYankOperator | |
nmap <leader>yy <leader>y_ | |
vmap <leader>y <Plug>OSCYankVisual | |
else | |
nmap <leader>y "+y | |
vmap <leader>y "+y | |
endif | |
" let g:fcitx5_remote = $HOME . '/.local/bin/fcitx-remote' | |
" let g:fcitx5_remote = '/usr/local/bin/im-select' | |
let g:fcitx5_remote = '/opt/homebrew/bin/im-select' | |
if filereadable(expand('~/.vim/autoload/plug.vim')) | |
call plug#begin() | |
if filereadable(g:fcitx5_remote) | |
Plug 'roachsinai/fcitx.vim', { 'branch': 'macos' } | |
endif | |
Plug 'ojroques/vim-oscyank', {'branch': 'main'} | |
call plug#end() | |
endif | |
if !has('gui_running') && !(has('win32') || has('win64')) | |
" set t_kb | |
endif | |
inoremap <C-h> <left> | |
inoremap <C-j> <down> | |
inoremap <C-k> <up> | |
inoremap <C-l> <right> | |
inoremap <c-a> <home> | |
inoremap <c-e> <end> | |
inoremap <c-d> <del> | |
inoremap <c-_> <c-k> | |
inoremap <c-b> <c-left> | |
inoremap <c-f> <c-right> | |
cnoremap <c-h> <left> | |
cnoremap <c-j> <down> | |
cnoremap <c-k> <up> | |
cnoremap <c-l> <right> | |
cnoremap <c-a> <home> | |
cnoremap <c-e> <end> | |
cnoremap <c-d> <del> | |
cnoremap <c-_> <c-k> | |
cnoremap <c-b> <c-left> | |
cnoremap <c-f> <c-right> | |
" show commands begin with current inputs | |
cnoremap <m-f> <c-d> | |
" https://vi.stackexchange.com/a/3029/16299 | |
function! Preserve(command) | |
" Preparation: save window state | |
let l:saved_winview = winsaveview() | |
" Run the command: | |
execute a:command | |
" Clean up: restore previous window position | |
call winrestview(l:saved_winview) | |
endfunction | |
nnoremap <leader>sw :call Preserve("%s/\\s\\+$//e")<CR> | |
xnoremap <leader>sw :call Preserve("'<,'>s/\\s\\+$//e")<CR> | |
hi TrailingWhitespace ctermbg=red guibg=red | |
call matchadd("TrailingWhitespace", '\v\s+$') | |
" needed in macos using iTerm2 | |
if $TMUX != '' | |
set ttimeoutlen=20 | |
elseif &ttimeoutlen > 60 || &ttimeoutlen <= 0 | |
set ttimeoutlen=60 | |
endif | |
" Get the directory of a file | |
" - On Ex command lines, returns the directory of the file ('./' for new files) | |
" - On other command lines (/,?) returns the keymap used to trigger it | |
function! CommandDir(keymap) abort | |
let l:command_type = getcmdtype() | |
if l:command_type isnot# ':' | |
return a:keymap | |
endif | |
let l:dir = expand('%:h') | |
if empty(l:dir) | |
let l:dir = '.' | |
endif | |
return l:dir . '/' | |
endfunction | |
" Quickly input the directory of the current file on the command line | |
cnoremap <expr> %% CommandDir('%%') | |
" Need 'recursive' mapping here for %% | |
nmap <leader>n :e %% | |
function! GotoLineWithString(str) | |
let l:line_number = 1 | |
while l:line_number <= line("$") | |
if getline(l:line_number) == a:str | |
call setpos('.', [0, l:line_number, 1, 0]) | |
return | |
endif | |
let l:line_number += 1 | |
endwhile | |
echo "No matching line found." | |
endfunction | |
" https://stackoverflow.com/a/60643538/6074780 | |
" |¦┆┊│⎸ ▏ | |
set fillchars+=vert:\│ | |
hi clear VertSplit | |
hi VertSplit guifg=black ctermfg=darkGrey | |
" https://vi.stackexchange.com/a/21800/16299 | |
" https://vonheikemen.github.io/devlog/tools/using-netrw-vim-builtin-file-explorer/ | |
" Explore | |
let g:NetrwIsOpen=0 | |
function! ToggleNetrw(...) | |
if g:NetrwIsOpen | |
let g:NetrwIsOpen=0 | |
let i = bufnr("$") | |
while (i >= 1) | |
if (getbufvar(i, "&filetype") == "netrw") | |
silent exe "bwipeout " . i | |
endif | |
let i-=1 | |
endwhile | |
else | |
let g:NetrwIsOpen=1 | |
let g:prev_fname = expand("%:t") | |
if a:0 > 0 | |
silent exe "Vexplore " . a:1 | |
else | |
" https://github.com/vim/vim/tags?after=v7.4.001 | |
silent Vexplore " no Lexplore on 7.4 | |
endif | |
call GotoLineWithString(g:prev_fname) | |
endif | |
endfunction | |
if has('mac') | |
" https://github.com/vim/vim/issues/4738#issuecomment-856925080 | |
let g:netrw_http_cmd = 'open' | |
endif | |
let g:netrw_keepdir = 0 | |
let g:netrw_winsize = 15 | |
let g:netrw_banner = 0 | |
let g:netrw_list_hide = '\(^\|\s\s\)\zs\.\S\+' | |
let g:netrw_localcopydircmd = 'cp -r' | |
hi! link netrwMarkFile Search | |
nnoremap <leader>l :call ToggleNetrw("%:p:h")<CR> | |
nnoremap <leader>L :call ToggleNetrw()<CR> | |
function! NetrwLExp() | |
let l:filename = getline(".") | |
let l:lastchar = l:filename[-1:] | |
if index(["@", "*", "/"], l:lastchar) >= 0 | |
let l:filename = l:filename[:-2] | |
endif | |
let l:filename = expand('%:p:h') . '/' . l:filename | |
if !isdirectory(l:filename) | |
wincmd p | |
" else | |
" exec "normal! \<Plug>NetrwLocalBrowseCheck" | |
endif | |
exec 'edit ' . l:filename | |
if &hlsearch | |
set nohlsearch | |
endif | |
endfunction | |
function! NetrwMapping() | |
" nmap must reset each time swith to netrw window on 7.4 | |
nmap <buffer> H u | |
nmap <buffer> h -^ | |
nmap <buffer> l <CR> | |
nmap <buffer> <CR> :call NetrwLExp()<CR> | |
nmap <buffer> . gh | |
nmap <buffer> P <C-w>z | |
nmap <buffer> <c-l> :vertical resize +5<cr> | |
" must move call GotoLineWithString(g:prev_fname) | |
" to TmuxMove, as not work at here on 7.4 | |
endfunction | |
augroup netrw_mapping | |
autocmd! | |
autocmd FileType netrw call NetrwMapping() " filetype not working on 7.4 | |
augroup END | |
set directory^=$HOME/.vim/swap// | |
set undofile | |
set undodir=$HOME/.vim/undo | |
" if !isdirectory(&undodir) | |
" call mkdir(&undodir, 'p', 0755) | |
" endif | |
" https://stackoverflow.com/a/14449484/6074780 | |
autocmd BufReadPost * | |
\ if line("'\"") > 0 && line("'\"") <= line("$") | | |
\ exe "normal! g`\"" | | |
\ endif | |
nmap <leader>cs :.s/\[\zs.*\ze]/\=substitute(submatch(0), '_', '\\_', 'g')/<CR> | |
nmap <leader>zs k0Di[]<esc>PJxDa()<esc>P0 | |
" https://github.com/vim-scripts/BufOnly.vim/blob/master/plugin/BufOnly.vim | |
command! -nargs=? -complete=buffer -bang Bonly | |
\ :call BufOnly('<args>', '<bang>') | |
command! -nargs=? -complete=buffer -bang BOnly | |
\ :call BufOnly('<args>', '<bang>') | |
command! -nargs=? -complete=buffer -bang Bufonly | |
\ :call BufOnly('<args>', '<bang>') | |
command! -nargs=? -complete=buffer -bang BufOnly | |
\ :call BufOnly('<args>', '<bang>') | |
function! BufOnly(buffer, bang) | |
if a:buffer == '' | |
" No buffer provided, use the current buffer. | |
let buffer = bufnr('%') | |
elseif (a:buffer + 0) > 0 | |
" A buffer number was provided. | |
let buffer = bufnr(a:buffer + 0) | |
else | |
" A buffer name was provided. | |
let buffer = bufnr(a:buffer) | |
endif | |
if buffer == -1 | |
echohl ErrorMsg | |
echomsg "No matching buffer for" a:buffer | |
echohl None | |
return | |
endif | |
let last_buffer = bufnr('$') | |
let delete_count = 0 | |
let n = 1 | |
while n <= last_buffer | |
if n != buffer && buflisted(n) | |
if a:bang == '' && getbufvar(n, '&modified') | |
echohl ErrorMsg | |
echomsg 'No write since last change for buffer' | |
\ n '(add ! to override)' | |
echohl None | |
else | |
silent exe 'bdel' . a:bang . ' ' . n | |
if ! buflisted(n) | |
let delete_count = delete_count+1 | |
endif | |
endif | |
endif | |
let n = n+1 | |
endwhile | |
if delete_count == 1 | |
echomsg delete_count "buffer deleted" | |
elseif delete_count > 1 | |
echomsg delete_count "buffers deleted" | |
endif | |
endfunction | |
" delete buffer without losing the split window | |
nnoremap <silent> <leader>bd :bp\|bd #<CR> | |
" delete all buffers except current | |
" command! BufOnly silent! execute "%bd|e#|bd#" | |
nnoremap <silent> <leader>bo :BufOnly<CR> | |
nnoremap <leader>co :copen<CR> | |
nnoremap <leader>cc :cclose<CR> | |
" https://www.zhihu.com/question/636018229/answer/3386613023 | |
" Vim 7.4 not support function execute() | |
command! -range ExecVimL call ExecVimLRange(<line1>, <line2>) | |
command! -range ExecLua call ExecLuaRange(<line1>, <line2>) | |
function! ExecVimLRange(line1, line2) | |
let l:vim_code = join(getline(a:line1, a:line2), "\n") | |
" https://vi.stackexchange.com/a/29508/16299 | |
let l:vim_code = substitute(l:vim_code, '\n\s*\\\s*', ' ', 'g') | |
execute l:vim_code | |
endfunction | |
function! ExecLuaRange(line1, line2) | |
let l:lua_code = join(getline(a:line1, a:line2), "\n") | |
execute 'lua ' . l:lua_code | |
endfunction | |
" [S]ource | |
nnoremap <silent> <expr> <leader>s ((&ft=='lua' ? ':ExecLua' : ':ExecVimL') . '<cr>:<c-u>echo "Current line executed"<cr>') | |
xnoremap <silent> <expr> <leader>s ((&ft=='lua' ? ':ExecLua' : ':ExecVimL') . '<cr>:<c-u>echo "Selected range executed"<cr>') | |
" https://stackoverflow.com/a/16679182/6074780 | |
" delete file from Disk | |
" shfit+d in :Ex | |
nnoremap <leader>rm :call delete(expand('%')) \| bdelete!<CR> | |
" https://vi.stackexchange.com/a/2187/16299 | |
" buffer list | |
nnoremap <leader>bl :set nomore <Bar> :ls <Bar> :set more <CR>:b<Space> | |
" https://skywind3000.com/blog/archives/2021/ <leader>zs not work | |
" https://blog.lilydjwg.me/posts/23574.html '.' not work | |
" https://github.com/skywind3000/vim/blob/master/plugin/altmeta.vim#L25 | |
function! Set_key(key, keyCode) | |
if get(g:, 'altmeta_skip_meta', 0) == 0 | |
execute "set " . a:key . "=" . a:keyCode | |
endif | |
endfunc | |
function! Init_meta_letters() | |
let c = 'a' | |
while c <= 'z' | |
call Set_key("<M-" . c . ">", "\e" . c) | |
let c = nr2char(char2nr(c) + 1) | |
endwhile | |
endfunc | |
call Init_meta_letters() | |
let g:prev_fname = '' | |
" https://www.zhihu.com/question/278228687/answer/413375553 | |
" https://gist.github.com/mislav/5189704?permalink_comment_id=3312967#gistcomment-3312967 | |
function! TmuxMove(direction) | |
if a:direction == 'h' | |
" suppose current buffer is not netrw | |
let g:prev_fname = expand("%:t") | |
endif | |
if &hlsearch | |
set nohlsearch | |
redraw | |
endif | |
let wnr = winnr() | |
silent! execute 'wincmd ' . a:direction | |
" If the winnr is still the same after we moved, it is the last pane | |
if wnr == winnr() | |
call system('tmux select-pane -' . tr(a:direction, 'phjkl', 'lLDUR')) | |
elseif &filetype == "netrw" | |
if line('$') == 2 && getline(1) == getline(2) | |
exec "normal! \<Plug>NetrwRefresh" | |
endif | |
call GotoLineWithString(g:prev_fname) | |
end | |
endfunction | |
nnoremap <silent> <m-h> :call TmuxMove('h')<cr> | |
nnoremap <silent> <m-j> :call TmuxMove('j')<cr> | |
nnoremap <silent> <m-k> :call TmuxMove('k')<cr> | |
nnoremap <silent> <m-l> :call TmuxMove('l')<cr> | |
inoremap <m-h> <esc>:call TmuxMove('h')<cr> | |
inoremap <m-l> <esc>:call TmuxMove('j')<cr> | |
inoremap <m-j> <esc>:call TmuxMove('k')<cr> | |
inoremap <m-k> <esc>:call TmuxMove('l')<cr> | |
noremap <m-H> <c-w>H | |
noremap <m-L> <c-w>L | |
noremap <m-J> <c-w>J | |
noremap <m-K> <c-w>K | |
inoremap <m-H> <esc><c-w>H | |
inoremap <m-L> <esc><c-w>L | |
inoremap <m-J> <esc><c-w>J | |
inoremap <m-K> <esc><c-w>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=<c-_> | |
tnoremap <m-h> <c-_>h | |
tnoremap <m-l> <c-_>l | |
tnoremap <m-j> <c-_>j | |
tnoremap <m-k> <c-_>k | |
tnoremap <m-q> <c-\><c-n> | |
elseif has('nvim') | |
" neovim 没有 termwinkey 支持,必须把 terminal 切换回 normal 模式 | |
tnoremap <m-h> <c-\><c-n><c-w>h | |
tnoremap <m-l> <c-\><c-n><c-w>l | |
tnoremap <m-j> <c-\><c-n><c-w>j | |
tnoremap <m-k> <c-\><c-n><c-w>k | |
tnoremap <m-q> <c-\><c-n> | |
endif | |
nnoremap <c-l> :vertical resize +5<cr> | |
nnoremap <c-k> :resize +5<cr> | |
nnoremap <c-j> :resize -5<cr> | |
nnoremap <c-h> :vertical resize -5<cr> | |
" insert tab at beginning of each line of current buffer | |
nnoremap <leader>it :%s/^/\t/g<CR> | |
" format zhihu share | |
nmap <leader>zs k0Di[]<esc>PJxDa()<esc>P0 | |
" format csdn link/share | |
nmap <leader>cs :.s/\[\zs.*\ze]/\=substitute(submatch(0), '_', '\\_', 'g')/<CR> | |
" https://stackoverflow.com/a/61624228/6074780 | |
vnoremap al :<C-U>normal 0v$h<CR> | |
omap al :normal val<CR> | |
vnoremap il :<C-U>normal ^vg_<CR> | |
omap il :normal vil<CR> | |
vnoremap ae :<C-U>normal ggVG<CR> | |
omap ae :normal vae<CR> | |
vnoremap ie :<C-U>normal ggvG$<CR> | |
omap ie :normal vie<CR> | |
function! GetRootDir() | |
let l:current_file = expand('%:p') | |
while l:current_file != '/' | |
let l:current_file = fnamemodify(l:current_file, ':h') | |
if filereadable(l:current_file . '/.git') || filereadable(l:current_file . '/.root') | |
return l:current_file | |
endif | |
endwhile | |
return getcwd() | |
endfunction | |
" https://dev.to/pbnj/interactive-fuzzy-finding-in-vim-without-plugins-4kkj | |
function! FZF() abort | |
let l:tempname = tempname() | |
" fzf | awk '{ print $1":1:0" }' > file | |
let l:cwd = fnameescape(GetRootDir()) | |
if l:cwd == getcwd() | |
execute 'silent !fzf --multi ' . '| sed ''s/$/:1:0/'' > ' . fnameescape(l:tempname) | |
else | |
execute 'silent !find ' . l:cwd . ' -mindepth 1 | fzf --multi ' . '| sed ''s/$/:1:0/'' > ' . fnameescape(l:tempname) | |
endif | |
try | |
execute 'cfile ' . l:tempname | |
redraw! | |
finally | |
call delete(l:tempname) | |
endtry | |
endfunction | |
" :Files | |
command! -nargs=* Files call FZF() | |
nnoremap <leader>e :Files<cr> | |
function! RG(args) abort | |
let l:tempname = tempname() | |
let l:pattern = '.' | |
if len(a:args) > 0 | |
let l:pattern = a:args | |
endif | |
let l:cwd = fnameescape(GetRootDir()) | |
" rg --vimgrep <pattern> | fzf -m > file | |
execute 'silent !rg --vimgrep ''' . l:pattern . ''' ' . l:cwd . ' | fzf -m > ' . fnameescape(l:tempname) | |
try | |
execute 'cfile ' . l:tempname | |
redraw! | |
finally | |
call delete(l:tempname) | |
endtry | |
endfunction | |
" :Rg [pattern] | |
command! -nargs=* Rg call RG(<q-args>) | |
nnoremap <Leader>aw :Rg <cword><cr> | |
nnoremap <Leader>ai :Rg<space> | |
highlight MatchParen | |
\ cterm=underline,bold ctermbg=NONE ctermfg=lightblue | |
\ gui=underline,bold guibg=NONE guifg=lightblue | |
highlight Search | |
\ cterm=reverse,bold ctermfg=108 ctermbg=235 | |
\ gui=reverse,bold guifg=#8ec07c guibg=#282828 | |
hi Visual cterm=none ctermbg=darkgrey ctermfg=cyan | |
set incsearch " Highlight while searching with / or ?. | |
set nohlsearch " disable explicitely as hlsearch on default in Vim 7.4 | |
" same effect as: highlight clear Search | |
" https://www.reddit.com/r/neovim/comments/j6ugb4/comment/g91ru7q | |
" highlight last searched until CursorMoved | |
function! HLNext() | |
" SpellRare when select only one character | |
let l:higroup = matchend(getline('.'), '\c'.@/, col('.')-1) == col('.') | |
\ ? 'SpellRare' : 'IncSearch' | |
let b:match_id = matchadd(l:higroup, '\c\%#'.@/, 101) | |
if !&hlsearch | |
set hlsearch | |
redraw | |
call HLNextAug() | |
endif | |
endfunction | |
function! HLSearch() | |
let b:hlsearch_on = 1 | |
if !&hlsearch | |
set hlsearch | |
redraw | |
call HLNextAug() | |
endif | |
endfunction | |
function! HLNextAug() | |
augroup HLNext | |
autocmd! | |
autocmd CursorMoved <buffer> call RemoveHighlight() | |
augroup END | |
endfunction | |
function! RemoveHighlight() | |
if exists('b:match_id') | |
silent! call matchdelete(b:match_id) | |
unlet b:match_id | |
if &hlsearch | |
set nohlsearch | |
redraw | |
endif | |
endif | |
if exists('b:hlsearch_on') | |
let l:search_reg = getreg("/") | |
let l:current_line = getline('.') | |
let l:cursor_col = col('.') | |
let l:content_after_cursor = current_line[cursor_col - 1 : cursor_col + len(l:search_reg) - 2] | |
if l:content_after_cursor == l:search_reg | |
return | |
endif | |
unlet b:hlsearch_on | |
if &hlsearch | |
set nohlsearch | |
redraw | |
endif | |
endif | |
endfunction | |
nnoremap <silent> * *:call HLNext()<CR> | |
nnoremap <silent> # #:call HLNext()<CR> | |
nnoremap <silent> n n:call HLNext()<CR> | |
nnoremap <silent> N N:call HLNext()<CR> | |
" Set the search register '@/' to the last or current visually selected text | |
function! VSetSearchReg() | |
let temp = @s | |
norm! gv"sy | |
let @/ = '\V' . substitute(escape(@s, '/\'), '\n', '\\n', 'g') | |
let @s = temp | |
endfunction | |
xnoremap <silent> * :<C-u>call VSetSearchReg()<CR>/<C-R>/<CR>:call HLNext()<CR> | |
xnoremap <silent> # :<C-u>call VSetSearchReg()<CR>?<C-R>/<CR>:call HLNext()<CR> | |
nnoremap / :call HLSearch()<CR>/ | |
nnoremap ? :call HLSearch()<CR>? | |
" https://stackoverflow.com/a/10362177/6074780 | |
" https://stackoverflow.com/a/20836543/6074780 | |
command! -bar -nargs=1 -bang -complete=file Rename : | |
\ let s:file = expand('%:p') | | |
\ setlocal modified | | |
\ keepalt saveas<bang> <args> | | |
\ if s:file !=# expand('%:p') | | |
\ call delete(s:file) | | |
\ endif | | |
\ unlet s:file | |
nnoremap <leader>m :call FileOperationMenu()<CR> | |
function! FileOperationMenu() | |
let l:prev_cwd = getcwd() | |
execute 'cd' fnameescape(expand('%:p:h')) | |
let l:file_name = expand("%:t") | |
let l:cwd = getcwd() | |
let l:pcwd = l:prev_cwd | |
if has('win32') || has('win16') || has('win64') || has('win95') | |
let l:cwd = substitute(l:cwd, "\\", '/', 'g') | |
let l:pcwd = substitute(l:prev_cwd, "\\", '/', 'g') . '/' | |
endif | |
let l:actions = [':e ', ':Rename ', ':Move ', ':Chmod ', ':Delete!'] | |
let l:action_prompts = ['Create file: ', | |
\ 'Rename file to: ' . l:cwd . '/', | |
\ 'Move file to: ', | |
\ 'Input permission: '] | |
let l:action_default_parameter = [l:cwd . '/', l:file_name, l:pcwd, ''] | |
let l:count = len(l:actions) - 1 | |
execute 'cd' l:prev_cwd | |
let l:choice = confirm('Action?', "&New file/directory\n&Rename\n&Move\n&Chmod\n&Delete", 0) | |
redraw | |
if l:choice == 0 | return | endif | |
" Delete 一个没有保存到硬盘上的 buffer 会报错,通常是一个新建的 blank buffer | |
if getbufvar('%', '&mod') && (l:choice == 2 || l:choice == 4 || l:choice == 5) | |
echo "Please save buffer first!" | |
return | |
endif | |
let l:choice -= 1 | |
if l:choice != l:count | |
let l:text = l:action_default_parameter[l:choice] | |
let l:command_arg = input(l:action_prompts[l:choice], l:text) | |
if l:command_arg == "" || l:command_arg ==# l:text | |
redraw | |
echo "No file operation." | |
return | |
endif | |
else | |
let l:command_arg = "" | |
endif | |
exe l:actions[l:choice] . command_arg | |
endfunction | |
" https://gist.github.com/voyeg3r/223f148a115c17a02a15660cc7335f4c | |
" Plugin https://github.com/tpope/vim-commentary | |
function! s:surroundings() abort | |
return split(get(b:, 'commentary_format', substitute(substitute(substitute( | |
\ &commentstring, '^$', '%s', ''), '\S\zs%s',' %s', '') ,'%s\ze\S', '%s ', '')), '%s', 1) | |
endfunction | |
function! s:strip_white_space(l,r,line) abort | |
let [l, r] = [a:l, a:r] | |
if l[-1:] ==# ' ' && stridx(a:line,l) == -1 && stridx(a:line,l[0:-2]) == 0 | |
let l = l[:-2] | |
endif | |
if r[0] ==# ' ' && (' ' . a:line)[-strlen(r)-1:] != r && a:line[-strlen(r):] == r[1:] | |
let r = r[1:] | |
endif | |
return [l, r] | |
endfunction | |
function! s:go(...) abort | |
if !a:0 | |
let &operatorfunc = matchstr(expand('<sfile>'), '[^. ]*$') | |
return 'g@' | |
elseif a:0 > 1 | |
let [lnum1, lnum2] = [a:1, a:2] | |
else | |
let [lnum1, lnum2] = [line("'["), line("']")] | |
endif | |
let [l, r] = s:surroundings() | |
let uncomment = 2 | |
let force_uncomment = a:0 > 2 && a:3 | |
for lnum in range(lnum1,lnum2) | |
let line = matchstr(getline(lnum),'\S.*\s\@<!') | |
let [l, r] = s:strip_white_space(l,r,line) | |
if len(line) && (stridx(line,l) || line[strlen(line)-strlen(r) : -1] != r) | |
let uncomment = 0 | |
endif | |
endfor | |
if get(b:, 'commentary_startofline') | |
let indent = '^' | |
else | |
let indent = '^\s*' | |
endif | |
let lines = [] | |
for lnum in range(lnum1,lnum2) | |
let line = getline(lnum) | |
if strlen(r) > 2 && l.r !~# '\\' | |
let line = substitute(line, | |
\'\M' . substitute(l, '\ze\S\s*$', '\\zs\\d\\*\\ze', '') . '\|' . substitute(r, '\S\zs', '\\zs\\d\\*\\ze', ''), | |
\'\=substitute(submatch(0)+1-uncomment,"^0$\\|^-\\d*$","","")','g') | |
endif | |
if force_uncomment | |
if line =~ '^\s*' . l | |
let line = substitute(line,'\S.*\s\@<!','\=submatch(0)[strlen(l):-strlen(r)-1]','') | |
endif | |
elseif uncomment | |
let line = substitute(line,'\S.*\s\@<!','\=submatch(0)[strlen(l):-strlen(r)-1]','') | |
else | |
let line = substitute(line,'^\%('.matchstr(getline(lnum1),indent).'\|\s*\)\zs.*\S\@<=','\=l.submatch(0).r','') | |
endif | |
call add(lines, line) | |
endfor | |
call setline(lnum1, lines) | |
let modelines = &modelines | |
try | |
set modelines=0 | |
silent doautocmd User CommentaryPost | |
finally | |
let &modelines = modelines | |
endtry | |
return '' | |
endfunction | |
function! s:textobject(inner) abort | |
let [l, r] = s:surroundings() | |
let lnums = [line('.')+1, line('.')-2] | |
for [index, dir, bound, line] in [[0, -1, 1, ''], [1, 1, line('$'), '']] | |
while lnums[index] != bound && line ==# '' || !(stridx(line,l) || line[strlen(line)-strlen(r) : -1] != r) | |
let lnums[index] += dir | |
let line = matchstr(getline(lnums[index]+dir),'\S.*\s\@<!') | |
let [l, r] = s:strip_white_space(l,r,line) | |
endwhile | |
endfor | |
while (a:inner || lnums[1] != line('$')) && empty(getline(lnums[0])) | |
let lnums[0] += 1 | |
endwhile | |
while a:inner && empty(getline(lnums[1])) | |
let lnums[1] -= 1 | |
endwhile | |
if lnums[0] <= lnums[1] | |
execute 'normal! 'lnums[0].'GV'.lnums[1].'G' | |
endif | |
endfunction | |
command! -range -bar -bang Commentary call s:go(<line1>,<line2>,<bang>0) | |
xnoremap <expr> <Plug>Commentary <SID>go() | |
nnoremap <expr> <Plug>Commentary <SID>go() | |
nnoremap <expr> <Plug>CommentaryLine <SID>go() . '_' | |
onoremap <silent> <Plug>Commentary :<C-U>call <SID>textobject(get(v:, 'operator', '') ==# 'c')<CR> | |
nnoremap <silent> <Plug>ChangeCommentary c:<C-U>call <SID>textobject(1)<CR> | |
if !hasmapto('<Plug>Commentary') || maparg('gc','n') ==# '' | |
xmap gc <Plug>Commentary | |
nmap gc <Plug>Commentary | |
omap gc <Plug>Commentary | |
nmap gcc <Plug>CommentaryLine | |
nmap gcu <Plug>Commentary<Plug>Commentary | |
endif | |
nmap <silent> <Plug>CommentaryUndo :echoerr "Change your <Plug>CommentaryUndo map to <Plug>Commentary<Plug>Commentary"<CR> | |
" Plugin end | |
" https://stackoverflow.com/questions/2109503/how-to-jump-to-the-beginning-of-the-current-function-body-in-vim#comment113077038_2109620 | |
nnoremap <silent> [f [m[{ | |
nnoremap <silent> ]f ]m]} |
mkdir ~/.vim/swap
mkdir ~/.vim/undo
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
'�'
in\ '�' : 'V·Block',
isCtrl V, Ctrl V
.and
Ctrl V, Ctrl S
in\ '�' : 'S·Block',
.