mirror of
https://github.com/d0zingcat/dotfiles.git
synced 2026-05-13 15:09:34 +00:00
440 lines
14 KiB
Bash
440 lines
14 KiB
Bash
###############################################################################
|
|
# My Dotfiles - Zsh Configuration
|
|
###############################################################################
|
|
# This configuration includes both personal and work-related functions.
|
|
# Work-related functions are marked with "# ==== WORK: xxx" comments.
|
|
###############################################################################
|
|
|
|
# -- Environment Variables --
|
|
export GOPATH=$HOME/.go
|
|
export PNPM_HOME="$HOME/.pnpm"
|
|
export BUN_HOME="$HOME/.bun"
|
|
export CARGO_HOME=$HOME/.cargo
|
|
|
|
export PATH="/opt/homebrew/sbin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"
|
|
export PATH="/opt/homebrew/opt/rustup/bin:$PATH"
|
|
export PATH="$CARGO_HOME/bin:$GOPATH/bin:$PATH"
|
|
export PATH="$HOME/.local/bin:${HOME}/.krew/bin:$PATH"
|
|
export PATH="$PNPM_HOME:$PATH"
|
|
export PATH="$BUN_HOME/bin:$PATH"
|
|
export PATH="$HOME/.docker/bin:$PATH"
|
|
export PATH="$PATH:$HOME/.spicetify"
|
|
|
|
export LC_ALL=en_US.UTF-8
|
|
export EDITOR=vim
|
|
export LANG=en_US.UTF-8
|
|
export MANPAGER="sh -c \"col -b | vim -c 'set ft=man ts=8 nomod nolist nonu' \
|
|
-c 'nnoremap i <nop>' \
|
|
-c 'nnoremap <Space> <C-f>' \
|
|
-c 'noremap q :quit<CR>' -\""
|
|
typeset -a kubeconfigs
|
|
kubeconfigs=("$HOME"/.kube/*config*(N))
|
|
if (( ${#kubeconfigs[@]} )); then
|
|
export KUBECONFIG="${(j/:/)kubeconfigs}"
|
|
fi
|
|
export HELM_CACHE_HOME=$HOME/.cache/helm
|
|
export FZF_DEFAULT_OPTS="--height=50% --layout=reverse"
|
|
export GPG_TTY=$(tty)
|
|
|
|
arch=$(uname -m)
|
|
if [ $arch = "x86_64" ]; then
|
|
brew_opt="/usr/local/opt"
|
|
elif [ $arch = "arm64" ]; then
|
|
brew_opt="/opt/homebrew/opt"
|
|
fi
|
|
LDFLAGS="-L$brew_opt/zlib/lib -L$brew_opt/openssl@3/lib"
|
|
CPPFLAGS="-I$brew_opt/zlib/include -I$brew_opt/openssl@3/include"
|
|
export LDFLAGS=$LDFLAGS
|
|
export CPPFLAGS=$CPPFLAGS
|
|
export ZSH_HIGHLIGHT_MAXLENGTH=60
|
|
export GIT_EXTERNAL_DIFF=difft
|
|
|
|
FPATH="$brew_opt/share/zsh/site-functions:${FPATH}"
|
|
DISABLE_MAGIC_FUNCTIONS=true
|
|
|
|
HISTSIZE=10000 # Number of commands to remember in memory (in-session)
|
|
SAVEHIST=50000 # Number of commands to save to the history file
|
|
HISTFILE=~/.zsh_history # File where history is stored
|
|
|
|
# -- Antigen for plugin management --
|
|
if [ -f "$HOME/.antigen/antigen.zsh" ]; then
|
|
source "$HOME/.antigen/antigen.zsh"
|
|
antigen use oh-my-zsh
|
|
antigen bundle zsh-users/zsh-autosuggestions
|
|
antigen bundle zsh-users/zsh-syntax-highlighting
|
|
antigen bundle zsh-users/zsh-completions
|
|
antigen bundle git
|
|
antigen bundle kubectl
|
|
antigen bundle autojump
|
|
antigen bundle pip
|
|
antigen bundle nvim
|
|
antigen bundle darvid/zsh-poetry
|
|
antigen bundle Aloxaf/fzf-tab
|
|
antigen bundle vi-mode
|
|
#antigen bundle MichaelAquilina/zsh-autoswitch-virtualenv
|
|
# antigen bundle jeffreytse/zsh-vi-mode
|
|
antigen apply
|
|
else
|
|
mkdir $HOME/.antigen
|
|
curl -L git.io/antigen > $HOME/.antigen/antigen.zsh
|
|
fi
|
|
|
|
# -- Aliases --
|
|
alias ta='tmux a'
|
|
alias tl='tmux ls && read session && tmux attach -t ${session:-default} || tmux new -s ${session:-default}'
|
|
alias l='ls -l'
|
|
alias la='ls -a'
|
|
alias lla='ls -la'
|
|
alias lt='ls --tree'
|
|
alias kns='kubens'
|
|
alias kctx='kubectx'
|
|
alias kd='kubectl debug'
|
|
alias kk='kubectl krew'
|
|
alias kzeus='kubectl --context zeus '
|
|
alias khybrid='kubectl --context hybrid'
|
|
alias kget='kubectl get'
|
|
alias kdesc='kubectl describe'
|
|
alias klog='kubectl logs'
|
|
alias kapply='kubectl apply'
|
|
alias gce='gh copilot explain'
|
|
alias gcs='gh copilot suggest'
|
|
alias vi='nvim'
|
|
alias batc='bat --paging=never'
|
|
alias batcp='bat --plain --paging=never'
|
|
alias fixscreen='sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.screensharing.plist && sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.screensharing.plist'
|
|
# do not use -r as it skips the non-regular files
|
|
alias tf_push='rsync -avhti . devops-cloud-1:~/meex-deploy/ --exclude=.terraform/ --exclude=.terraform.lock.hcl --exclude=terraform.tfstate'
|
|
alias tf_push_state='rsync -avhti . devops-cloud-1:~/meex-deploy/ --exclude=.terraform/ --exclude=.terraform.lock.hcl'
|
|
alias tf_pull_state='rsync -avhti devops-cloud-1:~/meex-deploy/terraform/terraform.tfstate terraform/.'
|
|
alias git_branch="git for-each-ref --sort=committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'"
|
|
alias clean_tmux_session='ls ~/.tmux/resurrect/* -1dtr | head -n 100 | xargs rm -v'
|
|
alias pn='pnpm'
|
|
alias python='python3'
|
|
alias pip='pip3'
|
|
alias sed='gsed'
|
|
alias grep='ggrep'
|
|
alias tailscale="/Applications/Tailscale.app/Contents/MacOS/Tailscale"
|
|
alias ghostty='/Applications/Ghostty.app/Contents/MacOS/ghostty'
|
|
alias cc='claude --append-system-prompt-file ~/.config/opencode/AGENTS.md --model claude-opus-4.6'
|
|
alias oc='opencode'
|
|
|
|
# -- Functions --
|
|
# menu
|
|
function m() {
|
|
if [[ -n "$TMUX" ]]; then
|
|
exit 0
|
|
fi
|
|
tmux ls -F '#{session_name}' | fzf --bind=enter:replace-query+print-query | xargs echo | read session && tmux attach -t ${session:-default} || tmux new -s ${session:-default}
|
|
}
|
|
|
|
# find network ports
|
|
function macnst (){
|
|
netstat -Watnlv | grep LISTEN | awk '{"ps -o comm= -p " $9 | getline procname;colred="\033[01;31m";colclr="\033[0m"; print colred "proto: " colclr $1 colred " | addr.port: " colclr $4 colred " | pid: " colclr $9 colred " | name: " colclr procname; }' | column -t -s "|"
|
|
}
|
|
|
|
# As clash for windows provides TUN mode/ClashX provides enhance mode, there's no necessity to set proxy munally(which proxy all traffix transparently)
|
|
# proxy by clashx function clashproxy() {
|
|
# local proxy=http://127.0.0.1:7890
|
|
# export https_proxy=$proxy http_proxy=$proxy all_proxy=socks5://127.0.0.1:7891;
|
|
# echo "proxy all set!"
|
|
#}
|
|
#
|
|
## unset proxy
|
|
#function clashproxy_unset() {
|
|
# unset http_proxy
|
|
# unset https_proxy
|
|
# unset all_proxy
|
|
# echo "proxy all unset!"
|
|
#}
|
|
|
|
# ==== WORK: Kubernetes logs viewer
|
|
function klogs() {
|
|
keyword=$1
|
|
k get pods --sort-by=.metadata.creationTimestamp | grep "$keyword" | head -n 1 | awk '{print $1}' | xargs kubectl logs -f
|
|
}
|
|
|
|
# ==== WORK: Git remote URL switcher
|
|
function replace_remote() {
|
|
if (( $# != 1 ));
|
|
then
|
|
echo 'Invalid parameter!'
|
|
else
|
|
url=$(git remote -v | head -n 1 | cut -d $'\t' -f 2 | cut -d ' ' -f 1)
|
|
suffix=$(echo $url | cut -d ':' -f 2)
|
|
case $1 in
|
|
ops)
|
|
new_url=opsgit:$suffix
|
|
git remote set-url origin $new_url
|
|
;;
|
|
work)
|
|
new_url=workgit:$suffix
|
|
git remote set-url origin $new_url
|
|
;;
|
|
play)
|
|
new_url=personalgit:$suffix
|
|
git remote set-url origin $new_url
|
|
;;
|
|
*)
|
|
echo 'Invalid parameter'
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
# ==== WORK: Remote sync to work servers
|
|
function rsync_work() {
|
|
remote_dir="/root"
|
|
local_work=`pwd`
|
|
local_dir=${PWD##*/}
|
|
local_dir=${local_dir:-/}
|
|
if [ $# -eq 0 ]; then
|
|
remote_work="devops-cloud-1:$remote_dir/$local_dir"
|
|
elif [ $# -eq 1 ]; then
|
|
remote_work="devops-cloud-$1:$remote_dir/$local_dir"
|
|
elif [ $# -eq 2 ]; then
|
|
remote_work="devops-cloud-$1:$remote_dir/$local_dir"
|
|
if [ "$2" = "back" ]; then
|
|
# swap local and remote
|
|
t=$local_work
|
|
local_work=$remote_work
|
|
remote_work=$t
|
|
else
|
|
echo "Invalid argument! should be 'back'"
|
|
exit(1)
|
|
fi
|
|
else
|
|
echo "invalid argument!"
|
|
exit(1)
|
|
fi
|
|
rsync_exclude="$local_work/rsync_exclude.txt"
|
|
if [ -f $rsync_exclude ]; then
|
|
rsync -avhti --exclude-from=$rsync_exclude --exclude=/venv --exclude=/.vscode --exclude=/.git $local_work/ $remote_work
|
|
else
|
|
rsync -avhti --exclude=/venv --exclude=/.vscode --exclude=/.git $local_work/ $remote_work
|
|
fi
|
|
}
|
|
|
|
function claude_with() {
|
|
local name="$1"
|
|
|
|
if [ -z "$name" ]; then
|
|
echo "usage: claude_with <provider-name>"
|
|
return 1
|
|
fi
|
|
|
|
# 根据 name 找 id
|
|
local id
|
|
id=$(cc-switch provider list | awk -F'┆' -v n="$name" '$3 ~ n {gsub(/ /,"",$2); print $2}')
|
|
|
|
if [ -z "$id" ]; then
|
|
echo "provider not found: $name"
|
|
return 1
|
|
fi
|
|
|
|
# 当前 provider
|
|
local old
|
|
old=$(cc-switch provider list | awk -F'┆' '/✓/ {gsub(/ /,"",$2); print $2}')
|
|
|
|
cc-switch provider switch "$id" || return 1
|
|
|
|
claude
|
|
local exit_code=$?
|
|
|
|
# 恢复
|
|
if [ "$old" != "$id" ]; then
|
|
cc-switch provider switch "$old" >/dev/null
|
|
fi
|
|
|
|
return $exit_code
|
|
}
|
|
|
|
|
|
function git_clean() {
|
|
git fetch --all --prune
|
|
|
|
base_branch="$1"
|
|
if [[ -z "$base_branch" ]]; then
|
|
base_branch=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's#^origin/##')
|
|
fi
|
|
|
|
if [[ -z "$base_branch" ]]; then
|
|
for branch in main master develop; do
|
|
if git show-ref --verify --quiet "refs/heads/$branch" || git show-ref --verify --quiet "refs/remotes/origin/$branch"; then
|
|
base_branch="$branch"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [[ -z "$base_branch" ]]; then
|
|
echo 'Could not detect base branch. Pass it explicitly, e.g. git_clean main'
|
|
return 1
|
|
fi
|
|
|
|
git checkout "$base_branch" && \
|
|
git config pull.rebase false && \
|
|
git pull && \
|
|
git branch --merged | grep -v " $base_branch$" | xargs git branch -d 2>/dev/null; \
|
|
git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -D 2>/dev/null; \
|
|
git worktree prune --verbose
|
|
}
|
|
|
|
function git_config() {
|
|
git config user.name $1
|
|
git config user.email $2
|
|
git config gpg.format ssh
|
|
git config user.signingkey "$3"
|
|
}
|
|
|
|
# ==== WORK: Multi-environment Git config (work)
|
|
function git_config_work() {
|
|
if [ ! $# -eq 2 ]; then
|
|
echo 'should be like git_config_work {name} {email}'
|
|
fi
|
|
git_config $1 $2 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF23DQtdH5PODF9fYUHr49I1J3lfKLAPk4LG54MVUTcg'
|
|
}
|
|
|
|
# ==== WORK: Multi-environment Git config (play)
|
|
function git_config_play() {
|
|
if [ ! $# -eq 1 ]; then
|
|
echo 'should be like gait_config_play {email}'
|
|
fi
|
|
git_config d0zingcat $1 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPaVruhhL4O9BiAncnW1wH3jc7/hsqsXLknA8Xtnjjee'
|
|
}
|
|
|
|
# ==== WORK: Kubernetes secret sealer
|
|
function bitnami_seal() {
|
|
if [[ $# != 2 ]]
|
|
then
|
|
echo 'Invalid parameter, should be like bitnami_seal <namespace> <filename>'
|
|
else
|
|
if [[ ! -f $2 ]]
|
|
then
|
|
echo "The file does not exist"
|
|
exit 1
|
|
fi
|
|
if [[ $2 != *".raw.yaml" ]]; then
|
|
echo "The variable does not have the .raw.yaml extension"
|
|
exit 1
|
|
fi
|
|
# parse *.raw.yaml to *.yaml
|
|
newname=${2//.raw/}
|
|
kubeseal --controller-namespace sealed-secrets --controller-name sealed-secrets -oyaml -n $1 -f $2 > $newname
|
|
fi
|
|
}
|
|
|
|
# Create dev workspace in tmux
|
|
# Usage: dev [-g] [session-name]
|
|
# default: Claude Code | Yazi (top-right) + shell (bottom-right)
|
|
# -g/--git: 2x2 layout adding lazygit (bottom-left)
|
|
function dev() {
|
|
local session=""
|
|
local layout="simple"
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-g|--git) layout="full" ;;
|
|
*) session="$arg" ;;
|
|
esac
|
|
done
|
|
|
|
session="${session:-$(basename $(pwd))}"
|
|
local cwd="$(pwd)"
|
|
|
|
if tmux has-session -t "$session" 2>/dev/null; then
|
|
if [[ -n "$TMUX" ]]; then
|
|
tmux switch-client -t "$session"
|
|
else
|
|
tmux attach-session -t "$session"
|
|
fi
|
|
return
|
|
fi
|
|
|
|
# Create session; first pane = left (Claude Code)
|
|
tmux new-session -d -s "$session" -c "$cwd"
|
|
local left
|
|
left=$(tmux display-message -p -t "${session}:1.1" "#{pane_id}")
|
|
|
|
if [[ "$layout" == "full" ]]; then
|
|
# 2x2: Claude Code | Yazi / shell | lazygit
|
|
local tr
|
|
tr=$(tmux split-window -t "$left" -h -c "$cwd" -P -F "#{pane_id}")
|
|
local br
|
|
br=$(tmux split-window -t "$tr" -v -c "$cwd" -P -F "#{pane_id}")
|
|
local bl
|
|
bl=$(tmux split-window -t "$left" -v -c "$cwd" -P -F "#{pane_id}")
|
|
|
|
tmux send-keys -t "$left" "cc" Enter
|
|
tmux send-keys -t "$tr" "yazi" Enter
|
|
tmux send-keys -t "$br" "lazygit" Enter
|
|
else
|
|
# simple: Claude Code (left) | Yazi (top-right) + shell (bottom-right)
|
|
local tr
|
|
tr=$(tmux split-window -t "$left" -h -c "$cwd" -P -F "#{pane_id}")
|
|
local br
|
|
br=$(tmux split-window -t "$tr" -v -c "$cwd" -P -F "#{pane_id}")
|
|
|
|
tmux send-keys -t "$left" "cc" Enter
|
|
tmux send-keys -t "$tr" "yazi" Enter
|
|
fi
|
|
|
|
tmux select-pane -t "$left"
|
|
|
|
if [[ -n "$TMUX" ]]; then
|
|
tmux switch-client -t "$session"
|
|
else
|
|
tmux attach-session -t "$session"
|
|
fi
|
|
}
|
|
|
|
# -- MISC Configuration --
|
|
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
|
|
command -v starship >/dev/null 2>&1 && eval "$(starship init zsh)"
|
|
command -v direnv >/dev/null 2>&1 && eval "$(direnv hook zsh)"
|
|
command -v lsd >/dev/null 2>&1 && alias ls='lsd'
|
|
|
|
export ZSH_COMPLETION_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/zsh"
|
|
mkdir -p "$ZSH_COMPLETION_CACHE"
|
|
|
|
if [[ $commands[kubectl] ]]; then
|
|
if [[ ! -s "$ZSH_COMPLETION_CACHE/_kubectl" ]]; then
|
|
command kubectl completion zsh >| "$ZSH_COMPLETION_CACHE/_kubectl" 2>/dev/null
|
|
fi
|
|
if [[ -s "$ZSH_COMPLETION_CACHE/_kubectl" ]]; then
|
|
source "$ZSH_COMPLETION_CACHE/_kubectl"
|
|
compdef __start_kubectl k
|
|
fi
|
|
fi
|
|
|
|
if [[ $commands[helm] ]]; then
|
|
if [[ ! -s "$ZSH_COMPLETION_CACHE/_helm" ]]; then
|
|
command helm completion zsh >| "$ZSH_COMPLETION_CACHE/_helm" 2>/dev/null
|
|
fi
|
|
if [[ -s "$ZSH_COMPLETION_CACHE/_helm" ]]; then
|
|
source "$ZSH_COMPLETION_CACHE/_helm"
|
|
fi
|
|
fi
|
|
[ -s "$HOME/.bun/_bun" ] && source "$HOME/.bun/_bun"
|
|
|
|
[ -f /usr/local/etc/profile.d/autojump.sh ] && . /usr/local/etc/profile.d/autojump.sh
|
|
[ -f /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.zsh.inc ] && . /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.zsh.inc
|
|
|
|
if command -v fzf >/dev/null 2>&1; then
|
|
if [[ ! -s "$ZSH_COMPLETION_CACHE/fzf.zsh" ]]; then
|
|
command fzf --zsh >| "$ZSH_COMPLETION_CACHE/fzf.zsh" 2>/dev/null
|
|
fi
|
|
if [[ -s "$ZSH_COMPLETION_CACHE/fzf.zsh" ]]; then
|
|
source "$ZSH_COMPLETION_CACHE/fzf.zsh"
|
|
fi
|
|
fi
|
|
|
|
bindkey -M viins '^b' vi-backward-char
|
|
bindkey -M viins '^f' vi-forward-char
|
|
bindkey -M viins '^d' vi-delete-char
|
|
[ -f ~/.env ] && source ~/.env
|
|
|
|
# Added by Antigravity
|
|
export PATH="$HOME/.antigravity/antigravity/bin:$PATH"
|
|
|
|
alias claude-mem='bun "$HOME/.claude/plugins/marketplaces/thedotmack/plugin/scripts/worker-service.cjs"'
|