add post: zsh terminal setup
This commit is contained in:
445
content/posts/my-zsh-terminal-setup.md
Normal file
445
content/posts/my-zsh-terminal-setup.md
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
---
|
||||||
|
date: '2026-05-28T22:05:00+08:00'
|
||||||
|
draft: false
|
||||||
|
title: '我的 Zsh 终端配置:Zinit、Powerlevel10k 与日常效率优化'
|
||||||
|
tags:
|
||||||
|
- zsh
|
||||||
|
- terminal
|
||||||
|
- dotfiles
|
||||||
|
- zinit
|
||||||
|
- powerlevel10k
|
||||||
|
categories:
|
||||||
|
- 技术
|
||||||
|
---
|
||||||
|
|
||||||
|
## 前言
|
||||||
|
|
||||||
|
一个好用的 Shell 配置,不应该只是“看起来很酷”。它更应该做到三件事:
|
||||||
|
|
||||||
|
1. **启动快**:进入终端后立刻可输入命令,而不是等待一堆插件初始化。
|
||||||
|
2. **提示准**:当前目录、Git 状态、命令执行结果、语言环境等信息一眼可见。
|
||||||
|
3. **操作顺手**:常用命令短、路径跳转快、补全和历史建议足够智能。
|
||||||
|
|
||||||
|
这篇文章记录我的 Zsh 配置思路。整体方案是:**Zinit 管理插件,Powerlevel10k 负责提示符,Oh My Zsh 提供成熟插件生态,再配合 eza、yazi、pnpm、n 等工具优化日常开发体验**。
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
## 整体结构
|
||||||
|
|
||||||
|
我的 Zsh 配置主要由两个文件组成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/.zshrc # 主配置:环境变量、zinit、插件、别名、函数
|
||||||
|
~/.p10k.zsh # Powerlevel10k 主题配置
|
||||||
|
```
|
||||||
|
|
||||||
|
加载顺序大致如下:
|
||||||
|
|
||||||
|
```text
|
||||||
|
启动 Zsh
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Powerlevel10k instant prompt
|
||||||
|
|
|
||||||
|
v
|
||||||
|
基础环境变量与 Shell options
|
||||||
|
|
|
||||||
|
v
|
||||||
|
加载 zinit
|
||||||
|
|
|
||||||
|
v
|
||||||
|
加载 OMZ library / Powerlevel10k / 插件
|
||||||
|
|
|
||||||
|
v
|
||||||
|
source ~/.p10k.zsh
|
||||||
|
|
|
||||||
|
v
|
||||||
|
注册 alias / function / PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
这种拆分的好处是:`.zshrc` 保持“启动流程与插件管理”,`.p10k.zsh` 专注“提示符长什么样”。以后更换主题时,也不会影响插件和别名体系。
|
||||||
|
|
||||||
|
## 用 instant prompt 提升启动体验
|
||||||
|
|
||||||
|
配置最顶部是 Powerlevel10k 的 instant prompt:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
它的作用是:在完整配置加载完成之前,先显示一个临时 Prompt,让终端看起来“秒开”。
|
||||||
|
|
||||||
|
同时我设置了:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet
|
||||||
|
```
|
||||||
|
|
||||||
|
这样可以减少 instant prompt 对启动时输出内容的干扰。对于需要频繁打开新终端、tmux pane 或远程会话的人来说,这一点体验提升很明显。
|
||||||
|
|
||||||
|
## 基础环境与 Zsh options
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
path=(~/.local/bin $path)
|
||||||
|
typeset -x XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||||
|
|
||||||
|
setopt correct
|
||||||
|
setopt interactive_comments
|
||||||
|
```
|
||||||
|
|
||||||
|
这里做了几个基础设定:
|
||||||
|
|
||||||
|
| 配置 | 作用 |
|
||||||
|
|------|------|
|
||||||
|
| `~/.local/bin` 前置到 `PATH` | 优先使用用户级安装的命令 |
|
||||||
|
| `XDG_CONFIG_HOME` | 统一配置目录,默认指向 `~/.config` |
|
||||||
|
| `setopt correct` | 命令输错时给出纠正建议 |
|
||||||
|
| `setopt interactive_comments` | 交互式 Shell 中也允许使用 `#` 注释 |
|
||||||
|
|
||||||
|
`interactive_comments` 很适合在终端里临时记录命令意图,比如粘贴多行命令时可以保留注释说明。
|
||||||
|
|
||||||
|
## 为什么选择 Zinit
|
||||||
|
|
||||||
|
插件管理器我使用的是 Zinit:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git"
|
||||||
|
[[ ! -d "${ZINIT_HOME}" ]] && mkdir -p "$(dirname "${ZINIT_HOME}")"
|
||||||
|
[[ ! -d "${ZINIT_HOME}/.git" ]] && git clone https://gh-proxy.org/https://github.com/zdharma-continuum/zinit.git "${ZINIT_HOME}"
|
||||||
|
source "${ZINIT_HOME}/zinit.zsh"
|
||||||
|
```
|
||||||
|
|
||||||
|
Zinit 的核心价值是:**可以精细控制插件加载时机**。比如有些插件必须同步加载,有些插件可以延迟 1 秒、2 秒、3 秒再加载;对于启动速度敏感的 Shell 配置来说,这比简单地 `source` 一堆脚本更可控。
|
||||||
|
|
||||||
|
配置里还使用了 GitHub 代理地址,主要是为了在国内网络环境下更稳定地安装 Zinit。你也可以按自己的网络情况替换为官方仓库地址。
|
||||||
|
|
||||||
|
## 先加载 Oh My Zsh 的基础库
|
||||||
|
|
||||||
|
我没有直接使用完整的 Oh My Zsh 框架,而是通过 Zinit 按需加载其中的 library 和 plugin。
|
||||||
|
|
||||||
|
同步加载的 OMZ library:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
for i in theme-and-appearance.zsh git.zsh prompt_info_functions.zsh history.zsh; do
|
||||||
|
zinit snippet "OMZL::${i}"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
延迟加载的 OMZ library:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
for i in completion.zsh key-bindings.zsh; do
|
||||||
|
zinit ice lucid wait="1"
|
||||||
|
zinit snippet "OMZL::${i}"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
这里的思路是:
|
||||||
|
|
||||||
|
| 类型 | 加载策略 | 原因 |
|
||||||
|
|------|----------|------|
|
||||||
|
| theme / git / prompt / history | 同步加载 | 主题和提示符依赖,越早越好 |
|
||||||
|
| completion / key-bindings | 延迟加载 | 对首屏 Prompt 不是硬依赖 |
|
||||||
|
|
||||||
|
补全初始化则交给:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zpcompinit
|
||||||
|
zpcdreplay
|
||||||
|
```
|
||||||
|
|
||||||
|
这样可以配合 Zinit 的补全 replay 机制,让插件延迟加载后仍然能正确注册补全。
|
||||||
|
|
||||||
|
## Powerlevel10k:两行式 Prompt
|
||||||
|
|
||||||
|
主题使用 Powerlevel10k:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zinit ice depth=1
|
||||||
|
zinit light romkatv/powerlevel10k
|
||||||
|
|
||||||
|
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
|
||||||
|
```
|
||||||
|
|
||||||
|
`depth=1` 可以减少 clone 体积,只拉取必要历史。
|
||||||
|
|
||||||
|
我的 `.p10k.zsh` 是通过 `p10k configure` 生成的 rainbow 风格配置,主要特点是:
|
||||||
|
|
||||||
|
| 项目 | 配置 |
|
||||||
|
|------|------|
|
||||||
|
| 字体 | Nerd Font v3 |
|
||||||
|
| 风格 | powerline + rainbow |
|
||||||
|
| Prompt | 两行式 |
|
||||||
|
| 分隔符 | angled separators |
|
||||||
|
| 图标 | small icons / many icons |
|
||||||
|
| 显示密度 | sparse、concise |
|
||||||
|
|
||||||
|
左侧 Prompt 保留最核心的信息:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
|
||||||
|
os_icon
|
||||||
|
dir
|
||||||
|
vcs
|
||||||
|
newline
|
||||||
|
prompt_char
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
右侧 Prompt 则放一些上下文信息,例如命令状态、执行耗时、后台任务、Python 虚拟环境、Node 环境、Kubernetes context、Terraform workspace、云 CLI profile、时间等。
|
||||||
|
|
||||||
|
这种布局的优点是:**左边只显示当前操作最常用的信息,右边显示“有就看、没有也不影响”的上下文**。两行式 Prompt 也能避免路径太长时挤压命令输入区域。
|
||||||
|
|
||||||
|
## 插件设计:按“必要程度”延迟加载
|
||||||
|
|
||||||
|
我的插件并不是一股脑同步加载,而是按使用频率和必要程度分层。
|
||||||
|
|
||||||
|
| 插件 | 加载方式 | 用途 |
|
||||||
|
|------|----------|------|
|
||||||
|
| `command-not-found` | `wait=0` | 命令不存在时提示可安装的软件包 |
|
||||||
|
| `colored-man-pages` | `wait=3` | 彩色 man 页面 |
|
||||||
|
| `fast-syntax-highlighting` | async | 命令行语法高亮 |
|
||||||
|
| `zsh-autosuggestions` | async + `atload` | 基于历史记录的命令建议 |
|
||||||
|
| `sudo` | `wait=2` | 双击 `Esc` 给当前命令加 `sudo` |
|
||||||
|
| `z` | `wait=1` | 根据访问频率跳转目录 |
|
||||||
|
| `git` | `wait=1` | Git 常用别名与函数 |
|
||||||
|
| `extract` | `wait=1` | 一条命令解压多种格式 |
|
||||||
|
| `kubectl` | `wait=1` | Kubernetes 别名、补全与辅助函数 |
|
||||||
|
|
||||||
|
其中最影响交互体验的是两个插件:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zinit light zdharma-continuum/fast-syntax-highlighting
|
||||||
|
zinit light zsh-users/zsh-autosuggestions
|
||||||
|
```
|
||||||
|
|
||||||
|
- `fast-syntax-highlighting`:输入命令时实时高亮,能提前发现命令、路径、参数是否写错。
|
||||||
|
- `zsh-autosuggestions`:根据历史记录给出灰色建议,按右方向键即可补全。
|
||||||
|
|
||||||
|
这两个插件会让命令行从“纯文本输入框”变成“带反馈的交互环境”。
|
||||||
|
|
||||||
|
## 文件列表:eza 优先,ls 兜底
|
||||||
|
|
||||||
|
我把常用 `ls` 系列命令封装成了别名,如果系统安装了 `eza`,就优先使用 `eza`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
if [[ -n "$(command -v eza)" ]]; then
|
||||||
|
DISABLE_LS_COLORS=true
|
||||||
|
alias ls='eza --color=auto'
|
||||||
|
alias l='eza -lbah --icons=auto'
|
||||||
|
alias la='eza -labgh --icons=auto'
|
||||||
|
alias ll='eza -lbg --icons=auto'
|
||||||
|
alias lt='eza -lTbg --icons=auto'
|
||||||
|
alias lsa='eza -lbagR --icons=auto'
|
||||||
|
alias lst='eza -lTabgh --icons=auto'
|
||||||
|
else
|
||||||
|
alias ls='ls --color=auto'
|
||||||
|
alias l='ls -lah'
|
||||||
|
alias la='ls -lAh'
|
||||||
|
alias ll='ls -lh'
|
||||||
|
alias lsa='ls -lah'
|
||||||
|
alias lst='tree -pCsh'
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
常用别名含义如下:
|
||||||
|
|
||||||
|
| 别名 | 作用 |
|
||||||
|
|------|------|
|
||||||
|
| `l` | 长列表,显示隐藏文件、人类可读大小、图标 |
|
||||||
|
| `la` | 类似 `l`,但更适合查看权限和分组信息 |
|
||||||
|
| `ll` | 简洁长列表 |
|
||||||
|
| `lt` | 树状展示目录 |
|
||||||
|
| `lsa` | 递归列出所有文件 |
|
||||||
|
| `lst` | 树状递归展示并包含隐藏文件 |
|
||||||
|
|
||||||
|
这里的关键是“有增强工具就增强,没有就优雅降级”。配置可以在新机器上直接使用,不会因为缺少 `eza` 导致 Shell 启动失败。
|
||||||
|
|
||||||
|
## 路径跳转与目录历史
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
alias ...=../..
|
||||||
|
alias ....=../../..
|
||||||
|
alias .....=../../../..
|
||||||
|
alias ......=../../../../..
|
||||||
|
|
||||||
|
alias 1='cd -'
|
||||||
|
alias 2='cd -2'
|
||||||
|
alias 3='cd -3'
|
||||||
|
# ...一直到 9
|
||||||
|
```
|
||||||
|
|
||||||
|
这组别名解决两个常见问题:
|
||||||
|
|
||||||
|
1. 多级返回目录时不用反复输入 `cd ../../..`。
|
||||||
|
2. 在多个目录之间来回切换时,可以直接用 `1` 到 `9` 访问目录栈。
|
||||||
|
|
||||||
|
配合 OMZ 的 `z` 插件,可以覆盖两类跳转场景:
|
||||||
|
|
||||||
|
- **已知相对路径**:使用 `...`、`....`。
|
||||||
|
- **经常访问的目录**:使用 `z <keyword>`。
|
||||||
|
|
||||||
|
## yazi:退出文件管理器后自动 cd
|
||||||
|
|
||||||
|
配置中有一个很实用的 `y()` 函数:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
function y() {
|
||||||
|
local tmp cwd
|
||||||
|
tmp="$(mktemp -t yazi-cwd.XXXXXX)"
|
||||||
|
yazi "$@" --cwd-file="$tmp"
|
||||||
|
cwd="$(cat -- "$tmp")"
|
||||||
|
if [[ -n "$cwd" && "$cwd" != "$PWD" ]]; then
|
||||||
|
builtin cd -- "$cwd"
|
||||||
|
fi
|
||||||
|
rm -f -- "$tmp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
普通文件管理器的问题是:你在里面进入了某个目录,但退出后 Shell 仍然停留在原目录。这个函数通过 `--cwd-file` 记录 yazi 退出时所在目录,然后让当前 Shell 自动 `cd` 过去。
|
||||||
|
|
||||||
|
实际体验就是:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
y
|
||||||
|
# 在 yazi 中进入目标目录
|
||||||
|
# 退出 yazi 后,Shell 自动切换到那个目录
|
||||||
|
```
|
||||||
|
|
||||||
|
这比在终端里反复 `cd`、`ls`、再 `cd` 要顺手很多。
|
||||||
|
|
||||||
|
## Git、解压、sudo 与搜索
|
||||||
|
|
||||||
|
除了视觉和补全,我还保留了一些非常实用的小别名:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
alias _='sudo '
|
||||||
|
alias gc1='git clone --recursive --depth=1'
|
||||||
|
alias md='mkdir -p'
|
||||||
|
alias rd='rmdir'
|
||||||
|
alias afind='ack -il'
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
alias egrep='egrep --color=auto'
|
||||||
|
alias fgrep='fgrep --color=auto'
|
||||||
|
```
|
||||||
|
|
||||||
|
| 别名 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| `_` | 快速给命令加 `sudo` 前缀 |
|
||||||
|
| `gc1` | 浅克隆并递归拉取子模块 |
|
||||||
|
| `md` | 创建多级目录 |
|
||||||
|
| `rd` | 删除空目录 |
|
||||||
|
| `afind` | 用 `ack` 搜索包含关键词的文件 |
|
||||||
|
| `grep` 系列 | 默认开启彩色输出 |
|
||||||
|
|
||||||
|
此外 OMZ 的 `extract` 插件也很省心:不需要记住 `tar.gz`、`zip`、`xz`、`bz2` 等格式分别怎么解压,统一用 `extract` 即可。
|
||||||
|
|
||||||
|
## 代理开关:为国内网络环境准备
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
alias proxy-on='export http_proxy=http://127.0.0.1:7890 https_proxy=http://127.0.0.1:7890'
|
||||||
|
alias proxy-off='unset http_proxy https_proxy'
|
||||||
|
```
|
||||||
|
|
||||||
|
这两个别名适合临时让命令行工具走本地代理,例如拉取 GitHub 仓库、安装依赖、访问国外 API 等。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
proxy-on
|
||||||
|
# 执行需要代理的命令
|
||||||
|
proxy-off
|
||||||
|
```
|
||||||
|
|
||||||
|
我没有把代理永久写进环境变量,因为那样容易影响内网服务、容器网络和一些只需要直连的命令。按需开启更可控。
|
||||||
|
|
||||||
|
## Node 与前端工具链
|
||||||
|
|
||||||
|
配置末尾还包含 pnpm 和 n 的环境变量:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
export PNPM_HOME="/root/.local/share/pnpm"
|
||||||
|
case ":$PATH:" in
|
||||||
|
*":$PNPM_HOME/bin:"*) ;;
|
||||||
|
*) export PATH="$PNPM_HOME/bin:$PATH" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
export N_PREFIX="$HOME/n"
|
||||||
|
[[ :$PATH: == *":$N_PREFIX/bin:"* ]] || PATH+=":$N_PREFIX/bin"
|
||||||
|
```
|
||||||
|
|
||||||
|
这里有两个目的:
|
||||||
|
|
||||||
|
1. `pnpm` 的全局 bin 目录加入 `PATH`,方便直接运行全局安装的 CLI。
|
||||||
|
2. `n` 管理的 Node.js 路径加入 `PATH`,让当前 Shell 使用用户目录下的 Node 版本。
|
||||||
|
|
||||||
|
如果你也用 pnpm 和 n,建议把它们放在 Shell 配置末尾,避免覆盖前面插件初始化所需的环境。
|
||||||
|
|
||||||
|
## 依赖清单
|
||||||
|
|
||||||
|
这套配置推荐安装的依赖如下:
|
||||||
|
|
||||||
|
| 依赖 | 必需 | 用途 |
|
||||||
|
|------|:----:|------|
|
||||||
|
| `zsh` | ✅ | Shell 本体 |
|
||||||
|
| `git` | ✅ | 安装 zinit、拉取插件 |
|
||||||
|
| `zinit` | ✅ | 插件管理器 |
|
||||||
|
| `powerlevel10k` | ✅ | Prompt 主题 |
|
||||||
|
| Nerd Font | ✅ | 正确显示图标和 powerline 符号 |
|
||||||
|
| `eza` | 可选 | 更现代的 `ls` 替代品 |
|
||||||
|
| `tree` | 可选 | `eza` 不存在时作为树状列表兜底 |
|
||||||
|
| `ack` | 可选 | `afind` 搜索别名 |
|
||||||
|
| `yazi` | 可选 | 终端文件管理器 |
|
||||||
|
| `kubectl` | 可选 | Kubernetes 补全与别名 |
|
||||||
|
| `command-not-found` | 可选 | 命令不存在时提示安装包 |
|
||||||
|
| `pnpm` | 可选 | Node 包管理器 |
|
||||||
|
| `n` | 可选 | Node 版本管理 |
|
||||||
|
|
||||||
|
最小安装只需要:`zsh`、`git`、Nerd Font。其他工具可以按需补齐。
|
||||||
|
|
||||||
|
## 可复用的安装步骤
|
||||||
|
|
||||||
|
如果要在新机器上复用这套配置,可以按这个流程:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 安装基础依赖
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y zsh git
|
||||||
|
|
||||||
|
# 2. 可选增强工具
|
||||||
|
sudo apt install -y tree ack
|
||||||
|
|
||||||
|
# 3. 安装 eza / yazi / pnpm / n 等工具
|
||||||
|
# 不同发行版包名可能不同,可按实际系统调整
|
||||||
|
|
||||||
|
# 4. 放置配置文件
|
||||||
|
cp .zshrc ~/.zshrc
|
||||||
|
cp .p10k.zsh ~/.p10k.zsh
|
||||||
|
|
||||||
|
# 5. 切换默认 Shell
|
||||||
|
chsh -s "$(command -v zsh)"
|
||||||
|
```
|
||||||
|
|
||||||
|
首次进入 Zsh 时,配置会自动安装 Zinit,并通过 Zinit 拉取 Powerlevel10k 和插件。
|
||||||
|
|
||||||
|
## 我的取舍
|
||||||
|
|
||||||
|
这套配置没有追求“插件越多越好”,而是围绕日常使用做了几个取舍:
|
||||||
|
|
||||||
|
1. **不完整引入 Oh My Zsh**:只按需加载 OMZ library 和 plugin,减少框架开销。
|
||||||
|
2. **Prompt 信息分层**:左侧保留目录与 Git,右侧显示环境上下文。
|
||||||
|
3. **增强工具必须有 fallback**:`eza` 不存在就退回 `ls`,避免新机器启动失败。
|
||||||
|
4. **代理手动开关**:避免代理污染所有命令。
|
||||||
|
5. **插件延迟加载**:把首屏可交互时间放在第一优先级。
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
我的 Zsh 配置可以概括为:
|
||||||
|
|
||||||
|
- **Zinit**:负责插件安装、延迟加载和补全 replay。
|
||||||
|
- **Powerlevel10k**:提供高信息密度、低干扰的两行 Prompt。
|
||||||
|
- **OMZ snippets**:按需复用 Oh My Zsh 的成熟插件生态。
|
||||||
|
- **eza / yazi / z / autosuggestions**:提升文件浏览、目录跳转和命令输入效率。
|
||||||
|
- **pnpm / n**:补齐前端和 Node.js 开发环境。
|
||||||
|
|
||||||
|
终端配置是一个长期迭代的系统。最好的配置不是最复杂的配置,而是能让你在每天打开终端时少想一步、少敲几个字、少等几百毫秒的配置。
|
||||||
Reference in New Issue
Block a user