" == Naming convention. == {{{1 " Command name " - CamelCase " Global function name " - CamelCase " Local function name " - s:split_by_underbar " Group name for autocmd " - split-by-dash " In vimrc, start with "vimrc" " - vimrc-{unique-name} " In vim plugin, start with "plugin" " - plugin-{plugin-name} " - plugin-{plugin-name}-{unique-name} " In other custom files, start with "custom" " - custom-{unique-name} " == Initial process. == {{{1 " Startup time. if !v:vim_did_enter && has('reltime') let g:startuptime = reltime() augroup vimrc-startuptime autocmd! VimEnter * ++once \ let g:startuptime = reltime(g:startuptime) \ | redraw \ | echomsg 'startuptime: ' .. reltimestr(g:startuptime) augroup END endif if v:vim_did_enter command! -nargs=+ -bar Set setglobal else command! -nargs=+ -bar Set set endif " == Encoding settings. == {{{1 " Use utf-8. if &encoding !=? 'utf-8' let &termencoding = &encoding Set encoding=utf-8 endif " Must after set of 'encoding'. scriptencoding utf-8 if has('guess_encode') Set fileencodings=ucs-bom,utf-8,iso-2022-jp,guess,euc-jp,cp932,latin1 else Set fileencodings=ucs-bom,utf-8,iso-2022-jp,euc-jp,cp932,latin1 endif Set fileformats=unix,dos Set guioptions+=M " runtimepath. if $VIM_USERDIR ==# '' let $VIM_USERDIR = \ substitute( \ get( \ filter( \ map(['~/vimfiles', '~/.vim'], 'expand(v:val)'), \ 'isdirectory(v:val)' \ ), \ 0, ''), \ '\\\+', '/', 'g') endif if !v:vim_did_enter Set runtimepath& if !isdirectory(expand('~/vimfiles')) " Even Windows uses "$HOME/.vim". let &runtimepath = substitute(&runtimepath, \ escape($HOME, '\') .. '/vimfiles', escape($HOME, '\') .. '/.vim', 'g') endif endif " Interface dll {{{2 if isdirectory($ASDF_DIR) let s:ext = has('mac') ? 'dylib' : 'so' let s:tool_versions = {} eval '~/.tool-versions'->expand()->readfile() \ ->map({ _, v -> split(v, '\s\+')->filter({ _, v -> v isnot# 'system' }) }) \ ->map({ _, v -> extend(s:tool_versions, {v[0]: v[1 :]}) }) " if_perl if exists('+perldll') let s:perl_ver = s:tool_versions->get('perl')->get(0) if s:perl_ver isnot# '' let &perldll = \ printf('%s/installs/perl/%s/lib/%s/x86_64-linux/CORE/libperl.%s', \ $ASDF_DIR, s:perl_ver, s:perl_ver, s:ext) endif unlet s:perl_ver endif " if_ruby if exists('+rubydll') let s:ruby_ver = s:tool_versions->get('ruby')->get(0) if s:ruby_ver isnot# '' let &rubydll = \ printf('%s/installs/ruby/%s/lib/libruby.%s', \ $ASDF_DIR, s:ruby_ver, s:ext) endif unlet s:ruby_ver endif " if_python let s:python_ver = s:tool_versions->get('python') if exists('+pythondll') let s:py_v2 = s:python_ver->copy()->filter({ _, v -> v =~# '^2' })->get(0) if s:py_v2 isnot# '' let &pythondll = \ printf('%s/installs/python/%s/lib/libpython%s.%s', \ $ASDF_DIR, s:py_v2, matchstr(s:py_v2, '^\d\+\.\d\+'), s:ext) endif unlet s:py_v2 endif if exists('+pythonthreedll') let s:py_v3 = s:python_ver->copy()->filter({ _, v -> v =~# '^3' })->get(0) if s:py_v3 isnot# '' let &pythonthreedll = \ printf('%s/installs/python/%s/lib/libpython%s.%s', \ $ASDF_DIR, s:py_v3, matchstr(s:py_v3, '^\d\+\.\d\+'), s:ext) endif unlet s:py_v3 endif unlet s:python_ver unlet s:ext s:tool_versions endif " }}}2 " Plugin Manager let g:vimproc#download_windows_dll = 1 source :h/dein.vim " localrc.vim let s:vim_config_dir = expand('~/.config/vim') if dein#is_sourced('localrc') call localrc#load('local.pre.vim', s:vim_config_dir, 1) if !v:vim_did_enter call localrc#load('.init.vimrc', getcwd()) endif endif " singleton.vim if dein#is_sourced('singleton') call singleton#enable() endif " vital.vim if dein#is_sourced('vital') " let g:vital_debug = 1 let g:V = vital#vital#new().load( \ ['Prelude'], \ 'Vim.Buffer', \ ['Vim.Compat', 'Compat'], \ ['Math'], \ ['DateTime'], \ ['System.Filepath', 'Path'], \ ['Process', 'P'], \ ['Data.List'], \ ['Data.String'], \ ['Data.Dict', 'Dict'], \ 'Random', \ ['Vim.Message', 'Message'], \ ['Web.JSON', 'J'], \ ['Web.XML', 'X'], \ ['Web.HTTP']) endif " == Utilities for vimrc. == {{{1 let s:is_win = has('win32') function s:SID() abort return matchstr(expand(''), '\zs\d\+\ze_SID$') endfunction function s:SIDP() abort return '' .. s:SID() .. '_' endfunction function s:check_flag(flag) abort for scope in [w:, b:, g:] let f = get(scope, a:flag, v:null) if f isnot v:null return f endif endfor return 0 endfunction function s:toggle_flag(scope, name) abort let a:scope[a:name] = !get(a:scope, a:name, 0) endfunction function s:get_range(type, mode) abort if a:mode ==# 'o' let vm = { \ 'line' : 'V', \ 'char' : 'v', \ 'block' : "\" }[a:type] let [sm, em] = ['[', ']'] let save_sel = &selection set selection=inclusive elseif a:mode ==# 'v' let [vm, sm, em] = [a:type, '<', '>'] else return '' end let save_reg = @" execute 'silent normal! `' .. sm .. vm .. '`' .. em .. 'y' let selected = @" let @" = save_reg if exists('save_sel') let &selection = save_sel endif return selected endfunction function s:clamp(value, min, max) abort return a:value < a:min ? a:min : \ a:max < a:value ? a:max : \ a:value endfunction " == Appearance settings. == {{{1 syntax enable augroup vimrc-highlight autocmd! autocmd ColorScheme * call s:highlight_additional() augroup END function s:highlight_additional() abort highlight CursorIM guibg=Red guifg=NONE let env = has('gui_running') ? 'gui' : 'cterm' for hl in ['TabLine', 'TabLineSel'] let id = synIDtrans(hlID(hl)) let bg = synIDattr(id, 'bg', env) let bg = bg =~# '^#\?\w\+$' ? env .. 'bg=' .. bg : '' let attrs = filter(['bold', 'italic', 'reverse', 'inverse', \ 'standout', 'underline', 'undercurl'], \ 'synIDattr(id, v:val, env)') let attr = empty(attrs) ? '' : env .. '=' .. join(attrs, ',') execute 'highlight' hl .. 'Number' env .. 'fg=Red' bg attr execute 'highlight' hl .. 'TabNumber' env .. 'fg=DarkCyan' bg attr endfor endfunction " colorscheme. if !exists('g:colors_name') Set background=dark let g:gruvbox_contrast_dark = 'hard' try if !s:is_win || has('gui_running') " ['candycode', 'wuye', 'freya', 'leo'] colorscheme gruvbox else "CUI win32 " ['oceandeep'] colorscheme default endif catch colorscheme habamax endtry endif " Show (partial) command in the last line of the screen. Set showcmd " Show invisible characters. Set list listchars=tab:^\ ,trail:_,extends:>,precedes:< " Set list listchars=tab:^\ ,trail:␣,extends:>,precedes:< Set nolinebreak showbreak=> " Display the last line as much as possible in a window. Set display=lastline if has('directx') && &encoding ==# 'utf-8' Set renderoptions=type:directx endif Set matchpairs& matchpairs+=<:> Set laststatus=2 statusline=%!MakeStatusLine() Set showtabline=2 tabline=%!MakeTabLine() " Don't show :intro when startup. Set shortmess& shortmess+=I if has('kaoriya') && s:is_win && has('gui_running') Set ambiwidth=auto else Set ambiwidth=double endif Set helplang=ja,en " Get character code on cursor with 'fileencoding'. function GetCharacterCode() abort let str = matchstr(getline('.'), '.', col('.') - 1) let str = iconv(str, &encoding, &fileencoding) let out = '0x' if str ==# '' return out .. '00' endif for i in range(strlen(str)) let out ..= printf('%02X', char2nr(str[i])) endfor return out endfunction " Return the current file size in human readable format. function GetFileSize() abort if &encoding ==# &fileencoding || &fileencoding ==# '' let size = line2byte(line('$') + 1) - 1 else let size = getfsize(expand('%')) endif if size < 0 let size = 0 endif for unit in ['B', 'KB', 'MB'] if size < 1024 return size .. unit endif let size = size / 1024 endfor return size .. 'GB' endfunction function GetSyntaxInfo() abort let line = synstack(line('.'), col('.'))->map( \ 'printf("%s (%s)", synIDattr(v:val, "name"), synIDattr(synIDtrans(v:val), "name"))' \ )->join(',') endfunction function STLBufnr() abort return s:check_flag('statusline_bufnr') \ ? printf('[%d] ', bufnr('%')) : '' endfunction function STLHighLight() abort return s:check_flag('statusline_highlight') \ ? printf('[%s]', GetSyntaxInfo()) : '' endfunction function STLCharacterCode() abort return s:check_flag('statusline_char') \ ? printf('[%s]', GetCharacterCode()) : '' endfunction function STLFileSize() abort return s:check_flag('statusline_filesize') \ ? printf('[%s]', GetFileSize()) : '' endfunction function GetBufname(...) abort let bufnr = get(a:000, 0, '') let tail = get(a:000, 1, 0) let bufname = bufname(bufnr) let buftype = getbufvar(bufnr, '&buftype') if bufname ==# '' if buftype ==# '' return '[No Name]' elseif buftype ==# 'quickfix' return '[Quickfix List]' elseif buftype ==# 'nofile' || buftype ==# 'acwrite' return '[Scratch]' endif endif if tail && bufname =~# '^[[:alnum:].+-]\+://' let head = matchstr(bufname, '^[[:alnum:].+-]\+://[^/]\+') let file = matchstr(bufname, '[^/]\+$') let short_path = head .. '/../' .. file return strwidth(bufname) < strwidth(short_path) ? bufnr : short_path endif if buftype ==# 'nofile' || buftype ==# 'acwrite' return bufname endif if tail return fnamemodify(bufname, ':t') endif if exists('b:lcd') && b:lcd !=# '' let fullpath = fnamemodify(bufname, ':p') let bufname = matchstr(fullpath, '^\V\(' .. escape(b:lcd, '\') \ .. '\v)?[/\\]?\zs.*') if exists('g:actual_curbuf') let actual_lcd = getbufvar(g:actual_curbuf - 0, 'lcd', '') if actual_lcd !=# '' && actual_lcd !=# b:lcd let bufname = '*' .. bufname endif endif endif return bufname endfunction function StatusLineExtra() abort let extra = '' for scope in ['w:', 'b:', 't:', 'g:'] if exists(scope .. 'statusline_extra') let e = {scope .. 'statusline_extra'} if e[0] ==# '=' let r = eval(e[1 :]) let e = type(r) == v:t_string ? r : string(r) endif let extra ..= e endif endfor return extra endfunction function MakeStatusLine(...) abort let multi = a:0 && a:1 let line = '' let line ..= '%{STLBufnr()}' " Buffer number. let line ..= '%<' " Truncate point. " Buffer name. let line ..= '%{GetBufname()}' if multi let line ..= '%@' else let line ..= ' ' endif " Character encoding let line ..= '[%{(&fenc!=#"" ? &fenc : &enc) .. (&bomb ? "(BOM)" : "")}:' " File format (+ &binary and &endofline) if exists('+fixendofline') let line ..= '%{&ff .. (&bin?":bin":"") .. (&eol?"":":noeol")}]' else let line ..= '%{&ff .. (&bin?"(BIN" .. (&eol?"":"-noeol") .. ")":"")}]' endif let line ..= '%y' " Filetype. let line ..= '%m' " Modified flag. let line ..= '%r' " Readonly flag. let line ..= '%{get(b:, "swapfile_exists", 0) ? "[swp]" : ""}' let line ..= '%h' " Help buffer hlag. let line ..= '%w' " Preview window flag. " The state of SKK. let line ..= '%{get(b:, "skk_on", 0) ? SkkGetModeStr() : ""}' if exists('*eskk#statusline') let line ..= '%{eskk#statusline()}' endif if exists('*Skkeleton_statusline') let line ..= '%{Skkeleton_statusline()}' endif if exists('*SyntasticStatuslineFlag') let line ..= '%{SyntasticStatuslineFlag()}' endif let line ..= '%{STLHighLight()}' let line ..= '%{StatusLineExtra()}' " let line ..= StatusLineExtra() let line ..= '%=' " Separation point. let line ..= '%{STLFileSize()}' " Rough file size. let line ..= '%{STLCharacterCode()}' " Character code under the cursor. let line ..= $LANG =~# '^ja' ? ' %l/%L行 %3v桁' \ : ' %l/%LL %2vC' " Line and column. let line ..= ' %3p%%' " Percentage through file in lines. return line endfunction function s:buf_label(bufnr, i, is_cur) abort let label = GetBufname(a:bufnr, 1) if getbufvar(a:bufnr, '&modified') let label ..= '+' endif let curmark = a:is_cur ? '>' : ' ' return printf(' %s%d) %s', curmark, a:i, label) endfunction function s:tabpage_label(n, ...) abort let is_sidebar = a:0 && a:1 let n = a:n let bufnrs = tabpagebuflist(n) let curwinnr = tabpagewinnr(n) let curbufnr = bufnrs[curwinnr - 1] " first window, first appears let hi = n == tabpagenr() ? 'TabLineSel' : 'TabLine' let label = printf('%%#%sTabNumber#%d:%%#%s# ', hi, n, hi) let label ..= '%<' let title = gettabvar(n, 'title') if is_sidebar && get(g:, 'tabsidebar_show_all_window', 0) let cwd = getcwd(curwinnr, n) let label ..= title !=# '' ? title : fnamemodify(cwd, ':t') .. '/' let labels = map(copy(bufnrs), { i, v -> \ s:buf_label(v, i + 1, curwinnr == i + 1) \ }) let label ..= "\n" .. join(labels, "\n") elseif title !=# '' let label ..= title else let text = GetBufname(curbufnr, 1) let mod_bufs = filter(copy(bufnrs), 'getbufvar(v:val, "&modified")') let mod = len(mod_bufs) ? '+' : '' let label ..= text .. mod let no = len(bufnrs) if 2 <= no let label ..= ' %#' .. hi .. 'Number#' .. no let label ..= '%#' .. hi .. '#' endif endif return label endfunction function MakeTabLine() abort let sep = ' | ' let has_tabsidebar = has('tabsidebar') && \ (&g:showtabsidebar == 2 || \ &g:showtabsidebar == 1 && 2 <= tabpagenr('$')) if has_tabsidebar let tabs = '%{GetBufname()}' else let titles = map(range(1, tabpagenr('$')), 's:tabpage_label(v:val)') let titles = map(titles, function('printf', ['%%%dT%s%%T%%#TabLineFill#'])) let tabs = join(titles, sep) .. sep .. '%#TabLineFill#%T' endif let info = '%#TabLine#' if exists('t:tabline_extra') let info ..= t:tabline_extra .. sep endif if dein#is_sourced('current-func-info') let info ..= cfi#format('%s()' .. sep, '') endif if exists('*Uptime') && has_tabsidebar let info ..= Uptime(2) .. sep endif if dein#is_sourced('reanimate') let last_point = reanimate#last_point() if last_point =~# '^session/' let info ..= matchstr(last_point, '/\zs.*') .. sep endif endif if dein#is_sourced('gina') let branch = gina#component#repo#branch() if branch !=# '' let info ..= branch .. sep endif endif let cwd = fnamemodify(getcwd(), ':~') " TODO: vcs#root() occurs an error by unknown reason, and can not catch it let vcs_root = exists('*vcs#root') ? vcs#root(cwd) : '' if vcs_root !=# '' let vcs_root = fnamemodify(vcs_root, ':~') if len(vcs_root) < len(cwd) let cwd = substitute(vcs_root, '\([/\\][^/\\]\)[^/\\]*', '\1', 'g') \ .. cwd[len(vcs_root) :] endif endif let info ..= cwd .. ' ' return tabs .. '%=' .. info endfunction if has('tabsidebar') function s:update_showtabsidebar() abort let &g:showtabsidebar = 80 * 2 + &g:tabsidebarcolumns <= &columns endfunction call s:update_showtabsidebar() Set tabsidebarcolumns=32 Set tabsidebarwrap let g:tabsidebar_show_all_window = 1 let g:tabsidebar_vertsplit = 1 let &g:tabsidebar = \ '%!' .. get(function('s:tabpage_label'), 'name') .. \ '(g:actual_curtabpage, 1)' augroup tabsidebar-highlight autocmd! autocmd ColorScheme * highlight! link TabSideBar TabLine autocmd ColorScheme * highlight! link TabSideBarSel TabLineSel autocmd ColorScheme * highlight! link TabSideBarFill TabLineFill augroup END augroup tabsidebar-size autocmd! autocmd VimResized * call s:update_showtabsidebar() augroup END doautocmd tabsidebar-highlight ColorScheme endif " == Behavior settings. == {{{1 " Enable FileType if v:vim_did_enter " To reapply 'ftdetect/*.vim'. filetype off endif filetype plugin indent on " Search. Set ignorecase smartcase incsearch hlsearch if has('migemo') " 'migemo' option changes the behavior of "g?". " NOTE: 'migemo' option is local to buffer. Set nomigemo migemodict=$VIM_USERDIR/dict/migemo/migemo-dict endif if executable('rg') if executable('jq') let &grepprg = 'rg --json $* \| jq -r ''select(.type=="match")\|.data as $data\|$data.submatches[]\|"\($data.path.text):\($data.line_number):\(.start+1):\(.end+1):\($data.lines.text//""\|sub("\n$";""))"''' Set grepformat=%f:%l:%c:%k:%m else Set grepprg=rg\ --no-heading\ --column\ --color\ never endif elseif executable('jvgrep') Set grepprg=jvgrep\ -RC elseif executable('ag') Set grepprg=ag\ --nogroup\ --column\ --nocolor Set grepformat=%f:%l:%c:%m,%l:%c:%m elseif executable('ack') Set grepprg=ack\ --nogroup\ --column\ --nocolor else Set grepprg=internal endif " Tab and indent. Set shiftround softtabstop=-1 shiftwidth=0 tabstop=2 Set autoindent copyindent preserveindent Set breakindent Set expandtab Set cinoptions& cinoptions+=b1,l1,g0,N-s,(1s,m1 Set cinkeys& cinkeys+=0=break " Auto reload when changed by external. Set autoread " Enable backspace. Set backspace=indent,eol,start " Allow move between line end and next line head. Set whichwrap=b,s,<,>,[,] if exists('+fixendofline') Set nofixendofline endif " Format settings for multi byte character. Set formatoptions& formatoptions+=mM Set formatoptions-=r formatoptions-=o formatoptions+=j formatoptions+=n " The following needs autofmt plugin. let g:plugin_format_disable = 1 Set formatexpr=autofmt#japanese#formatexpr() " Minimal number of screen lines to keep above and below the cursor. Set scrolloff=3 Set nostartofline Set sidescroll=1 sidescrolloff=1 Set modeline " Open a window. Set splitbelow splitright Set switchbuf& switchbuf+=useopen " Completion. Set complete& complete+=k Set completeopt& completeopt+=menuone completeopt-=preview Set infercase " Command-line completion. Set wildmenu wildmode=list:longest,full wildignorecase " Foldings. Set foldlevelstart=99 " History number for search and command mode. Set history=1000 " Toggle Command-line mode and cmdwin with let &g:cedit = "\" Set timeoutlen=5000 Set ttimeout ttimeoutlen=50 Set nrformats& nrformats-=octal if has('patch-8.2.0860') Set nrformats+=unsigned endif " spelling Set spelllang& spelllang+=cjk Set spelloptions& spelloptions+=camel Set spellfile=~/.local/share/vim/spell/en.utf-8.add call mkdir(expand('~/.local/share/vim/spell'), 'p') " encryption if has('crypt-blowfish2') Set cryptmethod=blowfish2 endif " backup. Set backup Set backupdir=~/.cache/vim/backup// " Paths of swap file and backup file. if $TMP !=# '' execute 'Set backupdir+=' .. escape(expand($TMP), ' \') elseif has('unix') Set backupdir+=/tmp endif Set directory=~/.cache/vim/swap// if has('persistent_undo') Set undodir=~/.cache/vim/undo augroup vimrc-undofile autocmd! autocmd BufReadPre ~/* setlocal undofile if s:is_win autocmd BufReadPre D:/* setlocal undofile endif augroup END endif Set backupcopy=yes Set viewdir=~/.cache/vim/view call mkdir(expand('~/.cache/vim/backup'), 'p') call mkdir(expand('~/.cache/vim/swap'), 'p') call mkdir(expand('~/.cache/vim/undo'), 'p') " Swap Set swapfile augroup vimrc-swapfile autocmd! autocmd SwapExists * call s:on_SwapExists() augroup END function s:on_SwapExists() abort if !filereadable(expand('')) let v:swapchoice = 'd' return endif let v:swapchoice = get(b:, 'swapfile_choice', 'o') unlet! b:swapfile_choice if v:swapchoice !=# 'd' let b:swapfile_exists = 1 endif endfunction command! SwapfileRecovery call s:swapfile_recovery() command! SwapfileDelete call s:swapfile_delete() function s:swapfile_recovery() abort if get(b:, 'swapfile_exists', 0) let b:swapfile_choice = 'r' unlet b:swapfile_exists edit endif endfunction function s:swapfile_delete() abort if get(b:, 'swapfile_exists', 0) let b:swapfile_choice = 'd' unlet b:swapfile_exists edit endif endfunction if has('viminfo') " TELLME: The history is not saved in specified number. Set viminfo='500,<500,s50,h,rA:,rB: end " Free move in Visual mode blockwise. Set virtualedit& virtualedit+=block " Don't search tags file in current directory. And search upward. Set tags& tags-=tags tags+=./tags; Set tagcase=match " autocmd if has('multi_statusline') augroup vimrc-multi-statusline autocmd! BufEnter \ * if 80 < len(GetBufname()) \ | setlocal statusline=%!MakeStatusLine(1) statuslineheight=2 \ | else \ | setlocal statusline< statuslineheight< \ | endif augroup END endif augroup vimrc-auto-cursorline autocmd! autocmd CursorMoved,CursorMovedI * call s:auto_cursorline('CursorMoved') autocmd CursorHold,CursorHoldI * call s:auto_cursorline('CursorHold') autocmd WinEnter * call s:auto_cursorline('WinEnter') autocmd WinLeave * call s:auto_cursorline('WinLeave') let s:cursorline_lock = 0 function s:auto_cursorline(event) abort if &l:buftype isnot# '' || get(b:, 'cursorline_disable', 0) return endif if a:event ==# 'WinEnter' setlocal cursorline let s:cursorline_lock = 2 elseif a:event ==# 'WinLeave' setlocal nocursorline elseif a:event ==# 'CursorMoved' if s:cursorline_lock if 1 < s:cursorline_lock let s:cursorline_lock = 1 else setlocal nocursorline let s:cursorline_lock = 0 endif endif elseif a:event ==# 'CursorHold' setlocal cursorline let s:cursorline_lock = 1 endif endfunction augroup END augroup vimrc-lcd autocmd! autocmd BufReadPre,BufFilePre * unlet! b:lcd autocmd BufReadPost,BufFilePost,FileType * call s:lcd() function s:lcd() abort if &l:buftype !=# '' && &l:buftype !=# 'help' if exists('b:lcd_original') lcd `=b:lcd_original` endif " unlet! b:lcd b:lcd_original return endif if exists('b:lcd') && (b:lcd ==# '' || getcwd() ==# b:lcd) return endif let path = s:lcd_path() if isdirectory(path) let b:lcd_original = getcwd() lcd `=path` let b:lcd = getcwd() let b:lcd_count = get(b:, 'lcd_count', 0) + 1 endif endfunction let g:lcd = [ \ ['tags'], \ [ \ 'Gemfile', \ 'package.json', \ 'Cargo.toml', \ ], \ [ \ '.svn/', \ '.git/', \ '.git', \ '.bzr/', \ '.hg/', \ 'doc/:vim,help,vimspec', \ ], \ ['README.*', 'README'], \ ['src/', 'include/'], \ ] function s:lcd_path() abort let path = '' let simple = expand('%:p:h:gs?\\\+?/?') if &l:buftype ==# 'help' return simple endif for lib_pat in [ \ '^.*/vendor/bundle/\%(ruby/[^/]\+/\)\?\%(bundler/\)\?gems/[^/]\+/', \ '^.*/node_modules/[^/]\+/', \ ] let lib_base = matchstr(simple, lib_pat) if lib_base !=# '' return lib_base endif endfor for targets in g:lcd let dir = expand('%:p:h') let pdir = '' while dir isnot# pdir for target in targets let [name; opts] = split(target, ':') if !empty(opts) && index(split(opts[0], ','), &l:filetype) < 0 continue endif let t = dir .. '/' .. name if name =~# '/$' ? isdirectory(t) : len(glob(t)) return dir endif endfor let pdir = dir let dir = fnamemodify(dir, ':h') endwhile endfor return simple endfunction augroup END augroup vimrc-auto-mkdir autocmd! autocmd BufWritePre * call s:auto_mkdir(expand(':p:h'), v:cmdbang) function s:auto_mkdir(dir, force) abort if &l:buftype !=# '' || bufname('%') =~# '^[^:]\+://' return endif let mes = '"%s" does not exist. Create? [y/N]' if !isdirectory(a:dir) && (a:force || \ input(printf(mes, a:dir)) =~? '^y\%[es]$') call mkdir(a:dir, 'p') endif endfunction augroup END if executable('chmod') augroup vimrc-autoexecutable autocmd! autocmd BufWritePost * call s:add_permission_x() augroup END function s:add_permission_x() abort let file = expand('%:p') if getline(1) =~# '^#!' && !executable(file) silent! call system('chmod a+x ' .. shellescape(file)) endif endfunction endif augroup vimrc-fileencoding autocmd! autocmd BufReadPost * if &modifiable && !&modified && \ !search('[^\x00-\x7F]', 'cnw') \ | setlocal fileencoding= \ | endif augroup END if !v:vim_did_enter && &binary " launched with -b option augroup vimrc-xxd autocmd! autocmd BufReadPost * if &l:binary | setlocal filetype=xxd | endif augroup END endif augroup vimrc-misc autocmd! " Set 'dictionary'. autocmd FileType \ * if filereadable(expand('$VIM_USERDIR/dict/' .. &l:filetype .. '.dict')) \ | let &l:dict = '$VIM_USERDIR/dict/' .. &l:filetype .. '.dict' \ | endif autocmd FileType \ * if &l:buftype !=# 'help' && &l:kp ==# '' && mapcheck('K', 'n') ==# '' \ | silent! execute 'nnoremap K }' \ | endif " Auto open/close Quickfix/location window. autocmd QuickFixCmdPost [^l]* leftabove cwindow | redraw! autocmd QuickFixCmdPost l* silent! lwindow | redraw! " Update filetype. autocmd BufWritePost \ * if &l:filetype ==# '' || exists('b:ftdetect') \ | unlet! b:ftdetect \ | filetype detect \ | endif " Check timestamp more for 'autoread'. autocmd WinEnter,FocusGained * checktime % autocmd BufReadPost bzr_log.* let &l:fileencoding = &termencoding " Edit something to avoid the confirmation when aborting. autocmd BufReadPost bzr_log.* if empty(getline(1)) \ | 1 delete _ | silent write \ | endif autocmd InsertEnter * if &l:foldmethod ==# 'expr' \ | let b:foldinfo = [&l:foldmethod, &l:foldexpr] \ | setlocal foldmethod=manual foldexpr=0 \ | endif autocmd InsertLeave * if exists('b:foldinfo') \ | let [&l:foldmethod, &l:foldexpr] = b:foldinfo \ | endif autocmd InsertLeave * if &paste | set nopaste | endif autocmd InsertLeave * if &diff | diffupdate | endif autocmd VimResized * wincmd = augroup END " == Key mappings & command definition. == {{{1 " It is likely to be changed by $VIM/vimrc. if !v:vim_did_enter mapclear mapclear! endif function s:meta_map(key, rhs, ...) abort let mode = a:0 ? a:1 : 'n' let modifier = has('mac') ? 'D' : 'M' execute printf('%snoremap <%s-%s> %s', mode, modifier, a:key, a:rhs) endfunction " -- Key mappings. {{{2 " Physical moving. noremap j gj noremap k gk noremap gj j noremap gk k nnoremap 0 &l:wrap ? 'g0' : '0' nnoremap g0 &l:wrap ? '0' : 'g0' nnoremap ^ &l:wrap ? 'g^' : '^' nnoremap g^ &l:wrap ? '^' : 'g^' nnoremap $ &l:wrap ? 'g$' : '$' nnoremap g$ &l:wrap ? '$' : 'g$' " Yank to the end of line. (It is same as C and D) nnoremap Y y$ " Current line at center of window and open the folding. noremap n nzzzv noremap N Nzzzv " Very magic by default. nnoremap / /\v nnoremap ? ?\v cnoremap s/ getcmdline() =~# '^\A*$' ? 's/\v' : 's/' cnoremap g/ getcmdline() =~# '^\A*$' ? 'g/\v' : 'g/' cnoremap v/ getcmdline() =~# '^\A*$' ? 'v/\v' : 'v/' cnoremap s// s// cnoremap g// g// cnoremap v// v// nnoremap gA AU nnoremap " Control search highlight. if dein#is_sourced('asterisk') noremap (vimrc-searchafter) zz noremap * (asterisk-z*)(vimrc-searchafter) noremap # (asterisk-z#)(vimrc-searchafter) noremap g* (asterisk-gz*)(vimrc-searchafter) noremap g# (asterisk-gz#)(vimrc-searchafter) let g:asterisk#keeppos = 1 endif nnoremap nohlsearch " Search the word nearest to the cursor in new window. nnoremap * s* nnoremap # s# nnoremap V vgF " repeat :substitute with same flag noremap & :&& " Search selected area. vnoremap z/ /\v%V vnoremap z? ?\v%V " Repeat on Visual-mode. vnoremap . :normal . vnoremap @q :normal @q " Switch the tab page. nnoremap gt nnoremap gT for s:n in range(1, 9) call s:meta_map(s:n, s:n .. 'gt') endfor unlet! s:n " Scroll + Move nnoremap gj nnoremap gk nnoremap [c &diff ? '[c' : 'cprevious' nnoremap ]c &diff ? ']c' : 'cnext' nnoremap [l lprevious nnoremap ]l lnext " Swap ; and : noremap ; : noremap : ; function s:good_feeling_prefix() abort return printf(":\%s", 78 * 2 <= winwidth(0) ? 'vertical ' : '') endfunction nnoremap good_feeling_prefix() .. 'h ' nnoremap tm good_feeling_prefix() .. 'terminal' " Show :messages quickly. nnoremap v:count ? '' .. v:count .. 'messages' : '' nnoremap ]p paste_with_indent() function s:paste_with_indent() abort if getregtype(v:register) isnot# 'V' call setreg(v:register, getreg(v:register) . "\n") endif return "]p:undojoin\=`]" endfunction " Don't move at escaping from insert mode. " inoremap :keepjumps normal! `^ " Quick completion. inoremap " Create an undo point before and . " XXX: doesn't work on inoremap (pumvisible() ? '' : '') .. 'u' inoremap u " inoremap pumvisible() ? '' : '' inoremap " To uppercase/lowercase the word immediately before. inoremap gUvbgi inoremap guvbgi " Make inputting a character by code easily. inoremap (vimrc-input-char-by-code) \ =nr2char(eval(input('char? ', '0x'))) inoremap x (vimrc-input-char-by-code) inoremap u (vimrc-input-char-by-code) inoremap U (vimrc-input-char-by-code) " Select the last changed. nnoremap gc '`[' .. getregtype()[0] .. '`]' onoremap gc normal gc onoremap gv normal gv onoremap q /["',.{}()[\]<>] " Do not select whitespace of outer of quotes. :help v_iquote onoremap a" 2i" onoremap a' 2i' onoremap a` 2i` " Prevent a typing error. nmap imap cmap nnoremap h nnoremap j nnoremap k nnoremap l nnoremap H nnoremap J nnoremap K nnoremap L call s:meta_map('h', 'h') call s:meta_map('j', 'j') call s:meta_map('k', 'k') call s:meta_map('l', 'l') call s:meta_map('H', 'H') call s:meta_map('J', 'J') call s:meta_map('K', 'K') call s:meta_map('L', 'L') nnoremap c "_c nnoremap C "_C " Don't use commands. noremap ZZ noremap ZQ noremap noremap nnoremap =ae KeepCursor normal! gg=G " Mappings for command-line mode. cnoremap cnoremap cnoremap " Move the cursor not complete list. cnoremap cnoremap cnoremap cnoremap cnoremap cnoremap nnoremap " Quick save and quit. nnoremap w update nnoremap W update! nnoremap q quit nnoremap Q quit! " Change encodings and formats. nnoremap e nnoremap es setlocal fenc=cp932 nnoremap ee setlocal fenc=euc-jp nnoremap eu setlocal fenc=utf-8 nnoremap ej setlocal fenc=iso-2022-jp nnoremap ed setlocal ff=dos nnoremap ex setlocal ff=unix " Change statusline. nnoremap s for [s:key, s:var] in [['n', 'bufnr'], ['c', 'char'], \ ['s', 'filesize'], ['h', 'highlight']] for [s:prefix, s:scope] in [['', 'g'], ['b', 'b'], ['w', 'w']] execute printf('nnoremap s%s%s ' \ .. 'call toggle_flag(%s:, "statusline_%s")' \ .. 'redrawstatus!', \ s:prefix, s:key, s:scope, s:var) endfor endfor unlet! s:key s:var s:prefix s:scope " Quick toggle options. nnoremap o nnoremap oe setlocal expandtab! expandtab? nnoremap of \ let &l:foldcolumn=1-&l:foldcolumn:setlocal foldcolumn? nnoremap on setlocal number! number? nnoremap ol setlocal list! list? nnoremap ow setlocal wrap! wrap? nnoremap os setlocal spell! spell? nnoremap op set paste! paste? " Tabpage operation. nnoremap t nnoremap tn tabnew nnoremap tc :=v:count?v:count:''tabclose " q as prefix nnoremap