MacOS でも Windows でもまぁまぁ使える tmux + vim 環境を作ってみた

先日、Inkdrop というアプリを開発している TAKUYA さんの動画を見て衝撃を受けた。

tmux と vim を組合せて開発をしているのだが、キーボード操作が抜群に速い。マウス操作がほとんど出てこないからこそ実現できる開発速度で、VSCode 使いの自分も tmux + vim の世界に魅了されてしまった。

ただ、自分の信条として、「オレオレ設定を極めすぎないこと」というモノも掲げている。一般的な客先常駐の SE は、好みのマシンやハードウェアを中々選べなかったりするし、数年で異動すると以前の環境をそのまま持ち込むことができなかったりするからだ。

VSCode も使い慣れているし、VSCode を捨てる気はない。ただ、「ちょっとしたカスタマイズ (※)」の範囲で、tmux + vim の便利な環境を作れたらいいなと思い、tmux + vim 道に入門することにした。

以下、MacOS を中心に、Windows でも同様の環境を実現しようとしているので、OS ごとに分けて説明する。

目次

先にどんなターミナルが出来上がるか紹介

セットアップを始める前に、このセットアップを行うとどんなターミナルが出来上がるのか紹介しよう。

まずは MacOS。

MacOS ターミナルでの Tmux

次は Windows。

Windows Git SDK ターミナルでの Tmux

それぞれセットアップ手順を紹介していこう。

ツールのインストール : MacOS 編

まずは MacOS で、tmux + vim の環境を整えてみる。使用するターミナルは OS 標準の「ターミナル.app」。

vim の用意

MacOS は標準で vivim が使えるが、いずれも --version を見ると、-clipboard という表記が見える。コレは、Vim と MacOS とでクリップボードを共有できない、ということだ。

そこで、クリップボード共有ができる Vim を Homebrew でインストールする。

$ brew install vim

Homebrew でインストールした Vim が優先的に使われるよう PATH を直して、ついでに alias vi='vim' なんかも入れておこう。Homebrew でインストールした vi も、クリップボード共有機能が使えないからだ。

$ vim --version を見て、+clipboard という表記が見えていれば、Vim の準備は完了。あとは、後述する ~/.vimrc を導入するだけ。

tmux の用意

tmux も Homebrew で入れられる。MacOS で tmux とクリップボード共有をするためには、reattach-to-user-namespace というツールを使う必要があるので、一緒にインストールしておく。

$ brew install tmux reattach-to-user-namespace

$ tmux -V でバージョンが確認できたら OK。自分がインストールしたのは 2.9a というバージョンだった。あとは後述する ~/.tmux.conf を導入するだけ。

ツールのインストール : Windows 編

Windows の場合は、Pacman というパッケージ管理ツールが使える「GitSDK」と、それに付属する「GitBash (git-bash.exe)」を使用する。GitSDK については以下の記事を参照。

vim の用意

GitSDK 付属の Vim で OK。あとは後述する ~/.vimrc を入れるだけ。

tmux の用意

Windows における tmux は、GitSDK を開き、pacman コマンドでインストールする。MacOS の場合は reattach-to-user-namespace を一緒にインストールしたが、Windows におけるクリップボード共有は標準の clip.exe を使うので特にインストールは不要。

$ pacman -S tmux

コチラも $ tmux -V でバージョンが確認できれば OK。あとは後述する ~/.tmux.conf を入れるだけ。

設定ファイルを導入する

tmux と vim のインストールが終わったので、設定ファイルを用意する。拙作の Dotfiles に現物があるので、そちらも参考にされたし。

~/.vimrc (とカラースキーム)

ホームディレクトリ直下に、.vimrc という名前のファイルを作り、以下の内容をコピペする。

" ================================================================================
" .vimrc
" ================================================================================

" 文字コードを UFT-8 に設定する
set fenc=utf-8
" バックアップファイルを作らない
set nobackup
" スワップファイルを作らない
set noswapfile
" 編集中のファイルが変更されたら自動で読み直す
set autoread
" バッファが編集中でもその他のファイルを開けるようにする
set hidden
" 入力中のコマンドをステータスに表示する
set showcmd
" クリップボード連携を有効にする (MacOS の場合は unnamedplus ではなく unnamed で有効にできた・vi ではなく vim を使うこと)
set clipboard&
set clipboard^=unnamed
" クリップボード連携を有効にした時に BackSpace (Delete) が効かなくなるので設定する
set backspace=indent,eol,start

" 見た目
" ------------------------------------------------------------

" Monokai カラースキーム
syntax on
colorscheme monokai
" 範囲選択が見づらいので変更する
hi Visual ctermbg=227

" 行番号を表示する
set number
" 現在の行を強調表示する
set cursorline
" カーソルラインの色をクリアする
hi clear CursorLine
" 行末の1文字先までカーソルを移動できるようにする
set virtualedit=onemore
" スマートインデントにする
set smartindent
" ビープ音を可視化する
set visualbell
" 括弧入力時の対応する括弧を表示する
set showmatch
" ステータスラインを常に表示する
set laststatus=2
" コマンドライン補完を有効にする
set wildmode=list:longest
" 折り返し時に表示行単位での移動をできるようにする
nnoremap j gj
nnoremap k gk

" Tab 文字
" ------------------------------------------------------------

" 不可視文字を可視化 (タブが「▸-」と表示される)
set list listchars=tab:\\-
" Tab 文字を半角スペースにする
set expandtab
" 行頭以外の Tab 文字の表示幅 (スペースの数)
set tabstop=2
" 行頭での Tab 文字の表示幅
set shiftwidth=2

" 検索
" ------------------------------------------------------------

" 検索文字列が小文字の場合は大文字小文字を区別なく検索する
set ignorecase
" 検索文字列に大文字が含まれている場合は区別して検索する
set smartcase
" 検索文字列入力時に順次対象文字列にヒットさせる
set incsearch
" 検索時に最後まで行ったら最初に戻る
set wrapscan
" 検索語をハイライト表示する
set hlsearch

" ウィンドウ
" ------------------------------------------------------------

" t + \ ・ t + | でウィンドウを垂直縦分割する
nmap t<Bslash> :vsplit<Return><C-w>w
nmap t<Bar> :vsplit<Return><C-w>w
" t + - でウィンドウを水平横分割する
nmap t- :split<Return><C-w>w

" t + hjkl でウィンドウ移動する
map th <C-w>h
map tj <C-w>j
map tk <C-w>k
map tl <C-w>l
" Ctrl + w → 矢印キーでウィンドウをリサイズする
nmap tH <C-w>>
nmap tJ <C-w>-
nmap tK <C-w>+
nmap tL <C-w><

" t + 矢印キーでウィンドウ移動する
map t<Left> <C-w>h
map t<Down> <C-w>j
map t<Up> <C-w>k
map t<Right> <C-w>l
" Ctrl + w → 矢印キーでウィンドウをリサイズする
nmap <C-w><Left> <C-w>>
nmap <C-w><Down> <C-w>-
nmap <C-w><Up> <C-w>+
nmap <C-w><Right> <C-w><

" Space でウィンドウ移動する
nmap <Space> <C-w>w

" Tab・Space + Tab でタブ移動
nmap <Tab> :tabnext<Return>
nmap <S-Tab> :tabprev<Return>

" Ctrl + z で元に戻す (u)
nnoremap <C-z> u
" Ctrl + y でやり直す (Ctrl + r)
nnoremap <C-y> <C-r>

" Esc 連打で :nohlsearch が出ないようにする
nnoremap <Esc><Esc> <Esc>

また、~/.vim/colors/ というディレクトリを作り、その下に以下のリポジトリにある monokai.vim を入れておく。

コレは Monokai カラースキームなので、お好みで変更されたし。

~/.tmux.conf

続いて tmux。コチラもホームディレクトリ直下に .tmux.conf というファイルを作り、以下の内容をコピペする。MacOS でも Windows GitSDK でも動作するよう調整してある。

# ================================================================================
# .tmux.conf
# ================================================================================

# Session Global Option (set-option -g)
# ================================================================================

# Prefix を Ctrl + t にする
set-option -g prefix C-t

# ペインの番号を 1 から開始する (デフォルトは 0)
set-option -g base-index 1

# tmux 上の vi で colorscheme が有効にならないため設定する
set-option -g default-terminal screen-256color

# 通常の枠線を水色にする
set-option -g pane-border-style fg="colour51"

# アクティブなペインの枠線を赤色にする
set-option -g pane-active-border-style fg="colour196"

# マウス操作を有効にする
set-option -g mouse on

# キーストロークのディレイを減らす
set-option -sg escape-time 1

# リフレッシュ間隔を変更する
set-option -g status-interval 1

# ステータスバーの右部分に時計を表示する
set-option -g status-right "[%Y-%m-%d (%a) %H:%M:%S]"

# MacOS : reattach-to-user-namespace を使用してクリップボード共有を有効にする
if -b 'command -v reattach-to-user-namespace > /dev/null 2>&1'  'set-option -g default-command "reattach-to-user-namespace -l bash"'

# Window Global Option (set-window-option)
# ================================================================================

# ウィンドウの番号を 1 から開始する (デフォルトは 0)
set-window-option -g pane-base-index 1

# コピーモード (Prefix + [ で開始) で vi キーバインドを使う
set-window-option -g mode-keys vi

# Bind Key
# ================================================================================

# Prefix + \ ・ Prefix + | でペインを縦に分割する
bind-key \ split-window -h
bind-key | split-window -h
# Prefix + - でペインを横に分割する
bind-key - split-window -v

# Prefix + hjkl でペイン移動
bind-key -r h select-pane -L
bind-key -r j select-pane -D
bind-key -r k select-pane -U
bind-key -r l select-pane -R

# Prefix + Shift + hjkl でペインをリサイズする
bind-key -r H resize-pane -L 5
bind-key -r J resize-pane -D 5
bind-key -r K resize-pane -U 5
bind-key -r L resize-pane -R 5

# Prefix + r で設定ファイルをリロードする
bind-key r source-file ~/.tmux.conf \; display "Reloaded."

# Prefix + o で tmux 用の画面クリアコマンドを入力する
bind-key o send-keys "clear && tmux clear-history" \; send-keys Enter

# Prefix + v でコピーモードを開始する (デフォルトは Prefix + [)
bind-key v copy-mode \; display "Copy Mode!"

# Prefix + Ctrl + p でペースト (デフォルトは Prefix + ]・クリップボード共有しているので Cmd + V でも OK)
bind-key C-p paste-buffer

# コピーモード中 v か Space で選択を始める
bind-key -T copy-mode-vi v send -X begin-selection \; display "Copy Start."
bind-key -T copy-mode-vi Space send -X begin-selection \; display "Copy Start."
# コピーモード中 V で行選択を始める
bind-key -T copy-mode-vi V send -X select-line \; display "Copy Line Start."
# コピーモード中 Ctrl + v で矩形選択を始める
bind-key -T copy-mode-vi C-v send -X rectangle-toggle \; display "Copy Rectangle Start."

# コピーモード中 y か Enter でヤンク (コピー)
# MacOS : reattach-to-user-namespace を使用
if -b 'command -v reattach-to-user-namespace > /dev/null 2>&1'  'bind-key -T copy-mode-vi y     send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy" \; display "Copied!"'
if -b 'command -v reattach-to-user-namespace > /dev/null 2>&1'  'bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy" \; display "Copied!"'
# Windows : tmux save-buffer で echo しパイプを使って clip.exe に渡す
if -b 'command -v clip.exe                   > /dev/null 2>&1'  'bind-key -T copy-mode-vi y     send-keys -X copy-pipe-and-cancel "tmux save-buffer - | clip.exe" \; display "Copied!"'
if -b 'command -v clip.exe                   > /dev/null 2>&1'  'bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "tmux save-buffer - | clip.exe" \; display "Copied!"'

# コピーモード中 Esc で中止
bind-key -T copy-mode-vi Escape send -X cancel

ターミナルのカラー・フォント設定を揃える

あとはターミナルのカラーやフォントの設定を調整しておく。

MacOS ターミナル

標準で入っている Homebrew テーマをベースに、テキストの色を緑から白にしておく。色はお好みで明るめに。フォントは Osaka 等幅。メイリオ改を使ったりしていたが、結局コレが一番見やすい。

MacOS ターミナルのフォント設定

Windows Git SDK

GitBash は青色が特に見づらいので、~/.minttyrc にてカラーを設定してやることにする。ThemeFile プロパティは空にしておくことで、カラー指定が有効にできる。

# ================================================================================
# .minttyrc
# ================================================================================

Charset  = UTF-8
Language = ja
Locale   = ja_JP

Columns  = 120
Rows     = 25

Font          = Consolas
FontHeight    = 11
FontWeight    = 700
FontIsBold    = yes
FontSmoothing = full
BoldAsColour  = yes
BoldAsFont    = yes

AllowBlinking     = yes
CursorType        = block
OpaqueWhenFocused = yes
Term              = xterm-256color
ThemeFile         =

ForegroundColour = 240,240,240
BackgroundColour =   0,  0,  0
CursorColour     = 240,240,240
Black            = 100,100,100
BoldBlack        = 100,100,100
Red              = 240,  0,  0
BoldRed          = 240,  0,  0
Green            =   0,220,  0
BoldGreen        =   0,220,  0
Yellow           = 255,255,  0
BoldYellow       = 255,255,  0
Blue             =   0,140,255
BoldBlue         =   0,140,255
Magenta          = 255,  0,240
BoldMagenta      = 255,  0,240
Cyan             =   0,240,240
BoldCyan         =   0,240,240
White            = 255,255,255
BoldWhite        = 255,255,255

フォントはメイリオ改や Osaka 等幅を使いたかったが、いずれも tmux で罫線が狂ってしまった。日本語表示が一番マシな英語フォントの Consolas を選んでお茶を濁した。

Windows でのフォント設定

コレで完了

コレで設定完了。あとは使っていくだけ…。

カスタマイズした内容を確認する

…とはいっても、いきなり設定ファイルを渡してさあどうぞ、というのも難しいと思うので、設定ファイルでカスタマイズした内容の詳細を見ていき、それに合わせて使い方を解説しよう。

Vim

" クリップボード連携を有効にする (MacOS の場合は unnamedplus ではなく unnamed で有効にできた・vi ではなく vim を使うこと)
set clipboard&
set clipboard^=unnamed
" クリップボード連携を有効にした時に BackSpace (Delete) が効かなくなるので設定する
set backspace=indent,eol,start

unnamedunnamedplus が調べてもよく分からずじまいだったが、とりあえず上の設定で、MacOS も Windows も動作した。ただ、コレを入れると、インサートモードで BackSpace (Delete) キーが効かなくなる問題があったので、set backspace も入れた次第。

次。

" Monokai カラースキーム
syntax on
colorscheme monokai
" 範囲選択が見づらいので変更する
hi Visual ctermbg=227
" t + \ ・ t + | でウィンドウを垂直縦分割する
nmap t<Bslash> :vsplit<Return><C-w>w
nmap t<Bar> :vsplit<Return><C-w>w
" t + - でウィンドウを水平横分割する
nmap t- :split<Return><C-w>w
" t + hjkl でウィンドウ移動する
map th <C-w>h
map tj <C-w>j
map tk <C-w>k
map tl <C-w>l

" t + 矢印キーでウィンドウ移動する
map t<Left> <C-w>h
map t<Down> <C-w>j
map t<Up> <C-w>k
map t<Right> <C-w>l
" t + HJKL でウィンドウをリサイズする
nmap tH <C-w>>
nmap tJ <C-w>-
nmap tK <C-w>+
nmap tL <C-w><

" Ctrl + w → 矢印キーでウィンドウをリサイズする
nmap <C-w><Left> <C-w>>
nmap <C-w><Down> <C-w>-
nmap <C-w><Up> <C-w>+
nmap <C-w><Right> <C-w><
" Ctrl + z で元に戻す (u)
nnoremap <C-z> u
" Ctrl + y でやり直す (Ctrl + r)
nnoremap <C-y> <C-r>

tmux

tmux の設定は set (= set-option)、setw (= set-window-option)、bind (bind-key) などがある。

# Prefix を Ctrl + t にする
set-option -g prefix C-t
# マウス操作を有効にする
set-option -g mouse on
# MacOS : reattach-to-user-namespace を使用してクリップボード共有を有効にする
if -b 'command -v reattach-to-user-namespace > /dev/null 2>&1'  'set-option -g default-command "reattach-to-user-namespace -l bash"'
# コピーモード (Prefix + [ で開始) で vi キーバインドを使う
set-window-option -g mode-keys vi
# Prefix + \ ・ Prefix + | でペインを縦に分割する
bind-key \ split-window -h
bind-key | split-window -h
# Prefix + - でペインを横に分割する
bind-key - split-window -v
# Prefix + hjkl でペイン移動
bind-key -r h select-pane -L
bind-key -r j select-pane -D
bind-key -r k select-pane -U
bind-key -r l select-pane -R

# Prefix + Shift + hjkl でペインをリサイズする
bind-key -r H resize-pane -L 5
bind-key -r J resize-pane -D 5
bind-key -r K resize-pane -U 5
bind-key -r L resize-pane -R 5
# Prefix + r で設定ファイルをリロードする
bind-key r source-file ~/.tmux.conf \; display "Reloaded."
# Prefix + o で tmux 用の画面クリアコマンドを入力する
bind-key o send-keys "clear && tmux clear-history" \; send-keys Enter
# Prefix + v でコピーモードを開始する (デフォルトは Prefix + [)
bind-key v copy-mode \; display "Copy Mode!"

# Prefix + Ctrl + p でペースト (デフォルトは Prefix + ]・クリップボード共有しているので Cmd + V でも OK)
bind-key C-p paste-buffer

# コピーモード中 v か Space で選択を始める
bind-key -T copy-mode-vi v send -X begin-selection \; display "Copy Start."
bind-key -T copy-mode-vi Space send -X begin-selection \; display "Copy Start."
# コピーモード中 V で行選択を始める
bind-key -T copy-mode-vi V send -X select-line \; display "Copy Line Start."
# コピーモード中 Ctrl + v で矩形選択を始める
bind-key -T copy-mode-vi C-v send -X rectangle-toggle \; display "Copy Rectangle Start."
# コピーモード中 y か Enter でヤンク (コピー)

# MacOS : reattach-to-user-namespace を使用
if -b 'command -v reattach-to-user-namespace > /dev/null 2>&1'  'bind-key -T copy-mode-vi y     send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy" \; display "Copied!"'
if -b 'command -v reattach-to-user-namespace > /dev/null 2>&1'  'bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy" \; display "Copied!"'

# Windows : tmux save-buffer で echo しパイプを使って clip.exe に渡す
if -b 'command -v clip.exe                   > /dev/null 2>&1'  'bind-key -T copy-mode-vi y     send-keys -X copy-pipe-and-cancel "tmux save-buffer - | clip.exe" \; display "Copied!"'
if -b 'command -v clip.exe                   > /dev/null 2>&1'  'bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "tmux save-buffer - | clip.exe" \; display "Copied!"'

…こんな感じ。

基本的には Vim の操作を覚えていれば、その流れで Vim のペイン操作や tmux のペイン操作ができるようにしてある。覚えるのは |- (ペイン分割)、hjkl (移動関連)、vyp (ヤンク周り) ぐらいだ。

以上

あんまりガッツリと tmux + vim を触ることはないけど、ちょっとした時に使いたい、というライトな人向けの、~/.tmux.conf~/.vimrc 設定を紹介した。