NeovimのPress ENTERが消える ui2のメッセージ欄
Neovimには、メッセージ欄とコマンドラインを作り直したui2という仕組みが入っています。有効にすると、長い出力のあとに出る「Press ENTER or type command to continue」の待ちが無くなり、メッセージは通常のウィンドウとして扱われます。0.12から入っていた実験機能ですが、0.13で設定の置き場所が'messagesopt'へ移り、ページャの入り口も変わりました。安定版の0.12.4でもそのまま動くので、両方で押して確かめた結果を並べます。
検証環境:安定版の Neovim 0.12.4(NVIM v0.12.4)と、開発中の Neovim 0.13 のnightly(NVIM v0.13.0-dev-1536+g050fa30632)です。どちらもmacOSで--cleanから起動しました。ui2は実験機能で、有効にするために私的な名前空間の関数を呼びます。この記事のキー操作はすべて両方の版で実際に打ち、画面を見て確かめています。
メッセージ欄がウィンドウになる
従来のNeovimは、画面のいちばん下の1行('cmdheight'の高さ)をメッセージ用に確保していました。ここに収まらない出力が出ると「Press ENTER」で入力を止め、それでも足りなければ-- More --でさらに止めます。この止まり方は、単に読みづらいだけでなく、キーを連続して打っているときに邪魔になります。
ui2はこの層を作り直したもので、メッセージを4種類のウィンドウに振り分けます。ヘルプの:help ui2に並んでいるのが次の4つです。
| 窓 | 役割 |
|---|---|
| コマンドライン | cmd。既定ではメッセージ・'showcmd'・'showmode'・'ruler'もここに出る |
| メッセージ窓 | msg。その場限りのメッセージを出す。'cmdheight'が0のときに効く |
| ページャ | pager。:messagesの内容を送りながら読む |
| ダイアログ | dialog。入力を待つ問い合わせを出す |
4つとも本物のバッファで、'filetype'がそれぞれcmd、msg、pager、dialogに設定されます。FileTypeのautocmdを書けば、メッセージ欄だけ折り返しを変えるといった調整ができます。
有効にするのは1行
設定ファイルに次の1行を書くだけです。設定ファイルの置き場所はinit.luaです。
-- init.lua
require('vim._core.ui2').enable({ enable = true })
0.12.4でも0.13のnightlyでも、このrequireは同じように通りました。安定版を使っている人が試すのに、nightlyを落としてくる必要はありません。
Press ENTERが出なくなる
いちばん分かりやすい差が:versionです。4行の出力に対して、従来は入力待ちが1つ増えます。
ui2なしで:versionを打つと、出力の下に入力待ちが1行増える下から2行目までが出力で、最後の行が入力待ちです。ここで何かキーを押すまで、次の操作に移れません。ui2を有効にした同じ操作がこちらです。
ui2を有効にし、targetsをmsgにしたところ。出力が右下に浮き、入力待ちが出ない待ちがありません。そのまま次のキーを打てます。:set allのように画面いっぱいに出るコマンドでも同じで、従来なら-- More --で何度も止まるところが、止まらずに出て終わります。全部を読みたいときだけ、あとからページャを開きます。
Run ":verbose version" for more info
Press ENTER or type command to continue
:versionRun ":verbose version" for more info
(待ちなし。次のキーを打てる)
メッセージを右下に浮かせる
出す先は選べます。targetsをmsgにすると、メッセージがコマンドラインではなく右下の窓に浮きます。コマンドラインには打った:versionがそのまま残るので、何を打った結果なのかが見える形です。
require('vim._core.ui2').enable({
enable = true,
msg = { targets = 'msg' }, -- メッセージを浮かせる
})
この形が効くのは'cmdheight'を0にしているときです。0にすると従来はメッセージの出る場所そのものが無くなりますが、ui2なら浮いた窓に出るので読めます。ヘルプのoptions.txtにも、cmdheight=0は実験的でui2と一緒のほうがうまく動く、と書かれています。実際に0にして:echoを打つと、本文が1行も削られないまま下に文字が出ました。
0.13で変わる3つ
ここからが0.13の変更です。すでにui2を使っている人には、1つ目が効きます。
- ページャの入り口がg<になりました:0.12.4では
:versionのあとEnterを押すとページャに入れましたが、0.13では入りません。過去のメッセージを送りながら読むにはg<を押します。Enterのままにしたい場合は:set messagesopt+=pager:<CR>で戻せます。 - 設定が
'messagesopt'へ移りました:Luaのテーブルに書いていたpager_charとtimeoutが、オプションのpagerとtimeoutになりました。既定値はhit-enter,history:500,progress:cで、これは0.12.4も0.13も同じでした。 - ルーラーとダイアログの細かい調整:
'ruler'が固定幅の箱でなくなったので、'rulerformat'の項目グループがヘルプどおりの意味で使えます。ダイアログの窓はマウスホイールで'mousescroll'の行数ぶん動くようになりました。
もう1つ、ヘルプ側の扱いも変わりました。hit-enterとhit-enter-promptがdeprecated.txtへ移り、ui2では従来のPress ENTERは当てはまらない、と書かれています。実験機能の側が本流になる方向で整理されていることが読み取れます。0.13の変更をまとめた記事にあるQやgQの入れ替えと同じで、手が覚えている操作が動かなくなる種類の変更です。
実験機能として付き合う
気をつけるところが1つあります。呼び出しに使うvim._coreはアンダースコアで始まる名前で、:help api-contractが「私的」と呼んでいる側の入り口です。ヘルプに載っていない名前や二重アンダースコアの関数は契約の外にあり、断りなく変わります。実際、この機能はヘルプの:help ui2に載ってはいますが、冒頭に実験的だという警告が付いています。設定に書くなら、上げたときにrequireが失敗しても起動が止まらないようpcallで包んでおくと安全です。
-- 名前が変わっても起動は止めない
pcall(function()
require('vim._core.ui2').enable({ enable = true })
end)
ヘルプにはもう1つ、収まりきらないメッセージが畳まれて[+x]という印が付く、という説明があります。手元では既定のtargetsのまま:versionや:set allを出しても、この印は出せませんでした。畳まれる条件までは追い切れていないので、そこは確かめた範囲の外です。
プラグインで同じことをしているものとしてはnoice.nvimが知られています。標準側がここまで来たので、メッセージ欄のためだけに入れているなら外せる可能性があります。0.12で標準に入った機能を、どのプラグインを外せるかで並べた記事と同じ見方です。
効き目がはっきり出たのは:set allでした。-- More --を送るのが面倒で、これまで:set all自体を避けて:verbose set foo?で1つずつ見ていたのですが、止まらないなら普通に打てます。逆に面食らったのがEnterで、0.12.4のつもりでページャに入ろうとして何も起きず、しばらく壊れたと思っていました。:help newsを読んでg<に変わったと知るまで10分ほど無駄にしています。targetsをmsgにする形は、右下に文字が浮くぶん最初は落ち着きませんでしたが、'cmdheight'を0にすると本文が1行広がるので、狭い画面ではこちらのほうが良かったです。
まとめ
ui2は、メッセージ欄とコマンドラインを本物のウィンドウに置き換える実験機能です。require('vim._core.ui2').enable({ enable = true })の1行で有効になり、安定版の0.12.4でも動きます。有効にするとPress ENTERの待ちと-- More --が出なくなり、過去のメッセージはg<で読みます。0.13では、そのg<がページャの既定の入り口になり、Luaのテーブルに書いていた設定が'messagesopt'へ移りました。'cmdheight'を0にする設定と組み合わせると、本文の1行を取り返せます。呼ぶ先が私的な名前空間なので、pcallで包んでおくのが無難です。