📺

macOSのzshではこれだけはやっておこう

commits12 min read

Homebrew を使います

まだ Homebrew をインストールしていない場合はこちら:

zsh
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

1. パスの設定

M1 Mac (Apple Silicon) の場合は、Homebrew 向けにパスを通しておく必要があります。

https://zenn.dev/unreact_wada/articles/e83098af190091
zsh
# デフォルトのパスを確認
zenn@mba ~ % echo $path
/usr/local/bin /usr/bin /bin /usr/sbin /sbin /Library/Apple/usr/bin /Library/Frameworks/Mono.framework/Versions/Current/Commands

Intel Mac であればこのままでも差し支えありませんが、Apple Silicon Mac では Homebrew のインストール先が /opt/homebrew 以下となるので、ここへパスを通しておきます。
ホームディレクトリ (/Users/ユーザー名) に .zshrc を作成します。

~/.zshrc
typeset -U path PATH
path=(
  /opt/homebrew/bin(N-/)
  /opt/homebrew/sbin(N-/)
  /usr/bin
  /usr/sbin
  /bin
  /sbin
  /usr/local/bin(N-/)
  /usr/local/sbin(N-/)
  /Library/Apple/usr/bin
)

優先してほしい順にパスを指定していきます。

Intel Mac では、/usr/local/bin/usr/local/sbin を優先させてください。

(N-/) は、もしそのディレクトリが存在していれば PATH に追加し、そうでなければ無視してくれるオプションです。
上のパス設定を反映させるには ~/.zshrc を読み込みます。

zsh
zenn@mba ~ % source ~/.zshrc

2. zsh-completions のインストール

コマンド入力にバシバシ補完を効かせてくれる zsh-completions をインストールします。

zsh
zenn@mba ~ % brew install zsh-completions

~ 略 ~
=> Caveats
To activate these completions, add the following to your .zshrc:

  if type brew &>/dev/null; then
    FPATH=$(brew --prefix)/share/zsh-completions:$FPATH

    autoload -Uz compinit
    compinit
  fi

You may also need to force rebuild `zcompdump`:

  rm -f ~/.zcompdump; compinit

Additionally, if you receive "zsh compinit: insecure directories" warnings when attempting
to load these completions, you may need to run this:

  chmod -R go-w '/opt/homebrew/share/zsh'
~ 略 ~

インストール時の Caveats には、/opt/homebrew/share/zsh (Intel Mac の場合は /usr/local/share/zsh) のみを go-w せよと表示されていますが、実際には share ディレクトリそのものを chmod -R go-w する必要があります。

zsh
zenn@mba ~ % chmod -R go-w /opt/homebrew/share

あとは Caveats の指示にしたがって、~/.zshrc への追記と補完キャッシュファイルの再生成をおこないます。

~/.zshrc
if type brew &>/dev/null; then
  FPATH=$(brew --prefix)/share/zsh-completions:$FPATH
  autoload -Uz compinit && compinit
fi
zsh
zenn@mba ~ $ source ~/.zshrc
zenn@mba ~ $ rm -f ~/.zcompdump; compinit

これでコマンド入力中に Tab キーまたは Ctrl+I を打鍵するとその後の候補を補完表示してくれます。

_ はカーソル位置を表しています。

zsh
% sysctl _  # <-- ここで Tab または \C-I を入力

% sysctl _
audit     hw        kperf     machdep   security  vfs
debug     kern      ktrace    net       user      vm

% sysctl hw._ # <-- ここでふたたび Tab

% sysctl hw._
activecpu               cpufrequency            l3cachesize
busfrequency            cpufrequency_max        logicalcpu
busfrequency_max        cpufrequency_min        logicalcpu_max
busfrequency_min        cpusubfamily            memsize

3. プロンプトの表示を変更

プロンプトのデフォルト値を確認します。

zsh
zenn@mba ~ $ echo $PROMPT
%n@%h %1~ %#

これらは以下のことを意味しています。

  • %n: ユーザー名
  • %h: ホスト名
  • %~: カレントディレクトリ(1 はディレクトリ深度)
  • %#: 一般ユーザーのときは %root になったときは # を表示

カレントディレクトリの表示形式にはいくつかのバリエーションがあります。

PROMPT 機能 実際の表示
%d フルパス /Users/zenn/Downloads/myapp:% _
%~ フルパス 2 ~/Downloads/myapp:% _
%c 相対パス myapp:% _
%2c ディレクトリ深度 2 Downloads/myapp:% _

ここでは次のように設定しました。

~/.zshrc
PROMPT="%n ($(arch)):%~"$'\n'"%# "
  • $(): カッコ内のコマンド結果を表示します
  • "$'\n'": プロンプトが長くなってしまったので途中に改行を挿入します
zsh
% source ~/.zshrc

zenn (arm64):~/Downloads/myapp
% _

https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html

4. コマンド実行結果のあとに空行を挿入する

コマンドの実行結果が表示されたあと、すぐにプロンプトが表示されるのはやや窮屈です。

zsh
zenn (arm64):~/Downloads
% ls -a
.		..		.DS_Store	.localized	myapp
zenn (arm64):~/Downloads
% _

zsh には、bash における PROMPT_COMMAND と同等のフック関数 precmd() が用意されています。
~/.zshrc へ以下を追記します。

~/.zshrc
add_newline() {
  if [[ -z $PS1_NEWLINE_LOGIN ]]; then
    PS1_NEWLINE_LOGIN=true
  else
    printf '\n'
  fi
}
precmd() { add_newline }

コマンド実行後に空行が挿入されるようになりました。

zsh
zenn (arm64):~/Downloads
% source ~/.zshrc

zenn (arm64):~/Downloads
% _

5. プロンプトへ色を付ける

zsh では簡単にプロンプトへ色をつけることができます。

まず、~/.zshrc の冒頭で色を扱うモジュールを有効化し、

~/.zshrc
autoload -Uz colors && colors

プロンプト内の文字列に色を指定します。

構文
%F{色の名前または色番号}hoge%f

%F ~ %f に挟まれた文字列 (hoge) に指定した色が付きます。

色の名前: black, red, green, yellow, blue, magenta, cyan, white

PROMPT="%F{green}%n%f %F{cyan}($(arch))%f:%F{blue}%~%f"$'\n'"%# "

色番号を調べるには以下のスクリプトを実行してみてください。

palette.sh(クリックで展開トグル)
palette.sh
#!/bin/sh
#
# 256色のカラーパレットを表示する
#  bash と zsh にて実行可能
#

target_shell=$1

if [ -z "$1" ]; then
    target_shell=$(basename "$SHELL")
fi

if [ "$target_shell" = "bash" ]; then
    bash <<< 'for code in {0..255}; do echo -n "[38;05;${code}m $(printf %03d $code)"; [ $((${code} % 16)) -eq 15 ] && echo; done'
elif [ "$target_shell" = "zsh" ]; then
    zsh  <<< 'for code in {000..255}; do print -nP -- "%F{$code}$code %f"; [ $((${code} % 16)) -eq 15 ] && echo; done'
else
    echo "error: Invalid argument ($target)"
    echo "Usage: $0 [bash|zsh]"
fi

https://yonchu.hatenablog.com/entry/2012/10/20/044603

6. プロンプトへ Git レポジトリの状態を表示する

まず、zsh-git-prompt をインストールします。

zsh
% brew install zsh-git-prompt

~ 略 ~
==> Caveats
Make sure zsh-git-prompt is loaded from your .zshrc:
  source "/opt/homebrew/opt/zsh-git-prompt/zshrc.sh"
~ 略 ~

Caveats の指示に従い、~/.zshrc の中でスクリプトを読み込み、

~/.zshrc
source $(brew --prefix)/opt/zsh-git-prompt/zshrc.sh

プロンプトの中で git_super_status 変数を展開するだけです。

~/.zshrc
PROMPT='%F{034}%n%f %F{036}($(arch))%f:%F{020}%~%f $(git_super_status)'
PROMPT+=""$'\n'"%# "

$(git_super_status)'' (シングルクオート) で囲まないと機能しません。
逆に "$'\n'"ダブルクオートが必要です。

zsh
zenn (arm64):~
% source ~/.zshrc

zenn (arm64):~ (:|)
% cd ~/Downloads/zenn

~/Downloads/zenn: (main|●1)
% _

Git レポジトリ以外では $(git_super_status) を表示させたくない場合

precmd() フックへ、そのディレクトリが Git レポジトリかどうか判定する関数を追加します。

~/.zshrc
git_prompt() {
  if [ "$(git rev-parse --is-inside-work-tree 2> /dev/null)" = true ]; then
    PROMPT='%F{034}%n%f %F{036}($(arch))%f:%F{020}%~%f $(git_super_status)'
    PROMPT+=""$'\n'"%# "
  else
    PROMPT="%F{034}%n%f %F{036}($(arch))%f:%F{020}%~%f "$'\n'"%# "
  fi
}

precmd() {
  git_prompt
  add_newline
}

ただし、この手法ではコマンド実行ごとに関数が実行されてしまうため、それなりにコストがかかります。

7. あたらしくインストールされたコマンドを即認識させる

デフォルト状態の zsh では、あたらしくインストールされたコマンドをただちに認識してはくれません。

zsh
~% brew install yarn

~% yarn --version
zsh: command not found: yarn

~/.zshrc の冒頭へ以下の行を追記しましょう。

~/.zshrc
zstyle ":completion:*:commands" rehash 1

8. tarball へ macOS の特殊ファイルを含めないようにする

macOS で作成した tar.gz を Windows などの他の OS で解凍すると、.DS_Store ファイルや ._ (ドットアンダーバー) ファイルなどの特殊ファイルが tarball に含まれてしまっていることがよくあります。
これを防ぐためのエイリアス関数を用意しましょう。

~/.zshrc
tgz() {
  env COPYFILE_DISABLE=1 tar zcvf $1 --exclude=".DS_Store" ${@:2}
}

使い方:

zsh
~% tgz dotfiles.tgz .zshrc .gitconfig .ssh/

a .zshrc
a .gitconfig
a .ssh
a .ssh/id_ed25519
a .ssh/id_ed25519.pub
a .ssh/config
a .ssh/known_hosts

~% ls
dotfiles.tgz

ここまでの ~/.zshrc 全文

~/.zshrc
autoload -Uz colors && colors
zstyle ":completion:*:commands" rehash 1

typeset -U path PATH
path=(
  /opt/homebrew/bin(N-/)
  /opt/homebrew/sbin(N-/)
  /usr/bin
  /usr/sbin
  /bin
  /sbin
  /usr/local/bin(N-/)
  /usr/local/sbin(N-/)
  /Library/Apple/usr/bin
)

if type brew &>/dev/null; then
  FPATH=$(brew --prefix)/share/zsh-completions:$FPATH
  autoload -Uz compinit && compinit
  source $(brew --prefix)/opt/zsh-git-prompt/zshrc.sh
fi

# PROMPT="%F{green}%n%f %F{cyan}($(arch))%f:%F{blue}%~%f"$'\n'"%# "
# PROMPT='%F{034}%n%f %F{036}($(arch))%f:%F{020}%~%f $(git_super_status)'
# PROMPT+=""$'\n'"%# "

git_prompt() {
  if [ "$(git rev-parse --is-inside-work-tree 2> /dev/null)" = true ]; then
    PROMPT='%F{034}%n%f %F{036}($(arch))%f:%F{020}%~%f $(git_super_status)'
    PROMPT+=""$'\n'"%# "
  else
    PROMPT="%F{034}%n%f %F{036}($(arch))%f:%F{020}%~%f "$'\n'"%# "
  fi
}

add_newline() {
  if [[ -z $PS1_NEWLINE_LOGIN ]]; then
    PS1_NEWLINE_LOGIN=true
  else
    printf '\n'
  fi
}

precmd() {
  git_prompt
  add_newline
}

tgz() {
  env COPYFILE_DISABLE=1 tar zcvf $1 --exclude=".DS_Store" ${@:2}
}

(おまけ その1) ls コマンドに Ubuntu ライクなエイリアスを設定する

ここから先はおまけです。お好みでどうぞ。

ls コマンドに Ubuntu GNU/Linux っぽいエイリアスを設定します。

~/.zshrc
# -F でファイル種別の表示
# -G で色を付ける (GNU/Linux での "--color=auto" と等価)
alias ls="ls -FG"

alias la="ls -a"
alias ll="ls -l"
alias lla="ls -la"

2021-09-17-154725.png

(おまけ その2) x64arm64 の環境を行ったり来たりする (Apple Silicon)

M プロセッサを搭載した Mac で Rosetta 2arm64 の環境をコマンドラインから切り替えられるようにします。

Rosetta 2 をオフ(デフォルト)にした環境での利用法です。

~/.zshrc
# エイリアスを設定
if (( $+commands[arch] )); then
  alias x64='exec arch -arch x86_64 "$SHELL"'
  alias a64='exec arch -arch arm64e "$SHELL"'
fi

# 上記エイリアスが実行されると環境変数を書き換えます
if [[ $(uname -m) == "x86_64" ]]; then
  export VOLTA_HOME="$HOME/.volta_x64"
  typeset -U path PATH
  path=(
    $VOLTA_HOME/bin
    /usr/local/bin(N-/)
    /usr/local/sbin(N-/)
    /usr/bin
    /usr/sbin
    /bin
    /sbin
    /Library/Apple/usr/bin
  )
else
  export VOLTA_HOME="$HOME/.volta"
  typeset -U path PATH
  path=(
    $VOLTA_HOME/bin
    /opt/homebrew/bin(N-/)
    /opt/homebrew/sbin(N-/)
    /usr/bin
    /usr/sbin
    /bin
    /sbin
    /usr/local/bin
    /usr/local/sbin
    /Library/Apple/usr/bin
  )
fi

2021-09-17-155039.png

(おまけ その3) Git 関連のショートカットを設定する

~/.zshrc
# ステージングしてステータスを表示
gas() {
  git add -A;
  git status;
}

# メッセージ付きでコミット
alias gcm="git commit -m"

2021-09-17-155259.png

関連記事

https://zenn.dev/sprout2000/articles/aad599d3625242
GitHubで編集を提案

Discussion

ログインするとコメントできます