読者です 読者をやめる 読者になる 読者になる

Vim の GUI 版が何であるかすらを理解することないまま gVim を使い続けてきたような情弱ゆとり廚がイキって恥を恥とも知らぬままに Neovim への移行について考えた愚行,いい加減痛いので晒しとこうと思います

もう自分のこの浅はかさたるや,ほんっと耐えられない.
こんな自分みたいな奴いたら,絶対イライラして,頼むから消えてくれと絶対思っていると思いますわ(怒.

IDIOTIDIOT / Say_No_To_Turtles




先日 Neovim への移行をぼんやりと考え始めている,と言うことについて触れましたが,このところ,その本気度は次第に高まりつつあったりします.

Drop-in replacement for Vim》を謳っているとは言え,両者間にはそれなりの段差はあるわけでして,これまでの感覚でいると思わぬトラップに出遭い,たびたびキッとすることがあるわけです.

勿論これをネガティブに受け止める気なんぞは全くなく,むしろ,この事象にちゃんと向き合ってみた,と言うのが今回のお話です.

今回は,より快適な移行のために,この "つまづき" の要因となっている,両者間の段差を解消するポイントについて考えてみようと思っています.

正直,移行については未だ迷っている中,この結果が,移行するか否かの判断材料になればと企んでおります.

「これまで MacVim-KaoriYa (以降 Vim) ではこうだったけど,Neovim でもそうしたいので,どうしたら良いか」と言った感じで試みています.

今回は Vim,Neovim 自身が持つネイティブな機能,設定のみを扱うつもりでいます.後で追加するようなプラグインに関するものは対象外とします.

そして基本,無理かなと思ったら,拘ることはせず,"それはそれ" で受け入れるスタンスでおります.

このような感じで,ここ数日の使用でつまづいた中,気になって,「これは出来るようになって欲しいな」と思って挙げたアイテムは,以下の通りとなりました.;

  1. インサートモード時,カーソルが気になる.|にしたい.
    → init.vim に, ;
    let $NVIM_TUI_ENABLE_CURSOR_SHAPE=1
  2. カラースキーマは反映されていないかも?
    → init.vim に, ;
    set termguicolors
  3. 入力モード (英字-ひらがな) の状態によってカーソルの色を変えたい.
    → N/A (xim)
  4. インサートモード抜けた時,ime をオフにしたい.
    → N/A (iminsert)
  5. 開いた時,前回閉じた時の場所を覚えていて欲しい.
    → init.vim に,
    au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\""
  6. バッファ移動のためのキーマッピングのうち,左移動の <c-h>ひとつだけ効かない.
    → ターミナルで,;
    infocmp $TERM | sed 's/kbs=^[hH]/kbs=\\177/' >$TERM.ti
    tic $TERM.ti
    
  7. フォントを変えたい.
    → N/A (guifont)
  8. :so %時の E905: Cannot set this option after startup: encoding=utf-8というエラーが怖い.
    → init.vim に, ;
    if !exists ('g:encoding_set') || !has('nvim')
        set encoding=utf-8  
        let g:encoding_set=1
    endif
    scriptencoding utf-8
    

こんなところでしょうか.

ちなみに Neovim のドキュメントに記載のあるものが殆んどかもしれません.

あとものによっては,Vim → Neovim の話ではなくむしろ,GUI 版 → 非 GUI 版によるものだったり,ターミナル等他の要因によるものもあったりするかと思います.

インサートモード時,カーソルが気になる.| にしたい.

init.vim に以下設定を追記.;

let $NVIM_TUI_ENABLE_CURSOR_SHAPE=1

参照先

» How can I change the cursor shape in the terminal?

カラースキーマは反映されていないかも?

init.vim に以下設定を追記.;

set termguicolors

参照先

» How can I use true colors in the terminal?

入力モード (英字-ひらがな) の状態によってカーソルの色を変えたい.

これは出来ないっぽい,みたいです.

:echo has(xim) は "0".
not available when compiled without the +multi_byte feature》と言うことなのだと思います.

メモ

やりたかった事はこんなこと.

macOs ですと has('xim') になると思うのですが...;

if has('multi_byte_ime')
highlight Cursor guifg=NONE guibg=Green
highlight CursorIM guifg=NONE guibg=Purple
endif

Cursor color with off IME is green. And purple cursor indicates that
status is on.

個人的にはこれ結構辛い.

何か代替の策があったりするのでしょうか.

にしても,どうして Neovim のヘルプに記載されているのだろう.
何かきちんと条件が揃えば,実現できたりするのだろうか.

参照先

» Cursor color when IME or XIM is on - Vim documentation: mbyte
» vim/gvimの色設定について - fudist

インサートモード抜けた時,ime をオフにしたい.

これも駄目みたい?

iminsert になると思っているのですが,どうも上手く効かないようで.

GUI 版ではないから,ということで良いのかな?

:set iminsert すると iminsert=0 と返ってくるのですがね...

メモ

今回この作業を通して,やっと理解できたことが有ります.

ime に関するこの手の問題に対し良く目にするのが,Karabiner*1 と言うツールを使ったレポートでして,この解決方法には個人的に不可解でしょうがありませんでした.

なぜならば,Vim 自身で iminsert なり noimdisable 辺りのオプションがあるじゃないですか.

どうしてかなー,と眺めていたのです.

でも今,やっと分かりました.

それは MacVim-KaoriYa だからであり,GUI 版の Vim だったから,と言うことだったのですね.orz
これを含め,何気なく使ってきた様々な機能は,そんな恩恵にあずかってのものであることを露ほども知らずに今まで来たと言うわけなのですね...

そんな感じで,今更に事の実状を理解できたことで,我が作業環境においても当該ツールの導入を考えなければならない,となるわけです.が,;

でもなー,... これだけのためにインストールするのもなー

そうなんですよねぇ.

そしたらこの問題を考えるにあたって,Google 日本語入力 が良い,と言う幾つかのレポートを目にするのです.

う~ん,悪くないかなぁ.

システムが標準で提供してくるものは,よっぽどの事情が無い限り,別のアプリやツールに頼ることなく,できるだけそのまま使うようにしたい派なのですが,このところ macOS 標準の JpaneseIM のもっさり感にとうとう疑問を持ち始めているのもあり,いいキッカケかな.

参照先

» Vimでコマンドモードに戻るときにIMEをオフにする - ほとラボ
» SSHを介してVimを使う人に感動的なESCキーを押すとESCキーが効きつつIMEがオフになる設定(Google日本語入力とVimの相性は最強!) - しふーのブログ
» remove imcmdline and 'imdisable' · Issue #1708 · neovim/neovim · GitHub
» [WIP] Account for :lmap in macros close #5652 by hardenedapple · Pull Request #5658 · neovim/neovim · GitHub

開いた時,前回閉じた時の場所を覚えていて欲しい.

init.vim に以下設定を追記します.;

au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\""
via. [痒いところに手が届いた!? vimテク(?)5選 - 初代Masteries][40]

こちらも失って初めて気付かされた振る舞いのひとつ.

メモ

ヘルプに :h last-position-jump ガッチリ書いてありました.

このオートコマンドはファイルを開いた時に,最後に開かれていた時
の行へ自動的にジャンプするものである.これは '" マークがセット
されている時にのみ有効である:

ちなみに " と言うマークは,バッファ終了時に付くマークなのだそう.;

現在のバッファを最後に終了した時のカーソル位置に
移動します.... バッファに対して1つの位置が記憶
されます.

平たく表現してみますと,開いた時に直前の終了時にセットし記憶したマーク " の位置に移動する,となるでしょうか.

なるほど.

参照先

» 痒いところに手が届いた!? vimテク(?)5選 - 初代Masteries
» :h last-position-jump

バッファ移動のためのキーマッピングのうち,左移動の <c-h> ひとつだけ効かない.

まず結果から.

これはターミナルでの作業になります. Neovim 内ではありません.
ターミナルで以下 2 行のコマンドラインを実行します.;

infocmp $TERM | sed 's/kbs=^[hH]/kbs=\\177/' > $TERM.ti
tic $TERM.ti

これは何をやっているか.

あまりにマニアックな世界で正直付いて行けないのが本当のところなのですが,怖いもの知らずの素人全開でアウトプットしてみますと.

<c-h> は,元々バックスペースキー kbs として紐づけられてしまっているので,そうではなくバックスペースキー kbs には "削除" \177 という振る舞うよう,割り当てを変えてやっている.

こんなところでしょうか.

メモ: <c-h> が想定通りの動作をしてくれていないのが原因

このセクションは便宜上 "キーマッピング" の話としてタイトルを打ちましたが,実際は <c-h> というキーストロークの話だったりします.;

» My CTRL-H mapping doesn't work

ページにも書いてある通り一度,Neovim 上で :CheckHealth なるコマンド叩いて,飛び出てくるバッファの [health#nvim#check] というセクションを見てみてください.[terminfo] と言うパラグラフに.;

:
## terminfo
  - ERROR: key_backspace (kbs) entry is ^H (ASCII DELETE): key_backspace=^H,

    - SUGGESTIONS:
      - Set key_backspace to \177 (ASCII BACKSPACE). Run these commands:
          infocmp $TERM | sed 's/kbs=^[hH]/kbs=\\177/' > $TERM.ti
          tic $TERM.ti
      - See https://github.com/neovim/neovim/wiki/FAQ

こんな内容があったら設定が必要,となります.

メモ: まずちょっと背景

背景としては,このレポートとほぼ似たようなものでして,;

» Ctrl-h mapping in Neovim's terminal emulator - Stack Overflow

バッファ間の移動のために .vimrc (init.vim) に以下のようなキーマッピングをしています.;

" バッファ移動
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-h> <C-w>h
nnoremap <C-l> <C-w>l

このなかで,左へ移動する <C-h> だけが効かない事に気付き,個人的には結構重宝していたマッピングだけ,まさか自分だけでは,と考えたりして結構焦りました.

そしたらそうでもないようでして.

メモ: 一応

infocmp $TERM | sed 's/kbs=^[hH]/kbs=\\177/' > $TERM.ti
tic $TERM.ti

infocmp と言うツールは,terminfotermcap と言う《端末 terminal のケイパビリティ capability を記述するデータベースの中身が覗けるようになる道具なのだそう

と言う事で,上の infocmp $TERM の部分は,現在の端末$TERM の中身を出力している,となるわけですね.

そしてパイプ | の次,sed 's/kbs=^[hH]/kbs=\\177/' では,
そのデータの kbs=^h 又は kbs=^H を,kbs=\177 で置換し,さらにその結果をリダイレクション >$TERM.ti というファイルに出力してやる,と言うのが 1 行目.

そして 2 行目では,
tic と言うツール使って,さっきの $TERM.tl という変更後の内容を《端末が使えるようにコンパイルし直してインストール》してやっているのだそう.

ケイパビリティ? 何のこっちゃ.どう訳すのが正解?

terminfotermcap

このデータベースについて,今回の事例になぞって解釈するのに都合の良い記述があったので,それを使わせて頂きますと,;

こういった操作は端末に対して命令として解釈される文字列(制御シーケンス)を出力して行うのですが,この命令用の文字列は端末の種類によって違ったりします.そこでプログラムは,使用している端末(環境変数TERMで指定します)で使いたい機能がどのような文字列になるかをtermcapやterminfoで調べて出力します.

今回の場合ですと,<c-h> を使いたいので,kbs が出力する制御文字は <c-h> ではなく \117 になるよう設定した,となるのでしょうか?

\177 という ASCII 制御文字

ちなみに \177 と言うのは "抹消 DEL" という《ASCII制御文字》を表すものらしい.あくまで《削除文字 delete character》で《現代のコンピュータでは「バックスペース」と呼ばれるもので,削除キーとは異なる》のだそう.

あと "<c-h> はバックスペース" と言うのは結構一般的なものらしく,Wiki にもガッチリ書いてありましたよ.

<c-h> (^H) がバックスペース,ということについて

バックスペースキーを押すと,ASCIIコードの "08" (BS, Backspace)が生成される... このコードは,コントロールキーを押しながらHを押下(Control-H)しても出力される. .. バックスペースの制御コードが前の文字を削除する機能にマッピングされていない端末では,バックスペースキーが押されたときにH(キャレット記法)が表示される.

と,思ったらこんなの見つける.;

control + H
挿入ポイントの左側にある文字を削除します.または,「delete」キーをお使いください.

orz...

参照先

重複しますが,かためて書いておきたいと思います.

Neovim での <c-h> について ;

» My CTRL-H mapping doesn't work
» Ctrl-h mapping in Neovim's terminal emulator - Stack Overflow

それ以外.;

» termcapとterminfo | doda's blog
→今回やったことを理解するのには,一番分かり易いと思いました.
» 第 20 回 デリイトキイは BS にあらず・ふたたび | 極私的 Emacs カスタマイズ紹介マガヂン | Emacs をわたし色に染めて♪
→《Back-space は C-h とかならず等価ですし,Delete キーは \177 で定義します.》.
» On-line Manual of 'terminfo'
→terminfo,kbs (key_backspace),infocmp,tic
» terminfo(5)
→上の英語版.
» term(7) - マクロのパッケージとその約束事 - YOS OPENSONAR
→terminfo,infocmp
» Terminfo - Wikipedia
→terminfo
» Termcap - Wikipedia
→terminfo
» ASCII - Wikipedia
H(<c-h>),\BS,\177,DEL
» バックスペースキー - Wikipedia
H(<c-h>)

フォントを変えたい.

今までですと,フォントは guifont で設定していたはず.

フォントじゃなく,カーソルの話ですが,;

AFAIK Neovim has removed support for all gui* options. Also I think the t_ stuff is only expected to work in terminals.

The best way IMO to implement this would be to have a MacSetCursorShape VimL function in nvimrc.

まぁそういう事なのでしょう.

ではどこで設定するか. おそらく使っているターミナル側で設定する,となるで良いのかしら.

E905: Cannot set this option after startup: encoding=utf-8

冒頭の set encoding=utf-8 は要らない,ってことですか.

You don't need to set this option, it is utf8 by default.

if !exists('g:encoding_set') || !has('nvim')
    set encoding=utf-8
    let g:encoding_set = 1
endif
scriptencoding utf-8

参照先

» neovim breaking changes · Issue #633 · carlhuda/janus · GitHub
» Warning messages on resource .nvimrc about utf · Issue #3435 · neovim/neovim · GitHub
» Expose startup phase in runtime #3421 · neovim/neovim · GitHub

Neovim に移行する?

やはり日本語入力周りなのでしょうか.

基本,開発環境とかコーディング作業ではなく,文書作成のツールとして使うような者にとっては結構辛いところ.

でも,何にも知らずに Vim を使ってきたような自分にとっては,今回の作業であったような無知を知ることがあるので,それを考えるとむしろ半ば強引にも Neovim に移行する,というのも良いのかなと思ったりもしています.

と言うことで,結局未だ迷って...はい、おしまい.

*1:以前は KeyRemap4MacBook と言う名称でしたね.実際自分が目にしていたのはこの時代のが多かったです.