# <<< 环境
_ZSH_DATA_DIR=${XDG_DATA_HOME}/zsh
_ZSH_CACHE_DIR=${XDG_CACHE_HOME}/zsh
_ZSH_PLUG_DIR=${XDG_DATA_HOME}/zinit

[[ -z $_ENV_ROOT ]] && [[ ${UID} == 0 || ${EUID} == 0 ]] && _ENV_ROOT=1
[[ -z $_ENV_SSH ]] && [[ -n ${SSH_CLIENT:-${SSH_TTY}} ]] && _ENV_SSH=1
[[ -z $_ENV_NVIM ]] && [[ -n ${NVIM} ]] && _ENV_NVIM=1
[[ -z $_ENV_PYVENV ]] && [[ -n ${VIRTUAL_ENV} ]] && _ENV_PYVENV=1
[[ -z $_ENV_NVM ]] && [[ -n ${NVM_BIN} ]] && _ENV_NVM=1
[[ -z $_ENV_FULL_UI ]] && [[ ! -z ${KITTY_PID} ]] && _ENV_FULL_UI=1

# 外部资源
_SRC_GIT_PROMPT=/usr/share/git/completion/git-prompt.sh
_SRC_FZF_COMPLETION=/usr/share/fzf/completion.zsh
_SRC_FZF_KEYBIND=/usr/share/fzf/key-bindings.zsh
_SRC_PKGFILE_HINT=/usr/share/doc/pkgfile/command-not-found.zsh
# >>>-----------------------------------


# <<< 选项
setopt correct			# 改正输错的命令
setopt interactive_comments	# 交互模式下允许注释
HISTSIZE=10000
SAVEHIST=100000
setopt share_history		# 多个实例共享历史记录
setopt hist_ignore_dups		# 不记录多条连续重复的历史
setopt hist_reduce_blanks	# 删除历史记录中的空行
setopt hist_find_no_dups	# 查找历史记录时忽略重复项
setopt auto_cd			# 进入目录而不是执行

# 设置$LS_COLORS，没有粗体
eval $(dircolors)
LS_COLORS=${LS_COLORS//=01/\=00}
# >>>-----------------------------------


# <<< 插件
declare -A ZINIT
ZINIT[HOME_DIR]=${_ZSH_PLUG_DIR}
ZINIT[BIN_DIR]=${_ZSH_PLUG_DIR}/bin
ZINIT[ZCOMPDUMP_PATH]=${_ZSH_CACHE_DIR}/zcompdump-${ZSH_VERSION}
source ${ZINIT[BIN_DIR]}/zinit.zsh

zinit ice lucid wait
zinit light zdharma-continuum/fast-syntax-highlighting	# 语法高亮
zinit ice lucid wait atload='_zsh_autosuggest_start'
zinit light zsh-users/zsh-autosuggestions	# 提示历史命令
zinit light zsh-users/zsh-completions		# 更多命令补全
zinit ice lucid wait
zinit light skywind3000/z.lua			# 快速跳转目录

# git扩展
zinit ice lucid wait'1' as"program" pick"$ZPFX/bin/git-*" \
	src"etc/git-extras-completion.zsh" make"PREFIX=$ZPFX"
zinit light tj/git-extras

# 主题
autoload -Uz colors && colors
source ${ZDOTDIR}/theme
((_ENV_FULL_UI)) && _theme_use_icon || _theme_use_text

# 与kitty集成
if [[ -n "$KITTY_INSTALLATION_DIR" ]]; then
	export KITTY_SHELL_INTEGRATION=enabled
	autoload -Uz "$KITTY_INSTALLATION_DIR"/shell-integration/zsh/kitty-integration
	kitty-integration
	unfunction kitty-integration
fi

# 其他
fpath+=(${ZDOTDIR}/functions ${ZDOTDIR}/Completion)
# 折叠路径
autoload -Uz collapsed_pwd
# >>>-----------------------------------
# <<< z.lua (var)
# 数据文件路径
export _ZL_DATA=${_ZSH_DATA_DIR}/zlua
# 仅在当前路径$PWD改变时才更新数据库
export _ZL_ADD_ONCE=1
# 在跳转后显示目标路径名称
export _ZL_ECHO=1
# 增强匹配模式
export _ZL_MATCH_MODE=1
# >>>-----------------------------------
# <<< zsh-autosuggestions (var)
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=0'
# 建议策略: history, completion, match_prev_cmd
ZSH_AUTOSUGGEST_STRATEGY=(history completion)
# >>>-----------------------------------


# <<< 提示符
setopt transient_rprompt	# 右提示符只出现一次
# git状态
[[ -f $_SRC_GIT_PROMPT ]] && source $_SRC_GIT_PROMPT
GIT_PS1_SHOWDIRTYSTATE=1
GIT_PS1_SHOWSTASHSTATE=1
GIT_PS1_SHOWUNTRACKEDFILES=1
GIT_PS1_STATESEPARATOR=
GIT_PS1_SHOWUPSTREAM="auto"
GIT_PS1_DESCRIBE_STYLE="default"

precmd() {
	local last_status=$?
	local prompt_array=()

	# 上一条命令的运行结果
	if [ $last_status -ne 0 ]; then
		prompt_array+=$_PROMPT_ERR
	else
		prompt_array+=$_PROMPT_OK
	fi

	# git状态
	if command -v __git_ps1 &>/dev/null; then
		local git_status=$(__git_ps1 "%s")
		if [[ -n $git_status ]]; then
			prompt_array+=${_PROMPT_COLOR_GIT}${git_status}%{$reset_color%}
		fi
	fi

	# 工作目录
	if command -v collapsed_pwd &>/dev/null; then
		prompt_array+=${_PROMPT_COLOR_PWD}$(collapsed_pwd)%{$reset_color%}
	else
		prompt_array+=$PWD
	fi

	((_ENV_PYVENV)) && prompt_array+=$_PROMPT_PYVENV
	((_ENV_NVM)) && prompt_array+=$_PROMPT_NVM
	((_ENV_NVIM)) && prompt_array+=$_PROMPT_NVIM
	((_ENV_SSH)) && prompt_array+=$_PROMPT_SSH

	# 用户类型
	if ((_ENV_ROOT)); then
		prompt_array+=$_PROMPT_ROOT
	else
		prompt_array+=$_PROMPT_USER
	fi

	PROMPT="$prompt_array "
}
((_ENV_SSH)) && RPROMPT="${_PROMPT_COLOR_SSH} %n@%m %{$reset_color%}"
# >>>-----------------------------------


# <<< 补全
zstyle :compinstall filename ${ZDOTDIR}/zshrc
autoload -Uz compinit
# 指定缓存文件所在目录必须先确保该目录存在
if [[ ! -d ${XDG_CACHE_HOME}/zsh/ ]]; then
	mkdir -p ${XDG_CACHE_HOME}/zsh/
fi
compinit -d ${_ZSH_CACHE_DIR}/zcompdump-${ZSH_VERSION}

setopt list_packed		# 减小补全列表的列宽

# 失败时的提示
zstyle ':completion:*:warnings' format '%F{red} -- No Matches Found --%f'
# 彩色菜单
zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
# 使用菜单切换候选
zstyle ':completion:*' menu select
# 列表分组
zstyle ':completion:*' group-name ''
zstyle ':completion:*:descriptions' format '%K{black} %d %k'
# 文件列表目录优先
zstyle ':completion:*' list-dirs-first true
zstyle ':completion:*' group-order local-directories

# 不区分大小写
zstyle ':completion:*' matcher-list '' 'm:{-a-zA-Z}={_A-Za-z}'
# 路径中多个斜杠被视为只有一个
zstyle ':completion:*' squeeze-slashes true

# 启用缓存
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path "${_ZSH_CACHE_DIR}/zcompcache"

# fzf
[[ -f $_SRC_FZF_COMPLETION ]] && source $_SRC_FZF_COMPLETION
export FZF_COMPLETION_TRIGGER=''
export FZF_DEFAULT_COMMAND='fd -uu -E .git -E .node_modules'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"

# 命令找不到时提示软件名(通过pkgfile)
[[ -f ${_SRC_PKGFILE_HINT} ]] && source ${_SRC_PKGFILE_HINT}
# >>>-----------------------------------


# <<< 按键绑定
bindkey -e	# emacs风格

# 补全菜单
zmodload zsh/complist
bindkey -M menuselect 'j' vi-down-line-or-history
bindkey -M menuselect 'k' vi-up-line-or-history
bindkey -M menuselect 'h' vi-backward-char
bindkey -M menuselect 'l' vi-forward-char
bindkey -M menuselect 'J' vi-forward-blank-word
bindkey -M menuselect 'K' vi-backward-blank-word
bindkey -M menuselect 'H' beginning-of-buffer-or-history
bindkey -M menuselect 'L' end-of-buffer-or-history
bindkey -M menuselect 's' accept-and-hold
bindkey -M menuselect '/' accept-and-infer-next-history

# 当前命令行在编辑器中打开
autoload -Uz edit-command-line
zle -N edit-command-line
bindkey "^X^E" edit-command-line

# 修改清屏方式
# 将内容挤出屏幕而不是直接清空
scroll-and-clear-screen() {
    printf '\n%.0s' {1..$LINES}
    zle clear-screen
} && zle -N scroll-and-clear-screen
bindkey '^l' scroll-and-clear-screen

# fzf
if [[ -f ${_SRC_FZF_KEYBIND} ]]; then
	source ${_SRC_FZF_KEYBIND}
fi

first-tab() {
    if [[ $#BUFFER == 0 ]]; then
	BUFFER="ls "
	CURSOR=3
	zle list-choices
	zle backward-kill-word
    else
        zle expand-or-complete
    fi
}
zle -N first-tab
bindkey '^I' first-tab

# 让 / = 作为分隔符
# 默认 WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>'
export WORDCHARS='*?_-.[]~&;!#$%^(){}<>'
# >>>-----------------------------------


# <<< alias, function
# sudo后面的命令可以是alias
alias sudo='sudo '

# 命令的默认行为
alias ls='ls --color=auto --time-style=iso --human-readable --hyperlink=auto -F'
alias grep='grep --color=auto'
alias diff='diff --color=auto'
alias ip='ip --color=auto'
alias ncdu='ncdu --color dark'
alias mv='mv -i'
alias mitmproxy="mitmproxy --set confdir=$XDG_CONFIG_HOME/mitmproxy"
alias mitmweb="mitmweb --set confdir=$XDG_CONFIG_HOME/mitmproxy"
alias rsync="rsync -avhHP"
if [[ $TERM == 'xterm-kitty' ]]; then
	alias ssh='kitty +kitten ssh'
	alias rg='kitty +kitten hyperlinked_grep'
	alias icat='kitty +kitten icat'
fi

alias sl='ls'
alias l='ls -l'
alias la='ls -A'
alias ll='ls -Al'

# 命令缩写
alias x='xdg-open'

# 需要搭配我的neovim配置
# https://github.com/rydesun/neovim-config/blob/master/init.lua#L3
# 使用neovim作为pager
alias v="nvim -R --cmd 'let paging=1'"
# 使用neovim作为pager，支持ANSI code
alias V="nvim -R --cmd 'let paging=1 | let ansi=1'"

if (($_ENV_NVIM)); then
	alias e='nvr --remote-tab'
else
	alias e='nvim'
fi
alias g='git'
alias cfg='GIT_DIR=$HOME/.myconf GIT_WORK_TREE=$HOME git'
alias cfg.e='GIT_DIR=$HOME/.myconf GIT_WORK_TREE=$HOME nvim'

mcd() { mkdir -p $1 && cd $1 }
mountdisk() {
	mount | grep -E '^(/dev/sd|/dev/nvme|/dev/mmcblk|gvfsd-fuse)' | \
		awk '{print $1 "\t" $5 "\t" $3 "\n\t\t" $6}'
}

# Arch Linux
alias pmq='pacman -Qs'
alias pms='pacman -Ss'
pmi() { pacman -Qii $1 2>/dev/null || pacman -Sii $1 }
pmo() { pacman -Qoq $1 2>/dev/null || pkgfile -i $1 }
pml() { (pacman -Qlq $1 2>/dev/null || pkgfile -lq $1) | sed -e '/\/$/d' -e '/^\/usr\/share\/locale\//d' }
pmb() { pml $1 | awk -F/ '/\/usr\/bin\/.+[^/]$/{print $NF}' }
pmd() { pml $1 | grep -e '\.service$' -e '\.socket$' -e '\.timer$' -e '\.desktop$' }
# >>>-----------------------------------


# vim: foldmethod=marker:foldmarker=<<<,>>>:foldlevel=0
