💥

Vim on tmuxのすゝめ

2024/12/03に公開

機能性が伴う浪漫。それが Vim on tmux

モダンな開発環境といえば、VSCodeやJetBrains系が定番ですが、今日は一味違う世界をのぞいてみましょう。Vim on tmuxは、見た目の美しさと機能性を兼ね備えた開発環境です。
導入は一瞬、そこから無限の可能性が広がります。

1. マイ主力兵器

$ nvim --version
NVIM v0.11.0-dev-973+gb7e896671

$ tmux -V
tmux next-3.6

$ alacritty --version
alacritty 0.14.0-dev (cb3a79db)

2. 主力兵器概要

Neovim

https://github.com/neovim/neovim

  • スパゲッティな古vimのリファクタであり、リアクター。
  • 2025年最も絶対確実にNo.1なコードエディター(当社比)
  • マウスはハードオフへGO

tmux

https://github.com/tmux/tmux

  • ターミナルマルチプレクサの王様
  • ペアプロ時はどこでもドアと化す
  • マウスはハードオフへGO

Alacritty

https://github.com/alacritty/alacritty

  • GPUを使って高速化されたRust製の次世代ターミナルエミュレータ。
  • タブやスプリット機能がないなら、tmuxを使えばいいじゃない。

3. Vim on tmux環境を10分で用意してみよう!

環境構築

インストール(macOSの場合)

brew install tmux neovim

インストール(Ubuntu/Debianの場合)

sudo apt update
sudo apt install tmux neovim

インストールされたかチェック

nvim --version
tmux -V 

tmux操作のための事前知識

基本操作

tmuxはprefixキー + [特定のキー]でコマンドが発火します。prefixキーのデフォルトは
Ctrl + b (以下 <C-b> と表記) です。

  1. セッション開始: tmux
  2. 画面分割:
    • 縦分割: <C-b> %
    • 横分割: <C-b> "
  3. ペイン操作:
    • 移動: <C-b> + 矢印キー
    • 最大化/戻す: <C-b> z
    • 閉じる: <C-b> x
  4. ウィンドウ操作:
    • 新規作成: <C-b> c
    • 一覧表示: <C-b> w
    • 次へ/前へ: <C-b> n / <C-b> p
  5. セッション操作:
    • デタッチ: <C-b> d
    • 一覧表示: <C-b> s
    • アタッチ: tmux a

Neovim操作のための事前知識

基本的な使い方

  1. ファイルを開く: nvim test.py
  2. モード:
    • ノーマルモード: Esc(デフォルトの状態。各モードから抜けるときはEscを押す)
    • 挿入モード: i(カーソル位置から)
    • 挿入モード: a(カーソルの次の位置から)
    • ビジュアルモード: v(選択)

編集方法

h, j, k, l    : 左, 下, 上, 右に移動
w / b         : 単語単位で前後移動
0 / $         : 行頭/行末に移動
gg / G        : ファイルの先頭/末尾に移動
dd            : 行を削除
yy            : 行をコピー
p             : カーソルの後にペースト
u             : undo
<C-r>         : redo

ファイル操作

全てノーマルモードの状態でのみ入力可能!Escポチポチ

:w            : 保存
:q            : 終了
:wq または ZZ : 保存して終了
:e ファイル名  : 新しいファイルを開く

最小限のNeovim設定

デフォルトだと武器無し状態なので~/.config/nvim/init.luaを作成して以下を記入してください

vim.opt.number = true          -- 行番号を表示
vim.opt.expandtab = true       -- タブをスペースに変換
vim.opt.tabstop = 4           -- タブ幅を4に設定
vim.opt.shiftwidth = 4        -- インデント幅を4に設定
vim.opt.autoindent = true     -- 自動インデント
vim.opt.smartindent = true    -- スマートインデント

Hello, Vim on tmux!

いよいよtmuxセッション内でneovimを起動します!ワクワク
目標は「上下にペインを分けて、上をnvim、下を実行ペインにする」です!

シンプルな開発レイアウトの作成

ウィンドウを上下のペインにわけます

# 新しいセッションを開始
tmux new -s dev

# セッション開始後の操作:
# 1. <C-b> " で上下分割
# 2. <C-b> 上矢印 上ペインを選択 

お試しコーディング

$ nvim hello.pyで実際に以下の内容をコーディングしてみましょう!
実行は下ペインで行うので入力が終わったら:wで保存だけしてください!

def hello():
    print("Welcome to Vim on tmux!")

if __name__ == "__main__":
    hello()

下ペインで実行

ペインを移動して、プログラムを実行してみましょう。

  1. <C-b> 下矢印 下ペインを選択
  2. python hello.py

実行できたらクリアです!

トラブルシューティング

# tmuxセッションが残っている場合
tmux kill-server

# vimが閉じれん!よくわからん!変更破棄していいからnvimを終了したい!
1. Enterポチポチ
2. Escポチポチ
3. :q!と入力
すると何もわかってなくても大抵終了できます。

次のステップ

ハンズオンはここまでです!お疲れ様でした。

触ってみて薄々気づいたかもしれませんが、デフォルトの設定はめちゃくちゃ簡素なのでカスタムする必要があります。
もし興味がある方はプラグインを入れてみると幸せになります。
おすすめのプラグインマネージャーは以下なので調べてみてください。

  • tmux: tpm

https://github.com/tmux-plugins/tpm

  • neovim: lazy.nvim

https://github.com/folke/lazy.nvim


これ以降は私の環境設定を少しだけシェアします🙇

4. ざっくりマイNeovim設定

基本的なインストール方法やパッケージマネージャの導入はClaude君に聞くべきなので割愛します。
configはGitHubにプッシュしているので興味がある方がいればみてやってください。
https://github.com/TomoyaFujita2016/dotfiles/tree/main/.config/nvim
.config/nvimの構成はこんな感じ

  • /init.lua : エントリーポイント
  • /lua/*.lua : キーマッピングやプラグイン以外の設定はここに書く
  • /lua/plugins/*.lua : プラグインごとの設定はここに書く。ファイル名はプラグイン名でも良いし、機能名でも良い
  • /lua/utils.lua : よく使う関数をまとめたファイル。poetry, pyenv, systemの優先順で環境を取得するget_python_envがかなり良い
utils.luaの一部
local cached_python_env = nil
local cached_env_info = nil
function M.get_python_env()
  -- キャッシュされた環境がある場合はそれを返す
  if cached_python_env then
    return cached_python_env
  end

  -- 1. Poetry
  local poetry_path = vim.fn.system("poetry env info -p 2>/dev/null"):gsub("\n", "")
  if poetry_path ~= "" then
    cached_python_env = poetry_path .. "/bin/python"
    cached_env_info = "Poetry environment detected: " .. poetry_path
    M.info(cached_env_info)
    return cached_python_env
  end

  -- 2. Pyenv virtualenv
  local pyenv_version = vim.fn.system("pyenv version-name 2>/dev/null"):gsub("\n", "")
  if pyenv_version ~= "" and pyenv_version ~= "system" then
    cached_python_env = vim.fn.expand("~/.pyenv/versions/" .. pyenv_version .. "/bin/python")
    cached_env_info = "Pyenv environment detected: " .. pyenv_version
    M.info(cached_env_info)
    return cached_python_env
  end

  -- 3. Mason
  local mason_path = vim.fn.stdpath("data") .. "/mason/packages"
  if vim.fn.isdirectory(mason_path) ~= 0 then
    cached_python_env = mason_path .. "/python/venv/bin/python"
    cached_env_info = "Mason environment detected: " .. mason_path
    M.info(cached_env_info)
    return cached_python_env
  end

  -- fallback: system's Python
  cached_python_env = "python"
  cached_env_info = "No Python environment detected. Using system Python."
  M.warn(cached_env_info)
  return cached_python_env
end

直近イチオシプラグイン

danielfalk/smart-open.nvim
https://github.com/danielfalk/smart-open.nvim

lazy.nvimでの設定例
{
  "danielfalk/smart-open.nvim",
  priority = 1000,
  dependencies = {
    { "kkharji/sqlite.lua", lazy = true },
    { "nvim-telescope/telescope-fzy-native.nvim", lazy = true },
  },
  keys = {
    {
      "<leader>ff",
      function()
        require("telescope").extensions.smart_open.smart_open({ cwd_only = true, filename_first = false })
      end,
    },
  },
  config = function()
    require("telescope").load_extension("smart_open")
  end,
},

telescopeのファイル検索を拡張するプラグインです。
:Telescope find_filesでは届かなかった歯がゆさが解消されて、探しているファイルが見つからなかったことがなくなりました!

READMEによると以下が考慮されているようです

考慮項目
  • ファイルパスと検索テキストの一致度

    How well the file path matches the search text

  • ファイル名と検索テキストとの一致度(ファイル名の詳細は注記を参照)

    How well the file name matches the search text (see notes for file name details)

  • 直近のオープン日

    Recency of last open

  • ファイルが最後に編集されたものかどうか(つまり代替バッファかどうか)

    Whether the file is the last-edited (that is, alternate buffer)

  • 現在開いているファイル

    The file is currently open

  • ファイルの親ディレクトリが、現在開いているファイルの親ディレクトリにどれだけ近いか

    How close the file's parent directory is to the currently-open file's

  • 「Frecency - ファイルが開かれた頻度。

    "Frecency" - how frequently the file has been opened, with a bias toward recent opens.

  • ファイルが現在の作業ディレクトリの下にあるかどうか。これは、プロジェクトのトップレベルディレクトリに cd する拡張機能を使う場合に特に便利です。

    Whether the file is anywhere under the current working directory. This is especially useful if using an extension that cd's to your project's top-level directory.

5. ざっくりマイtmux設定

https://github.com/TomoyaFujita2016/dotfiles/blob/main/.tmux.conf
基本的な操作感はvimに

bind-key v split-window -h -c '#{pane_current_path}'
bind-key s split-window -v -c '#{pane_current_path}'
bind-key h select-pane -L
bind-key j select-pane -D
bind-key k select-pane -U
bind-key l select-pane -R

開発時のレイアウトはこんな感じ

  • エディター用ペインでコードを書き、複数枚の実行中ペインでプログラムを実行し、作業ペインでgit操作などを行います。
  • コードをガッツリ書くときは、prefix + zで一時的にペインを最大化できます。もう一度prefix + zで戻せます。

あとは、スクリプトを組んで、aliasに登録すると一発で好きなレイアウト組めるのでオススメです

~/.scripts/tmux_layout.sh

#!/bin/bash

tmux split-window -v
tmux split-window -h
tmux resize-pane -D 15
tmux select-pane -t 0

~/.zshrc

alias ppp="~/.scripts/tmux_layout.sh"

6. 最後に

ここまでの内容で、基本的なVim on tmuxの世界を体験していただけたと思います。

余力がある方はGitHubで「dotfiles」と検索すると多くの方の設定が見つかるので見て試してみるのも楽しいかもしれません。
徐々に新しいキーバインドを覚えて操作を効率化、Vim on tmuxの世界で、あなた専用の「浪漫」を見つけていただけたら幸いです。

ここまで、拙い記事を読み進めていただきありがとうございました!

Discussion