Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 5608

ターミナルマルチプレクサ tmux をカスタマイズする

$
0
0

前提

ターミナルマルチプレクサとは、

  • GNU screen
  • tmux

などの仮想端末マネージャのことです。

メリット

  • マウスを使わず端末内でコピペできる(スクロールバックで端末画面外に流れてしまった情報にアクセスできる)
  • アタッチ・デタッチ機能で一時停止ができる
  • 画面分割により、一画面でコマンドラインとエディタを表示できる
  • 画面管理もできるので、すべてのウィンドウをタブのように管理できる
  • すべて設定ファイルでカスタマイズできる

ことが挙げられます。デメリットとしては、Vim や Emacs にように初期の導入コストが高いことでしょうか。これらの類はとっつきにくいイメージが有りますが、エディタのそれよりは簡単です。

参考

こんな感じ

これが普段使いの環境です。私の場合ですが、OS X 10.10で利用し、インストールは Homebrewからです。ターミナル.app をフルスクリーンモードにして、その中で tmux から画面を分割したり束ねたりして利用しています。

$ tmux -V
tmux 1.9a

tmux.png

少し解説を入れます。

私はモバイル機・デスクトップ機ともに OS X なので、目の動きを同じにするためにステータスバーは上部に配置しています(これは Linux ユーザにも言えるかも)。

さらに、私は大画面で開発したいので、ターミナル.app をフルスクリーンモードで利用しているのですが、それゆえに OS X のステータスバーが隠れてしまいます。これでは、現在時刻や Wi-Fi やバッテリ残量なども確認できないので、専用スクリプトを書いて tmux 上のステータスバーに表示できるようにしています。

.tmux.conf
set-option -g status-right '#(get_ssid) #(battery -c tmux) [%Y-%m-%d(%a) %H:%M]'
  • get_ssid

これは、Wi-Fi の SSID を取得するスクリプトです。ここからダウンロードし、実行権限(chmod 755 get_ssid)をつけてパスの通ったディレクトリ(例:/usr/local/bin)にインストールしてください。※現在、Mac のみ対応

  • battery -c tmux

これは、バッテリー残量を取得するスクリプトです。残量を 時:分と パーセンテージで表示します。ここからダウンロードし、get_ssidと同様にインストールしてください。batteryはオプションなしで実行すると色はついていません。-c tmuxとすることで、tmux 用のカラーがオンになります。※Mac 完全対応、Linux 一部対応

  • :充電中
  • :20% 〜 100%(緑 100% になると Full charged と表示され青くなる)
  • :1% 〜 19%

3.png

4.png

5.png

ちなみに、ステータスバーを上部に配置できるようになったのは tmux 1.7からです。

tmux_2.png

ステータスバー

上で挙げたカスタマイズ例を設定ファイルから見てみます。

.tmux.conf
# ステータスバーをトップに配置する
set-option -g status-position top

# 左右のステータスバーの長さを決定する
set-option -g status-left-length 90
set-option -g status-right-length 90

# #H => マシン名
# #P => ペイン番号
# 最左に表示
set-option -g status-left '#H:[#P]'

# Wi-Fi、バッテリー残量、現在時刻
# 最右に表示
set-option -g status-right '#(get_ssid) #(battery -c tmux) [%Y-%m-%d(%a) %H:%M]'

# ステータスバーを Utf-8 に対応
set-option -g status-utf8 on

# ステータスバーを1秒毎に描画し直す
set-option -g status-interval 1

# センタライズ(主にウィンドウ番号など)
set-option -g status-justify centre

カラースキーム

上記画像で見せた環境は Terminal.app 上で tmux、(zsh、)vim です。すべてカラースキームは Solarizedで統一しています。Solarizedは低コントラストで視認性もよく飽きがこないお勧めカラースキームです。

簡単にそれぞれの設定方法を紹介しておきます。

Terminal.app

上記リンク先から Dark または Light をダウンロードする。Command+,で環境設定を開き、「歯車マーク」>読み込む...から先ほどダウンロードした .terminalファイルを読み込めばオッケー。

terminal.png

tmux

上記リンク先にカラースキームの dark と light があるので、好きな方を ~/.tmux.confにコピペするだけです。

Vim

NeoBundle ユーザは以下を ~/.vimrcに記述するだけです。

.vimrc
NeoBundle 'altercation/vim-colors-solarized'syntax enable
setbackground=dark"または lightcolorscheme solarized

プラグインマネージャを使用していない場合は以下です。

$ git clone https://github.com/altercation/vim-colors-solarized
$ cd vim-colors-solarized/colors
$ mv solarized.vim ~/.vim/colors/

そして、~/.vimrcに以下を記述します。

.vimrc
syntax enable
setbackground=dark"または lightcolorscheme solarized

コピーモード

tmux の魅力の一つのコピーモードです。コピーモードは端末上でマウス操作を一切なしでコピペできる優れ機能です。また、デフォルトでは 2000 行までのスクロールバック(端末画面外に消えてしまった出力)をさかのぼれます(Ctrl-fCtrl-b)。

copy-mode.gif

このコピーは tmux のバッファスタックに保存されます。つまり、OS のクリップボードと連携できません。では、さっそく連携させましょう。

.tmux.conf
# Vi キーバインド
set-window-option -g mode-keys vi

# Prefix+v でコピーモード開始
bind-key v copy-mode \; display "Copy mode!"
#bind-key -t vi-copy v begin-selection

# Prefix+Enter/y でコピー
bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy"
bind-key -t vi-copy y     copy-pipe "reattach-to-user-namespace pbcopy"

# Prefix+p でペースト
# クリップボードにも保存されているので Cmd-v でもペースト可能
bind-key p paste-buffer

これは Enter/y押下時に reattach-to-user-namespace pbcopyを実行しています。pbcopyは OS X ターミナル上からクリップボードを利用するコマンドですね。reattach-to-user-namespaceはそれの橋渡し的存在です。Homebrewユーザなら、

brew install reattach-to-user-namespace

で OK です。

ちなみに copy-pipeは tmux 1.8 から利用可能です。それ以前はとてもややこしい方法で実現させていました

また、Vim とでも tmux のコピペができると便利なので連携させましょう(参考:tmuxとMacのクリップボードを共有する(copy-mode, vim))。

.tmux.conf
# vim <=> tmux 間でクリップボード利用を可能にする
set-option -g default-command "reattach-to-user-namespace -l $SHELL"

以前はスクロールバック用のモードがあったのですが、今はコピーモードに統合されました。なので、コピーモードのキーバインドをカスタマイズすれば、カーソル移動やページめくりが便利になります。

.tmux.conf
# Esc キーでコピーの反転を解除(コピーモードは抜けない)
bind-key -t vi-copy Escape clear-selection
# Ctrl-c キーでコピーの反転を解除し、コピーモードから抜ける
bind-key -t vi-copy C-c   cancel

# コピーモード中(Prefix+v 後)C-v で矩形選択開始
bind-key -t vi-copy C-v   rectangle-toggle
# 1行選択
bind-key -t vi-copy V    select-line

# Vi モード中に Ctrl-a で行頭に(Emacs ライク)
bind-key -t vi-copy C-a   start-of-line
# Vi モード中に Ctrl-e で行末に(Emacs ライク)
bind-key -t vi-copy C-e   end-of-line

# 単語の最初の1文字に移動
bind-key -t vi-copy w    next-word
# 単語の最後の1文字に移動
bind-key -t vi-copy e    next-word-end
# w の逆の動き back
bind-key -t vi-copy b    previous-word

# 画面上に映る最上行に移動
bind-key -t vi-copy g    top-line
# 画面上に映る最下行に移動
bind-key -t vi-copy G    bottom-line

# 前方検索
bind-key -t vi-copy /    search-forward
# 後方検索
bind-key -t vi-copy ?    search-backward

# ページスクロール
bind-key -t vi-copy C-n   page-up
bind-key -t vi-copy C-f   page-down
# ページ送り
bind-key -t vi-copy C-u   scroll-up
bind-key -t vi-copy C-d   scroll-down

ペイン・ウィンドウ操作

tmux はペインでウィンドウを分割でき、開発内容や案件ごとにウィンドウを保持し、サーバーごとにセッションを管理できます。

ペインウィンドウセッションクライアント
ウィンドウを分割した領域
縦分割、横分割
タブのようなもの
ペインを管理する領域
ウィンドウの集まり
を総称したもの
tmux を起動している
ターミナルや端末のこと

tmux_words.jpg

これらの切り替えをスムーズにする設定をしましょう。ペインやウィンドウの切り替えは vi ライクなキーバインドにしています。コピーモードでも vi ライクなものにしているので統一しておくのがいいでしょう。

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

# Prefix+- で横に、Prefix+| で縦に分割(ペイン)する
bind-key | split-window -h
bind-key - split-window -v

# Prefix + Ctrl-h/l でウィンドウ切り替え
# Prefix + Ctrl-h,h,h,h,...と連打できる
bind-key -r C-h select-window -t :-
bind-key -r C-l select-window -t :+

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

# ペインサイズを上下左右(Prefix+JKHL)に変更
# Prefix+J,J,J,J,...と連打してリサイズ可能
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

# Ctrl-o でペインをローテーションしながら移動
# Prefix を用いないのでタイプが楽だが、Ctrl-o を使用してしまう
# 他のソフトウェアの設定に支障をきたさないように注意
bind-key -n C-o select-pane -t :.+

シェルと連携する

さあ、ここまで来ると便利さがわかってきた tmux。しかし、このままではシェルとの連携ができていません。つまり、シェルにログインした時(ターミナル.app を再起動した時など)、いちいち

$ tmux

としないと、tmux に入れません。これでは非常に面倒なので、シェルにログインした時にデタッチされたセッションに自動にアタッチ出来るようにしましょう。tmux では Prefix+dで明示的にデタッチもできますが、端末が終了したとき(ログインシェルで exitした時や、Command+qでターミナル.app を終了した時)にも自動でデタッチされます。

よって、シェルにログインした時に、デタッチされたセッションがあればアタッチし、なければ tmux new-sessionを実行するようにしてみましょう。

.zshrc
function is_exists(){type"$1">/dev/null 2>&1;return$?;}function is_osx(){[[$OSTYPE== darwin* ]];}function is_screen_running(){[ ! -z "$STY"];}function is_tmux_runnning(){[ ! -z "$TMUX"];}function is_screen_or_tmux_running(){ is_screen_running || is_tmux_runnning;}function shell_has_started_interactively(){[ ! -z "$PS1"];}function is_ssh_running(){[ ! -z "$SSH_CONECTION"];}function tmux_automatically_attach_session(){if is_screen_or_tmux_running;then
        ! is_exists 'tmux'&&return 1

        if is_tmux_runnning;thenecho"${fg_bold[red]} _____ __  __ _   ___  __ ${reset_color}"echo"${fg_bold[red]}|_   _|  \/  | | | \ \/ / ${reset_color}"echo"${fg_bold[red]}  | | | |\/| | | | |\  /  ${reset_color}"echo"${fg_bold[red]}  | | | |  | | |_| |/  \  ${reset_color}"echo"${fg_bold[red]}  |_| |_|  |_|\___//_/\_\ ${reset_color}"elif is_screen_running;thenecho"This is on screen."fielseif shell_has_started_interactively && ! is_ssh_running;thenif ! is_exists 'tmux';thenecho'Error: tmux command not found' 2>&1
                return 1
            fiif tmux has-session >/dev/null 2>&1&& tmux list-sessions | grep -qE '.*]$';then# detached session exists
                tmux list-sessions
                echo -n "Tmux: attach? (y/N/num) "readif[["$REPLY"=~ ^[Yy]$ ]]||[["$REPLY"=='']];then
                    tmux attach-session
                    if[$? -eq 0];thenecho"$(tmux -V) attached session"return 0
                    fielif[["$REPLY"=~ ^[0-9]+$ ]];then
                    tmux attach -t "$REPLY"if[$? -eq 0];thenecho"$(tmux -V) attached session"return 0
                    fififiif is_osx && is_exists 'reattach-to-user-namespace';then# on OS X force tmux's default command# to spawn a shell in the user's namespacetmux_config=$(cat $HOME/.tmux.conf <(echo'set-option -g default-command "reattach-to-user-namespace -l $SHELL"'))
                tmux -f <(echo"$tmux_config") new-session &&echo"$(tmux -V) created new session supported OS X"else
                tmux new-session &&echo"tmux created new session"fififi}
tmux_automatically_attach_session

上記コードを ~/.bashrcなり、~/.zshrcなりに貼り付ければいいです(それ以外のシェルでは動作未確認)。

では簡単にどんな動きをするか解説します。

  • ターミナルマルチプレクサが既に動いていたら、その旨を出力する(tmux に関しては AA を表示している)
  • screen や tmux 上でなく、ssh 接続先でもなくインタラクティブシェルとして起動されたログインシェルなら以下に分岐する
    • デタッチされたセッションがある場合
      • yまたは Enterが入力された場合:最後にいたセッションにアタッチする
      • 数字が入力された場合:その数字のセッション番号のセッションにアタッチする
      • それ以外が入力された場合:新規セッションを作成
    • デタッチされたセッションがない場合
      • 新規セッションを作成

attach.png

とりあえず、最後のセッションにアタッチしたけりゃ Enterで問題無いです。

最後に

ターミナルマルチプレクサはターミナル生活を豊かにします。今回は tmux を題材にその周辺環境を含めて紹介してみました。本記事で載せた tmux に関するコードはすべてここにあります。コピペして ~/.tmux.confに配置し再読み込みすれば利用できるはずです。需要があれば以下の設定方法も追記しようと思います。

  • ログイン時に tmux 自動起動されるが、これに自動画面分割の処理も加える
  • 別のペイン/ウィンドウのカレントディレクトリに移動する

SEE ALSO

b4b4r07/dotfiles - GitHub

vim_on_zsh_on_tmux.png


Viewing all articles
Browse latest Browse all 5608

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>