set encoding=utf-8 scriptencoding utf-8 " Note: Skip initialization for vim-tiny or vim-small. if 0 | endif " ref. http://qiita.com/jiminko/items/f4b337ab41db751388f7 if has('vim_starting') set runtimepath+=~/.vim/plugged/vim-plug if !isdirectory(expand('~/.vim/plugged/vim-plug')) echo 'install vim-plug...' if has('win32') call system('mkdir ' . $HOME . '\.vim\plugged\vim-plug') else call system('mkdir -p ~/.vim/plugged/vim-plug') endif call system('git clone https://github.com/junegunn/vim-plug.git ' \ . $HOME . '/.vim/plugged/vim-plug/autoload') end endif let g:eclim_filetypes = ['scala', 'java', 'php', 'ruby'] call plug#begin('~/.vim/plugged') Plug 'junegunn/vim-plug', {'dir': '~/.vim/plugged/vim-plug/autoload'} Plug 'vim-jp/vimdoc-ja' Plug 'xolox/vim-misc' | Plug 'xolox/vim-session' if has('nvim') Plug 'neovim/node-host', {'do': 'npm install'} endif Plug 'tomtom/tcomment_vim' Plug 'airblade/vim-gitgutter' Plug 'tpope/vim-sleuth' if !has('win32') Plug 'junegunn/fzf', {'do': '$HOME/.vim/plugged/fzf/install'} Plug 'junegunn/fzf.vim' endif Plug 'junegunn/vader.vim' Plug 'vim-jp/vital.vim' Plug 'haya14busa/vital-safe-string' Plug 'haya14busa/vital-vimlcompiler' Plug 'haya14busa/vital-power-assert' Plug 'Shougo/neosnippet.vim' Plug 'Shougo/neco-vim', \ {'dir': '~/.vim/bundle-custom/neco-vim', \ 'frozen': 1, 'for': 'vim'} Plug 'Valodim/vim-zsh-completion', \ {'dir': '~/.vim/bundle-custom/vim-zsh-completion', \ 'frozen': 1, 'for': 'zsh'} Plug 'dansomething/vim-eclim' , {'for': g:eclim_filetypes} Plug 'ternjs/tern_for_vim', \ {'do': 'npm install', 'for': 'javascript'} Plug 'davidhalter/jedi-vim', \ {'do': 'git submodule update --init', 'for': 'python'} Plug 'shawncplus/phpcomplete.vim' Plug 'othree/yajs.vim', {'for': 'javascript'} Plug 'othree/es.next.syntax.vim', {'for': 'javascript'} Plug 'digitaltoad/vim-pug', {'for': 'pug'} Plug 'wavded/vim-stylus', {'for': ['stylus', 'pug']} Plug 'tobyS/vmustache' | Plug 'tobyS/pdv', {'for': 'php'} Plug 'jwalton512/vim-blade' Plug 'alunny/pegjs-vim', {'for': 'pegjs'} Plug 'elzr/vim-json', {'for': 'json'} Plug 'mrk21/yaml-vim' Plug 'vim-pandoc/vim-pandoc' Plug 'vim-pandoc/vim-pandoc-syntax' Plug 'othree/html5.vim' Plug 'hail2u/vim-css3-syntax' Plug 'othree/csscomplete.vim' Plug 'ap/vim-css-color' Plug 'luochen1990/rainbow' Plug 'dpy-/molokai' call plug#end() filetype plugin indent on " ref. http://qiita.com/b4b4r07/items/fa9c8cceb321edea5da0 let s:plug = {"plugs": get(g:, 'plugs', {})} function! s:plug.is_installed(name) return has_key(self.plugs, a:name) ? isdirectory(self.plugs[a:name].dir) : 0 endfunction function! s:plug.check_installation() if empty(self.plugs) return endif let list = [] for [name, spec] in items(self.plugs) if !isdirectory(spec.dir) call add(list, spec.uri) endif endfor if len(list) > 0 let unplugged = map(list, 'substitute(v:val, "^.*github\.com/\\(.*/.*\\)\.git$", "\\1", "g")') " Ask whether installing plugs like NeoBundle echomsg 'Not installed plugs: ' . string(unplugged) if confirm('Install plugs now?', "yes\nNo", 2) == 1 PlugInstall endif endif endfunction augroup check-plug autocmd! autocmd VimEnter * if !argc() | call s:plug.check_installation() | endif augroup END " ------------------------------------ " appearance " ------------------------------------ " general " let loaded_matchparen = 1 set novisualbell set t_vb= set nospell set lazyredraw set updatetime=500 " syntax highlight if has('nvim') " let $NVIM_TUI_ENABLE_TRUE_COLOR=1 elseif !has('gui_running') set t_Co=256 endif if !has('gui_running') let g:rehash256 = 1 endif syntax on let g:molokai_italic = 0 colorscheme molokai source ~/.vim/highlight.vim " add random colors to braces let g:rainbow_active = 1 let g:rainbow_conf = { \ 'guifgs': ['#FFFFFF', '#ffafff', '#ffaf87', '#afffaf', '#87d7ff', '#d7afff'], \ 'ctermfgs': [255, 219, 216, 226, 157, 117, 183], \ 'operators': '_,_', \ 'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'], \ 'separately': { \ '*': {}, \ 'vim': { \ 'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/', 'start=/{/ end=/}/ fold', 'start=/(/ end=/)/ containedin=vimFuncBody', 'start=/\[/ end=/\]/ containedin=vimFuncBody', 'start=/{/ end=/}/ fold containedin=vimFuncBody'], \ }, \ 'html': 0, \ 'css': 0, \ 'json': 0, \ 'blade': 0 \ } \} " gutter set number set numberwidth=1 let g:gitgutter_realtime = 1 let g:gitgutter_eager = 1 let g:gitgutter_sign_column_always = 1 let g:gitgutter_max_signs = 9999 let g:gitgutter_diff_args = '--ignore-all-space' set cursorline " vertical split line set fillchars+=vert:\ highlight link TrailSpace Error highlight link WideSpace Error " ref. http://vim.wikia.com/wiki/Highlight_unwanted_spaces#Highlighting_with_the_syntax_command function! SetWhiteSpaceSyntax() abort " highlight as error trailing whitespaces, " but exclude comment blocks & empty lines syntax match LeadSpace excludenl /^\s\+$/ containedin=ALL syntax match TrailSpace excludenl /\s\+$/ containedin=ALLBUT,.*Comment.*,LeadSpace " highlight japanese wide-width space, everywhere syntax match WideSpace excludenl / / containedin=ALL endfunction augroup whitespace_syntax autocmd! autocmd Syntax * call SetWhiteSpaceSyntax() augroup END " completion popup set pumheight=10 set splitbelow "show Scratch Preview pane on the bottom " set completeopt=menuone,preview set completeopt=menuone set showfulltag set shortmess+=c "supress 'Pattern not found' message " augroup close_scratch_preview " autocmd! " autocmd CompleteDone * :pclose " augroup END " markdown let g:pandoc#modules#disabled=["spell","chdir","menu","formatting","command","bibliographies", "folding", "completion"] let g:pandoc#modules#enabled=["metadata","keyboard","toc","hypertext"] let g:pandoc#syntax#conceal#use=0 "let g:pandoc#syntax#emphases=0 "let g:pandoc#syntax#underline_special=0 let g:pandoc#syntax#codeblocks#embeds#langs = ["javascript", "python", "bash=sh", "zsh=sh", "vim"] " json let g:vim_json_syntax_conceal = 0 " diff (merge tool) if &diff set diffopt=filler,context:1000000,horizontal endif " terminal-mode if has('nvim') highlight TermCursor ctermfg=251 ctermbg=0 guifg=#c6c6c6 guibg=#000000 highlight TermCursorNC ctermfg=251 ctermbg=0 guifg=#c6c6c6 guibg=#000000 source ~/.vim/nvim-term-colors.vim endif if &term =~ "mlterm" let &t_ti .= "\e[?6h\e[?69h" let &t_te .= "\e7\e[?69l\e[?6l\e8" let &t_CV = "\e[%i%p1%d;%p2%ds" let &t_CS = "y" endif " ------------------------------------ " Session " ------------------------------------ " ref. http://qiita.com/take/items/3be8908bbf4ad5b49e46 let s:local_session_directory = xolox#misc#path#merge(getcwd(), '.vimsessions') if isdirectory(s:local_session_directory) let g:session_directory = s:local_session_directory let g:session_autosave = 'yes' let g:session_autoload = 'yes' let g:session_autosave_periodic = 1 else let g:session_autosave = 'no' let g:session_autoload = 'no' endif unlet s:local_session_directory let g:session_autosave_silent=1 if has('win32') set undodir=~/.vimundo/ set nobackup endif " ------------------------------------ " Git cooperation " ------------------------------------ " ref. http://vim-jp.org/vim-users-jp/2011/03/12/Hack-206.html set autoread function! UpdateWindow() abort checktime endfunction augroup vimrc-checktime autocmd! autocmd BufEnter * :call UpdateWindow() augroup END " ------------------------------------ " Auto Completion Popup " ------------------------------------ " i wish i could use Shougo/deoplete but i noticed some conflict " " mix up omnifunc & neosnippet & custom dictionaries " ref. http://vi.stackexchange.com/questions/2618/one-pop-up-menu-with-keyword-and-user-defined-completion function! SortCandidates(l, r) abort let l = a:l.pos let r = a:r.pos return l == r ? 0 : l > r ? 1 : -1 endfunction function! MatchCandidates(candidates, cur_text) abort let l:candidates = a:candidates let l:matches = [] for l:k in l:candidates if type(l:k) == type("") let l:candidate = {"word": l:k} elseif type(k) == type({}) let l:candidate = l:k endif unlet l:k if !exists('l:candidate') continue endif " ignore special symbols & ignore case let l:candidate.pos = stridx( \ tolower(substitute(l:candidate.word, '[^a-zA-Z0-9]', '', 'g')), \ tolower(substitute(a:cur_text, '[^a-zA-Z0-9]', '', 'g')) \) if l:candidate.pos == -1 continue endif call add(l:matches, l:candidate) unlet l:candidate endfor return sort(l:matches, "SortCandidates") endfunction function! MixComplete(findstart, base) if a:findstart return call(&omnifunc, [a:findstart, a:base]) endif let l:matches = [] let l:omni_matches = call(&omnifunc, [0, a:base]) if type(l:omni_matches) == type({}) && has_key(l:omni_matches, 'words') let l:matches += l:omni_matches.words elseif type(l:omni_matches) == type([]) let l:matches += l:omni_matches endif if a:base == "" return l:matches endif if &dictionary != "" let l:dict = readfile(expand(&dictionary)) let l:keyword_matches = MatchCandidates(l:dict, a:base) call map(l:keyword_matches, \ '{"word": v:val.word, "menu": "(keyword)"}' \) let l:matches += l:keyword_matches endif let l:snippets = neosnippet#helpers#get_snippets() let l:snippet_matches = MatchCandidates(keys(l:snippets), a:base) call map(l:snippet_matches, \ '{"word": v:val.word, ' \ . '"menu": "(snip)", ' \ . '"info": l:snippets[v:val.word]["description"]}' \) let l:matches += l:snippet_matches return l:matches endfunction augroup completedone autocmd! " `v:completed_item` is readonly var. " i want to consume it, so copy to buffer local var autocmd CompleteDone * let b:completed_item = v:completed_item augroup END set omnifunc=syntaxcomplete#Complete set completefunc=MixComplete let g:neosnippet#snippets_directory = [] let g:neosnippet#snippets_directory += ["~/.vim/snippets"] let g:neosnippet#scope_aliases = {} let g:neosnippet#scope_aliases['vim'] = 'vim,vim-functions' let g:neosnippet#disable_runtime_snippets = {'_' : 1} let g:funcsnips = {} augroup setomniafterfiletype autocmd! autocmd FileType stylus setlocal omnifunc=CompleteStylus autocmd FileType pug setlocal omnifunc=CompleteJade autocmd FileType blade setlocal omnifunc=CompleteBlade augroup END let g:EclimCompletionMethod = 'omnifunc' let g:EclimProjectProblemsUpdateOnSave = 1 function! EclimComplete(findstart, base) let l:filetype = &filetype if l:filetype == 'blade' let l:filetype = 'php' endif if l:filetype == 'php' let l:compfunc='phpcomplete#CompletePHP' else let l:compfunc = 'syntaxcomplete#Complete' endif if eclim#PingEclim(0) && index(g:eclim_filetypes, l:filetype) >= 0 let l:compfunc='eclim#' . l:filetype . '#complete#CodeComplete' " cancel completion before eclim gathers global candidates " cuz its very slow if l:filetype == 'php' let l:pattern = '\%(new\s\+\|[^a-zA-Z0-9]\\\)$' if a:findstart if getline('.')[0: col('.') - 2] =~ l:pattern return -1 endif else if getline('.') . a:base =~ l:pattern return [] endif endif endif endif return call(l:compfunc, [a:findstart, a:base]) endfunction function! s:start_eclimd() abort if !has('nvim') || eclim#PingEclim(0) || exists('g:eclimd_will_start') return endif let l:eclipse_project_dir = '' let l:dirstack = split(expand(":p:h"), '/') let l:dirstack_len = len(l:dirstack) for l:i in range(l:dirstack_len - 1, 0, -1) let l:dir = '/' . join(l:dirstack[0: l:i], '/') let l:project_file_path = l:dir . '/.project' if filereadable(l:project_file_path) let l:eclipse_project_dir = l:dir break endif endfor if l:eclipse_project_dir == "" return endif let g:eclimd_will_start = 1 call system('$ECLIPSE_HOME/eclimd 2>&1 1>/dev/null &') endfunction augroup eclim autocmd! autocmd FileType java,php call s:start_eclimd() | setlocal omnifunc=EclimComplete augroup END " ------------------------------------ " Indent Styles " ------------------------------------ set noautoindent augroup indentexpr autocmd! autocmd FileType stylus,pug,blade setlocal indentexpr= autocmd FileType stylus setlocal autoindent augroup END " ref. http://rcmdnk.github.io/blog/2014/07/14/computer-vim/ set breakindent augroup breakindent autocmd! autocmd BufEnter * set breakindentopt=min:20,shift:0 augroup END " ------------------------------------ " Auto Mode Change " ------------------------------------ " ref. http://stackoverflow.com/questions/6593299/change-from-insert-to-normal-mode-when-switching-to-another-tab set insertmode augroup mode_select autocmd! autocmd BufReadPost,BufNewFile,BufEnter * call ModeSelectBufEnter() augroup END function! ModeSelectBufEnter() if !&diff && !&readonly && &modifiable set insertmode startinsert else set noinsertmode stopinsert endif endfunction " ------------------------------------ " Cursor Vertical Guide " ------------------------------------ " console.log('ayp') " ^ ^ ^ " 3 2 1 " " when cursor on and after 2 (like 1), hide vertical guide line " when cursor in range 2-3, show vertical guide line " --------------------------------- set nocursorcolumn function! VerticalGuide() abort if &buftype != "" || &filetype == 'markdown' setlocal nocursorcolumn return endif if indent('.') >= virtcol('.') - 1 setlocal cursorcolumn else setlocal nocursorcolumn endif endfunction augroup vertguide autocmd! autocmd CursorMoved,CursorMovedI,WinEnter * call VerticalGuide() autocmd WinLeave,BufWinLeave * setlocal nocursorcolumn if has('nvim') autocmd TermOpen * setlocal nocursorcolumn endif augroup END " ------------------------------------- " Line Color Change on Loclist/Quickfix " ------------------------------------- function! ToggleLineColor() abort if &buftype == 'quickfix' for l:nr in range(winnr('$')) call setwinvar(l:nr, "&cursorline", 0) endfor highlight cursorline ctermbg=237 guibg=#3a3a3a setlocal cursorline else highlight cursorline ctermbg=none guibg=NONE for l:nr in range(winnr('$')) call setwinvar(l:nr, "&cursorline", 1) endfor endif endfunction augroup linecolor autocmd! autocmd BufReadPost,BufNewFile,BufEnter * call ToggleLineColor() augroup END " ------------------------------------ " Neovim remote " ------------------------------------ " grep in zsh -> append loclist in nvim function! RestoreQuickfixCursor() abort if &buftype == 'quickfix' && exists('w:last_cursor') call setpos(".", w:last_cursor) endif endfunction function! SaveQuickfixCursor() abort if &buftype == 'quickfix' let w:last_cursor = getpos(".") endif endfunction augroup loclist_cursor autocmd! autocmd BufEnter * call RestoreQuickfixCursor() autocmd BufLeave * call SaveQuickfixCursor() augroup END function! AppendLocList(loclist_bufnr, entries) abort let l:loclist_winnr = bufwinnr(a:loclist_bufnr) let l:current_winnr = winnr() if l:loclist_winnr == l:current_winnr let w:last_cursor = getpos(".") endif call setloclist(l:loclist_winnr, eval(a:entries), 'a') if l:loclist_winnr == l:current_winnr call setpos(".", w:last_cursor) endif endfunction " ------------------------------------ " Testing " ------------------------------------ let g:__vital_power_assert_config = {'__debug__': 1} " ------------------------------------ " keybinds " ------------------------------------ set ttimeout set ttimeoutlen=10 set timeoutlen=100 set t_ku= set t_kd= set t_kr= set t_kl= source $VIMRUNTIME/mswin.vim let g:neosnippet#disable_select_mode_mappings = 0 let g:unite_enable_start_insert=1 set whichwrap+=~ " [disable unwanted keymaps] inoremap " [show auto completion popup menu & auto select first item without insertion] " try to show popup " clear selection of popup item " if pumvisible() popup appeared " select first item without insertion " else " end completion-mode inoremap =pumvisible() ? "\Down>" : "\C-e>" " is in vim inoremap =pumvisible() ? "\Down>" : "\C-e>" " alphabet keys and dot, space for k in add( \split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._!"#$%&(=-~^\@[+*:<,?/`','\zs'), \'' \) execute 'inoremap ' . k . ' u' . k \ . '=pumvisible()' \ . ' ? "\Down>" : "\C-e>"' endfor " single quote inoremap ' u'=pumvisible() ? "\Down>" : "\C-e>" " [continue popup on backspace] inoremap u=pumvisible() ? "\Down>" : "" " [close completion popup menu] " pipe inoremap \| =pumvisible() ? "\C-e>" : ""u\| " other symbols for k in split('{>);}]','\zs') execute 'inoremap ' . k \ . ' (pumvisible() ? "\C-e>" : "") . ' \ . '"\u' . k . '"' endfor " inoremap =pumvisible() ? "\C-e>" : ""u " for other insert-mode keybinds " close completion popup menu before key function! IMapWithClosePopup(before, after, ...) let silent = (a:0 == 1 ? "" : " ") execute 'inoremap ' . silent . ' ' . a:before \ . ' (pumvisible() ? "\C-e>" : "") . "' . a:after . '"' endfunction " ---------------------------- " completion mode : accept item w/o expanding snippet " other modes : add new line w/o removing indent " --------------------------------- inoremap \ pumvisible() \ ? "\\:let b:completed_item={}\" \ : "\u\x\" " --------------------------- " snip mode : tabstop jump " completion mode : accept item " other modes : indent " --------------------------------- function! ExpandSnipGetResult() if exists("b:expandfunc") let l:result = call(function(b:expandfunc), []) let b:completed_item = {} if l:result return 1 endif endif if neosnippet#expandable() call feedkeys("\(neosnippet_expand)") return 1 endif return 0 endfunction function! ExpandSnip() abort call ExpandSnipGetResult() return "" endfunction function! JumpSnipOrTab() if ExpandSnipGetResult() return "" elseif neosnippet#jumpable() call feedkeys("\(neosnippet_jump)") return "" else return "\" endif endfunction " [accept item in completion popup menu & expand snippet immediately] nmap neosnippet#jumpable() \ ? "i\(neosnippet_jump)" : "" inoremap pumvisible() \ ? "\\=ExpandSnip()\" \ : "\=JumpSnipOrTab()\" " [indent selection lines] " select-mode -> visual-mode " v visual-mode -> normal-mode " `< move cursor to first char in last selection " g^ move cursor to first visible char on current line " v start visual selection " `> move cursor to last char in last selection " > right shift selection " ` to follow selection, repeat once again " "=&swl move cursor one 'shiftwidth' rightwards " o move cursor to first char in current selection " visual-mode -> select-mode smap neosnippet#jumpable() \ ? "\(neosnippet_jump)" \ : "\v`>`\"=&sw\lo\" " [deindent selection lines] snoremap `<`"=&swho inoremap g^<<u " --------------------------- " completion mode : close popup " snip mode : clear markers " after search : clear highlight " exists sub-pane : close sub-pane " select mode : exit select mode " " sub-pane means, " 'Location List', 'Scratch Preview' " --------------------------------- function! ClearSearch() abort call matchdelete(b:ring) set nohlsearch " let @/ = endfunction function! VariousClear() abort if pumvisible() return "\" elseif neosnippet#expandable_or_jumpable() return "\:NeoSnippetClearMarkers\" else return "\:silent! call ClearSearch()|:silent lclose|:silent pclose\" endif endfunction noremap :silent! call ClearSearch():silent lclose \| pclose nnoremap :silent! call ClearSearch():silent lclose \| pclosei inoremap VariousClear() snoremap vi set virtualedit=onemore " get next/prev cursor char (multibyte support! cool) " ref. http://d.hatena.ne.jp/eagletmt/20100623/1277289728 function! s:next_cursor_char(n) abort return matchstr(getline('.'), '.', col('.')-1, a:n) endfunction function! s:prev_cursor_char(n) let chars = split(getline('.')[0 : col('.')-1], '\zs') let len = len(chars) if a:n >= len return '' else return chars[len(chars) - a:n - 1] endif endfunction " ------------------ " ayapi's original smart word move " stop on camelCase upper char " stop on hiragana/katakana/others " --------------------------------- let s:char_groups = { \"symbol": "[\\u0021-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u007E]", \"upper": "[A-Z]", \"lower": "[a-z]", \"number": "[0-9]", \"blank": "[\\x20\\x09]", \"hiragana": "[\\u3040-\\u309F]", \"katakana": "[\\u30A0-\\u30FF]", \"other": "[^a-zA-Z0-9\\x20\\x09\\u0021-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u007E\\u3040-\\u309F\\u30A0-\\u30FF]" \} function! s:get_char_group(char) abort for l:item in items(s:char_groups) if a:char =~# l:item[1] let l:group = l:item break endif endfor return l:group endfunction function! s:get_char_by_direction(direction) abort return a:direction == 'h' \ ? s:prev_cursor_char(1) \ : s:next_cursor_char(1) endfunction set whichwrap+=h,l function! GoWord(direction, ...) abort if a:0 == 1 && a:1 == 1 " when entering select-mode silent! normal! v endif if a:0 == 2 && a:2 == 1 " while select-mode, need `gv`(restore selection) silent! normal! gv endif let l:from_char = s:get_char_by_direction(a:direction) if l:from_char == "" if a:direction == "h" " now cursor on the start of line if line(".") > 1 " go to end of the prev line (virtualedit onemore position) silent! normal! gkg$ endif else " now cursor on the end of line " go to start of the next line silent! normal! l endif return endif let l:from_group = s:get_char_group(l:from_char) " forwarding camelCase if a:direction == "l" && l:from_group[0] == "upper" let l:tmp_next_group = s:get_char_group(s:next_cursor_char(2)) if l:tmp_next_group[0] == "lower" " camelCase camelCase " ^^ ^ " 12 3 " cursor on 1, so forward to 2 now. (to forward to 3 later) silent! normal! l let l:from_group = l:tmp_next_group endif endif while 1 execute "silent! normal! ".a:direction let l:to_char = s:get_char_by_direction(a:direction) if l:to_char == "" || l:to_char !~# l:from_group[1] break endif endwhile if l:to_char == "" return endif " backwarding camelCase, go to upper char if a:direction == "h" && l:from_group[0] == "lower" let l:to_group = s:get_char_group(l:to_char) if l:to_group[0] == "upper" " camelCase camelCase " ^^ " 21 " cursor on 1, so backward to 2 now silent! normal! h endif endif endfunction " [move cursor word-by-word] " general move noremap :call GoWord("l") noremap :call GoWord("h") call IMapWithClosePopup("","\\:call GoWord(\\\"l\\\")\\") call IMapWithClosePopup("", "\\:call GoWord(\\\"h\\\")\\") " when entering select-mode call IMapWithClosePopup("","\\:call GoWord(\\\"l\\\", 1)\\\\") call IMapWithClosePopup("", "\\:call GoWord(\\\"h\\\", 1)\\\\") " while select-mode snoremap :call GoWord("l",0,1) snoremap :call GoWord("h",0,1) " when leaving select-mode snoremap v:call GoWord("l") snoremap v:call GoWord("h") " [delete word] noremap :call GoWord("l",1) call IMapWithClosePopup("","\\:call GoWord(\\\"l\\\", 1)\\\\\\") " [delete backward word] " is in urxvt noremap :call GoWord("h",1) call IMapWithClosePopup("","\\:call GoWord(\\\"h\\\", 1)\\\\\\") " for gvim noremap :call GoWord("h",1) call IMapWithClosePopup("","\\:call GoWord(\\\"h\\\", 1)\\\\\\") " -------------------------- " console.log('ayp') " ^ ^ ^ " 3 2 1 " " when hit & cursor on and after 2 (like 1), cursor will go to 2. " when hit & cursor in range 2-3, cursor will go to 3. " --------------------------------- function! GetGoHomeCmd() abort return indent('.') >= virtcol('.') - 1 ? "g0" : "g^" endfunction " --------------------------- " when current line is short than right edge of window " | " console.log('ayp') | " ^ | " cursor should go to here " " when current line is LONG than right edge of window (soft wrapped) " | " console.log(util.inspect(ay| " p, false,2,true)); | " ^ | " cursor should go to here " --------------------------------- function! GoEnd(cmd) range execute ":silent! normal! ".a:cmd if virtcol(".") < virtcol("$") silent! normal! l endif endfunction " [Move cursor by display lines when wrapping] " http://vim.wikia.com/wiki/Move_cursor_by_display_lines_when_wrapping " http://stackoverflow.com/questions/18678332/gvim-make-s-up-s-down-move-in-screen-lines " http://stackoverflow.com/questions/3676388/cursor-positioning-when-entering-insert-mode " general move nnoremap gj nnoremap gk nnoremap GetGoHomeCmd() nnoremap :call GoEnd("g$") nnoremap GetGoHomeCmd() nnoremap :call GoEnd("g$") inoremap pumvisible() ? "\" : "\gj" inoremap pumvisible() ? "\" : "\gk" call IMapWithClosePopup("", "\\:execute printf(\\\"normal! %s\\\", GetGoHomeCmd())\\") call IMapWithClosePopup("", "\\:call GoEnd(\\\"g$\\\")\\") call IMapWithClosePopup("","\\:execute printf(\\\"normal! %s\\\", GetGoHomeCmd())\\") call IMapWithClosePopup("", "\\:call GoEnd(\\\"g$\\\")\\") " when entering select-mode call IMapWithClosePopup("", "\\vgj\\") call IMapWithClosePopup("", "\\vgk\\") call IMapWithClosePopup("", "\\:execute printf(\\\"normal! v%s\\\", GetGoHomeCmd())\\") call IMapWithClosePopup("", "\\:call GoEnd(\\\"vg$\\\")\\\\") " while select-mode snoremap gj snoremap gk snoremap "\".GetGoHomeCmd() snoremap :call GoEnd("gvg$") " when leaving select-mode snoremap gj snoremap gk snoremap "\v`<".GetGoHomeCmd() snoremap v:call GoEnd("`>g$") snoremap "\v`<".GetGoHomeCmd() snoremap v:call GoEnd("`>g$") " [scroll page up/down] " on 1st page, should move cursor to 1st line. " on last page, should move cursor to last line, " and it shouldnt show after eof (`~` lines). " ref. http://vimrc-dissection.blogspot.se/2009/02/fixing-pageup-and-pagedown.html set scrolloff=3 noremap 1000 noremap 1000 snoremap v1000 snoremap v1000 snoremap 1000 snoremap 1000 inoremap pumvisible() ? "\" : "\1000\" inoremap pumvisible() ? "\" : "\1000\" call IMapWithClosePopup("", "\\v1000\\\\") call IMapWithClosePopup("", "\\v1000\\\\") " [scroll viewport up/down] " like a mouse wheel, scroll 3 lines. " if possible, without change cursor position noremap 3 inoremap 3 noremap 3 inoremap 3 " [delete] " to avoid going to normal-mode snoremap x snoremap x " [cut/copy/paste] " to prevent freezing on nvim exit, i use custom clipboard provider " i think it caused by the following commit " https://github.com/neovim/neovim/commit/49f04179888944943f0266cd77810e467f9d68ef if has('nvim') source ~/.vim/clipboard.vim endif " Prevent Vim from clearing the clipboard on exit " http://stackoverflow.com/questions/6453595/prevent-vim-from-clearing-the-clipboard-on-exit " cant use this on nvim if !has('nvim') augroup xsel autocmd! autocmd VimLeave * call system("xsel -ib", getreg('+')) augroup END endif " convert indent before paste, and select pasted text function! ConvertIndentPaste() abort let l:after_indent = &expandtab ? repeat(' ', &shiftwidth) : "\t" let l:clipboard = getreg('+') let l:converted = ConvertIndent(l:clipboard, l:after_indent) call setreg('j', l:converted, 'c') normal! "jgP if l:converted =~ '[\r?\n]' execute "normal! `[v`]l\" endif startinsert endfunction function! MapConvertIndentPaste() abort noremap :call ConvertIndentPaste() inoremap u:call ConvertIndentPaste() snoremap d:call ConvertIndentPaste() endfunction if has('nvim') augroup convertpaste autocmd! autocmd FileType * if &buftype == '' | call MapConvertIndentPaste() | endif augroup END endif " confirm message " ref. https://github.com/saihoooooooo/dotfiles/ function! s:Confirm(msg) return input(printf('%s [y/N]: ', a:msg)) =~? '^y\%[es]$' endfunction " write file with `sudo` " ref. http://stackoverflow.com/questions/2600783/how-does-the-vim-write-with-sudo-trick-work function! WriteWithSudo(filename) abort if s:Confirm('"'.a:filename.'" isnt writable. Write with sudo?') " redraw prompt " ref. http://vim.1045645.n5.nabble.com/Clear-input-prompt-after-input-is-entered-td5717719.html redraw execute ":silent write !sudo tee ".a:filename set nomodified execute ":silent file! ".a:filename endif endfunction " [save] function! Save() abort let l:filename = expand("%") if l:filename == "" call SaveAs() elseif filewritable(expand("%:p")) != 1 && \ filewritable(expand("%:p:h")) != 2 call WriteWithSudo(l:filename) else update endif endfunction noremap :call Save() inoremap :call Save() snoremap v:call Save() nnoremap :call Save() " [save as] " ref. http://vim.wikia.com/wiki/User_input_from_a_script function! SaveAs() call inputsave() let l:inputpath = input('Save As > File Name: ', expand("%")) call inputrestore() if l:inputpath == "" echoerr "empty filename, aborted." return endif " ref. http://vim.1045645.n5.nabble.com/dirname-td1185590.html let l:savepath = fnamemodify(expand(l:inputpath), ":p") let l:savedir = fnamemodify(expand(l:inputpath), ":p:h") let l:need_sudo = 0 if glob(l:savepath) != "" " file exists if filewritable(l:savepath) != 1 let l:need_sudo = 1 endif else if !isdirectory(l:savedir) " dir not exists " TODO: should `mkdir -p`... ? else if filewritable(l:savedir) != 2 let l:need_sudo = 1 endif endif endif if l:need_sudo call WriteWithSudo(l:savepath) return endif try execute ":saveas ".l:savepath catch /E13: File exists/ if s:Confirm('"'.l:savepath.'" already exists. Overwrite?') execute ":saveas! ".l:savepath endif endtry endfunction " i cant use caused by terminal's limitation " is `save as` in MS Office family " and i use urxvt's keysym to in .Xresources noremap :call SaveAs() inoremap :call SaveAs() snoremap v:call SaveAs() nnoremap :call SaveAs() " [undo/redo] vnoremap u vnoremap snoremap u snoremap inoremap pumvisible() ? "\\u" : "\u" " [open] if !has('win32') function! FilesFromRoot() abort call fzf#vim#files("/", {'options': '-q '.getcwd()[1:], 'down': '~40%'}) endfunction noremap :call FilesFromRoot() inoremap :call FilesFromRoot() nnoremap :call FilesFromRoot() endif " [quit] noremap :confirm quitall call IMapWithClosePopup("", "\\:confirm quitall", 1) nnoremap :confirm quitall " Set cursor colour different when on a highlighted word " ref. http://vi.stackexchange.com/questions/2761/set-cursor-colour-different-when-on-a-highlighted-word function! SearchHighlight() silent! call matchdelete(b:ring) let b:ring = matchadd('IncSearch', '\c\%#' . @/, 101) endfunction function! SearchNext() try execute 'normal! '.'Nn'[v:searchforward].'zz' catch /E385:/ echohl ErrorMsg | echo "E385: search hit BOTTOM without match for: " . @/ | echohl None endtry call SearchHighlight() endfun function! SearchPrev() try execute 'normal! '.'nN'[v:searchforward].'zz' catch /E384:/ echohl ErrorMsg | echo "E384: search hit TOP without match for: " . @/ | echohl None endtry call SearchHighlight() endfunction " immediately after search started with Enter, highlight first match function! SearchStart() autocmd! search_start augroup! search_start set hlsearch normal zz call SearchHighlight() endfunction function! AddSearchStartHook() abort augroup search_start autocmd! autocmd CursorMoved call SearchStart() augroup END endfunction " [find] set ignorecase set noincsearch noremap :call AddSearchStartHook()/ inoremap :call AddSearchStartHook()/ nnoremap :call AddSearchStartHook()/ snoremap :call AddSearchStartHook()/\%V nnoremap n :call SearchNext() nnoremap N :call SearchPrev() " [replace] noremap :%s///gc inoremap :%s///gc nnoremap :%s///gc snoremap :s/\%V\%V//gc " for replace with new line " = in my keysym cnoremap " [revert] " = in my keysym inoremap :GitGutterRevertHunk nnoremap :GitGutterRevertHunk " [jump git hunk] " ref. http://vim.wikia.com/wiki/Capture_ex_command_output function! s:Warning(msg) redraw echohl WarningMsg echo a:msg echohl None let v:warningmsg = a:msg endfunction function! CirculateNextHunk () abort echo "" let l:hunks = gitgutter#hunk#hunks() if len(l:hunks) == 0 call s:Warning("buffer has any git hunks") return endif redir => m silent call gitgutter#hunk#next_hunk(1) redir END if empty(m) normal! zz return endif if m =~ 'No more hunks' normal! gg silent call gitgutter#hunk#next_hunk(1) normal! zz call s:Warning("jump hit BOTTOM. Continueing at TOP") endif endfunction function! CirculatePrevHunk () abort echo "" let l:hunks = gitgutter#hunk#hunks() if len(l:hunks) == 0 call s:Warning("buffer has any hunks") return endif redir => m silent call gitgutter#hunk#prev_hunk(1) redir END if empty(m) normal! zz return endif if m =~ 'No previous hunks' normal! G silent call gitgutter#hunk#prev_hunk(1) normal! zz call s:Warning("jump hit Top. Continueing at BOTTOM") endif endfunction nnoremap m :call CirculateNextHunk() nnoremap M :call CirculatePrevHunk() " [reformat] noremap =iu " [comment toggle] let g:tcommentMaps = 0 let g:tcommentModeExtra = '#' if has("gui_running") noremap :TComment vnoremap :TCommentMaybeInline inoremap :TComment else " means `ctrl+/` noremap :TComment vnoremap :TCommentMaybeInline inoremap :TComment endif " [jump to line] " ref. http://vim.wikia.com/wiki/Jump_to_a_line_number " ref. http://vim.wikia.com/wiki/User_input_from_a_script function! JumpToLine() call inputsave() let lineno = input('Jump to Line > Number: ') call inputrestore() execute "normal! ".lineno."G" endfunction inoremap :call JumpToLine() nnoremap :call JumpToLine() " toggle gutter function! SetGutter() abort if !exists('b:gutter_state') let b:gutter_state = &buftype == '' endif if b:gutter_state == 0 setlocal nonumber setlocal norelativenumber elseif b:gutter_state == 1 setlocal number setlocal norelativenumber elseif b:gutter_state == 2 setlocal nonumber setlocal relativenumber endif endfunction augroup set_gutter autocmd! autocmd BufWinEnter * :call SetGutter() augroup END function! ToggleGutter() abort if !exists('b:gutter_state') let b:gutter_state = &buftype != '' else let b:gutter_state += 1 if b:gutter_state > 2 let b:gutter_state = 0 endif endif call SetGutter() endfunction noremap :call ToggleGutter() inoremap :call ToggleGutter() snoremap v:call ToggleGutter() nnoremap :call ToggleGutter() " [new tab] noremap :tabnew inoremap :tabnew nnoremap :tabnew " [close current tab] noremap :confirm tabclose inoremap :confirm tabclose nnoremap :confirm tabclose " [close other all tabs] " noremap :tabonly " inoremap :tabonly " nnoremap :tabonly " [show next tab] " vim xterm esc seq if has('nvim') || has('gui_running') noremap :tabnext inoremap :tabnext nnoremap :tabnext else noremap [27;5;9~ :tabnext inoremap [27;5;9~ :tabnext nnoremap [27;5;9~ :tabnext endif " [show prev tab] " xterm esc seq if has('nvim') || has('gui_running') noremap :tabNext inoremap :tabNext nnoremap :tabNext else noremap [27;6;9~ :tabNext inoremap [27;6;9~ :tabNext nnoremap [27;6;9~ :tabNext endif " TODO: "move tab" keymaps arent working in neovim " [move tab to left] if has('nvim') || has('gui_running') noremap :tabmove -1 inoremap :tabmove -1 nnoremap :tabmove -1 else " xterm esc seq noremap [5;6~ :tabmove -1 inoremap [5;6~ :tabmove -1 nnoremap [5;6~ :tabmove -1 endif " [move tab to right] if has('nvim') || has('gui_running') noremap :tabmove +1 inoremap :tabmove +1 nnoremap :tabmove +1 else " xterm esc seq noremap [6;6~ :tabmove +1 inoremap [6;6~ :tabmove +1 nnoremap [6;6~ :tabmove +1 endif function! MapAllMode(lhs, rhs) abort execute "noremap \ ".a:lhs." \".a:rhs execute "inoremap \ ".a:lhs." \".a:rhs execute "snoremap \ ".a:lhs." \".a:rhs execute "nnoremap \ ".a:lhs." ".a:rhs if has('nvim') execute "tnoremap \ ".a:lhs." \\".a:rhs endif endfunction " [resize pane] call MapAllMode("\M-+>", "\C-w>+") call MapAllMode("\M-->", "\C-w>-") " [select(focus) pane] " http://vim.wikia.com/wiki/Mapping_fast_keycodes_in_terminal_Vim#2a._Mappings map [27;3;9~ call MapAllMode("\M-Tab>", "\C-w>w") call MapAllMode("\M-S-Tab>", "\C-w>W") call MapAllMode("\M-Up>", "\C-w>k") call MapAllMode("\M-Down>", "\C-w>j") call MapAllMode("\M-Right>", "\C-w>l") call MapAllMode("\M-Left>", "\C-w>h") " [move pane] " ref. http://stackoverflow.com/questions/2586984/how-can-i-swap-positions-of-two-open-files-in-splits-in-vim function! StashLoclist() abort let l:start_bufnr = bufnr("%") let l:main_win = {} let l:start_win_loclist = getloclist(0) if &buftype == 'quickfix' if len(l:start_win_loclist) " maybe loclist " main window is above from loclist in my vim let l:loclist_last_cursor = getwinvar(0, 'last_cursor', 0) let l:loclist_title = getwinvar(0, 'quickfix_title', 0) wincmd k let l:above_win_loclist = getloclist(0) if l:start_win_loclist == l:above_win_loclist let l:main_win.loclist = {} let l:main_win.loclist.data = l:above_win_loclist let l:main_win.loclist.cursor = l:loclist_last_cursor let l:main_win.loclist.title = l:loclist_title lclose else " back to loclist wincmd p " maybe loclist is alone so close it lclose endif else "maybe quickfix endif else if len(l:start_win_loclist) " normal buffer has loclist let l:main_win.loclist = {} let l:main_win.loclist.data = l:start_win_loclist " go to window below, is it loclist? let l:main_winnr = winnr() wincmd j if l:main_winnr != winnr() \ && &buftype == 'quickfix' \ && getloclist(0) == l:start_win_loclist let l:main_win.loclist.cursor = getwinvar(0, 'last_cursor', 0) let l:main_win.loclist.title = getwinvar(0, 'quickfix_title', 0) endif " back to main window execute l:main_winnr.' wincmd w' if has_key(l:main_win.loclist, 'cursor') lclose endif endif endif let l:main_win.bufnr = bufnr("%") return l:main_win endfunction function! RestoreLoclist(stashed) abort if !has_key(a:stashed, 'loclist') call setloclist(0, []) return endif call setloclist(0, a:stashed.loclist.data) if has_key(a:stashed.loclist, 'cursor') lopen if type(a:stashed.loclist.cursor) == 3 let w:last_cursor = a:stashed.loclist.cursor call RestoreQuickfixCursor() let w:quickfix_title = a:stashed.loclist.title endif endif endfunction function! SwapBuffer(from, to) abort let l:from = a:from let l:to = a:to if l:from.bufnr == l:to.bufnr return endif let l:from.winnr = bufwinnr(l:from.bufnr) let l:to.winnr = bufwinnr(l:to.bufnr) execute l:from.winnr " wincmd w" execute 'hide buf' l:to.bufnr execute l:to.winnr " wincmd w" execute 'hide buf' l:from.bufnr let l:winnr_dict = {} let l:winnr_dict[bufwinnr(l:from.bufnr)] = l:from let l:winnr_dict[bufwinnr(l:to.bufnr)] = l:to execute bufwinnr(l:winnr_dict[max(keys(l:winnr_dict))]['bufnr'])." wincmd w" call RestoreLoclist(l:winnr_dict[max(keys(l:winnr_dict))]) execute bufwinnr(l:winnr_dict[min(keys(l:winnr_dict))]['bufnr'])." wincmd w" call RestoreLoclist(l:winnr_dict[min(keys(l:winnr_dict))]) execute bufwinnr(l:from.bufnr)." wincmd w" endfunction function! SwapBufferArrow(direction) abort let l:from = StashLoclist() execute 'wincmd '.a:direction let l:to = StashLoclist() call SwapBuffer(from, to) endfunction map [1;7A call MapAllMode("\M-C-Up>", ":call SwapBufferArrow('k')\CR>") map [1;7B call MapAllMode("\M-C-Down>", ":call SwapBufferArrow('j')\CR>") map [1;7C call MapAllMode("\M-C-Right>", ":call SwapBufferArrow('l')\CR>") map [1;7D call MapAllMode("\M-C-Left>", ":call SwapBufferArrow('h')\CR>") " lay aside buffer " " ~~~~~~~~~~~~~~~~~~ " before -> after " ----- ----- " 1 |3 1 |3 " |-- --| " --|4 2 |-- " 2 |-- --|4 " |5* 5*| " ----- ----- " ~~~~~~~~~~~~~~~~~~ " * = current buffer " " but if 2 is empty [no name] buffer, " " ~~~~~~~~~~~~~~~~~~ " before -> after " ----- ----- " 1 |3 1 |3 " |-- | " --|4 --|-- " 2 |-- 5*|4 " |5* | " ----- ----- " ~~~~~~~~~~~~~~~~~~ function! LayAsideBufferArrow(direction) abort let l:from = {} let l:from.bufnr = bufnr('%') let l:from.winnr = winnr() execute 'wincmd '.a:direction if &buftype == 'quickfix' new else let l:stop_win_winnr = winnr() let l:stop_win_loclist = getloclist(0) if len(l:stop_win_loclist) " go to window below, is it loclist? wincmd j if l:stop_win_winnr != winnr() \ && &buftype == 'quickfix' \ && getloclist(0) == l:stop_win_loclist " loclist is visible. insert new pane below new else " loclist not visible wincmd p new endif elseif expand('%') == '' && line('$') == 1 && getline(1) == '' " empty new buffer, reuse this else new endif endif " now cursor is in destination pane let l:to = StashLoclist() execute bufwinnr(l:from.bufnr).' wincmd w' unlet l:from let l:from = StashLoclist() call SwapBuffer(from, to) " destination is empty so close it execute bufwinnr(l:to.bufnr)." wincmd w" close execute bufwinnr(l:from.bufnr).' wincmd w' endfunction map [1;8C call MapAllMode("\M-C-S-Right>", ":call LayAsideBufferArrow('l')\CR>") map [1;8D call MapAllMode("\M-C-S-Left>", ":call LayAsideBufferArrow('h')\CR>") " [split pane w/ new file] set splitbelow set splitright " alt-pipe(|) call MapAllMode("\M-\\|>", ":vnew\CR>") " alt-equal(=) call MapAllMode("\M-=>", ":new\CR>") " [close pane] call MapAllMode("\M-x>", ":confirm quit\CR>") " [help] function! HelpGrepToLoclist(keyword) let l:keyword = a:keyword let l:from_bufnr = winbufnr(0) if &buftype == 'quickfix' let l:from_loclist = getloclist(winnr()) endif let l:from_empty_window = 0 if expand('%') == '' && &buftype == '' let l:from_empty_window = 1 endif for nr in range(1, winnr('$')) let l:buf_no = winbufnr(nr) let l:buf_type = getbufvar(l:buf_no, '&buftype', '') if l:buf_type == 'help' let l:help_winnr = nr break endif endfor let l:from_help_loclist = 0 if !exists("l:help_winnr") " open help window newly help if l:from_empty_window " help file was splitted to below from an empty window " no longer need a window above wincmd k close wincmd j endif else " move cursor to existing help window execute l:help_winnr."wincmd w" if exists('l:from_loclist') \ && getloclist(winnr()) == l:from_loclist let l:from_help_loclist = 1 endif endif let l:win_count_before_lclose = winnr('$') try lclose catch /E776: No location list/ " ignore error endtry if l:keyword == "" return endif let l:loclist_was_showing = l:win_count_before_lclose > winnr('$') let l:no_result = 0 try execute "lhelpgrep ".l:keyword."@ja" catch /E480/ let l:no_result = 1 endtry if len(getloclist(0)) == 0 let l:no_result = 1 endif if l:no_result == 1 set nohlsearch try lolder catch /E380: At bottom/ " ignore error endtry if l:loclist_was_showing lopen endif if !l:from_help_loclist execute bufwinnr(l:from_bufnr)."wincmd w" endif call s:Warning("No result") return endif lopen lrewind wincmd p " add highlight keyword " ref. rking/ag.vim let @/ = l:keyword call feedkeys(":set hlsearch\", 'n') endfunction noremap :call HelpGrepToLoclist(expand('')) inoremap :call HelpGrepToLoclist(expand('')) function! HelpGrepToLoclistPrompt() abort call inputsave() let l:keyword = input('HelpGrep > ', expand('')) call inputrestore() call HelpGrepToLoclist(l:keyword) endfunction map imap noremap :call HelpGrepToLoclistPrompt() inoremap :call HelpGrepToLoclistPrompt() " [diff(merge-tool) mode] function! MergeFromTop() let bufnr = winbufnr(1) execute 2 . 'wincmd w' execute 'diffget ' . bufnr diffupdate call feedkeys("zR", "n") endfunction function! MergeFromBottom() if winnr('$') == 3 let bufnr = winbufnr(3) execute 2 . 'wincmd w' execute 'diffget ' . bufnr elseif winnr('$') == 2 let bufnr = winbufnr(2) execute 1 . 'wincmd w' execute 'diffget ' . bufnr endif diffupdate call feedkeys("zR", "n") endfunction if &diff nnoremap j ]c nnoremap k [c nnoremap :call MergeFromTop() nnoremap :call MergeFromBottom() nnoremap u:diffupdate nnoremap :diffupdate endif " [neovim terminal-mode] if has('nvim') source ~/.vim/nvim-term-keysym.vim tnoremap tnoremap noremap :term inoremap :term tmap i endif