gitツールとしてのNeovim
この記事はVim駅伝2024年4月26日(金)の記事です。
前回の記事は ryoppippiさんの「Neovim + oil.nvim + Weztermで頑張って画像を表示する」という記事でした。
次回の記事は 4月29日(月) に投稿される予定です。
はじめに
Neovimは習熟するまでのハードルが高いと言われているエディタのひとつです。そのため、使いはじめたものの挫折してしまったという方も多いのではないでしょうか。
ですから、今回はテキストエディタとしてではなく、gitツールとしてNeovimを使う方法を紹介しようと思います。
git操作をNeovimでできるようになることで、あわよくばNeovim使いになってほしいなと願っています。
想定する読者
git commit
のときにしかvimを起動しない人- VSCodeなどのguiからgitを使っている人
- tuiツールでgitを使っている人
注意
windowsユーザーの皆さんすみません!!!windowsでは起動速度が遅いのでWSLで使うことを推奨します。
最終的なコードはこちらのレポジトリで公開しています。
実際の操作
必要なもの
Neovim
これがないと始まりません。
インストール方法はこちらを参照してください。
deno
deno製のプラグインを導入するため必要。インストール方法はこちらを参照してください。
必要なプラグイン
denops
denoでプラグインを動かすために必要な前提プラグイン
gin.vim
denopsを使って作られたgit操作をするためのプラグイン
gitsigns
これはdenops製ではない。
Vimの操作方法
今回使うのはNeovimですが、基本操作はvimと殆ど変わりません。
操作方法については、Vim駅伝2024年4月17日にyasunori0418さんが投稿した記事をご覧ください。
はじめのコード
まずはこのコードを貼り付けてください。
操作がわからない方はnvimを開いて"+y
の順にキーを押すことでコピーしたものが貼り付けられます。あとは:wq<Cr>
(<Cr>
はエンターキー)の順に押すことで保存して終了することができます。
-- windowsユーザーの方は
-- %LOCALAPPDATA%\nvim\init.lua
-- mac/linuxユーザーの方は
-- ~/.config/nvim.init.lua
-- plugin managerの導入
local path_package = vim.fn.stdpath('data') .. '/site/'
local mini_path = path_package .. 'pack/deps/start/mini.deps'
if not vim.loop.fs_stat(mini_path) then
vim.cmd('echo "Installing `mini.deps`" | redraw')
local clone_cmd = { 'git', 'clone', '--filter=blob:none', 'https://github.com/echasnovski/mini.deps', mini_path }
vim.fn.system(clone_cmd)
vim.cmd('packadd mini.deps | helptags ALL')
vim.cmd('echo "Installed `mini.deps`" | redraw')
end
vim.opt.number = true
require('mini.deps').setup { path = { package = path_package } }
local add, later = MiniDeps.add, MiniDeps.later
local opts = { noremap = true }
later(function()
add('lewis6991/gitsigns.nvim')
require('gitsigns').setup({
signcolumn = false,
numhl = true,
})
end)
later(function()
add {
source = 'lambdalisue/gin.vim',
depends = { 'vim-denops/denops.vim' },
}
-- nvim起動時にGinStatusを実行する
vim.api.nvim_create_autocmd('User', {
pattern = "DenopsPluginPost:gin",
callback = function()
vim.schedule(function()
vim.fn.execute('GinStatus')
end)
end,
once = true
})
end)
vim.cmd.colorscheme('habamax')
再度nvimを開くとプラグインのインストールが始まり、このような画面になればプラグインのインストールが完了です。
一度:q<Cr>
でNeovimを終了してgitで管理しているディレクトリからnvimコマンドでNeovimを起動します。git status -sb
の実行結果のような画面になれば成功です。
git管理していないディレクトリでNeovimを起動すると画面下部にエラーが表示されます。
各プラグインの役割
必要なプラグイン
で導入するプラグインの軽い説明をしましたが、もう少し具体的に説明します。
gin.vim
git操作全般を担当するプラグイン。
ファイルのステージ/アンステージ等の基本的な操作ははもちろんのこと、:Gin hoge
と実行することでgit hoge
を実行できるので、ターミナルに戻ることなく任意のgitコマンド実行ができる優れもの。
gitsigns.nvim
主にhunk単位での操作を行うために使います。
具体的にはhunk単位でのステージ/アンステージや、blameの確認、hunkの差分の確認ができます。
基本操作編
gin.vim
:Gin
と入力した状態で<C-d>
(Ctrlキーを押しながらdキーを押す)を押すとGinから始まるコマンド一覧を確認できます。
私がよく使う機能としては
git
コマンド相当のGin
git log
相当のGinLog
git branch
相当のGinBranch
.git
ディレクトリがある階層に自動的にcd
してくれるGinCd
git status
相当のGin
Status
です。逆にそれ以外のコマンドはほとんど使ったことがありません。ごめんなさい。
試しに:GinLog<Cr>
を実行します。
このようにターミナルの実行結果がそのままNeovim内で見られます。いいですね。
commitのハッシュが書いてある行で<Cr>
を押すとそのcommitの詳細を確認することができます。
この画面でa
と入力すると画面下部にaction:
と表示されます。
この状態で<C-d>
を押すとGinLog
内で実行できる様々なアクションを確認することができます。
このようにGinLog
では様々なアクションを実行することができます。
おすすめのアクションはfixup:instant-fixup
です。詳細についてはこちらの記事に委ねます。
a
を押してアクションを選択することはGinStatus
とGinBranch
でもできるので確認してみてください。
基本操作編にもかかわらず、ファイルのステージングの方法を書いていませんでした。
:GinStatus<Cr>
を実行するとこのような画面になります。
ステージングしたいファイルの行で<<
を押すことでステージングすることができます。
アンステージングは>>
で行うことができます。
初期設定されているキーマッピングについては?
を押すことで確認することができます。
gin.vimのヘルプを見たい方は、:h gin.txt<Cr>
で確認してみてください。
gitsigns.nvim
gitsignsで定義されているコマンドを確認してみましょう
:Gitsigns
(最後にスペース)と入力して<C-d>
を押すと定義されているコマンド一覧を確認することができます。
:GinStatus
でファイルの行へ移動して<Cr>
をするとそのファイルを開くことができます。
そして:Gitsigns next_hunk<Cr>
とすることで次のhunkへ移動することができます。これは言葉では説明が難しいので動画を撮ってみました。
動画を見ると分かるように、変更がされた行の行番号の色が変わっています。これもgitsignsの機能です。どの行が変更されたのか分かりやすくて気に入っています。
gitsigns.nvimのヘルプを見たい方は、:h gitsigns.txt<Cr>
で確認してみてください。
カスタマイズ編
gin.vim
pushやpullをするときに:Gin push
や:Gin pull
を毎回実行するのは面倒なので、キーマッピングを定義してみましょう。git pull
には--autostash
をつけたいタイプなので--autostash
付きです。
later(function()
add {
source = 'lambdalisue/gin.vim',
depends = { 'vim-denops/denops.vim' },
}
vim.api.nvim_create_autocmd('User', {
pattern = "DenopsPluginPost:gin",
callback = function()
vim.schedule(function()
vim.fn.execute('GinStatus')
end)
end,
once = true
})
+ vim.keymap.set('n', '<C-g>p', '<Cmd>Gin push<Cr>', opts)
+ vim.keymap.set('n', '<C-g>P', '<Cmd>Gin pull --autostash<Cr>', opts)
end)
これによって<C-g>p
を押すことによってgit push
と同等の操作ができ、<C-g>P
を押すことによってgit pull --autostash
と同等の操作ができるようになります。
:GinLog
、:GinBranch
、:GinStatus
も毎回入力するのは面倒なので同様に定義してみましょう。
later(function()
add {
source = 'lambdalisue/gin.vim',
...
vim.keymap.set('n', '<C-g>p', '<Cmd>Gin push<Cr>', opts)
vim.keymap.set('n', '<C-g>P', '<Cmd>Gin pull --autostash<Cr>', opts)
+ vim.keymap.set('n', '<C-g><C-s>', '<Cmd>GinStatus<Cr>', opts)
+ vim.keymap.set('n', '<C-g><C-b>', '<Cmd>GinBranch<Cr>', opts)
+ vim.keymap.set('n', '<C-g><C-l>', '<Cmd>GinLog<Cr>', opts)
+ vim.keymap.set('n', '<C-g>c', '<Cmd>Gin commit<Cr>', opts)
end)
それ以外に私がよく使うコマンドとして、、
- git fetch
- git merge
- git rebase
があるので一緒に定義していきましょう。
later(function()
add {
source = 'lambdalisue/gin.vim',
...
vim.keymap.set('n', '<C-g>p', '<Cmd>Gin push<Cr>', opts)
vim.keymap.set('n', '<C-g>P', '<Cmd>Gin pull --autostash<Cr>', opts)
vim.keymap.set('n', '<C-g><C-s>', '<Cmd>GinStatus<Cr>', opts)
vim.keymap.set('n', '<C-g><C-b>', '<Cmd>GinBranch<Cr>', opts)
vim.keymap.set('n', '<C-g><C-l>', '<Cmd>GinLog<Cr>', opts)
+ vim.keymap.set('n', '<C-g>f', ':Gin fetch ', opts)
+ vim.keymap.set('n', '<C-g>m', ':Gin merge ', opts)
+ vim.keymap.set('n', '<C-g>r', ':Gin rebase --autostash ', opts)
end)
これでコマンドを打たずとも好きな操作ができるようになりました。
gitsigns.nvim
hunkを移動するために、:Gitsigns next_hunk
を入力するのは面倒なのでこれもキーマッピングを定義します。
later(function()
add('lewis6991/gitsigns.nvim')
require('gitsigns').setup({
signcolumn = false,
numhl = true,
})
+ vim.keymap.set('n', ']g', '<Cmd>Gitsigns next_hunk<Cr>', opts)
+ vim.keymap.set('n', '[g', '<Cmd>Gitsigns prev_hunk<Cr>', opts)
end)
ついでに、自分の気に入っている設定も追加しておきます。
later(function()
add('lewis6991/gitsigns.nvim')
require('gitsigns').setup({
signcolumn = false,
numhl = true,
})
vim.keymap.set('n', ']g', '<Cmd>Gitsigns next_hunk<Cr>', opts)
vim.keymap.set('n', '[g', '<Cmd>Gitsigns prev_hunk<Cr>', opts)
+ vim.keymap.set('n', '<C-g><C-p>', '<Cmd>Gitsigns preview_hunk<Cr>', opts)
+ vim.keymap.set('n', '<C-g><C-v>', '<Cmd>Gitsigns blame_line<Cr>', opts)
+ vim.keymap.set('n', '<C-g>a', '<Cmd>Gitsigns stage_buffer<Cr>', opts)
end)
このようにカスタマイズを重ねていくと様々な操作ができるようになります。ぜひ自分だけのNeovimを作ってみてください。
私が実際に使っている設定も載せておきます。
https://github.com/staticWagomU/dotvim/blob/89e71e06d7fab936f52e4560d6aaae3e90ce3fec/nvim/init.lua#L335-L444
おわりに
今回はgitツールとしてNeovimを使う話です。
キーマッピングは自由なので好きにカスタマイズしてください!各プラグインのヘルプを読みながら設定するとより理解が深まるはずです。
これを機にNeovimに興味を持ってもらえると嬉しいです。
おまけ
Vim駅伝にてgin.vimについて取り上げた記事があります。興味がある方は読んでみてください。