Vimでcmdheight=0でのEnter入力待ちを出にくくしてみた

2022/08/02に公開

cmdheight=0とプラグイン

vimにも暗黒美無王様のcmdheight=0が来たので早速ためしてみました。
めちゃくちゃスッキリしてて美しい…

ところで私はeasy-motionを愛用してるのですが

はい
最後、Enter待ちになってしまいました
移動するたびにこれでは煩わしすぎます
しかしコレをなんとかしてでもcmdheight=0は採用したい美しさ…!

vim-auto-hide-cmdline

なんとかしました

https://github.com/utubo/vim-auto-hide-cmdline

easy-motionの直前にcmdheight=1を設定して、CursorHoldCursorMovedに数秒ディレイを入れてcmdheight=0に戻すというかなり強引な手法です
だーてぃーすぎる…
なおCmdLineLeavedだとeasy-motionが2つ目のキーをgetchar()で入力待ちする直前に発火されてしまうのでダメでした
CursorHoldならばgetchar()を待ってくれるのでこちらを採用しました

ALEのホバーメッセージ

上記で概ねうまくいったのですが、今のところcmdheight=0だとvim-aleのメッセージ表示がちらつくので以下の通り無理やりlightlineに表示して対処しました。
これはかなり強引なので参考程度に…

" cmdheight=0だとALEのホバーメッセージがちらつくのでg:ll_aleに代入してlightlineで表示する
let g:ale_echo_cursor = 0
let g:ll_are = ''
function! s:ALEEchoCursorCmdHeight0() abort
  let loc = ale#util#FindItemAtCursor(bufnr())[1]
  if !empty(loc)
    let g:ll_ale = loc.type ==# 'E' ? '🐞' : '🐝'
    let g:ll_ale .= ' '
    let g:ll_ale .= get(loc, 'detail', loc.text)
      \->split('\n')[0]
      \->substitute('^\[[^]]*\] ', '', '')
    else
      let g:ll_ale = ''
    endif
endfunction
au vimrc CursorMoved * call <SID>ALEEchoCursorCmdHeight0()
let g:lightline = {
  \   'active': {
  \     'left':  [['mode', 'paste'], ['fugitive', 'filename'], ['ale']],
  \   },
  \   component: { ale: '%=%{g:ll_ale}' },
  \ }

プラグイン以外でのチラつきを抑える

Enter待ちでは無いけれど、cmdlineがチラつくことがあったので、その時の自分の対応方法を記載しておきます。

:をやめて積極的に<Cmd>を使う

nnoremap <silent> <Esc> :<C-u>noh<CR><Esc>

なんて設定していると:に反応して一瞬だけcmdlineが表示されてしまいます。
<Cmd>を使えばモードを変えずに実行できるのでcmdlineを表示したくない箇所では積極的に使うようにしました。

nnoremap <Esc> <Cmd>noh<CR><Esc>

a:firstlinea:lastlineの代替

ビジュアルモードの選択範囲を示すa:firstlinea:lastlineは一度ビジュアルモードを抜けないと更新されないので、モードが変更されない<Cmd>では使えません。
代替としてすぐに更新されるline('.')line('v')を使うようにしました。
この2つは順序が逆転している場合あるので、それでは困るときは以下のようにします。

let l:firstline = min([line('.'), line('v')])
let l:lastline = max([line('.'), line('v')])

.vimrc内で定義しているrange対応の関数を上記の通り修正しました

<C-r>=を控える

<C-r>=は便利ですが、これも一瞬cmdlineが表示されてしまいます。
できるだけ控えたほうがちらつきを抑えられると思います。

" 例: yyyy/MM/ddを追記する
nnoremap <F5> a<C-r>=strftime('%Y/%m/%d')<CR><Esc>

<expr>で置き換えられないか検討する

大抵は<expr>で置き換えられると思います。

nnoremap <expr> <F5> 'a' .. strftime('%Y/%m/%d') .. '<Esc>'

feedkeysを使う

私はの場合は<expr>でほぼ賄えましたが、それがかなわないときはfeedkeysが使えるみたいです。
第2引数のnは再マッピング無し、iは「キーを現在位置に挿入」フラグです。この例では不要ですがiが無いと直感に反してしまうのでいつも入れるようにしています
(ただfeedkeysはテストが書きづらそう…)

inoremap <F5> <Cmd>call feedkeys(strftime('%Y/%m/%d'), 'ni')<CR><Esc>
GitHubで編集を提案

Discussion