ターミナルでVS Code的なコード閲覧環境を作る — Neovim + LazyVim入門
TL;DR
- Neovim + LazyVim でファイルツリー・タブ・LSP・ファジー検索が最初から揃う
- neo-tree をカスタマイズすると、ツリーでカーソル移動するだけでプレビュー表示される VS Code 的な体験が得られる
microやhelixも試したが、プロジェクト単位のコード閲覧には Neovim が一番完成度が高い
背景
ターミナルで VS Code のようにコードを閲覧・編集したかった。いくつかのツールを試した結果:
| ツール | 評価 | 理由 |
|---|---|---|
bat |
ファイル単体なら良い | プロジェクト単位の操作ができない |
micro |
編集は直感的 | filemanager プラグインの完成度が低い |
helix |
LSP内蔵で設定不要 | ファイルツリーが未実装 |
| Neovim + LazyVim | 採用 | ファイルツリー・タブ・LSP が全部入り |
セットアップ
インストール
brew install neovim ripgrep fd
LazyVim の導入
# 既存設定があればバックアップ
mv ~/.config/nvim ~/.config/nvim.bak 2>/dev/null
# LazyVim starter をクローン
git clone https://github.com/LazyVim/starter ~/.config/nvim
nvim で起動するとプラグインが自動インストールされる。
基本操作
ナビゲーション
| キー | 操作 |
|---|---|
Space |
リーダーメニュー(VS Code の Cmd+Shift+P 的) |
Space + e |
ファイルツリー表示 |
Space + f + f |
ファイル検索(Cmd+P 的) |
Space + s + g |
全文検索(Cmd+Shift+F 的) |
Ctrl + h |
左ウィンドウ(ツリー)にフォーカス |
Ctrl + l |
右ウィンドウ(エディタ)にフォーカス |
エディタ操作
| キー | 操作 |
|---|---|
i |
編集モードに入る |
Esc or Ctrl+c |
編集モードを抜ける |
Ctrl+f / Ctrl+b |
1ページ下/上 |
Ctrl+d / Ctrl+u |
半ページ下/上 |
g + d |
定義へジャンプ |
K |
ホバー情報 |
:wqa |
全保存して終了 |
:qa |
全終了(保存なし) |
neo-tree カスタマイズ: VS Code 的プレビュー体験
デフォルトの neo-tree は Space + e でツリーが開閉するだけ。以下をカスタマイズした:
- 起動時にツリーを常時表示
- ツリーでカーソル移動するだけでファイル内容をプレビュー
- プレビュー用バッファを1つだけ使い回す(タブが増殖しない)
- Enter で正式にファイルを開く(プレビューから確定)
- Enter でフォルダも展開/折りたたみ可能
設定ファイル
~/.config/nvim/lua/plugins/neo-tree.lua:
local preview_buf = nil
return {
{
"nvim-neo-tree/neo-tree.nvim",
opts = {
close_if_last_window = false,
filesystem = {
follow_current_file = { enabled = true },
use_libuv_file_watcher = true,
},
window = {
mappings = {
["<cr>"] = function(state)
local node = state.tree:get_node()
if node.type == "file" then
preview_buf = nil
vim.cmd("wincmd l")
vim.cmd("edit " .. vim.fn.fnameescape(node.path))
elseif node.type == "directory" then
require("neo-tree.sources.filesystem.commands").toggle_node(state)
end
end,
},
},
},
init = function()
-- 起動時にツリーを自動表示
vim.api.nvim_create_autocmd("VimEnter", {
callback = function()
vim.cmd("Neotree show")
end,
})
-- ツリー内でカーソル移動したらプレビュー表示
vim.api.nvim_create_autocmd("CursorMoved", {
pattern = "neo-tree*",
callback = function()
local ok, manager = pcall(require, "neo-tree.sources.manager")
if not ok then return end
local state = manager.get_state("filesystem")
if not state or not state.tree then return end
local node = state.tree:get_node()
if not node or node.type ~= "file" then return end
local cur_win = vim.api.nvim_get_current_win()
local target_win = nil
for _, win in ipairs(vim.api.nvim_list_wins()) do
if win ~= cur_win then
target_win = win
break
end
end
if not target_win then return end
local cur_buf = vim.api.nvim_win_get_buf(target_win)
local cur_name = vim.api.nvim_buf_get_name(cur_buf)
if cur_name == node.path then return end
if preview_buf and vim.api.nvim_buf_is_valid(preview_buf)
and preview_buf ~= cur_buf then
pcall(vim.api.nvim_buf_delete, preview_buf, { force = true })
end
vim.api.nvim_win_call(target_win, function()
vim.cmd("edit " .. vim.fn.fnameescape(node.path))
end)
preview_buf = vim.api.nvim_win_get_buf(target_win)
end,
})
end,
},
}
ポイント
preview_buf変数で前回のプレビューバッファを追跡し、新しいファイルを開く前に削除する。これでタブが無限に増えないCursorMovedautocmd で neo-tree バッファ内のカーソル移動を検知。after_renderイベントではカーソル移動を拾えない- Enter は
node.typeで分岐。ファイルなら右ペインで開き、ディレクトリなら展開/折りたたみ
まとめ
Vim のモーダル操作は慣れが必要だが、LazyVim + neo-tree カスタマイズで「ツリーからファイルを選んでプレビュー → Enter で確定」という VS Code 的なワークフローはターミナル内で実現できる。