恥は/dev/nullへ by 初心者

プログラミング素人がのろのろと学んだことをつづっています♪

起動中のVimで2つのファイルの差分(diff)を調べる

疑問

Vimで2つのファイルの違い(差分)を調べる方法をネット検索すると、次のようにコマンドラインで入力する方法が出てきました。

vim -d [ファイル 1] [ファイル 2]  
または  
vimdiff [ファイル 1] [ファイル 2]  


ここで疑問が浮かびました。「Vimで作業している途中でファイルの差分を調べたくなった場合はどうすればよいのか?」という疑問です。上述した方法を使うためにVimを一度終了するのは無駄な気がするのです。

そこで、既にVimを起動している最中にファイル差分(Diff)をチェックする方法を調べてみました。

vertical diffsplitを使う

既にVimを起動している状況で2つのファイルの差分を調べる場合は次のようにします。

(1)比較したい2つのファイルのうち、1つをVim上で開いておく  
(2)ノーマルモードで :vertical diffsplit を使って、もう1つのファイルを開く  


たとえば、aaa.txt と bbb.txtというファイルを比較する場合は次のようにします。

(1) aaa.txtをVim上で開いておく  
(2) :vertical diffsplit bbb.txt を実行する  

毎回使うタグを挿入するVimコマンド

はてなブログを書いていて、必ず使うタグが2種類あります。

<br> 改行
<span style="color: #b388dd"> </span> 見出しのテキスト色を指定


今まで brタグは必要な箇所に手入力し、spanタグは辞書登録して使っていました。しかし、文章を全て書き終えてから一発でタグを挿入した方が手間が少ないので、Vimコマンドにすることにしました。

目次


留意事項(特殊文字の入力)

この記事には ^M という文字が登場します。この文字を.vimrcに記述する場合は、

CTRL + v  CTRL + m

または

CTRL + v  RETURN

とする必要があります。

H1レベルの見出しにspanタグを挿入する

たとえば、次のような文章があったとします(Markdown)。

# 卵の中身を取り出す
器の縁に卵をぶつけて、ヒビを入れます。ヒビが入ったら両手で
卵を支えながら、慎重に器に中身を落とします。

# 卵をとく
精神を統一し、器を片手で支え、もう一方の手に持った道具(箸
など)で卵をかき回します。

この文章に登場する見出しは # で始まる「卵の中身を取り出す」と「卵をとく」です。これらのテキスト色を変更するためにspanタグを挿入して、以下のようにしようと思います。

# <span style="color: #b388dd">卵の中身を取り出す</span>
器の縁に卵をぶつけて、ヒビを入れます。ヒビが入ったら両手で
卵を支えながら、慎重に器に中身を落とします。

# <span style="color: #b388dd">卵をとく</span>
精神を統一し、器を片手で支え、もう一方の手に持った道具(箸
など)で卵をかき回します。


substituteコマンドで実行するなら、次のような感じでしょうか。

:%s/^# \([^<]..*\)/# \<span style="color: #b388dd"\>\1\<\/span\>/

ちなみに、[^<] は、既にタグを挿入してある見出しにこのコマンドが適用されないようにするためのものです。

これをコマンドとして利用できるよう、.vimrcに次の1行を追記しました。

" SetH1 コマンド
command SetH1 %s/^# \([^<]..*\)/# \<span style="color: #b388dd"\>\1\<\/span\>/


段落の後に空行が2つあったらbrタグを挿入

次はbrタグの挿入です。次のようなテキストがあるとします。

(1) 卵を割って容器に中身を落とします。

(2) 箸などで卵をかき回します。  


(3)卵をとき終えたら、卵に醤油をたらします。

このテキストに登場する3つのパートのうち、(2)と(3)の間には空行が2つあります。しかし、はてなブログにこのテキストを貼り付けると、この空行2つは1つの空行にまとめられてしまいます。

そこで、(2)の行末に半角スペースを2つ挿入し、その次の行にbrタグを挿入します。イメージとしては次のような感じです。

(1) 卵を割って容器に中身を落とします。

(2) 箸などで卵をかき回します。[space][space]
<br>

(3)卵をとき終えたら、卵に醤油をたらします。


substituteコマンドで実行するなら、次のような感じでしょうか。

:%s/\n^\n^\n/  ^M<br>^M^M/


これをコマンドとして利用できるよう、.vimrcに次の1行を追記しました。

" SetBRtag コマンド
command SetBRtag %s/\n^\n^\n/  ^M<br>^M^M/


関数にまとめたもの

上記のように個々のコマンドとして利用してもよいのですが、どちらのコマンドも毎回使用するので、まとめて関数にしてみました(Vimの関数について余り分かっていないため手探りですが・・・)。

" functionを使ったもの
function SetBlogTags()
    " [^<]はタグ挿入済みの行を除外するためのもの
    silent %s/^# \([^<]..*\)/# \<span style="color: #b388dd"\>\1\<\/span\>/
    silent %s/\n^\n^\n/  ^M<br>^M^M/
endfunction

command SetBlogTags call SetBlogTags()


" defを使ったもの
def SetBlogTags()
    silent :%s/^# \([^<]..*\)/# \<span style="color: #b388dd"\>\1\<\/span\>/
    silent :%s/\n^\n^\n/  ^M<br>^M^M/
enddef

command SetBlogTags call SetBlogTags()


これらのいずれかを.vimrcに記述して

:SetBlogTags

を実行します。

defとfunctionの違い

試してみたところ、functionを使った場合とdefを使った場合とで次の違いがありました。

・defを使ったものでは、%sの前に : が必要(functionを使ったものでは不要)
・defを使ったものでは、関数定義の途中にコメントを入れるとエラーになる


少し手を加えたもの(実験)

上述の内容を実際に使ってみたら、少々物足りないことに気づいたのでもう少し手を加えてみました。なお、以下の自作関数では、H1レベルではなくH4レベルの見出し(####)に対してテキスト色を指定しています。

function SetBlog()  
    silent %s/^#### \([^<]..*\)/#### \<span style="color: #b388dd"\>\1\<\/span\>/  
    silent %s/\n/  ^M/                   " 行末に半角スペース2つを挿入  
    silent %s/^\(```[a-z].*\)  \n/\1^M/  " ```hitmlや```vim等の行末にある半角スペースを除去  
    silent %s/^  \n^  \n/<br>^M  ^M/     " 空行が2つ連続している部分は1行目をbrタグにする  
    silent %s/  \n^  \n/  ^M<br>^M/      " 半角space2つの直後にある空行をbrタグにする  
    call cursor(1,1)                     " カーソルをファイルの先頭に移動  
endfunction  

はてなブログでは「```html」や「```vim」等の行末に半角スペースがあるとシンタックスハイライトが有効にならなかったので、4行目で半角スペースを除去しています。


(追記)
試してみたら問題が生じました。具体的には、```で囲んだ範囲(コード等を記述してある範囲)の中にまで、半角スペースやbrタグが挿入されてしまいました。

そこで、ろくに書いたことのないVimscriptを書いてみました。

function SetBlog()
    silent! %s/^  *```/```/             " ```の前にspaceがあったら除去
    let inside_quote = 0
    for i in range(1, line("$"))
        call cursor(i, 1)
        let line_content = getline(line("."))
    
        if line_content[:2] =~ "```"
            if inside_quote == 0
                let inside_quote = 1
            else
                let inside_quote = 0
            endif 
        endif
        if inside_quote == 0
            silent s/\n/  ^M/           " 行末に半角spaceを2つ挿入
        endif
    endfor
    unlet inside_quote
    unlet line_content

    silent! %s/^  \n^  \n/<br>^M  ^M/  " 半角space2つの行が2つ連続している部分は1行目を<br>にする
    silent! %s/  \n^  \n/  ^M<br>^M/    "「半角space2つ(行末)」「(行頭)半角space2つ(行末)」の後半を<br>にする
    silent! %s/^#### \([^<]..*\)  /#### \<span style="color: #b388dd"\>\1\<\/span\>/  " H4見出しの色を設定
    call cursor(1,1)                   " カーソルをファイルの先頭に移動
endfunction

このコードを書くまで知らなかったのですが、silent!は便利だと感じました。

たとえば、2行目では「バッククォート3つ」の前に半角spaceがあったら半角spaceを除去していますが、そのような箇所が存在しない場合、エラーメッセージが表示されます。これを抑制するためにsilent!を使用しています。

恥をさらしますと、ファイルの行数を取得する方法が分からなくて、line("$")の代わりに、当初は以下のようなコードを書いていました(汗)。

let line_count = len(readfile(expand('%:t')))


ひとまず問題は解決したものの、美しくないですね。正規表現の知識があったらもっと簡潔に処理できるんじゃないかしらと思いまして・・・。

Shift_JIS、CP932、SJIS

自分が文章を作成する場合はUTF-8を使っていますが、古いファイルや人から渡されるファイルの中にはUTF-8以外のものもあります。

そこで、個人的に紛らわしいと思っている「Shift_JIS、CP932、SJIS」について、違いを少し調べてみました。本来は専門書を当たるべきなのでしょうけれど、仕事で調査しているわけではないのでWikipediaで済ませました。


一般論

まずは、Shift_JISとCP932の違いから。
WikipediaでCP932に関する項目を見ると、

Microsoft コードページ 932は(以下 CP932)、マイクロソフト及び、
MS-DOSのOEMベンダがShift_JISを独自に拡張した文字コードである。
また、同時にCP932は、Shift_JISのWindowsアプリケーションにおける
「実装」を指す用語であるとも言える。

と書かれています。この記述から、CP932はMicrosoft社などがShift_JISを独自拡張したものだと分かります。

Shift_JISよりもCP932の方が扱う文字の範囲が広いので、CP932を使って作成されたファイルをShift_JISに変換したら失われる文字があるかもしれませんね。

次はWindows-31Jに関するWikipediaの記述です。

Windows-31J
Windows 3.1 (J) のリリースに合わせて、マイクロソフトが IBMと日本電気(NEC)
のコードを統合して作った符号化文字集合。1993 年以降、マイクロソフトが
自社のドキュメント等で「CP932」という用語を使って表している対象は、
常にこの「Windows-31J」である。この名前は IANA に登録されている。

この記述を読むと、1993年以降、CP932の中身は「Windows-31J」のようです。

最後にSJISに関するWikipediaの記述

SJIS
Shift_JISの短縮形。

この記述からSJISShift_JISと同じだと分かります。

ここまでをまとめると以下のようになります。

・SJISはShift_JISを短縮した名称
・CP932はShift_JISをMicrosoft社などが独自拡張したもの
・1993年以降のCP932はWindows-31J


現実はもう少し複雑

一般論としては上述したとおりですが、現実はもう少しややこしいようです。

たとえば、エンコーディングに関する実装において「SJIS」というワードを「Windows-31J」に割り当てている場合もあるようです。この状況だと「SJIS = Shift_JIS」ではありませんね。

こういうケースがあるので、何か上手く行かなかった時にその都度どんなセッティングになっているのか調べるしかなさそうです。


素朴な疑問(Vimsjis

いきなりVimの話になりますが、Vimのヘルプでencodingに関する部分を読むと

2   cp932    日本語 (Windows only)
2   euc-jp  日本語 (Unix only)
2   sjis    日本語 (Unix only)

という記述がありました。気になるのは3行目のsjisです。このsjisShift_JISと同一視してよいのか分かりません。はて?

Neovimのキーマップ設定 and 自作コマンド定義

目次


情報源

情報源は、Lua-guideのMappingsという項目と、Neovimのヘルプです。

Lua-guide - Neovim docs


キーマップを設定するにはvim.keymap.set()を使う

キーマップを設定するにはvim.keymap.set()を使います。
たとえば、ノーマルモードで j に gj を割り当てる場合、init.lua

vim.keymap.set('n', 'j', 'gj')

と記述します。n はノーマルモードを指します。

この設定は、Vim

nnoremap j gj

に相当します。

一方、

nmap j gj

のようにしたい場合は

vim.keymap.set('n', 'j', 'gj', {remap = true})

と記述します。

https://neovim.io/doc/user/lua-guide.html#lua-guide-mappings-set
に以下の記述があります。

remap: By default, all mappings are nonrecursive by default 
(i.e., vim.keymap.set() behaves like :noremap). 
If the {rhs} is itself a mapping that should be executed, 
set remap = true:

つまり、デフォルトではremapされないようになっています。よって、remapを有効にするには {remap = true} を記述する必要があります。


コマンドをキーに割り当てる

私はVaffleというプラグインを使っているのですが、これを呼び出す場合

:Vaffle

を実行します。
これを s というキーに割り当てる場合、init.lua

vim.keymap.set('n', 's', '<cmd>Vaffle<CR>')

と記述します。

ちなみに、次のように記述しても同じように動作しました。

vim.keymap.set('n', 's', ':Vaffle<CR>')


キーマップ設定例

以下は、設定したキーマップの一部です。

vim.keymap.set('n', 's', '<Nop>')               -- s押下時は何もしない
vim.keymap.set('n', 'sa', '<cmd>set wrap<CR>')  -- saで折り返し表示

-- Ctrl+LにESCを割り当てる
vim.keymap.set('' , '<C-l>', '<ESC>') -- Normal, Visual, Operator-pendingに適用
vim.keymap.set('i', '<C-l>', '<ESC>') -- Insertに適用

-- Ctrl+LにCtrl+Cを割り当てる
vim.keymap.set('c', '<C-l>', '<C-c>') -- CommandからNormalに戻る

-- Ctrl+Sに再描画を割り当てる
vim.keymap.set('n' , '<C-s>', '<C-l>')

-- 表示行でカーソル移動
vim.keymap.set('n', 'j', 'gj')
vim.keymap.set('v', 'j', 'gj')
vim.keymap.set('n', 'k', 'gk')
vim.keymap.set('v', 'k', 'gk')

-- init.luaを開く
vim.keymap.set('n', '<Leader>ev', '<cmd>e ~/.config/nvim/init.lua<cr>')


自作コマンドを定義する

ついでに、自作コマンドを定義する手順を調べてみました。

ホームディレクトリにある.vimrcを開く「Hoge」というコマンドを自作したいとします。Vimの.vimrcに記述する場合

command Hoge :e ~/.vimrc

という表現になりますが、同じことをNeovimのinit.luaに記述する場合は次のようになります。

vim.api.nvim_create_user_command('Hoge', 'e ~/.vimrc', {})

vim.api.nvim_create_user_command()には3つの引数を指定します。1つ目はコマンド名です。2つ目はVimコマンドかLua関数です。3番目はコマンド属性です。

コマンド属性は数が多いので、必要に応じて下記リンク先を参照すればよいと思います。
https://neovim.io/doc/user/map.html#user-commands

Neovimでautocmdとcolorschemeの設定をする

情報源

今回の情報源も以下のLua-guideです。

Lua-guide - Neovim docs


autocmdの設定

Vimに記述しているautocmdをNeovimにも設定してみようと調べてみました。

Vimで以下の設定をしているとして、

augroup vimrc
  autocmd!
  autocmd FileType vim setlocal keywordprg=:help
augroup END


これをNeovimのinit.luaに記述する場合、次のようになります。

vim.api.nvim_create_augroup('vimrc', { clear = true })
vim.api.nvim_create_autocmd({ 'FileType' }, {
  pattern = 'vim',
  group = 'vimrc',
  command = 'setlocal keywordprg=:help',
})

1行目で vimrcというaugroupを作成しています。clear = trueはautocmd!の役割を担っています。 2行目以降は見たまんまで、FileTypeがvimの時にcommand行で指定したsetlocal keywordprg=:help を実行します。

Lua-guideに載っていた例を真似して下から2行目の行末に , を記述していますが、別に記述しなくても問題ありません。

Markdownファイルを編集している時に一部の _ (アンダースコア)がハイライトする問題に対処するため、以下のautocmdを記述してみました。

-- Markdownファイルにおいて一部の _ がハイライトするのを防止する
local cmhgroup = vim.api.nvim_create_augroup('clear_markdownError_highlight', { clear = true })
vim.api.nvim_create_autocmd({ 'FileType' }, {
  pattern = 'markdown',
  group = cmhgroup,
  command = 'highlight link markdownError NONE'
})

1行目でclear_markdownError_highlightというaugroupを作成しています。先の例と同じくclear = trueは autocmd! に相当します。2行目以降では、FileTypeがmarkdownの場合に(Markdownファイルを開くと)、command行にある highlight link markdownError NONE というコマンドが実行されます。

それと、こちらではaugroupの名前が長いので cmhgroupという変数を用意しています。そして、この変数をgroup行で使用しています。

ちなみに、vim.api.nvim_create_augroup関数はグループを識別する数を返すので、変数cmhgroupに格納されるのは文字列ではなく数です。

これを確認するために

print('cmhgroup is '..cmhgroup)

という文を記述しておいたら、次のように表示されました。

cmhgroup is 6


colorschemeの設定

カラースキームを設定してみます。たとえば、「torte」というカラースキームを使う場合、

vim.cmd[[colorscheme torte]]

とinit.luaに記述します。

失敗例を書いておきます。Lua-guideには

vim.cmd("colorscheme habamax")

という例が載っているのですが、この書き方ではカラースキームが有効になりませんでした。ちなみに、使用しているNeovimのバージョンは0.9.0です。

それと自作のカラースキームファイルを使う場合、以下のディレクトリの中にファイルを配置します。

~/.config/nvim/colors


追記

後から気づいたのですが、この記事に書いた

vim.api.nvim_create_augroup()
vim.api.nvim_create_autocmd()

を使ったautocmdの記述例は、Vimで以下のようにするのと同じ形ですね。

augroup takoyaki
  autocmd!
augroup END

autocmd takoyaki FileType txt set ignorecase
autocmd takoyaki FileType cpp set noignorecase

(この形ではautocmd行にグループ名を記述する手間があるので、普段は余り使いませんが・・・)

Neovimのオプション設定(init.lua)

Neovimのオプション設定をしてみたのですが、Lua形式の設定を知らなかったので時間がかかりました。

目次


Lua-guide

Lua-guide - Neovim docs

NeovimでLuaを使う場合の基礎が上記のページに記述されています。このページを拾い読みしながらinit.lua(Neovimの設定ファイル)を作成しました。

設定を記述するファイル

Neovimの各種設定を記述するファイルはinit.luaです。オプションの設定もこのファイルに記述します。

~/.config/nvim/init.lua


オプション設定の基本形

オプションを設定する時の基本形は

vim.opt.[オプション名] = [引数]

です。

Vimで次のようなオプション設定をしていたとして、

" 現在行から見た行番号を表示する
set relativenumber

これをNeovimのinit.luaファイルに記述する場合、次のようになります。

-- 現在行から見た行番号を表示する
vim.opt.relativenumber = true

(備考)-- から右側はコメントとなります。

ちなみに、オプションには種類があり、「グローバルオプション、バッファローカルオプション、ウィンドウローカルオプション」の3つです。この3つを区別して次のように記述することもできます。

vim.o.[オプション名]  = [value]  グローバルオプション
vim.bo.[オプション名] = [value]  バッファローカルオプション
vim.wo.[オプション名] = [value]  ウィンドウローカルオプション


vim.optとvim.o等

vim.o、vim.bo、vim.woではグローバル、バッファローカル、ウィンドウローカルを区別して記述しますが、vim.optはそれらを区別することなく使用できるので便利です。

NeovimのLua-guideによると、vim.optの不便な所はオプションの値を調べる時に:get()を使う必要があることだそうです(以下はLua-guideからの引用です)。

print(vim.opt.smarttab)
--> {...} (big table)
print(vim.opt.smarttab:get())
--> false

vim.optを使用した1行目のprint文ではsmarttabオプションに設定されている値を取得できていません。3行目のprint文では :get()を使うことで値を取得できています。

一方、vim.o vim.bo vim.wo を使用した場合、オプションの値を直接調べられます(以下はLua-guideからの引用です)。

vim.o.smarttab = false   -- :set nosmarttab
print(vim.o.smarttab)
--> false

1行目の「-- :set nosmarttab」はコメントなので無視してください。
1行目でsmarttabにfalseという値をセットし、2行目のprint文では(:get()を使うことなく)セットした値を取得できています。

ついでに引用しておくと、Lua-guideには以下の記述もありました。

vim.o : behaves like :set
vim.go: behaves like :setglobal
vim.bo: for buffer-scoped options
vim.wo: for window-scoped options


オプション設定例

オプションの設定例をいくつか記載します。

数値を指定する場合

vim.opt.tabstop = 4


bool値を指定する場合

vim.opt.relativenumber = true

(備考)trueかfalseを指定します。

文字列を指定する場合

vim.opt.clipboard = 'unnamedplus'


Vimの +=、^=、-=に相当するもの(以下はLua-guideからの引用です)。

vim.opt.shortmess:append({ I = true })
vim.opt.wildignore:prepend('*.o')
vim.opt.whichwrap:remove({ 'b', 's' })

たとえば、Vimの.vimrcにおいて

set formatoptions+=mM

と記述していたものは、次のように記述します。

vim.opt.formatoptions:append({m = true, M = true})


以下はNeovimのオプションではなく、Vaffleというプラグインのオプションですが、これを例にして変数を使う場合に触れておくと、

let g:vaffle_show_hidden_files = 1

Vimで記述していた場合、Neovimでは

vim.g.vaffle_show_hidden_files = 1

と記述します。

Lua-guideから引用しておきます。

vim.g: global variables (g:)
vim.b: variables for the current buffer (b:)
vim.w: variables for the current window (w:)
vim.t: variables for the current tabpage (t:)
vim.v: predefined Vim variables (v:)
vim.env: environment variables defined in the editor session


ヘルプでオプションを調べる

ヘルプを調べる場合、調べたいオプション名にシングルクォーテーションを付けます。

:h 'relativenumber'


なお、オプションがグローバル、バッファローカル、ウィンドウローカルのいずれなのかはヘルプの冒頭に記述されています。以下はrelativenumberのヘルプです。

'relativenumber' 'rnu'   boolean (default off)
                        local to window
    Show the line number relative to the line with the cursor
    in front of each line. (以下略)

local to windowという記述から、このオプションはウィンドウローカルオプションだと分かります。

booleanという記述があるので指定する値はtrueかfalseです。

vim.opt.relativenumber = true


オプションの一覧を見る

オプションの一覧を見る場合は次のようにします。

:h option-list


失敗談

失敗談を書きます。undoファイルの場所を指定する場合、

vim.opt.undodir = '/home/hoge/.nvim/undo'

のようにしますが、これを

vim.opt.undodir = '~/.nvim/undo'

と記述したら、ホームディレクトリに ~ という名前のディレクトリが作成されていました(汗)。そこで、~を使わずに/home/hoge/という風に書いています。


記法をいくつか試した時のメモ

whichwrapオプションを設定するにあたり、NeovimのLua-guideに載っていた記法をいくつか試しました。以下はその時のメモです(私がLuaという言語を分かっていないので、意味不明なことをしているだけだと思いますが)。

結果だけ先に書いておきますと、

vim.opt.whichwrap = 'h,l,<,>,[,],~'

と記述するのが一番楽だなと思いました。

以下、試したことを羅列します。

Lua-guideにある

vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }

という記述例を真似して

vim.opt.whichwrap = {'h', 'l'}

と記述したらinit.lua読み込み時にエラーとなりました。

Lua-guideに

vim.opt.whichwrap:remove({ 'b', 's' })

という記載があったので、append、prepend、removeは使えそうだと思い、試してみました。

vim.opt.whichwrap:append('h', 'l')

と記述したら、h は機能しますが l は機能しませんでした。先頭のものしかappendされていないようです。

vim.opt.whichwrap:append('h')
vim.opt.whichwrap:append('l')

と記述したら、h も l も機能しました。しかし、これだと行数が多くなるので使いたくありませんね。

vim.opt.whichwrap:append('h,l')

と記述すると h も l も機能しましたが、これなら

vim.opt.whichwrap = 'h,l'

と記述した方が文字数が少なくて良いですね。

次に

vim.opt.whichwrap = { h = true, l = true }

と記述したら、これは h も l も機能しました。
しかし、< 等の記号には使用できませんでした。たとえば、

vim.opt.whichwrap = {< = true}

と記述したら、init.lua読み込み時にエラーとなりました(< をエスケープすれば良いのかもしれませんが、Luaの知識が無いので不明です)。

< 等の記号でもappendでは使用できました。たとえば

vim.opt.whichwrap:append('<')

と記述すると、< が機能しました。

Neovimをほんの少し触ってみた

Vimから乗り換える予定はありませんが、Neovimが少し気になったのでDebian11に入れてみました。


Neovimのインストール

下記サイトにAppImage形式のNeovimがあったので、それを使うことにしました。

https://github.com/neovim/neovim/wiki/Installing-Neovim

curlコマンドでファイルをダウンロードします。

curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage


私はAppImageを使ったことが無かったので、ホームディレクトリにAppImage用のディレクトリを作成しました。

$ mkdir .appimages

ダウンロードしたnvim.appimagesを.appimagesディレクトリに移動し

$ mv nvim.appimage .appimages/

実行権限を付与しました。

$ cd .appimages/
$ chmod u+x nvim.appimage

私の環境では~/.local/binにパスを通してあるので、そこにシンボリックリンクを配置しました。

$ ln -s /home/hoge/.appimages/nvim.appimage /home/hoge/.local/bin/nvim


固まったらCtrl + C

理由は不明ですが、Neovimが固まることが時々あります。
固まった場合、とりあえず「Ctrl + C」を押すと何とかなります。


おや?挙動が少し違うような?

少し触ってみて最初に違和感を覚えたのはモーションコマンドの挙動がVimと若干違うことでした。

たとえば、ggを叩いたところ、先頭行には移動するけれど行頭にはカーソルが移動しません。ヘルプを見たら、startoflineオプションがセットされていないと、行頭には移動しないとのことでした(移動前にカーソルがあった列と同じ列に移動する)。

そこで、init.luaに以下の設定を記述しました。

vim.opt.startofline = true

これでggによって先頭行の行頭にカーソルが移動します。

次に気づいたのはYの挙動です。VimだとyyもYも同じ挙動をしていますがNeovimでYを叩いたら、行全体ではなく、カーソル位置から行末までがコピーされました。これに関しては、この挙動の方が好みだなと思ったので、NeovimではなくVimのキーマップを変更しました。

nnoremap Y y$


あと、Vimではデフォルトで有効になっていないオプションがNeovimでは最初からセットされていることが多かった気がします。ただ、大抵はその方が便利だなと思うことが多かったです。