Linux
tmux

linuxにおけるtmuxの設定(クリップボード, ステータスライン)

概要

  • powerlineを使わずにpowerlineみたいな表示にしてます。そのため特殊文字を使います。
    2018-01-18_10_10_39.png
    2018-01-28_11_52_55.png
    2018-01-28_11_57_19.png

  • setw -g window-active-style fg='#C5C8C6',bg='#cc8f88'setw -g window-style fg='#C5C8C6',bg='#4286f4'で背景を変えれる。あんまり見ないので書いておきます。
    2018-01-31_21_39_06.png

  • ステータスラインの表示をシェルスクリプトで行ってます。メモリ消費量、ロードアベレージ、信号強度、音量、電池残量と時間を表示しています。

  • ステータスラインがウィンドウを狭めると完全に消えるのが悲しいので、画面幅によって表示を変えています。画面幅はtput colsというコマンドでわかります。

  • Xのクリップボードとtmuxのbufferを連携させています。

  • 音量をステータスラインに表示しています。ですが、tmuxのステータスラインはn秒で更新するので、それにより音量を変えたときの表示がもっさりします。解決策として、音量を変えるキーバインドにステータスラインを更新するコマンドを&&で繋いで書きます。&& tmux refresh -S

  • 左側のステータスラインはtmuxのセッションとzshのモードを表示しています。その処理は.zshrcに書いてます。

動作環境

  • Arch Linux(4.18.4-arch1-1-ARCH)
  • tmux 2.7
  • True Colorをサポートしているターミナル。gnome-terminal, mlterm, ...
  • 特殊文字(三角形を90度傾けたやつなど)をサポートしているフォント。Hack, FiraCode, ...
  • pulseaudioがインストールされている。サウンドに関するパッケージ。大抵の場合は入っている。音量を表示するときに使用する。
  • iwがインストールされている。ネットワークに関するパッケージ。電波強度やSSIDを取得する。iwlist, iwconfig, iwgetidなどでも取得できるが非推奨になっている。
  • xselがインストールされている。Xのクリップボードと連携する際に使用する。

コマンド

set == set-option
setw == set-window-option
bind == bind-key -T prefix
prefix-keyを押さずにbindとした処理が走る。
bind -n == bind-key -T root

tmuxの設定

.tmux.conf
# prefix-keyの指定
set -g prefix C-q
# prefix-keyの解除
unbind-key C-b
# 設定ファイルをリロード
bind-key -T prefix r source-file ~/.tmux.conf \; display "再読み込み"
# True Colorを使用する
set -g default-terminal "screen-256color"
set -ga terminal-overrides ",xterm-256color:Tc"
# ESCの反応を早くする
set -g escape-time 1
# 添字を1から始める
set -g base-index 1
setw -g pane-base-index 1
# マウスを有効
setw -g mouse on
# ステータスラインの更新間隔を1秒にする
set -g status-interval 1
# ウィンドウを閉じた際に番号を詰める
set -g renumber-windows on
# prefix-keyの有効時間をミリ秒で指定
# bind-key -rで指定しているkeyはprefix-keyを再度押さなくとも連続で効く
set -g repeat-time 400

#キーバインド------------------------------------
#ペイン間の移動
bind-key -T prefix -r h select-pane -L
bind-key -T prefix -r j select-pane -D
bind-key -T prefix -r k select-pane -U
bind-key -T prefix -r l select-pane -R
bind-key -T root -r M-h select-pane -L
bind-key -T root -r M-j select-pane -D
bind-key -T root -r M-k select-pane -U
bind-key -T root -r M-l select-pane -R
#ウィンドウ間の移動
bind-key -T prefix -r u select-window -t :-
bind-key -T prefix -r i select-window -t :+
bind-key -T root -r M-u select-window -t :-
bind-key -T root -r M-i select-window -t :+
#新しいウィンドウ(current-directoryを引き継ぐ)
bind-key -T prefix c new-window -c "#{pane_current_path}"
#ペインの大きさを調整
bind-key -T prefix -r < resize-pane -L 5
bind-key -T prefix -r > resize-pane -R 5
bind-key -T prefix -r - resize-pane -D 5
bind-key -T prefix -r + resize-pane -U 5
#ペインを区切る(current-directoryを引き継ぐ)
bind-key -T prefix v split-window -h -c "#{pane_current_path}"
bind-key -T prefix s split-window -v -c "#{pane_current_path}"
#ペインの移動(右回り)
bind-key -T prefix -r N swap-pane -D
#ペインの移動(左回り)
bind-key -T prefix -r P swap-pane -U
#ウィンドウの削除
bind-key -T prefix X confirm-before -p "kill-window #I? (y/n)" kill-window
#ペインを指定したウィンドウに移動
bind-key -T prefix ! join-pane -t :1
bind-key -T prefix '"' join-pane -t :2
bind-key -T prefix '#' join-pane -t :3
bind-key -T prefix '$' join-pane -t :4
bind-key -T prefix % join-pane -t :5
bind-key -T prefix & join-pane -t :6
bind-key -T prefix "'" join-pane -t :7
bind-key -T prefix ( join-pane -t :8
bind-key -T prefix ) join-pane -t :9

#ステータスラインを設定------------------------------
set -g status on
set -g status-keys vi
#window-statusの位置を中央にする
set -g status-justify centre
setw -g window-status-format "#W.#I"
setw -g window-status-current-format "#W.#I"

# 左右のステータスラインの最大長を指定
set -g status-left-length 160
set -g status-right-length 160

# 右のステータスライン
# 画面の横幅で表示項目を変える。159以下で項目を減らす。tput colsで現在の画面幅がわかる。
set -g status-right "#{?#{==:1,#([[ $(echo #{client_width}) -ge 160 ]] && echo 1 || echo 0)},#(${HOME}/dotfiles/tmux/tmux_right_status.sh),#(${HOME}/dotfiles/tmux/tmux_right_status.sh short)}"

#色の設定----------------------------------------
# statusの色
set -g status-style fg=default,bg=default
# message表示時のstatus lineの色。dispaly,confirm-before -p などのコマンド出力の色
set -g message-style fg=blue,reverse,bg=default
# command-promptでviのノーマルモード時のstatus lineの色。
set -g message-command-style fg=default,bg=default
# コピーモードのときに、右上に出てくる表示の色
set -g mode-style fg=black,bg=blue

# paneを区切っている線の色
set -g pane-active-border-style fg=green,bg=default
set -g pane-border-style fg=default,bg=default

# setw -g window-status-current-format で指定した文字列の色
setw -g window-status-current-style fg=colour25,bold,bg=default
# setw -g window-status-format で指定した文字列の色
setw -g window-status-style fg=default,bg=default

# window自体の色。terminalの設定ファイルではなく、ここで色を設定する。
setw -g window-active-style fg='#C5C8C6',bg='#1D1F21'
setw -g window-style fg='#C5C8C6',bg='#121216'

#コピーモードの設定--------------------------------
#キーバインドをviにする
setw -g mode-keys vi
bind-key -T copy-mode-vi v send-keys -X begin-selection

# tmuxのbufferとxのclipboardを連携させる
if-shell 'type xsel' \
  "bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xsel -ib'"
if-shell 'type xsel' \
  "bind-key -T copy-mode-vi Y send-keys -X copy-pipe 'xsel -ib'"
if-shell 'type xsel' \
  "bind ] run-shell 'xsel -ob | xargs -0 tmux set-buffer && tmux paste-buffer'"

tmuxの右側のステータスライン用のスクリプト

tmux_right_status.sh
#!/usr/bin/bash

# 区切り文字
function sep() {
  [[ $# -lt 1 ]] && return 1
  format $1 ''
}

function value() {
  [[ $# -lt 2 ]] && return 1
  format $1 " $2 "
}

function format() {
  local black='#[fg=black,bg=blue]'
  local blue='#[fg=blue,bg=black]'
  local def='#[default]'

  [[ $# -lt 2 ]] && return 1

  [[ $1 == 'black' ]] \
    && echo "${black}$2${def}" && return 0
  [[ $1 == 'blue' ]] \
    && echo "${blue}$2${def}" && return 0
  echo "$1$2${def}"
}

# メモリ使用量
function memory() {
  local src=$(free -h | sed '/^Mem:/!d;s/  */ /g' | cut -d' ' -f3)
  echo "$(sep 'blue')$(value 'black' ${src})"
}

# ロードアベレージ
function load_average() {
  local src=$(uptime | sed -E 's/.*load average: ([0-9]\.[0-9][0-9]).*/\1/g')
  local cpus=$(grep 'processor' /proc/cpuinfo | wc -l)
  echo "$(sep 'black')$(value 'blue' ${src}/${cpus})"
}

# ネットワーク
function wlan() {
  type iw &> /dev/null \
    && [[ $(iw dev wlp4s0 link) != 'Not connected.' ]] \
    && local signal="-$(iw dev wlp4s0 link | grep signal | grep -o '[0-9]*')dBm"
  echo "$(sep 'blue')$(value 'black' ${signal:----})"
}

# 音量
function sound() {
  type pactl &> /dev/null \
    || { echo "$(sep 'black')$(value 'blue' '×')" && return 1 ;}

  [[ -n $(pactl list sinks | grep 'RUNNING') ]] \
    && local cmd="grep -A 10 'RUNNING'" \
    || local cmd='tee'
  local volume=$(
    pactl list sinks \
    | eval ${cmd} \
    | grep -o '[0-9]*%' \
    | head -1 \
    | sed 's/%//g')
  local blocks=$(seq -f '%02g' -s '' 1 5 ${volume} | sed 's/.\{2\}/■/g')
  # local spaces=$(seq -f '%02g' -s '' ${volume} 5 95 | sed 's/.\{2\}/ /g')
  local spaces=$(seq -s '_' ${volume} 5 100 | tr -d '[:digit:]')
  local mute=$(pactl list sinks | eval ${cmd} | grep 'Mute:' | cut -d' ' -f2)
  [[ ${mute} == 'no' ]] \
    && local color='blue' \
    || local color='#[fg=colour237,bg=black] '
  echo "$(sep 'black')$(value ${color} [${blocks}${spaces}])" \
    | sed 's/_/ /g'
}

# 時刻
function hours_minutes() {
  echo "$(sep 'blue')$(value 'black' $(date +%H:%M))"
}

# バッテリー残量
function battery() {
  function online() {
    if [[ $(cat /sys/class/power_supply/ADP1/online) == '1' ]];then
      local char=('◜' '◝' '◞' '◟')
      local i=$(expr $(date +%S) % 4)
      value 'blue' ${char[${i}]}
    else
      echo ''
    fi
  }

  [[ -e '/sys/class/power_supply/BAT1' ]] \
    || { echo "$(sep 'black')$(online)" && return ;}

  local charge=$(< /sys/class/power_supply/BAT1/capacity)
  if [[ ${charge} -gt 79 ]];then
    local color='#[fg=#08d137,bg=black]'
  elif [[ ${charge} -gt 20 ]];then
    local color='#[fg=#509de0,bg=black]'
  else
    local color='#[fg=#f73525,bg=black]'
  fi
  echo "$(sep 'black')$(online)$(value ${color} ${charge}%)"
}

if [[ $1 == 'short' ]];then
  echo "$(memory)$(load_average)"
else
  echo "$(memory)$(load_average)$(wlan)$(sound)$(hours_minutes)$(battery)"
fi

tmuxの左側のステータスライン用のスクリプト

.zshrc
function _tmux_status() {
  [[ -z ${TMUX} ]] && return
  typeset -r sep=''
  [[ ${KEYMAP} == 'vicmd' ]] \
  && typeset -r mode="#[fg=black,bg=green]#{?#{==:#{pane_current_command},zsh}, -- NORM -- #[default]#[fg=green]#[bg=blue]#{?client_prefix,#[bg=yellow],}${sep},}" \
  || typeset -r mode="#[fg=blue,bg=black]#{?#{==:#{pane_current_command},zsh}, -- INS -- #[default]#[fg=black]#[bg=blue]#{?client_prefix,#[bg=yellow],}${sep},}"

  tmux set -g status-left "${mode}#[fg=black,bg=blue]#{?client_prefix,#[bg=yellow],} S/#S #[default]#[fg=blue]#{?client_prefix,#[fg=yellow],}${sep}"
}
zle -N zle-line-init _tmux_status
zle -N zle-keymap-select _tmux_status