zsh 真正簡單設定 (無 iTern2, 無 oh-my-zsh)

  1. zsh 真正簡單設定 (無 iTern2, 無 oh-my-zsh)
    1. 起因
    2. 我原本的 bash 長這樣
    3. 不容易的原因,改很大的分享很好找。
      1. 顏色的設定
    4. 最後,我的 zsh 長這樣
    5. 設定 git branch[3]
    6. 靠右對齊
    7. 電源顯示
    8. 後記
      1. 附上我的完整版設定

zsh 真正簡單設定 (無 iTern2, 無 oh-my-zsh)

起因

因為 bash 不被新版的 Mac 當作預設的 shell 了。
要改 zsh 當作預設的 shell[1],所以要改變是未來的趨勢。

但是我又不想要改得花枝招展,想要一保 bash 的樸素。所以特別花時間找文件來看看要怎麼設定可以把 zsh 設定得和 bash 一樣。

我原本的 bash 長這樣

那個長得像 IP 的 31-154-12-102 我也想知道為什麼叫這名字,原本它應該是主機名稱,一個我訂的名字,不知道他怎麼變這樣了。QQ

它的組成

  • 31-154-12-102: 應該是主機名稱的名稱
  • ~/Desktop: 是以 HOME 起跳的完整路徑
  • chris: 使用者名稱

然後,顏色簡單配一下就好。

這就是我們的目標。

不容易的原因,改很大的分享很好找。

隨便找都一堆改 oh-my-zsh 或者要我裝 iTerm2 的文章。
就不想裝這麼多東西。

就堅持著這樣的信念,找到了一個系列文章 - Moving to zsh
作者一樣是 Mac 的使用者,也是一樣的原因出了這一系列的文章。建議有機會詳讀。

這一系列的其中一篇Moving to zsh, part 6 – Customizing the zsh Prompt 正是介紹外觀的客制化設定。而且確定沒有叫我安裝任何多餘的東西。 讚

在你的 .zshrc 文件中,新增

PROMPT='你的設定'
  • PROMPT: 代表 bashexport PATH
  • '你的設定': 設定的值必須要是字串格式

顏色的設定

查色碼

設定之前,先看一下這個顏色的色碼,等一下的設定要從這裡查 Xterm Number 欄位

設定顏色

%F{2}%m%f
  • %F{色碼}: 用來設定某個顏色的開始
  • %f: 用來設定成預設的樣式,也可以說是設定好的顏色結束。
  • %m: 主機名稱,在此只是示範夾在顏色中間的東西

特殊符號[2]

  • %m: 主機名稱
  • %~: 以 HOME 為起點的完整路徑表示
  • %n: 使用者名稱

我自己設定好,長這樣

PROMPT='%F{2}%m%f:%F{30}%~%f %F{184}%n%f $'

最後,我的 zsh 長這樣

除了上面的設定,我還想斷行怎辦?
出乎意料的簡單,只要在設定文章上斷行,就可以了,不用任何特殊符號

設定 git branch[3]

直接看結果和註解

1
2
3
4
5
6
7
8
9
# Load version control information
autoload -Uz vcs_info
precmd() { vcs_info }

# Format the vcs_info_msg_0_ variable
zstyle ':vcs_info:git:*' formats '%F{1}(%b)%f'

# Set up the prompt (with git branch name)
setopt PROMPT_SUBST

再把

PROMPT='%F{2}%m%f:%F{30}%~%f
%F{184}%n%f $ '

加上 ${vcs_info_msg_0_}

PROMPT='%F{2}%m%f:%F{30}%~%f ${vcs_info_msg_0_}
%F{184}%n%f $ '

靠右對齊

靠右有兩種方式

  1. 使用 RPROMPT 可以直接在你的 shell 提示結束那一行顯示在右邊 (就是游標停下來的右邊)
  2. 自己算,如果像我想要兩行的提示,那麼第一行的右邊就是要自己計算空白有幾個,再印出文字

在此分享一個第 2 個的函式做法(寫得很好讀)[4]

PROMPT="$(fill-line "$top_left" "$top_right")"$'\n'$bottom_left
RPROMPT=$bottom_right

會顯示

~/code/foo                    master
% █ 11:51

可以發現它有一個 fill-line 函數

1
2
3
4
5
6
7
8
9
10
11
12
13
function fill-line() {
emulate -L zsh
local left_len=$(prompt-length $1)
local right_len=$(prompt-length $2 9999)
local pad_len=$((COLUMNS - left_len - right_len - ${ZLE_RPROMPT_INDENT:-1}))
if (( pad_len < 1 )); then
# Not enough space for the right part. Drop it.
echo -E - ${1}
else
local pad=${(pl.$pad_len.. .)} # pad_len spaces
echo -E - ${1}${pad}${2}
fi
}

而這之中又引用了一個 prompt-length 函數

function prompt-length() {
emulate -L zsh
local COLUMNS=${2:-$COLUMNS}
local -i x y=$#1 m
if (( y )); then
while (( ${${(%):-$1%$y(l.1.0)}[-1]} )); do
x=y
(( y *= 2 ));
done
local xy
while (( y > x + 1 )); do
m=$(( x + (y - x) / 2 ))
typeset ${${(%):-$1%$m(l.x.y)}[-1]}=$m
done
fi
echo $x
}

兩個都貼上去,就可以直接使用 fill-line 囉,函數的參數由空白分開

最後,我的 terminal 變成這樣

RPROMPT='${vcs_info_msg_0_}'
PROMPT='$(fill-line %F{2}%m%f:%F{30}%~%f %*)
%F{184}%n%f $ '

電源顯示

再附上電源的指示,最後的版本長這樣。

後記

記錄一些選擇性的設定,或其實寫得很完整,但這次沒用上的文章

附上我的完整版設定

# Add RVM to PATH for scripting. Make sure this is the last PATH variable change.
export PATH="$PATH:$HOME/.rvm/bin"

## for nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm

## autocomplete
# autoload -Uz compinit && compinit

## 選單補全,用 tab 移動選擇
zstyle ':completion:*' menu select

# setopt completealiases

# Load version control information
autoload -Uz vcs_info
precmd() { vcs_info }

# Format the vcs_info_msg_0_ variable
zstyle ':vcs_info:git:*' formats ' %F{1}%b%f'

# Set up the prompt (with git branch name)
setopt PROMPT_SUBST

# 靠右上的提示
# 因為要自己計算剩下的長度還可以怎麼用才可以對齊右邊
function prompt-length() {
emulate -L zsh
local COLUMNS=${2:-$COLUMNS}
local -i x y=$#1 m
if (( y )); then
while (( ${${(%):-$1%$y(l.1.0)}[-1]} )); do
x=y
(( y *= 2 ));
done
local xy
while (( y > x + 1 )); do
m=$(( x + (y - x) / 2 ))
typeset ${${(%):-$1%$m(l.x.y)}[-1]}=$m
done
fi
echo $x
}
# 所以滿一行中間要空白
function fill-line() {
emulate -L zsh
local left_len=$(prompt-length $1)
local right_len=$(prompt-length $2 9999)
local pad_len=$((COLUMNS - left_len - right_len - ${ZLE_RPROMPT_INDENT:-1}))
if (( pad_len < 1 )); then
# Not enough space for the right part. Drop it.
echo -E - ${1}
else
local pad=${(pl.$pad_len.. .)} # pad_len spaces
echo -E - ${1}${pad}${2}
fi
}

# Docker
fpath=(~/.zsh/completion $fpath)
autoload -Uz compinit && compinit -i
# exec $SHELL -l


## battery
function battery_pct() {
local smart_battery_status="$(ioreg -rc "AppleSmartBattery")"
typeset -F maxcapacity=$(echo $smart_battery_status | grep '^.*"MaxCapacity"\ =\ ' | sed -e 's/^.*"MaxCapacity"\ =\ //')
typeset -F currentcapacity=$(echo $smart_battery_status | grep '^.*"CurrentCapacity"\ =\ ' | sed -e 's/^.*CurrentCapacity"\ =\ //')
integer i=$(((currentcapacity/maxcapacity) * 100))
echo $i
}

function plugged_in() {
[ $(ioreg -rc AppleSmartBattery | grep -c '^.*"ExternalConnected"\ =\ Yes') -eq 1 ]
}

function battery_pct_remaining() {
if plugged_in ; then
echo "External Power"
else
battery_pct
fi
}

function battery_pct_prompt () {
if [[ $(ioreg -rc AppleSmartBattery | grep -c '^.*"ExternalConnected"\ =\ No') -eq 1 ]] ; then
b=$(battery_pct_remaining)
if [ $b -gt 50 ] ; then
color='green'
elif [ $b -gt 20 ] ; then
color='yellow'
else
color='red'
fi
echo "⚡%F{$color}$(battery_pct_remaining)%% %f"
else
echo "⚡%F{green}∞ %f"
fi
}

# output
RPROMPT='${vcs_info_msg_0_}'
PROMPT='$(fill-line %F{2}%m%f:%F{30}%~%f %*$(battery_pct_prompt))
%F{184}%n%f $ '

  1. 在 Mac 上使用 zsh 做為預設 shell ↩︎

  2. zsh: 13 Prompt Expansion, 13.2.5 Visual effects ↩︎

  3. Add Git branch information to your ZSH prompt ↩︎

  4. zsh在ps1中右對齊 ↩︎