vimrcでよくね?
そのプラグイン、vimrcにちょっと書くだけで再現できるくね?な記事です。
前回の記事
そもそもの設定系
vimのset number
みたいなのって、もうデフォルトで全部ONになってろよと思うので、むりくり1行にまとめました。
vimrcにぶち込むなり、一時的にコマンド実行するなりしましょう
set fileformat=unix fileencoding=utf8 noswapfile nobackup noundofile hidden autoread clipboard+=unnamed background=dark title showcmd list listchars=tab:»-,trail:-,eol:↲,extends:»,precedes:«,nbsp:% number relativenumber signcolumn=yes scrolloff=5 cursorline cursorcolumn ruler laststatus=2 showtabline=2 notitle splitright virtualedit=all whichwrap=b,s,h,l,<,>,[,],~ backspace=indent,eol,start showmatch matchtime=3 autoindent smartindent smarttab shiftwidth=4 tabstop=4 expandtab wildmenu wildchar=<Tab> wildmode=full complete=.,w,b,u,U,k,kspell,s,i,d,t completeopt=menuone,noinsert,preview,popup incsearch hlsearch ignorecase smartcase shortmess-=S belloff=all ttyfast regexpengine=0 foldmethod=marker foldlevel=1 | let &titleold=getcwd() | syntax on | filetype plugin on | au QuickFixCmdPost *grep* cwindow
選択した行を、行まるごと移動
VSCodeとかだとAlt + 上下とかでやるやつ。
vnoremap <C-j> "zx"zp`[V`]
vnoremap <C-k> "zx<Up>"zP`[V`]
jiangmiao/auto-pairs
カッコ系を自動で対も入力したりするやつ。
(を入力後に
(|)
↑カーソル
となってくれるもの。(のあとに)を入力すれば、())とならず、カーソル移動になる
VSCodeとかの挙動と同じで、(|)の状態で(を消せば)も消えてくれる。
めっちゃ大変そうに思えるけど、意外と簡単に書ける
inoremap ( ()<left>
inoremap [ []<left>
inoremap { {}<left>
inoremap ` ``<left>
inoremap ' ''<left>
inoremap " ""<left>
inoremap <expr>) getline('.')[col('.')-1] == ")" ? "\<right>" : ")"
inoremap <expr>] getline('.')[col('.')-1] == "]" ? "\<right>" : "]"
inoremap <expr>} getline('.')[col('.')-1] == "}" ? "\<right>" : "}"
inoremap <expr><BS> match(["()", "[]", "{}", "``","''", '""'], getline('.')[col('.')-2:col('.')-1]) >=0 ? "\<right>\<BS>\<BS>" : "\<BS>"
ヤンク部分をハイライト
au TextYankPost * cal s:hl_yank()
fu! s:hl_yank() abort
if v:event.operator !=# 'y' || v:event.regtype !=# 'v' || len(v:event.regcontents) != 1 | retu | endif
let word = v:event.regcontents[0]
let tid = matchaddpos('IncSearch', [[line('.'), match(getline('.'), escape(word, '\')) + 1, strlen(word)]])
cal timer_start(300, {-> matchdelete(tid)})
endf
ヤンク文字が正規表現系のワード含んでるとなんか変になるけど
まぁあんまり使わないしいらないかなぁ
ぬるぬるスクロール
nnoremap <silent><C-u> :<C-u>cal <SID>scroll(0, 25)<CR>
nnoremap <silent><C-d> :<C-u>cal <SID>scroll(1, 25)<CR>
nnoremap <silent><C-b> :<C-u>cal <SID>scroll(0, 15)<CR>
nnoremap <silent><C-f> :<C-u>cal <SID>scroll(1, 15)<CR>
fu! s:scroll(vector, delta)
let tid = timer_start(a:delta, { -> feedkeys(a:vector == 0 ? "\<C-y>" : "\<C-e>") }, {'repeat': -1})
cal timer_start(600, { -> timer_stop(tid) })
endf
f文字ハイライト+f連打で移動
f文字ハイライト
→今回は1撃文字の剪定はせず、普通に単語の最初の文字だけハイライト
f連打で移動
→行跨いでの移動や、大文字小文字の無視はしない
au ColorScheme * hi FC cterm=bold
au CursorMoved,CursorMovedI * if exists('w:f')&&w:f!=-1|sil! cal matchdelete(w:f)|let w:f=-1|endif|let w:f=matchadd('FC','\%'.line('.').'l\(\<\w\)',99)
nnoremap <silent>f :<C-u>cal <SID>fmode(1)<CR>
nnoremap <silent>F :<C-u>cal <SID>fmode(0)<CR>
au ColorScheme * hi FChar ctermfg=155 cterm=bold,underline
fu! s:fmode(vec)
if !exists('w:fmode') || w:fmode == 0 | let w:fmode = 1 | let w:char = nr2char(getchar()) | endif
if exists('w:fmatch') && w:fmatch != -1 | sil! cal matchdelete(w:fmatch) | let w:fmatch = -1 | endif
let w:fmatch = matchadd('FChar', '\%' . line('.') . 'l' . w:char, 100)
exe "normal! ".(a:vec == 1 ? "f" : "F").w:char
if exists('g:fmode_tid') && g:fmode_tid != -1 | cal timer_stop(g:fmode_tid) | endif
let g:fmode_tid = timer_start(1000, { -> execute("let w:fmode = 0 | sil! cal matchdelete(w:fmatch)") })
endf
これらをこの行数で実装できるのはかなり頑張ったのでは
Air Line
au ColorScheme * hi User1 cterm=bold ctermfg=235 ctermbg=39
au ColorScheme * hi User2 cterm=bold ctermfg=235 ctermbg=114
au ColorScheme * hi User3 cterm=bold ctermfg=235 ctermbg=204
au ColorScheme * hi User4 cterm=bold ctermfg=235 ctermbg=180
au ColorScheme * hi User5 cterm=bold ctermfg=235 ctermbg=170
let LF = {'dos': 'CRLF', 'unix': 'LF', 'mac': 'CR'}
fu! SetStatusLine()
let dict = {'i': '1* INSERT', 'n': '2* NORMAL', 'R': '3* REPLACE', 'c': '4* COMMAND', 't': '4* TERMIAL', 'v': '5* VISUAL', 'V': '5* VISUAL', "\<C-v>": '5* VISUAL'}
let mode = match(keys(dict), mode()) != -1 ? dict[mode()] : '5* SP'
retu '%'.mode.' %* %<%F%m%r%h%w%=%2* %p%% %l/%L %02v | %{&filetype} | %{&fenc!=""?&fenc:&enc} | %{LF[&ff]} %*'
endf
set statusline=%!SetStatusLine()
fu! SetTabLine()
let s=''
for b in range(1,bufnr('$'))
if bufexists(b)&&buflisted(b)
let n = empty(bufname(b)) ? '[No Name]' : fnamemodify(bufname(b),':t')
let m = getbufvar(b, '&modified') ? '*' : ''
let s.=(b==bufnr('%')?'%#TabLineSel#':'%#TabLine#').'%'.b.'T '.n.m.' '
endif
endfor
retu s.'%#TabLineFill#'
endf
set tabline=%!SetTabLine()
au ColorScheme * hi Comment term=bold ctermfg=245
au ColorScheme * hi Normal ctermbg=none
au ColorScheme * hi LineNr ctermfg=245
au ColorScheme * hi Visual ctermbg=240
colorscheme habamax
fzf
fzfコマンドとfzf.vimの2つが必要だが、vimrcに以下の33行を書くだけでいける
nnoremap <silent><Space>f :<C-u>cal <SID>fzf()<CR>
au ColorScheme * hi FzfCurLine ctermfg=235 ctermbg=114
fu! s:fzf()
let g:fzf_query = [] | let g:fzf_cur = 0
let g:fzf_files = system(system('git status')=~'fatal' ? "find . -type f" : "git ls-files")->split('\n')
let g:fzf_matches = g:fzf_files[0:29]
let g:fzf_wid = popup_create(g:fzf_files[0:29], #{title: "", zindex: 99, line: 18, col: 50, minwidth: 100, maxwidth: 100, minheight: 30, maxheight: 30, border:[], borderchars: ['─','│','─','│','╭','╮','╯','╰']})
let g:fzf_q_wid = popup_create("", #{title: "fzf", zindex: 100, line: 15, col: 50, minwidth: 100, maxwidth: 100, minheight: 1, maxheight: 1, border:[], borderchars: ['─','│','─','│','╭','╮','╯','╰'], mapping: 0, filter: function('s:fzf_filter')})
let g:match_id = matchaddpos('FzfCurLine', [[g:fzf_cur + 1]], 10, -1, {'window': g:fzf_wid})
endf
fu! s:fzf_filter(winid, key)
if a:key == "\<CR>"
cal popup_close(g:fzf_q_wid) | cal popup_close(g:fzf_wid)
exe "e ".g:fzf_matches[g:fzf_cur]
retu 1
elseif a:key == "\<ESC>"
cal popup_close(g:fzf_q_wid) | cal popup_close(g:fzf_wid)
retu 1
elseif a:key == "\<C-n>" | let g:fzf_cur = (g:fzf_cur + 1) % len(g:fzf_matches)
elseif a:key == "\<C-p>" | let g:fzf_cur = (g:fzf_cur - 1 + len(g:fzf_matches)) % len(g:fzf_matches)
elseif a:key == "\<BS>" | if !empty(g:fzf_query) | cal remove(g:fzf_query, -1) | endif
elseif a:key == "\<C-w>" | let g:fzf_query = []
elseif strtrans(a:key) == "<80><fd>`" | retu 1 " noop (for polyglot bug adhoc)
else | cal add(g:fzf_query, a:key)
endif
let g:fzf_matches = empty(g:fzf_query) ? g:fzf_files[0:29] : matchfuzzy(g:fzf_files, join(g:fzf_query, ''))[0:29]
if len(g:fzf_matches)-1 < g:fzf_cur | let g:fzf_cur = 0 | endif
if g:match_id != -1 | sil! cal matchdelete(g:match_id, g:fzf_wid) | endif
let g:match_id = matchaddpos('FzfCurLine', [[g:fzf_cur + 1]], 10, -1, {'window': g:fzf_wid})
cal popup_settext(g:fzf_q_wid, join(g:fzf_query, ''))
cal popup_settext(g:fzf_wid, g:fzf_matches)
retu 1
endf