Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Powerlevel10k로 zsh 설정하기

그동안 꾸준히 bash를 사용했다. zsh이나 Fish가 더 강력한 부분이 있는 건 알고 있었지만 새로 세팅하는 것이 귀찮기도 했고 로컬 환경을 너무 잘 꾸며놓고 익숙해져도 서버 같은데 들어갔을 때나 다른 환경에서 사용이 어려워진다는 생각이 있어서 적당한 선에서만 편하게 유지하는 것도 있었다.

$ echo $0
-bash

위처럼 현재 shell을 확인해 보면 bash(Bourne Again Shell)로 설정된 걸 알 수가 있다. 하지만 macOS 10.15 Catalina부터는 bash가 아니라 zsh이 기본이 되었다. macOS가 기본 쉘을 바꾼 건 bash 최신 버전의 라이센스인 GPL v3 때문에 최신 bash로 올리지 못하고 있기 때문으로 알고 있다.

시스템 환경 설정에서 Control을 누르고 사용자 명을 누르면 기본 쉘을 변경할 수 있다.

macOS 사용자 및 그룹 설정

Catalina 이후에는 Terminal을 쓰면 zsh 쓰라는 안내대로 터미널에서 chsh -s /bin/zsh를 실행해도 된다.

Last login: Sun Jul 26 15:30:59 on ttys002

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.

미루다가 이번에 zsh로 갈아탔다. 언젠가는 zsh로 가긴 해야 할 것 같아서...

zsh 설정할 때 가장 많이 사용하는 Oh My Zsh과 최근에 알게 된 starship도 있었지만 트위터에서 추천받은 Powerlevel10k를 사용했다. 원래는 starship이랑 비교해 볼 생각이지만 Powerlevel10k 설정에 너무 많은 시간을 소비해서 그냥 Powerlevel10k에 안착했다.

Powerlevel10k

일단 Powerlevel10k를 설정해 보자. Powerlevel10k 문서에 아직 잘 모르겠으면 수동 설치를 권장하길래 수동 설치를 했다. 사용하는 zsh 플러그인 매니저가 있으면 해당 플러그인 매니저로 설치해서 관리하는 게 더 좋은 것 같다.

$ git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
$ echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>! ~/.zshrc

~/.zshrc 자체가 아예 없었기 때문에 powerlevel10k가 제공하는 내용으로 ~/.zshrc를 생성했다.

그러고 나면 자동으로 설정 마법사가 터미널에 열리게 된다. 아니면 p10k configure를 직접 실행해도 설정 마법사를 시작할 수 있다.

powerlevel10k 설정 마법사

powerlevel10k 설정 마법사

프롬프트 스타일, 시간 표시 등 설정 마법사에서 원하는 스타일로 설정할 수 있고 당연히 이후에도 수정할 수 있다.

설정이 끝나면 아래처럼 ~/.zshrc 파일이 생성된다.

# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

source ~/powerlevel10k/powerlevel10k.zsh-theme

# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

이 파일이 zsh의 기본 설정 파일이지만 Powerlevel10k는 같이 생성된 ~/.p10k.zsh 파일에서 원하는 대로 스타일이나 기능을 변경할 수 있다. ~/.p10k.zsh를 열어보면 어디를 먼저 봐야 할지 모를 정도로 많은 설정이 있다. 자세히 보면 모든 상황에 대한 색상, 문자, 기능들을 조정할 수 있는데 처음 사용해봐서 아직 잘 모르기도 하고 필요한 부분만 수정해서 설정했다.

Powerlevel10k 설정

특히, Powerlevel10k는 속도를 위해 많은 부분을 비동기로 처리하고 있어서 기존에 사용하던 동기 코드로 설정한 것과 맞지 않는 부분이 있었다. 동기로 처리되는 작업이 느리면 zsh을 시작할 때 시간이 걸리게 되는데 이런 작업을 비동기로 실행하고 지연시간을 없애서 바로 프롬프트를 사용할 수 있게 한 기능이 Instant prompt다. 작업을 비동기로 처리하기 때문에 처리 중 콘솔 출력이 있으면 이를 어떻게 처리할지 정해야 하는데 설정 마법사에서 아직 익숙지 않으면 verbose로 설정하라고 해서 POWERLEVEL9K_INSTANT_PROMPT=verbose로 설정해서 사용하고 있다.

그래서 내가 애용하는 direnv를 사용하면 zsh를 시작할 때 다음과 같은 경고 메시지가 나온다.

[WARNING]: Console output during zsh initialization detected.

When using Powerlevel10k with instant prompt, console output during zsh
initialization may indicate issues.

You can:

  - Recommended: Change ~/.zshrc so that it does not perform console I/O
    after the instant prompt preamble. See the link below for details.

    * You will not see this error message again.
    * Zsh will start quickly and prompt will update smoothly.

  - Suppress this warning either by running p10k configure or by manually
    defining the following parameter:

      typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet

    * You will not see this error message again.
    * Zsh will start quickly but prompt will jump down after initialization.

  - Disable instant prompt either by running p10k configure or by manually
    defining the following parameter:

      typeset -g POWERLEVEL9K_INSTANT_PROMPT=off

    * You will not see this error message again.
    * Zsh will start slowly.

  - Do nothing.

    * You will see this error message every time you start zsh.
    * Zsh will start quickly but prompt will jump down after initialization.

For details, see:
https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt

-- console output produced during zsh initialization follows --

direnv: loading .envrc

사실상 direnv의 출력은 direnv: loading .envrc 부분이고 앞은 powerlevel10k가 보여준 안내 메시지이다. 익숙해 지면 이 부분을 꺼도 될 것 같은데 어느 정도는 킨 채로 사용할 생각이다. bash를 쓸 때는 다 동기로 동작했기 때문에 이런 비동기 설정을 어떻게 해야 하는지 고민되는 부분이 있는데 온종일 만지고 있었더니 약간은 익숙해 진 것 같다.

zsh의 git 상태 표시

Git 설정이 된 디렉터리에 들어가면 브랜치와 커밋을 표시하고 수정된 파일과 git에 추가되지 않은 파일 수가 나온다. ~/.p10k.zsh에서 브랜치가 없을 때만 표시되게 되어 있던 커밋이 항상 보이도록 조건절을 없애고 res+="${meta}@${clean}${VCS_STATUS_COMMIT[1,8]}" 부분만 남겼다. 이전에 커밋 메시지를 계속 보면서 확인하던 설정이 익숙하던 터라...

~/.zshrc 파일에 사용 중인 rbenv, pyenv, direnv를 초기화하는 설정을 넣었다.

# rbenv
eval "$(rbenv init -)"
# pyenv
eval "$(pyenv init -)"
# direnv
eval "$(direnv hook zsh)"

덕분에 해당 환경이 활성화되면 쉘에서 지정한 버전이 표시된다.

zsh의 python 버전 표시

pyenv로 지정한 Python 버전이 표시된다.

zsh의 ruby 버전 표시

rbenv로 지정한 Ruby 버전이 표시된다.

zsh의 direnv 활성화 표시

direnv가 활성화되면 우측에 별(⭐)이 표시된다. 폴더 경로도 화면에 비해 길 경우 알아서 줄여준다. 필요에 따라 커스텀 가능하지만 이런 부분을 알아서 지원해주어서 무척 편하다.

입력하는 명령에 따라 동적으로 상태도 표시해 준다.

Terraform 프로필 표시

terraform 명령어를 입력하면 우측에 현재 클라우드와 AWS 프로필이 표시된다. AWS_PROFILE=tf로 설정되어 있어서 우측에 저렇게 나온 것이다.

zsh의 Kubernetes 컨텍스트 표시

kubectl을 입력하면 현재 Kubernetes 컨텍스트가 표시된다. 기본 네임스페이스도 보여주고 싶은데 아직 이 부분은 설정하지 못했다. 동적으로 표시하는 게 아니라 kube-ps1처럼 껐다가 키려면 문서에 나온 대로 kube-toggle()~/.zshrc에 추가하면 된다.

function kube-toggle() {
  if (( ${+POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND} )); then
    unset POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND
  else
    POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc|istioctl|kogito'
  fi
  p10k reload
  if zle; then
    zle push-input
    zle accept-line
  fi
}

이제 kube-toggle을 입력할 때마다 Kubernetes 컨텍스트를 보였다 안 보였다 할 수 없다. bash와 달리 우측에도 뭔가 표시할 수 있어서 좋긴 하다.

Zinit

Zinit은 zsh 플러그인 매니저이다. zsh을 처음 사용해본지라 Powerlevel10k를 추천해 주신 simnalamburt님의 .zshrc에서 보고 괜찮아 보여서 적용했다.

$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zinit/master/doc/install.sh)"

문서에 나온 대로 설치는 쉽게 할 수 있고 설치하고 나면 ~/.zinit/bin을 생성하고 이후 플러그인도 ~/.zinit 아래 설치된다. 그리고 ~/.zshrc 파일에 아래 같은 부분이 추가된다. zinit이 설치 안 된 곳에서는 설치하고 zinit을 초기화하는 코드다.

### Added by Zinit's installer
if [[ ! -f $HOME/.zinit/bin/zinit.zsh ]]; then
    print -P "%F{33}▓▒░ %F{220}Installing %F{33}DHARMA%F{220} Initiative Plugin Manager (%F{33}zdharma/zinit%F{220})…%f"
    command mkdir -p "$HOME/.zinit" && command chmod g-rwX "$HOME/.zinit"
    command git clone https://github.com/zdharma/zinit "$HOME/.zinit/bin" && \
        print -P "%F{33}▓▒░ %F{34}Installation successful.%f%b" || \
        print -P "%F{160}▓▒░ The clone has failed.%f%b"
fi

source "$HOME/.zinit/bin/zinit.zsh"
autoload -Uz _zinit
(( ${+_comps} )) && _comps[zinit]=_zinit

# Load a few important annexes, without Turbo
# (this is currently required for annexes)
zinit light-mode for \
    zinit-zsh/z-a-rust \
    zinit-zsh/z-a-as-monitor \
    zinit-zsh/z-a-patch-dl \
    zinit-zsh/z-a-bin-gem-node

아직 zsh은 잘 몰라서 터미널 사용에 편해 보이는 몇 가지 플러그인을 설치했다.

~/.zshrc에 아래 코드를 넣고 새 터미널 창을 열면 비동기로 플러그인을 설치한다. 한번 설치하면 이후에는 바로 로딩되니 그냥 사용하면 된다.

zinit light zdharma/fast-syntax-highlighting
zinit light zsh-users/zsh-autosuggestions
zinit light zsh-users/zsh-completions

zsh-completions에 따로 설정이 필요한지는 모르겠는데 Kubernetes와 Terraform 명령어는 자동 완성을 해주지 않아서 따로 ~/.zshrc에 추가했다.

zsh 속도

Powerlevel10k가 많은 작업을 비동기로 처리해 주기 때문에 뒤에서 진행되는 작업이 있어도 일단 프롬프트를 사용할 수 있다.

zsh 초기화 속도 테스트

설정하고 속도 테스트를 해봤는데 생각보다 빠르지는 않다. 이건 Powerlevel10k에 맞게 비동기로 설정하는 방법을 잘 몰라서 기존 bash에 쓰거나 필요한 설정을 그냥 넣었더니 쉘 초기화 속도에 영향을 미치는 것으로 보인다. 이건 이전 bash 쓸 때도 꽤 느렸기 때문에 불편하진 않지만, 천천히 zsh에 익숙해 지면서 튜닝을 해보려고 한다. 아무래도 계속 뭔가 추가하다 보면 더 느려질 테니까...

최근 bash 설정도 좀 너무 방치했더니 이상하게 된 부분이 있어서 정리가 필요했는데 이번 기회에 싹 정리하니까 좋긴 하다. zsh로 넘어가고 적응을 좀 걱정했는데 아직은 불편한 부분 없이 잘 쓰고 있다.

2020/07/29 00:49 2020/07/29 00:49