" __ " __ __ /\_\ ___ ___ _ __ ___ " /\ \/\ \\/\ \ /' __` __`\/\`'__\/'___\ " \ \ \_/ |\ \ \/\ \/\ \/\ \ \ \//\ \__/ " \ \___/ \ \_\ \_\ \_\ \_\ \_\\ \____\ " \/__/ \/_/\/_/\/_/\/_/\/_/ \/____/ " dein.vim settings {{{ " install dir {{{ let s:dein_dir = expand('~/.cache/dein') let s:dein_repo_dir = s:dein_dir . '/repos/github.com/Shougo/dein.vim' " }}} " dein installation check {{{ if &runtimepath !~# '/dein.vim' if !isdirectory(s:dein_repo_dir) execute '!git clone https://github.com/Shougo/dein.vim' s:dein_repo_dir endif execute 'set runtimepath^=' . s:dein_repo_dir endif " }}} " begin settings {{{ if dein#load_state(s:dein_dir) call dein#begin(s:dein_dir) " .toml file let s:rc_dir = expand('~/.vim') let s:toml = s:rc_dir . '/dein.toml' let s:lazy_toml = s:rc_dir . '/dein_lazy.toml' " read toml and cache call dein#load_toml(s:toml, {'lazy': 0}) call dein#load_toml(s:lazy_toml, {'lazy': 1}) " end settings call dein#end() call dein#save_state() endif " }}} " plugin installation check {{{ if dein#check_install() call dein#install() endif " }}} " plugin remove check {{{ let s:removed_plugins = dein#check_clean() if len(s:removed_plugins) > 0 call map(s:removed_plugins, "delete(v:val, 'rf')") call dein#recache_runtimepath() endif " }}} " }}} " general settings {{{ " ミュート {{{ set t_vb= set visualbell set noerrorbells " }}} " 文字コード {{{ set encoding=utf-8 set fileencodings=utf-8,iso-2022-jp,euc-jp,sjis set fileformats=unix,dos,mac " }}} " vim scriptでマルチバイト文字を使用しているため設定 {{{ scriptencoding utf-8 " }}} " https://vim-jp.org/vimdoc-ja/map.html#mapleader " Leaderキーをスペースに設定 {{{ let g:mapleader = "\" " }}} " シンタックスを有効にする {{{ syntax enable " }}} " カラースキームを使う {{{ colorscheme iceberg " }}} " https://vim-jp.org/vimdoc-ja/filetype.html#:filetype-plugin-on " https://vim-jp.org/vimdoc-ja/filetype.html#:filetype-indent-on " ファイル形式別プラグインとインデントを有効にする {{{ filetype plugin indent on " }}} " バックスペースとCtrl+hで削除を有効にする {{{ set backspace=2 " }}} " 改行時自動インデント {{{ set smartindent " }}} " 行番号を表示 {{{ set number " }}} " カーソルから相対的な行数を表示する {{{ set relativenumber " }}} " https://vim-jp.org/vimdoc-ja/options.html#'tabstop' " タブでも常に空白を挿入 {{{ set tabstop=4 set shiftwidth=4 "set expandtab " }}} " インクリメントサーチを有効にする {{{ set incsearch " }}} " https://vim-jp.org/vimdoc-ja/options.html#'ignorecase' " 検索時大文字小文字を区別しない {{{ set ignorecase " }}} " https://vim-jp.org/vimdoc-ja/options.html#'smartcase' " 検索時に大文字を入力した場合ignorecaseが無効になる {{{ set smartcase " }}} " ハイライトサーチを有効にする {{{ set hlsearch " }}} " undoできる最大数 {{{ set undolevels=1000 " }}} " mac os のクリップボードを共有 {{{ set clipboard+=unnamed " }}} " カーソルが常に中央に来るようにする {{{ set scrolloff=100 " }}} " スワップファイルに書き込まれる時間(ミリ秒単位) {{{ set updatetime=450 " }}} " マクロで効果発揮 {{{ set lazyredraw set ttyfast " }}} " 一行が長いファイルをsyntaxを制御することで軽くする {{{ set synmaxcol=256 " }}} " カーソルラインを表示する {{{ set cursorline " }}} " https://vim-jp.org/vimdoc-ja/pi_netrw.html#g:netrw_liststyle " netrwツリー表示を有効にする {{{ let g:netrw_liststyle=3 let g:netrw_banner=0 let g:netrw_sizestyle='H' let g:netrw_timefmt='%Y/%m/%d(%a) %H:%M:%S' let g:netrw_preview=1 " }}} " 拡張子ごとのインデントを指定する {{{ augroup fileTypeIndent autocmd! au BufRead,BufNewFile *.php setlocal tabstop=4 softtabstop=4 shiftwidth=4 au BufRead,BufNewFile *.html setlocal tabstop=4 softtabstop=4 shiftwidth=4 au BufRead,BufNewFile *.js setlocal tabstop=4 softtabstop=4 shiftwidth=4 au BufRead,BufNewFile *.vue setlocal tabstop=4 softtabstop=4 shiftwidth=4 augroup END " }}} " https://vim-jp.org/vimdoc-ja/options.html#'wildmode' " wildmenuを有効にする {{{ set wildmenu set wildmode=full " }}} " grepした結果をquickfixに表示する {{{ augroup grepwindow autocmd! au QuickFixCmdPost *grep* cwindow augroup END " }}} " カーソルラインの位置を保存する {{{ augroup cursorlineRestore autocmd! autocmd BufReadPost * \ if line("'\"") > 0 && line ("'\"") <= line("$") | \ exe "normal! g'\"" | \ endif augroup END " }}} " undoの保存先 {{{ if has('persistent_undo') set undodir=~/.vim/undo set undofile endif " }}} " visualモードのハイライトカラー {{{ hi Visual cterm=reverse ctermbg=NONE " }}} " 矩形選択時に文字の無いところまで選択範囲を広げる {{{ set virtualedit=block " }}} " ヘルプの言語を日本語優先にする {{{ set helplang=ja " }}} " ファイル保存時に整形する {{{ function! Format() abort let pos = getcurpos() execute 'normal 1G=G' call setpos('.', pos) endfunction function! JsFormat() abort if executable('js-beautify') " --type [js|css|html] default is js " -t indent with tabs let pos = getcurpos() exe "%!js-beautify --type js -t" call setpos('.', pos) else echo "js-beautify doesn't install, please refference the https://github.com/beautify-web/js-beautify" endif endfunction function! JsonFormat() abort if executable('jq') let pos = getcurpos() exe "%!jq --tab" call setpos('.', pos) else echo "jq doesn't install, please refference the https://stedolan.github.io/jq/" endif endfunction augroup format autocmd! autocmd BufWritePre *.js call JsFormat() autocmd BufWritePre *.vim call Format() autocmd BufWritePre *.html call Format() autocmd BufWritePre *.java call Format() autocmd BufWritePre *.json call JsonFormat() augroup END " }}} " プラグインディレクトリ配下の.vimをすべてsourceする {{{ function! SourceDir(...) abort let l:path = getcwd() if a:0 > 1 let l:path = a:1 endif if !isdirectory(l:path) return endif exe 'set rtp^=' . l:path if isdirectory(l:path . '/plugin') exe 'runtime plugin/*.vim' endif if isdirectory(l:path . '/autoload') exe 'runtime autoload/*.vim' endif if isdirectory(l:path . '/syntax') exe 'runtime syntax/*.vim' endif endfunction " }}} " listの設定 {{{ set list set listchars=tab:»-,trail:-,eol:↲,extends:»,precedes:«,nbsp:% "hi NonText ctermbg=None ctermfg=Yellow "hi SpecialKey ctermbg=None ctermfg=Yellow " }}} " {{{ 行末のホワイトスペース削除 autocmd BufWritePre * :silent %s/\s\+$//ge augroup HighlightTrailingSpaces autocmd! autocmd VimEnter,WinEnter,ColorScheme * highlight TrailingSpaces term=underline guibg=Red ctermbg=Red autocmd VimEnter,WinEnter * match TrailingSpaces /\s\+$/ augroup END " }}} " swapファイルを作成しない set noswapfile " セッションで保存する対象を設定する if !has('nvim') set sessionoptions=blank,buffers,curdir,folds,help,tabpages,winsize,terminal endif " ウィンドウサイズ自動調整を無効化 set noequalalways " タブを常に表示 set showtabline=2 " }}} " key mappings {{{ " *でカーソルを移動しないようにする noremap * *N " ファイル保存と終了 {{{ nnoremap w :w nnoremap q :q! " }}} " 検索 nnoremap :Ggrep " 置換 nnoremap re :%s;\<\>;g; " visualで選択したテキストを置換する vnoremap re y:%s;=substitute(@", "", "\\\\n", "g");;g " ハイライトを削除する nnoremap :nohlsearch " vimrcを開く nnoremap . :new ~/.vimrc nnoremap s :source ~/.vimrc " テキストオブジェクトキーマッピング {{{ onoremap 8 i( onoremap 2 i" onoremap 7 i' onoremap @ i` onoremap [ i[ onoremap { i{ onoremap a8 a( onoremap a2 a" onoremap a7 a' onoremap a@ a` onoremap a[ a[ onoremap a{ a{ " visual nnoremap v8 vi( nnoremap v2 vi" nnoremap v7 vi' nnoremap v@ vi` nnoremap v[ vi[ nnoremap v{ vi{ nnoremap va8 va( nnoremap va2 va" nnoremap va7 va' nnoremap va@ va` nnoremap va[ va[ nnoremap va{ va{ " }}} " 行先頭と行末 map H ^ map L $ " タブ切り替え nnoremap n gt nnoremap p gT " visual時に選択行を移動 vnoremap :m '>+1gv vnoremap :m '<-2gv " numberとrelativenumberの切り替え nnoremap n :set relativenumber! " 自作アプリケーションランチャー nnoremap l :bo term ++close gol -f " visual paste vnoremap "0p " ターミナル関連 {{{ " ターミナルを開く " a:1 new or vnew or tabnew(default is new) " a:2 path (default is current) " a:3 shell (default is &shell) function! s:open_terminal(...) abort let open_type = 'new' let shell = &shell let path = getcwd() if a:0 > 0 && a:0 !=# '' let open_type = a:1 endif if a:0 > 1 && a:2 !=# '' let path = a:2 endif if a:0 > 2 && a:3 !=# '' let shell = a:3 endif if open_type ==# 'new' let open_type = open_type endif exe printf('%s | lcd %s', open_type, path) exe printf('term ++curwin ++close %s', shell) exe 'call term_setrestore("%", printf("++close bash -c \"cd %s && bash\"", getcwd()))' endfunction command! -nargs=* OpenTerminal call s:open_terminal() " ターミナルを開く noremap \ :OpenTerminal vnew noremap - :OpenTerminal noremap ^ :OpenTerminal tabnew tnoremap \ :OpenTerminal vnew tnoremap - :OpenTerminal tnoremap ^ :OpenTerminal tabnew ""tnoremap . ""tnoremap . " ターミナルノーマルモード tnoremap n N " ターミナルでウィンドウ移動 tnoremap p :tabprevious tnoremap n :tabnext " ウィンドウリサイズ開始 tnoremap :WinResizerStartResize " リポジトリ移動 tnoremap cd :Repo " 単語削除 tnoremap . " }}} " 上下の空白に移動 nnoremap } nnoremap { " review augroup review au! au FileType review vnoremap hi c@{"} augroup END " 改行 nnoremap gj o nnoremap gk O " git status nnoremap gs :Gstatus " バッファ一覧 nnoremap gb :Buffers " ヘルプ augroup helpMapping au! au FileType help nnoremap q :q augroup END " コマンドラインで単語移動 {{{ cnoremap cnoremap cnoremap " }}} " }}} " vim-go settings {{{ " ファイル保存時go importを実行する let g:go_fmt_command = 'goimports' " ファイル保存時、linterを実行する let g:go_metalinter_autosave = 1 " linter実行時、go vetのみを実行する let g:go_metalinter_autosave_enabled = ['vet'] " golangci-lintを使う let g:go_metalinter_command = "golangci-lint" " vim-lspをしようするので、vim-goの`Ctrl+]`を無効にする "let g:go_def_mapping_enabled = 0 " GoDocでポップアップウィンドウを使用する let g:go_doc_popup_window = 1 " GoRunやGoTest時の画面分割方法変更 let g:go_term_mode = 'split' " テンプレート作成を無効化 let g:go_template_autocreate = 0 " すでに開いているバッファに定義ジャンプする let g:go_def_reuse_buffer = 1 " goplsで定義ジャンプ let g:go_def_mode = 'gopls' let g:go_fold_enable = ['block', 'import', 'varconst', 'package_comment'] " key mapping augroup goMapping autocmd! au FileType go nnoremap c (go-coverage) au FileType go nnoremap r (go-run) au FileType go nnoremap t (go-test) au FileType go nnoremap c (go-coverage) au FileType go nnoremap at :GoAddTags au FileType go nnoremap rt :GoRemoveTags au FileType go nnoremap fs :GoFillStruct au FileType go nnoremap ki :GoKeyify au FileType go nnoremap dd :GoDeclsDir au FileType go nnoremap dl :GoDecls au FileType go nnoremap ip :GoImpl au FileType go nnoremap rn :GoRename au FileType go nnoremap :GoDebugStart au FileType go nnoremap :GoDebugStop au FileType go set foldmethod=syntax augroup END " }}} " fzf settings {{{ " ファイル一覧を出すときにプレビュー表示 command! -bang -nargs=? -complete=dir Files \ call fzf#vim#files(, fzf#vim#with_preview(), 0) nnoremap :Files " }}} " lsp settings {{{ "nnoremap :LspDefinition nnoremap rf :LspReferences nnoremap im :LspImplementation augroup LspMapping autocmd! au FileType php nnoremap :LspDefinition au FileType c nnoremap :LspDefinition augroup END " 非同期補完を有効にする "let g:lsp_async_completion = 1 " lsp log "let g:lsp_log_verbose = 0 "let g:lsp_log_file = expand('~/vim-lsp.log') " enable signs "let g:lsp_signs_error = {'text': '✗'} "let g:lsp_signs_warning = {'text': '‼'} "let g:lsp_signs_enabled = 1 "let g:lsp_diagnostics_echo_cursor = 1 " Go {{{ "augroup LspGo " au! " if executable('gopls') " au User lsp_setup call lsp#register_server({ " \ 'name': 'gopls', " \ 'cmd': {server_info->['gopls', '-mode', 'stdio', '-logfile', '/Users/skanehira/gopls.log']}, " \ 'whitelist': ['go'], " \ }) " endif "augroup END " }}} " PHP {{{ augroup LspPHP au! au User lsp_setup call lsp#register_server({ \ 'name': 'php-language-server', \ 'cmd': {server_info->['php', expand('~/.cache/dein/repos/github.com/felixfbecker/php-language-server/bin/php-language-server.php')]}, \ 'whitelist': ['php'], \ }) augroup END " }}} " JavaScript {{{ augroup LspJavaScript au! if executable('flow-language-server') au User lsp_setup call lsp#register_server({ \ 'name': 'flow-language-server', \ 'cmd': {server_info->[&shell, &shellcmdflag, 'flow-language-server --stdio']}, \ 'root_uri':{server_info->lsp#utils#path_to_uri(lsp#utils#find_nearest_parent_file_directory(lsp#utils#get_buffer_path(), '.flowconfig'))}, \ 'whitelist': ['javascript', 'javascript.jsx'], \ }) endif augroup END " }}} " Docker {{{ augroup LspDocker au! if executable('docker-langserver') au User lsp_setup call lsp#register_server({ \ 'name': 'docker-langserver', \ 'cmd': {server_info->[&shell, &shellcmdflag, 'docker-langserver --stdio']}, \ 'whitelist': ['dockerfile'], \ }) endif augroup END " }}} " CSS {{{ augroup LspCSS au! if executable('css-languageserver') au User lsp_setup call lsp#register_server({ \ 'name': 'css-languageserver', \ 'cmd': {server_info->[&shell, &shellcmdflag, 'css-languageserver --stdio']}, \ 'whitelist': ['css', 'less', 'sass'], \ }) endif augroup END " }}} " clang {{{ augroup LspClangd if executable('clangd') au! au User lsp_setup call lsp#register_server({ \ 'name': 'clangd', \ 'cmd': {server_info->['clangd', '-background-index']}, \ 'whitelist': ['c', 'cpp', 'objc', 'objcpp'], \ }) endif augroup END " }}} " }}} " asyncomplete settings {{{ inoremap pumvisible() ? "\" : "\" inoremap pumvisible() ? "\" : "\" inoremap pumvisible() ? "\" : "\" " }}} " vim-markdown settings {{{ " mdを開くときの折りたたみを無効にする let g:vim_markdown_folding_disabled = 1 " }}} " vim-surround settings {{{ nmap 7 ysiw' nmap 2 ysiw" nmap ` ysiw` nmap 8 ysiw) nmap [ ysiw] nmap { ysiw} " }}} " ultisnips settings {{{ "let g:UltiSnipsExpandTrigger="" "let g:UltiSnipsJumpForwardTrigger="" "let g:UltiSnipsJumpBackwardTrigger="" " ultisnipes自動補完 "if has('python3') " call asyncomplete#register_source(asyncomplete#sources#ultisnips#get_source_options({ " \ 'name': 'ultisnips', " \ 'whitelist': ['*'], " \ 'completor': function('asyncomplete#sources#ultisnips#completor'), " \ })) "endif " }}} " profiling {{{ " vim +'call ProfileCursorMove()' <カーソルを動かすのが重いファイル> function! ProfileCursorMove() abort let profile_file = expand('./vim-profile.log') if filereadable(profile_file) call delete(profile_file) endif normal! ggzR execute 'profile start ' . profile_file profile func * profile file * augroup ProfileCursorMove autocmd! autocmd CursorHold profile pause | q augroup END for i in range(1000) call feedkeys('j') endfor endfunction " }}} " emment {{{ let g:user_emmet_install_global = 0 let g:user_emmet_settings = { \ 'variables': { \ 'lang' : 'ja' \ } \} augroup emmet autocmd! au FileType vue,html,js EmmetInstall au FileType vue,html,js imap , augroup END " }}} " lightline {{{ set laststatus=2 if !has('gui_running') set t_Co=256 endif " }}} " vim-vue {{{ " https://github.com/posva/vim-vue#my-syntax-highlighting-stops-working-randomly " vueファイルのシンタックスが効かなくなる問題対応 augroup VueSyntax autocmd! au FileType vue syntax sync fromstart augroup END " }}} " gitgutter {{{ " ハイライトを無効にする "highlight default link GitGutterAdd NONE "highlight default link GitGutterChange NONE "highlight default link GitGutterDelete NONE "highlight default link GitGutterChangeDelete NONE " }}} " nerd commenter {{{ " コメントの後にスペースを装入 let g:NERDSpaceDelims = 1 " }}} " calendar.vim {{{ " Googleカレンダー同期 let g:calendar_google_calendar = 1 " }}} " sonictemplate.vim {{{ let g:sonictemplate_author = 'skanehira' let g:sonictemplate_license = 'MIT' " }}} " vimhelpgenarator {{{ let g:vimhelpgenerator_version = 'Version : 0.0.1' let g:vimhelpgenerator_author = 'Author : skanehira ' let g:vimhelpgenerator_uri = 'https://github.com/skanehira/' let g:vimhelpgenerator_defaultlanguage = 'en' " }}} " {{{ MemoList let g:memolist_fzf = 1 " }}} " silicon {{{ if executable('silicon') let g:silicon = { \ 'theme': 'DarkNeon', \ 'font': 'Hack', \ 'background': '#aaaaff', \ 'shadow-color': '#555555', \ 'line-pad': 2, \ 'pad-horiz': 80, \ 'pad-vert': 100, \ 'shadow-blur-radius': 0, \ 'shadow-offset-x': 0, \ 'shadow-offset-y': 0, \ 'line-number': v:true, \ 'round-corner': v:true, \ 'window-controls': v:true, \ } endif " }}} " vsession {{{ let g:vsession_use_fzf = 1 " }}} " {{{ 自作関数 " {{{ リポジトリに移動 function! s:cd_repo(shell, repo) abort exe 'lcd' trim(system('ghq root')) .. '/' .. a:repo pwd endfunction function! s:repo(multi, cb) abort if executable('ghq') && exists('*fzf#run()') && executable('fzf') call fzf#run({ \ 'source': systemlist('ghq list'), \ 'sink': a:cb, \ 'options': a:multi, \ 'down': '40%'}, \ ) else echo "doesn't installed ghq or fzf.vim(require fzf)" endif endfunction command! Repo call s:repo('+m', function('s:cd_repo', [&shell])) " }}} " 新しいタブを開く {{{ function! s:open_tabs(shell, repo) abort exe printf('tabnew | lcd %s/%s', trim(system('ghq root')), a:repo) endfunction " fzf.vimのcallbackでは&shellがshになってしまうので、現在実行しているshellを渡す command! NewTab call s:repo('-m', function('s:open_tabs', [&shell])) " }}} " {{{ ウィンドウ一覧 function! s:get_win_info() abort let l:win_info_list = [] for win in getwininfo() if !has_key(win.variables, "netrw_prvfile") continue endif let l:tmp_file = split(win.variables.netrw_prvfile, '/') if empty(tmp_file) let l:file = '[No Name]' else let l:file = l:tmp_file[len(tmp_file)-1:][0] endif call add(l:win_info_list, {'winid':win.winid, 'file': l:file}) endfor return l:win_info_list endfunction function! s:goto_window(ctx, id, idx) abort if a:idx ==# -1 return endif call win_gotoid(a:ctx[a:idx-1].winid) endfunction function! s:win_list() abort let l:win_info = s:get_win_info() if empty(l:win_info) call s:echo_err('cannot find windows') return endif let l:view_content = [] let l:min_width = 40 for win in l:win_info call add(l:view_content, win.winid . "\t" . win.file) if len(win.file) > l:min_width let l:min_width = len(win.file) endif endfor call popup_menu(l:view_content, { \ 'border': [], \ 'borderchars': ['-','|','-','|','+','+','+','+'], \ 'padding': [0,0,0,0], \ 'filter': 'popup_filter_menu', \ 'callback': function('s:goto_window', [l:win_info]), \ 'minwidth': l:min_width, \ }) endfunction command! Windows call s:win_list() " }}} " {{{ エラーメッセージ出力 function! s:echo_err(message) abort echohl ErrorMsg redraw echo a:message echohl None endfunction " }}} " {{{ ファイル検索(ポップアップウィンドウ) if !exists('g:loaded_select') let g:loaded_select = 1 call prop_type_add('file_select', {'highlight': 'PmenuSel'}) endif function! s:get_files(path) abort let l:entries = [] for l:entry in readdir(a:path) if l:entry[0] ==# '.' continue endif let l:path_entry = a:path . '/' . l:entry if isdirectory(l:path_entry) let l:entries += s:get_files(l:path_entry) else if l:path_entry[0] ==# '.' let l:path_entry = l:path_entry[2:] endif cal add(l:entries, l:path_entry) endif endfor return l:entries endfunction function! s:highlight(ctx) abort let l:buf = winbufnr(a:ctx.id) let l:length = len(a:ctx.files[a:ctx.select]) let l:lnum_end = len(a:ctx.files) let l:lnum = a:ctx.select - a:ctx.offset + 1 if a:ctx.search_mode ==# 1 && !empty(a:ctx.filter_files) let l:length = len(a:ctx.filter_files[a:ctx.select]) let l:lnum_end = len(a:ctx.filter_files) endif call prop_clear(1, l:lnum_end, { \ 'bufnr': l:buf, \ }) call prop_add(l:lnum, 1, { \ 'bufnr': l:buf, \ 'type': 'file_select', \ 'length': l:length, \ }) call win_execute(a:ctx.id, 'redraw') endfunction function! s:update_files(ctx) abort let l:files = copy(a:ctx.files) if a:ctx.search_mode let l:tmp = [] for file in l:files if file =~? a:ctx.word[1:] call add(l:tmp, file) endif endfor let l:files = l:tmp let a:ctx.filter_files = l:tmp endif echo a:ctx.word call popup_settext(a:ctx.id, l:files[a:ctx.offset:]) call s:highlight(a:ctx) redraw endfunction function! s:popup_filter(ctx, id, key) abort let l:buf = winbufnr(a:id) let l:file = a:ctx.files[a:ctx.select] if a:ctx.search_mode ==# 0 if a:key ==# 'q' || a:key ==# 'x' call popup_close(a:id) return 1 elseif a:key ==# '/' let a:ctx.search_mode = 1 let a:ctx.word .= a:key elseif a:key ==# "\n" || a:key ==# "\r" return s:open_file(a:id, 'e', l:file) elseif a:key ==# "" return s:open_file(a:id, 'new', l:file) elseif a:key ==# "" return s:open_file(a:id, 'vnew', l:file) elseif a:key ==# "" return s:open_file(a:id, 'tabnew' , l:file) elseif a:key ==# 'j' let a:ctx.select += a:ctx.select ==# len(a:ctx.files)-1 ? 0 : 1 if a:ctx.select >= a:ctx.offset + a:ctx.maxheight let a:ctx.offset = a:ctx.select - (a:ctx.maxheight - 1) endif elseif a:key ==# 'k' let a:ctx.select -= a:ctx.select ==# 0 ? 0 : 1 if a:ctx.select < a:ctx.offset let a:ctx.offset = a:ctx.select endif elseif a:key ==# '0' let a:ctx.select = 0 let a:ctx.offset = 0 elseif a:key ==# 'G' let a:ctx.select = len(a:ctx.files)-1 let a:ctx.offset = len(a:ctx.files) - (a:ctx.maxheight) endif else " 検索モードの場合 if !empty(a:ctx.filter_files) let l:file = a:ctx.filter_files[a:ctx.select] else let l:file = '' endif if a:key ==# "\" || a:key ==# "\b" if strlen(a:ctx.word) == 1 let a:ctx.word = '' let a:ctx.search_mode = 0 else let a:ctx.word = a:ctx.word[:len(a:ctx.word)-2] endif elseif a:key ==# '}' let a:ctx.select += a:ctx.select ==# len(a:ctx.filter_files)-1 ? 0 : 1 if a:ctx.select >= a:ctx.offset + a:ctx.maxheight let a:ctx.offset = a:ctx.select - (a:ctx.maxheight - 1) endif elseif a:key ==# '{' let a:ctx.select -= a:ctx.select ==# 0 ? 0 : 1 if a:ctx.select < a:ctx.offset let a:ctx.offset = a:ctx.select endif elseif a:key ==# "\n" || a:key ==# "\r" return s:open_file(a:id, 'e', l:file) elseif a:key ==# "" return s:open_file(a:id, 'new', l:file) elseif a:key ==# "" return s:open_file(a:id, 'vnew', l:file) elseif a:key ==# "" return s:open_file(a:id, 'tabnew' , l:file) elseif a:key !=# "\" let a:ctx.select = 0 let a:ctx.offset = 0 let a:ctx.word .= a:key endif endif if a:key !=# "\" call s:update_files(a:ctx) endif return 1 endfunction function! s:open_file(id, key, file) abort if empty(a:file) return 1 endif call popup_close(a:id) exe a:key a:file return 1 endfunction function! s:popup_files(...) abort let l:path = '.' if a:0 > 0 let l:path = a:1 endif let l:files = s:get_files(l:path) if empty(l:files) echo 'not any files' return endif let l:ctx = { 'select': 0, \ 'files': l:files, \ 'offset': 0, \ 'maxheight': 15, \ 'word' : '', \ 'search_mode': 0, \ 'filter_files': [], \ } let l:maxwidth = 0 for file in l:ctx.files let length = len(file) if length > l:maxwidth let l:maxwidth = length endif endfor let l:ctx.id = popup_create(l:ctx.files, { \ 'filter': function('s:popup_filter', [l:ctx]), \ 'borderchars': ['-','|','-','|','+','+','+','+'], \ 'border': [], \ 'maxheight': l:ctx.maxheight, \ 'minwidth': l:maxwidth, \ 'padding': [0,0,0,0], \ 'mapping': 0, \ }) call s:highlight(l:ctx) endfunction command! -nargs=? PopupFiles call s:popup_files() " }}} " {{{ ディレクトリ自動生成 augroup vimrc-auto-mkdir autocmd! autocmd BufWritePre * call s:auto_mkdir(expand(':p:h'), v:cmdbang) function! s:auto_mkdir(dir, force) if !isdirectory(a:dir) && (a:force || \ input(printf('"%s" does not exist. Create? [y/N]', a:dir)) =~? '^y\%[es]$') call mkdir(iconv(a:dir, &encoding, &termencoding), 'p') endif endfunction augroup END " }}} " }}} " vim: tw=78 sw=4 foldmethod=marker