🐩
Neovimでhit-enter-promptを消すヘルパー関数
:checkhealth
コマンドがhit-enter-promptを出すのにイラっと来て作りました。
前提
Neovim(およびVim)がエコーした結果に対してcmdheightが足りないときなどにPress ENTER or type command to continue
が出ます。これがhit-enter-promptです。
以前はこれを回避するのは難しかったのですが、現代では'messagesopt'
が存在します。
開発時のやりとりはこちら。
'messagesopt'
は3つの値をまとめたオプションで、ちょっと複雑な構成です。
- history
- メッセージ履歴の件数を定める数値
- hit-enter
- hit-enter-promptを表示するかの真偽値(存在すれば真)
- wait
- hit-enter-promptを表示せず、出力の自動消去時間(ミリ秒数)を定める数値
- 0を指定すると何も表示しない
さらに、これらの値は完全に消去することはできません。以下のような条件があります。
- historyは常に必須
- hit-enterかwaitの少なくとも片方は必須
- 両方ある場合はhit-enterが有効になりwaitは無視される
この必須条件のため、いきなりset messagesopt-=hit-enter
しようとすると失敗します。さきにwait
を追加しなければなりません。
ただ、常にhit-enter-promptを消してしまうと:echo
などもすぐ消えてしまって不便です。
ということで、対象のlua関数を実行している間だけhit-enter-promptを無効にする仕組みを作りました。
ヘルパー関数
以下のskip_hit_enter
に関数を渡すと、'messagesopt'
を一時的に書き換えて実行する関数を返します。
--- skip hit-enter prompt
-- hit-enterプロンプトをスキップするラップされた関数を返す
-- @param fn function ラップする関数
-- @param opts table|nil オプションのテーブル
-- - wait (number|nil): 待機時間(ミリ秒) デフォルトは0
-- @return function ラップされた関数
local function skip_hit_enter(fn, opts)
opts = opts or {}
local wait = opts.wait or 0
return function(...)
local save_mopt = vim.opt.messagesopt:get()
vim.opt.messagesopt:append('wait:' .. wait)
vim.opt.messagesopt:remove('hit-enter')
fn(...)
vim.schedule(function()
vim.opt.messagesopt = save_mopt
end)
end
end
これを使って、例えば設定ファイルに以下のように記述します。設定をリロードしたときに多重ラップされるのを防ぐにはvim_starting
で判定すると良いです。
if vim.fn.has('vim_starting') == 1 then
vim.cmd.checkhealth = skip_hit_enter(vim.cmd.checkhealth)
end
これでvim.cmd.checkhealth('vim.lsp')
などでhit-enter-promptが抑制されます。
なおExコマンドの:checkhealth
の方には影響しませんが、そちらは:silent
で黙らせられるのでヨシとしました。
Discussion