概要
-
ステータスラインの表示をシェルスクリプトで行ってます。メモリ消費量、ロードアベレージ、信号強度、音量、電池残量と時間を表示しています。
-
ステータスラインがウィンドウを狭めると完全に消えるのが悲しいので、画面幅によって表示を変えています。画面幅は
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__