19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-01-27

概要

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

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

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

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

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

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

動作環境

  • Arch Linux(4.19.8-arch1-1-ARCH)
  • tmux 2.8
  • True Colorをサポートしているターミナル。 alacritty, termite, gnome-terminal, mlterm, ...
  • 特殊文字(三角形を90度傾けたやつなど)をサポートしているフォント。Hack, FiraCode, ...
  • pulseaudioがインストールされていること。サウンドに関するパッケージ。大抵の場合は入っています。音量を表示するときに使用します。
  • 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-g
# prefix-keyの解除
unbind-key C-b
# 設定ファイルをリロード
bind-key -T prefix r source-file ~/.tmux.conf \; display-message 'Reload'
# 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
# display-message
set -g display-time 1500
# focus events
set -g focus-events on

# ----------------------------------------
# Key bindings
# ----------------------------------------
# コマンドプロンプト
bind -n M-: command-prompt -p '>>>'
#ペイン間の移動
bind -n M-h select-pane -L
bind -n M-j select-pane -D
bind -n M-k select-pane -U
bind -n M-l select-pane -R
#新しいウィンドウ(current-directoryを引き継ぐ)
bind -n M-w new-window -c '#{pane_current_path}'
#ウィンドウ間の移動
bind -n M-u select-window -t :-
bind -n M-i select-window -t :+
bind -n M-1 select-window -t 1
bind -n M-2 select-window -t 2
bind -n M-3 select-window -t 3
bind -n M-4 select-window -t 4
bind -n M-5 select-window -t 5
bind -n M-6 select-window -t 6
bind -n M-7 select-window -t 7
bind -n M-8 select-window -t 8
bind -n M-9 select-window -t 9
# new-session
bind -n M-s  command-prompt -p \
  'new-session :' "new-session -s %% -c '#{pane_current_path}'"
# switch-client
bind c display-message 'switch-session' \; run-shell \
  'tmux choose-tree -s -f "##{!=:##{session_name},#{session_name}}"'
# kill-session
bind x display-message 'kill-session' \; run-shell \
  'tmux choose-tree -s -f "##{!=:##{session_name},#{session_name}}" \
    "kill-session -t %%"'
#ペインの大きさを調整
bind -r < resize-pane -L 5
bind -r > resize-pane -R 5
bind -r - resize-pane -D 5
bind -r + resize-pane -U 5
#ペインを区切る(current-directoryを引き継ぐ)
bind v split-window -h -c "#{pane_current_path}"
bind s split-window -v -c "#{pane_current_path}"
#ペインの移動(右回り)
bind -r N swap-pane -D
#ペインの移動(左回り)
bind -r P swap-pane -U
#ウィンドウの削除
bind X confirm-before -p 'kill-window #I? (y/n)' kill-window
#ペインを指定したウィンドウに移動
bind j command-prompt -1 'join-pane -ht :%%'

# ----------------------------------------
# Aliases
# ----------------------------------------
set -s command-alias[0] exit='kill-server'
set -s command-alias[1] only='kill-session -a'
set -s command-alias[2] d='detach-client'

# ----------------------------------------
# Status
# ----------------------------------------
set -g status on
set -g status-keys vi
#window-statusの位置を中央にする
set -g status-justify centre
setw -g window-status-format ' #I.#W:#{b:pane_current_path} '
setw -g window-status-current-format ' #I.<-> '

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

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

# ----------------------------------------
# Color
# ----------------------------------------
# statusの色
set -g status-style fg=default,bg=default
# message表示時のstatus lineの色。dispaly,confirm-before -p などのコマンド出力の色
set -g message-style fg=green,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='#8fa1b3',bold,bg=default
# setw -g window-status-format で指定した文字列の色
setw -g window-status-style fg='#535b66',bold,bg=default

# window自体の色。terminalの設定ファイルではなく、ここで色を設定する。
setw -g window-active-style fg='#c0c5ce',bg='#2b303b'
setw -g window-style fg='#c0c5ce',bg='#27292d'

# ----------------------------------------
# Copy Mode
# ----------------------------------------
#キーバインドを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 -I{} tmux set-buffer -- {} && tmux paste-buffer'"

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

tmux_right_status.sh
#!/usr/bin/env bash

set -euCo pipefail

function separator() {
  [[ $# -lt 1 ]] && return 1
  output --color-name $1 --string ''
}

function output() {
  [[ $# -lt 2 ]] && return 1

  local -rA colors=(
    ['black']='#[fg=black,bg=blue]'
    ['blue']='#[fg=blue,bg=black]'
    ['default']='#[default]'
  )

  for option in $@; do
    case ${option} in
      '-n'|'--color-name' )
        [[ -z $2 || $2 =~ ^-+ ]] && return 1
        local color=${colors[$2]}
        shift 2
      ;;
      '-c'|'--color-code' )
        [[ -z $2 || $2 =~ ^-+ ]] && return 1
        local color=$2
        shift 2
      ;;
      '-s'|'--string' )
        # -30dBm
        [[ -z $2 ]] && return 1
        local string=$2
        shift 2
      ;;
    esac
  done

  echo "${color} ${string}${colors['default']}"
}

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

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

# 電波強度
function network_level() {
  local -r interface='wlp4s0'

  [[ -n $(ip link show up dev ${interface}) ]] \
    && local -r signal=$(cat /proc/net/wireless \
      | tail -1 | tr -s ' ' | cut -d' ' -f4 | sed 's/\./dBm/') \
    || local -r signal='---'

  echo "$(separator 'blue')$(output -n 'black' -s ${signal})"
}

# 音量
function sound() {
  function get_volume() {
    local volume
    volume="$(pactl list sinks \
      | grep 'Volume' | grep -o '[0-9]*%' | head -1 | tr -d '%')"
    [[ ${volume} -gt 100 ]] && echo 100 || echo "${volume}"
  }

  function get_muted() {
    pactl list sinks \
      | grep 'Mute' | sed 's/[[:space:]]//g' | cut -d: -f2 | head -1
  }

  function to_blocks() {
    seq -f '%02g' -s '' 1 5 $1 | sed 's/.\{2\}/■/g'
  }

  function to_spaces() {
    seq -s '_' $1 5 100 | tr -d '[:digit:]'
  }

  function to_meters() {
    echo "[$(to_blocks $1)$(to_spaces $1)]"
  }

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

  local -rA colors=(
    ['yes']='#[fg=colour237,bg=black]'
    ['no']='blue'
  )
  local -rA options=(
    ['yes']='--color-code'
    ['no']='--color-name'
  )
  local muted
  muted=$(get_muted)

  echo "$(separator 'black')$(output \
      ${options[${muted}]} ${colors[${muted}]} \
      -s $(to_meters $(get_volume)))" \
      | sed 's/_/ /g'
}

# 時刻
function hours_minutes() {
  echo "$(separator 'blue')$(output -n 'black' -s $(date +%H:%M))"
}

# バッテリー残量
function battery() {
  function online() {
    [[ $(cat /sys/class/power_supply/ADP1/online) != '1' ]] \
      && return
    local -ar icons=('' '' '' '' '')
    local index
    index=$(expr $(date +%S) % ${#icons[@]})
    output -n 'blue' -s ${icons[${index}]}
  }

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

  local charge
  charge=$(< /sys/class/power_supply/BAT1/capacity)

  if [[ ${charge} -gt 79 ]];then
    local -r color='#[fg=#08d137,bg=black]'
  elif [[ ${charge} -gt 20 ]];then
    local -r color='#[fg=#509de0,bg=black]'
  else
    local -r color='#[fg=#f73525,bg=black]'
  fi

  echo "$(separator 'black')$(online) $(output -c ${color} -s ${charge}%)"
}

function main() {
  if [[ $1 == 'short' ]];then
    echo -n "$(memory)$(load_average)"
  else
    echo -n "$(memory)$(load_average)$(network_level)$(sound)$(hours_minutes)$(battery)"
  fi
  echo '  '
}

main ${1:-long}

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

.zshrc
function __tmux_status__() {
  # tmuxのSession番号を表示。commandがzshのときにはmodeも表示。

  [[ -z ${TMUX} ]] && return 1
  local -r separator=''
  [[ ${KEYMAP} == 'vicmd' ]] \
    && local -r \
      mode="#[fg=black,bg=green]#{?#{==:#{pane_current_command},zsh}, -- NORM -- #[default]#[fg=green]#[bg=blue]#{?client_prefix,#[bg=yellow],}${separator},}" \
    || local -r \
      mode="#[fg=blue,bg=black]#{?#{==:#{pane_current_command},zsh}, -- INS -- #[default]#[fg=black]#[bg=blue]#{?client_prefix,#[bg=yellow],}${separator},}"

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?