【気合い】Starshipを使わずにzshプロンプトをカスタマイズする
はじめまして。一般の大学生です。
最近やたらzshのプロンプトに懲りだして、苦節数日、starshipを使わないでそれっぽいやつを作る事に成功したので備忘録として残します。
参考にさせていただいたのは以下の通りです。
https://qiita.com/guri3/items/dd6dc6168fc4c984c4ae
https://dev.macha795.com/zsh-prompt-customize/
https://tomiylab.com/2020/03/prompt/
Starship使えよ
なんか上手く使えなかったんですよね。早々に断念しました。今から思えば絶対Starship頑張ったほうがよかったと思います。
本編
じゃあやっていきます。
環境
macOS 14.2.1(23C71)
M1 Max 32GB
zsh 5.9 (x86_64-apple-darwin23.0)
/bin/zsh
OrbstackのLinux
zsh 5.9 (x86_64-pc-linux-gnu)
/home/linuxbrew/.linuxbrew/bin/zsh
Requirements?
なにかしらNerd Font(本記事ではJetBrain Mono Nerd Fontを使用しています)
iTerm2 (ほかのターミナルエミュレータでは検証していません。)
homebrew
>> zsh-git-prompt
zsh-git-promptは使います。
.zshrc
#brew
if [ "$(uname -s)" = "Darwin" ]; then
if [ "$(uname -m)" = "arm64" ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
export PATH="/opt/homebrew/bin:$PATH"
elif [ "$(uname -m)" = "x86_64" ]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
# zsh-git-prompt
source /opt/homebrew/opt/zsh-git-prompt/zshrc.sh
elif [ "$(uname -s)" = "Linux" ]; then
eval "$(/home/linuxbrew/.linuxbrew/Homebrew/bin/brew shellenv)"
# zsh-git-prompt
source $(brew --prefix)/opt/zsh-git-prompt/zshrc.sh
fi
# Prompt editing
function orb_boat {
# コマンド呼びだし
time=$(date +" %H:%M:%S")
username=$(whoami)
# 形を変える
sharp="\uE0B0 \e[0m"
# OS とアーキテクチャを決定する
os_arch_prompt=""
if [ "$(uname -s)" = "Darwin" ]; then
os_arch_prompt="macOS[$(uname -m)]"
else
os_arch_prompt="$(uname -s)@$(uname -n)"
fi
# Check if inside a Git work tree
if [ "$(git rev-parse --is-inside-work-tree 2> /dev/null)" = true ]; then
# Display Git information in the prompt
echo "$bg[blue]$fg[cyan]${sharp}$bg[blue]${os_arch_prompt}$bg[green]$fg[blue]${sharp}$bg[green]${username}$bg[yellow]$fg[green]${sharp}$bg[yellow]$(git_super_status)${reset_color}"
else
# Prompt when not inside a Git work tree
echo "$bg[blue]$fg[cyan]${sharp}$bg[blue]${os_arch_prompt}$bg[green]$fg[blue]${sharp}$bg[green]${username}${reset_color}$fg[green]${sharp}${reset_color}"
fi
}
# add newline
function add_line {
if [[ -z $PS1_NEWLINE_LOGIN ]]; then
PS1_NEWLINE_LOGIN=true
else
printf '\n'
fi
}
precmd() {
add_line
PROMPT="$bg[cyan] %*$(orb_boat)
%F{cyan}%B╭@%b%f%F{green}%d%f
%F{cyan}%B╰─→%b %f"
}
# others
## colors
autoload -Uz colors
colors
内容
homebrewのパス関係
if [ "$(uname -s)" = "Darwin" ]; then
if [ "$(uname -m)" = "arm64" ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
export PATH="/opt/homebrew/bin:$PATH"
elif [ "$(uname -m)" = "x86_64" ]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
# zsh-git-prompt
source /opt/homebrew/opt/zsh-git-prompt/zshrc.sh
elif [ "$(uname -s)" = "Linux" ]; then
eval "$(/home/linuxbrew/.linuxbrew/Homebrew/bin/brew shellenv)"
# zsh-git-prompt
source $(brew --prefix)/opt/zsh-git-prompt/zshrc.sh
fi
armになってhomebrewのインストール場所が変わったので、それに合わせて読み込む場所も変わっています。
これはつまり、それぞれに必要なものをインストールする必要があるという事なのですが……試したらzsh-git-promptは問題なく動いたのでOSで共通の場所(arm版)のほうを読み込むようにしていますが、brew --prefix
でインストール場所の一番上が出てくるので、$(brew --prefix)/opt/zsh-git-prompt/zshrc.sh
でそれぞれのところにパスが通ります。
Prompt
ネーミングセンスはおいておくとしてfunction orb_boat
の中身についてです
username=$(whoami)
echoで呼び出すだけなのでべつに設定しなくても良いと思います。
sharp="\uE0B0 \e[0m"
\uE0B0
は
これです。 これのためだけにNerd Fontを使うといっても過言ではありません。
\e[0m
は{reset_color}と同じ働きです。後述の仕組み上、ここに置くほうが可読性が高いと思います。
os_arch_prompt=""
if [ "$(uname -s)" = "Darwin" ]; then
os_arch_prompt="macOS[$(uname -m)]"
else
os_arch_prompt="$(uname -s)@$(uname -n)"
fi
uname
でOSとアーキテクチャを調べます。macの場合はOSとアーキテクチャを返しますが、それ以外の場合はOSとマシン名を返します。
現状、Homebrew(Linuxbrew)がLinux on armに対応しておらず、zsh-git-promptを動かす大前提が成り立たないためです。homebrewのない生活なんて禁酒みたいなもんですからね。
# Check if inside a Git work tree
if [ "$(git rev-parse --is-inside-work-tree 2> /dev/null)" = true ]; then
# Display Git information in the prompt
echo "$bg[blue]$fg[cyan]${sharp}$bg[blue]${os_arch_prompt}$bg[green]$fg[blue]${sharp}$bg[green]${username}$bg[yellow]$fg[green]${sharp}$bg[yellow]$(git_super_status)${reset_color}"
else
# Prompt when not inside a Git work tree
echo "$bg[blue]$fg[cyan]${sharp}$bg[blue]${os_arch_prompt}$bg[green]$fg[blue]${sharp}$bg[green]${username}${reset_color}$fg[green]${sharp}${reset_color}"
fi
これはもうちょと良い書き方がある気がします。Starship使うとか。
仕組みとしては、背景色付きで出力した後、次のブロックの色を背景色にしたうえで直前のブロックの背景色を前景色にして、をだして、その後に色をリセットする。というものです。
gitが動いてますかでプロンプトの末尾を変えているので似たようなコードが続いてます。
$bg[]
で呼びだした色はどうやら背景の透明度に影響を受けるらしい(?)のでウィンドウの不透明度は100%ですね。
# add newline
function add_line {
if [[ -z $PS1_NEWLINE_LOGIN ]]; then
PS1_NEWLINE_LOGIN=true
else
printf '\n'
fi
}
色んな方が書いているのでいるんだろうな、と思ってます。
PROMPT="
hogehoge
huga"
とかでもいい気はするんですけどね。
precmd() {
add_line
PROMPT="$bg[cyan] %*$(orb_boat)
%F{cyan}%B╭@%b%f%F{green}%d%f
%F{cyan}%B╰─→%b %f"
}
毎回実行します。
# others
## colors
autoload -Uz colors
colors
いるのかな。
zshrc.sh
zsh-git-promptの設定です。
$(brew --prefix)/opt/zsh-git-prompt/zshrc.sh
にあります。
このパスはカレントバージョンへのシンボリックリンクになってますから、直接編集するよりも別なところでやったほうがよさそうですね。バージョンアップでなくなったりするリスクがあるかも、知らんけど。
git_super_status() {
precmd_update_git_vars
if [ -n "$__CURRENT_GIT_STATUS" ]; then
STATUS="$ZSH_THEME_GIT_PROMPT_PREFIX$ZSH_THEME_GIT_PROMPT_BRANCH $GIT_BRANCH ${reset_color}"
if [ "$GIT_BEHIND" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_BEHIND$GIT_BEHIND ${reset_color}"
fi
if [ "$GIT_AHEAD" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_AHEAD$GIT_AHEAD ${reset_color}"
fi
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_SEPARATOR"
if [ "$GIT_STAGED" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STAGED$GIT_STAGED ${reset_color}"
fi
if [ "$GIT_CONFLICTS" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CONFLICTS$GIT_CONFLICTS${reset_color}"
fi
if [ "$GIT_CHANGED" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED ${reset_color}"
fi
if [ "$GIT_UNTRACKED" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED ${reset_color}"
fi
if [ "$GIT_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN"
fi
STATUS="$STATUS${reset_color}$ZSH_THEME_GIT_PROMPT_SUFFIX"
echo "$STATUS"
fi
}
# Default values for the appearance of the prompt. Configure at will.
sharp="\uE0B0\e[0m"
ZSH_THEME_GIT_PROMPT_PREFIX=" "
ZSH_THEME_GIT_PROMPT_SUFFIX=""
ZSH_THEME_GIT_PROMPT_SEPARATOR=""
ZSH_THEME_GIT_PROMPT_BRANCH="$bg[magenta]"
ZSH_THEME_GIT_PROMPT_STAGED="$bg[yellow] ●"
ZSH_THEME_GIT_PROMPT_CONFLICTS="$bg[red] ✖"
ZSH_THEME_GIT_PROMPT_CHANGED="$bg[blue] ✚"
ZSH_THEME_GIT_PROMPT_BEHIND="$bg[yellow] ↓"
ZSH_THEME_GIT_PROMPT_AHEAD="$bg[cyan] ↑"
ZSH_THEME_GIT_PROMPT_UNTRACKED="$bg[magenta] ?"
ZSH_THEME_GIT_PROMPT_CLEAN="$bg[green] ✔ ${reset_color}$fg[green]${sharp}"
git_super_status()
以降を編集しています。変えていいよ!って言われているのは一番下だけですが……。
だいたいは元と同じです。空白の幅変えてみたりしてるくらい。
echo
で呼びだしてるので%{
は必要ありません。出てきちゃうので消します。
CLEANのときだけを出して視覚的にCLEANを分かりやすくしようとしています。
✔
は半角みたいなツラしてますけど全然全角のスペースで出力されるんで後ろの空白が必要になります。
結論
echoでやる部分がアレなせいでちょっと重いですけど満足行くものが出来たと思います。
ありがとうございました。
Discussion