From e5a491b8d4f0094b839d1d44d32afc4c432d7b76 Mon Sep 17 00:00:00 2001 From: Ian Date: Mon, 23 Mar 2026 17:34:32 +0300 Subject: [PATCH] Add files via upload --- scripts/setup-kali-zsh.sh | 736 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 736 insertions(+) create mode 100644 scripts/setup-kali-zsh.sh diff --git a/scripts/setup-kali-zsh.sh b/scripts/setup-kali-zsh.sh new file mode 100644 index 0000000..4104361 --- /dev/null +++ b/scripts/setup-kali-zsh.sh @@ -0,0 +1,736 @@ +#!/usr/bin/env bash +# ============================================================================= +# Kali Linux Zsh Setup — mirrors Manjaro zsh config +# Run as your normal user (sudo will be used where needed) +# ============================================================================= +set -euo pipefail + +ZDOTDIR="${HOME}" +ZSH_CUSTOM_DIR="${HOME}/.zsh-custom" +P10K_DIR="${HOME}/.zsh-custom/powerlevel10k" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +info() { echo -e "${GREEN}[INFO]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +die() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; } + +# ============================================================================= +# 1. Install packages +# ============================================================================= +info "Updating package lists..." +sudo apt-get update -qq + +info "Installing zsh and plugins..." +sudo apt-get install -y \ + zsh \ + zsh-syntax-highlighting \ + zsh-autosuggestions \ + git \ + curl \ + fonts-powerline \ + dircolors + +# zsh-history-substring-search is not in Kali repos — install from source +HIST_SEARCH_DIR="${ZSH_CUSTOM_DIR}/zsh-history-substring-search" +if [[ ! -d "$HIST_SEARCH_DIR" ]]; then + info "Installing zsh-history-substring-search..." + mkdir -p "$ZSH_CUSTOM_DIR" + git clone --depth=1 https://github.com/zsh-users/zsh-history-substring-search.git "$HIST_SEARCH_DIR" +else + info "zsh-history-substring-search already present, pulling latest..." + git -C "$HIST_SEARCH_DIR" pull --ff-only +fi + +# ============================================================================= +# 2. Install Powerlevel10k +# ============================================================================= +if [[ ! -d "$P10K_DIR" ]]; then + info "Installing Powerlevel10k..." + git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "$P10K_DIR" +else + info "Powerlevel10k already present, pulling latest..." + git -C "$P10K_DIR" pull --ff-only +fi + +# ============================================================================= +# 3. Install nvm +# ============================================================================= +if [[ ! -d "${HOME}/.nvm" ]]; then + info "Installing nvm..." + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash +else + info "nvm already installed." +fi + +# ============================================================================= +# 4. Write zsh-config (equivalent of /usr/share/zsh/manjaro-zsh-config) +# ============================================================================= +info "Writing ~/.zsh-config..." +cat > "${ZDOTDIR}/.zsh-config" << 'EOF' +## Options section +setopt correct +setopt extendedglob +setopt nocaseglob +setopt rcexpandparam +setopt nocheckjobs +setopt numericglobsort +setopt nobeep +setopt appendhistory +setopt histignorealldups +setopt autocd +setopt inc_append_history +setopt histignorespace + +zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' +zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" +zstyle ':completion:*' rehash true +zstyle ':completion:*' menu select +zstyle ':completion:*' accept-exact '*(N)' +zstyle ':completion:*' use-cache on +zstyle ':completion:*' cache-path ~/.zsh/cache +HISTFILE=~/.zhistory +HISTSIZE=10000 +SAVEHIST=10000 +WORDCHARS=${WORDCHARS//\/[&.;]} + +## Keybindings section +bindkey -e +bindkey '^[[7~' beginning-of-line +bindkey '^[[H' beginning-of-line +if [[ "${terminfo[khome]}" != "" ]]; then + bindkey "${terminfo[khome]}" beginning-of-line +fi +bindkey '^[[8~' end-of-line +bindkey '^[[F' end-of-line +if [[ "${terminfo[kend]}" != "" ]]; then + bindkey "${terminfo[kend]}" end-of-line +fi +bindkey '^[[2~' overwrite-mode +bindkey '^[[3~' delete-char +bindkey '^[[C' forward-char +bindkey '^[[D' backward-char +bindkey '^[[5~' history-beginning-search-backward +bindkey '^[[6~' history-beginning-search-forward +bindkey '^[Oc' forward-word +bindkey '^[Od' backward-word +bindkey '^[[1;5D' backward-word +bindkey '^[[1;5C' forward-word +bindkey '^H' backward-kill-word +bindkey '^[[Z' undo + +## Alias section +alias cp="cp -i" +alias df='df -h' +alias free='free -m' +alias gitu='git add . && git commit && git push' + +## Theming section +autoload -U compinit colors zcalc +compinit -d +colors + +# Color man pages +export LESS_TERMCAP_mb=$'\E[01;32m' +export LESS_TERMCAP_md=$'\E[01;32m' +export LESS_TERMCAP_me=$'\E[0m' +export LESS_TERMCAP_se=$'\E[0m' +export LESS_TERMCAP_so=$'\E[01;47;34m' +export LESS_TERMCAP_ue=$'\E[0m' +export LESS_TERMCAP_us=$'\E[01;36m' +export LESS=-R + +## Plugins — Kali/Debian paths +source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh +source "${HOME}/.zsh-custom/zsh-history-substring-search/zsh-history-substring-search.zsh" + +zmodload zsh/terminfo +bindkey "$terminfo[kcuu1]" history-substring-search-up +bindkey "$terminfo[kcud1]" history-substring-search-down +bindkey '^[[A' history-substring-search-up +bindkey '^[[B' history-substring-search-down + +# Terminal title support +function title { + emulate -L zsh + setopt prompt_subst + [[ "$EMACS" == *term* ]] && return + : ${2=$1} + case "$TERM" in + xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty|kitty|wezterm|st*) + print -Pn "\e]2;${2:q}\a" + print -Pn "\e]1;${1:q}\a" + ;; + screen*|tmux*) + print -Pn "\ek${1:q}\e\\" + ;; + *) + if [[ -n "$terminfo[fsl]" ]] && [[ -n "$terminfo[tsl]" ]]; then + echoti tsl + print -Pn "$1" + echoti fsl + fi + ;; + esac +} + +ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" +ZSH_THEME_TERM_TITLE_IDLE="%n@%m:%~" + +function mzc_termsupport_precmd { + [[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return + title $ZSH_THEME_TERM_TAB_TITLE_IDLE $ZSH_THEME_TERM_TITLE_IDLE +} + +function mzc_termsupport_preexec { + [[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return + emulate -L zsh + local -a cmdargs + cmdargs=("${(z)2}") + if [[ "${cmdargs[1]}" = fg ]]; then + local job_id jobspec="${cmdargs[2]#%}" + case "$jobspec" in + <->) job_id=${jobspec} ;; + ""|%|+) job_id=${(k)jobstates[(r)*:+:*]} ;; + -) job_id=${(k)jobstates[(r)*:-:*]} ;; + [?]*) job_id=${(k)jobtexts[(r)*${(Q)jobspec}*]} ;; + *) job_id=${(k)jobtexts[(r)${(Q)jobspec}*]} ;; + esac + if [[ -n "${jobtexts[$job_id]}" ]]; then + 1="${jobtexts[$job_id]}" + 2="${jobtexts[$job_id]}" + fi + fi + local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%} + local LINE="${2:gs/%/%%}" + title '$CMD' '%100>...>$LINE%<<' +} + +autoload -U add-zsh-hook +add-zsh-hook precmd mzc_termsupport_precmd +add-zsh-hook preexec mzc_termsupport_preexec + +zmodload zsh/langinfo + +function zsh_urlencode() { + emulate -L zsh + local -a opts + zparseopts -D -E -a opts r m P + local in_str="$@" + local url_str="" + local spaces_as_plus + if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi + local str="$in_str" + local encoding=$langinfo[CODESET] + local safe_encodings + safe_encodings=(UTF-8 utf8 US-ASCII) + if [[ -z ${safe_encodings[(r)$encoding]} ]]; then + str=$(echo -E "$str" | iconv -f $encoding -t UTF-8) + if [[ $? != 0 ]]; then + echo "Error converting string from $encoding to UTF-8" >&2 + return 1 + fi + fi + local i byte ord LC_ALL=C + export LC_ALL + local reserved=';/?:@&=+$,' + local mark='_.!~*''()-' + local dont_escape="[A-Za-z0-9" + if [[ -z $opts[(r)-r] ]]; then dont_escape+=$reserved; fi + if [[ -z $opts[(r)-m] ]]; then dont_escape+=$mark; fi + dont_escape+="]" + local url_str="" + for (( i = 1; i <= ${#str}; ++i )); do + byte="$str[i]" + if [[ "$byte" =~ "$dont_escape" ]]; then + url_str+="$byte" + else + if [[ "$byte" == " " && -n $spaces_as_plus ]]; then + url_str+="+" + else + ord=$(( [##16] #byte )) + url_str+="%$ord" + fi + fi + done + echo -E "$url_str" +} + +function mzc_termsupport_cwd { + local URL_HOST URL_PATH + URL_HOST="$(zsh_urlencode -P $HOST)" || return 1 + URL_PATH="$(zsh_urlencode -P $PWD)" || return 1 + printf "\e]7;%s\a" "file://${URL_HOST}${URL_PATH}" +} + +add-zsh-hook precmd mzc_termsupport_cwd + +# File and dir colors +export LS_OPTIONS='--color=auto' +eval "$(dircolors -b)" +alias ls='ls $LS_OPTIONS' +EOF + +# ============================================================================= +# 5. Write zsh-prompt (equivalent of /usr/share/zsh/manjaro-zsh-prompt) +# ============================================================================= +info "Writing ~/.zsh-prompt..." +cat > "${ZDOTDIR}/.zsh-prompt" << EOF +() { + emulate -L zsh + + source "${P10K_DIR}/powerlevel10k.zsh-theme" + source /usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh + + { + if ! zmodload zsh/langinfo zsh/terminfo || + [[ \$langinfo[CODESET] != (utf|UTF)(-|)8 || \$TERM == (dumb|linux) ]] || + (( terminfo[colors] < 256 )); then + local USE_POWERLINE=false + local parent + if { parent=\$(/dev/null + + if [[ \$USE_POWERLINE == false ]]; then + source "${ZDOTDIR}/.p10k-portable.zsh" + ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=black,bold' + else + source "${ZDOTDIR}/.p10k.zsh" + ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=244' + fi +} +EOF + +# ============================================================================= +# 6. Write p10k configs +# ============================================================================= +info "Writing p10k config files..." + +cat > "${ZDOTDIR}/.p10k.zsh" << 'P10K_EOF' +# Generated by Powerlevel10k configuration wizard on 2021-11-14 at 16:02 CET. +# Based on romkatv/powerlevel10k/config/p10k-rainbow.zsh, checksum 19497. +# Wizard options: nerdfont-complete + powerline, small icons, rainbow, unicode, +# angled separators, sharp heads, flat tails, 1 line, compact, many icons, concise, +# instant_prompt=quiet. +# Type `p10k configure` to generate another config. + +'builtin' 'local' '-a' 'p10k_config_opts' +[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases') +[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob') +[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand') +'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' + +() { + emulate -L zsh -o extended_glob + + unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR' + + autoload -Uz is-at-least && is-at-least 5.1 || return + + typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=( + os_icon + dir + vcs + ) + + typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=( + status + command_execution_time + background_jobs + direnv + asdf + virtualenv + anaconda + pyenv + goenv + nodenv + nvm + nodeenv + node_version + go_version + rust_version + dotnet_version + php_version + laravel_version + java_version + package + rbenv + rvm + fvm + luaenv + jenv + plenv + perlbrew + phpenv + scalaenv + haskell_stack + kubecontext + terraform + terraform_version + aws + aws_eb_env + azure + gcloud + google_app_cred + toolbox + context + nordvpn + ranger + nnn + lf + xplr + vim_shell + midnight_commander + nix_shell + vi_mode + vpn_ip + load + disk_usage + ram + swap + todo + timewarrior + taskwarrior + time + newline + ) + + typeset -g POWERLEVEL9K_MODE=nerdfont-complete + typeset -g POWERLEVEL9K_ICON_PADDING=none + typeset -g POWERLEVEL9K_BACKGROUND= # transparent background + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_{LEFT,RIGHT}_WHITESPACE= # no surrounding whitespace + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SUBSEGMENT_SEPARATOR=' ' # separate segments with a space + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= # no end-of-line symbol + typeset -g POWERLEVEL9K_VISUAL_IDENTIFIER_EXPANSION= # no segment icons + + typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX= + typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_PREFIX= + typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX= + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_SUFFIX= + typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_SUFFIX= + typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_SUFFIX= + + typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL= + typeset -g POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL= + typeset -g POWERLEVEL9K_SHOW_RULER=false + typeset -g POWERLEVEL9K_RULER_CHAR='─' + typeset -g POWERLEVEL9K_RULER_FOREGROUND=242 + + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' ' + + # os_icon + typeset -g POWERLEVEL9K_OS_ICON_FOREGROUND=212 + + # dir + typeset -g POWERLEVEL9K_DIR_FOREGROUND=31 + typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique + typeset -g POWERLEVEL9K_SHORTEN_DELIMITER= + typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=103 + typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=39 + typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=true + local anchor_files=( + .bzr + .citc + .git + .hg + .node-version + .python-version + .go-version + .ruby-version + .tool-versions + .shorten_folder_marker + .svn + .terraform + CVS + Cargo.toml + composer.json + go.mod + package.json + stack.yaml + ) + typeset -g POWERLEVEL9K_SHORTEN_FOLDER_MARKER="(${(j:|:)anchor_files})" + typeset -g POWERLEVEL9K_DIR_TRUNCATE_BEFORE_MARKER=false + typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=1 + typeset -g POWERLEVEL9K_DIR_MAX_LENGTH=80 + typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS=40 + typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT=50 + typeset -g POWERLEVEL9K_DIR_HYPERLINK=false + typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=v3 + + # vcs + typeset -g POWERLEVEL9K_VCS_BRANCH_ICON='\uF126 ' + typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?' + function my_git_formatter() { + emulate -L zsh + if [[ -n $P9K_CONTENT ]]; then + typeset -g my_git_format=$P9K_CONTENT + return + fi + local meta='%7F' + local clean='%76F' + local modified='%178F' + local untracked='%39F' + local conflicted='%196F' + local res + local where + if [[ -n $VCS_STATUS_LOCAL_BRANCH ]]; then + res+="${clean}${(g::)POWERLEVEL9K_VCS_BRANCH_ICON}" + where=${(V)VCS_STATUS_LOCAL_BRANCH} + elif [[ -n $VCS_STATUS_TAG ]]; then + res+="${meta}#" + where=${(V)VCS_STATUS_TAG} + else + res+="${meta}@" + where=${VCS_STATUS_COMMIT[1,8]} + fi + (( $#where > 32 )) && where[13,-13]="…" + res+="${clean}${where//\%/%%}" + if [[ -n ${VCS_STATUS_REMOTE_BRANCH:#$VCS_STATUS_LOCAL_BRANCH} ]]; then + res+="${meta}:${clean}${(V)VCS_STATUS_REMOTE_BRANCH//\%/%%}" + fi + if [[ $VCS_STATUS_COMMIT_SUMMARY == (|*[^[:alnum:]])(wip|WIP)(|[^[:alnum:]]*) ]]; then + res+=" ${modified}wip" + fi + (( VCS_STATUS_COMMITS_AHEAD || VCS_STATUS_COMMITS_BEHIND )) && res+=' ' + (( VCS_STATUS_COMMITS_BEHIND )) && res+="${clean}⇣${VCS_STATUS_COMMITS_BEHIND}" + (( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" " + (( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}⇡${VCS_STATUS_COMMITS_AHEAD}" + (( VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" ${clean}⇠${VCS_STATUS_PUSH_COMMITS_BEHIND}" + (( VCS_STATUS_PUSH_COMMITS_AHEAD && !VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" " + (( VCS_STATUS_PUSH_COMMITS_AHEAD )) && res+="${clean}⇢${VCS_STATUS_PUSH_COMMITS_AHEAD}" + (( VCS_STATUS_NUM_SKIP_WORKTREE_CHANGED || VCS_STATUS_NUM_ASSUME_UNCHANGED_CHANGED )) && res+=" ${modified}─" + (( VCS_STATUS_HAS_STAGED )) && res+=" ${modified}+" + (( VCS_STATUS_HAS_UNSTAGED )) && res+=" ${modified}!" + (( VCS_STATUS_HAS_UNTRACKED )) && res+=" ${untracked}${(g::)POWERLEVEL9K_VCS_UNTRACKED_ICON}" + (( VCS_STATUS_HAS_CONFLICTED )) && res+=" ${conflicted}~" + typeset -g my_git_format=$res + } + functions -M my_git_formatter 2>/dev/null + typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1 + typeset -g POWERLEVEL9K_VCS_DISABLED_WORKDIR_PATTERN='~' + typeset -g POWERLEVEL9K_VCS_DISABLE_GITSTATUS_FORMATTING=true + typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${$((my_git_formatter(1)))+${my_git_format}}' + typeset -g POWERLEVEL9K_VCS_LOADING_CONTENT_EXPANSION='${$((my_git_formatter(0)))+${my_git_format}}' + typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED,COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=-1 + typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_COLOR=76 + typeset -g POWERLEVEL9K_VCS_LOADING_VISUAL_IDENTIFIER_COLOR=244 + typeset -g POWERLEVEL9K_VCS_BACKENDS=(git) + typeset -g POWERLEVEL9K_VCS_CLEAN_FOREGROUND=76 + typeset -g POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=76 + typeset -g POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=178 + + # status + typeset -g POWERLEVEL9K_STATUS_EXTENDED_STATES=true + typeset -g POWERLEVEL9K_STATUS_OK=false + typeset -g POWERLEVEL9K_STATUS_OK_FOREGROUND=70 + typeset -g POWERLEVEL9K_STATUS_OK_VISUAL_IDENTIFIER_EXPANSION='✔' + typeset -g POWERLEVEL9K_STATUS_OK_PIPE=true + typeset -g POWERLEVEL9K_STATUS_OK_PIPE_FOREGROUND=70 + typeset -g POWERLEVEL9K_STATUS_OK_PIPE_VISUAL_IDENTIFIER_EXPANSION='✔' + typeset -g POWERLEVEL9K_STATUS_ERROR=true + typeset -g POWERLEVEL9K_STATUS_ERROR_FOREGROUND=160 + typeset -g POWERLEVEL9K_STATUS_ERROR_VISUAL_IDENTIFIER_EXPANSION='✘' + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL=true + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_FOREGROUND=160 + typeset -g POWERLEVEL9K_STATUS_VERBOSE_SIGNAME=false + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_VISUAL_IDENTIFIER_EXPANSION='✘' + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE=true + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_FOREGROUND=160 + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_VISUAL_IDENTIFIER_EXPANSION='✘' + + # command_execution_time + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3 + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0 + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=101 + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s' + + # background_jobs + typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VERBOSE=false + typeset -g POWERLEVEL9K_BACKGROUND_JOBS_FOREGROUND=37 + + # nvm + typeset -g POWERLEVEL9K_NVM_FOREGROUND=70 + + # node_version + typeset -g POWERLEVEL9K_NODE_VERSION_FOREGROUND=70 + typeset -g POWERLEVEL9K_NODE_VERSION_PROJECT_ONLY=true + + # go_version + typeset -g POWERLEVEL9K_GO_VERSION_FOREGROUND=37 + typeset -g POWERLEVEL9K_GO_VERSION_PROJECT_ONLY=true + + # rust_version + typeset -g POWERLEVEL9K_RUST_VERSION_FOREGROUND=37 + typeset -g POWERLEVEL9K_RUST_VERSION_PROJECT_ONLY=true + + # java_version + typeset -g POWERLEVEL9K_JAVA_VERSION_FOREGROUND=32 + typeset -g POWERLEVEL9K_JAVA_VERSION_PROJECT_ONLY=true + + # package + typeset -g POWERLEVEL9K_PACKAGE_FOREGROUND=117 + + # kubecontext + typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc|istioctl|kogito|k9s|helmfile|flux|fluxctl|stern|kubeseal|skaffold' + + # context + typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND=227 + typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND=180 + typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND=180 + typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE='%B%n@%m' + typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_TEMPLATE='%n@%m' + typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE='%n@%m' + typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION= + + # time + typeset -g POWERLEVEL9K_TIME_FOREGROUND=66 + typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}' + typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false + + # Transient prompt + typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off + + # Instant prompt + typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet + + # Hot reload + typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true + + (( ! $+functions[p10k] )) || p10k reload +} + +(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]} +'builtin' 'unset' 'p10k_config_opts' +P10K_EOF + +# Portable (8-color fallback) p10k config +cat > "${ZDOTDIR}/.p10k-portable.zsh" << 'PORTABLE_EOF' +'builtin' 'local' '-a' 'p10k_config_opts' +[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases') +[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob') +[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand') +'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' + +() { + emulate -L zsh -o extended_glob + + unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR' + autoload -Uz is-at-least && is-at-least 5.1 || return + + typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir vcs prompt_char) + typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time background_jobs) + + typeset -g POWERLEVEL9K_MODE=ascii + typeset -g POWERLEVEL9K_ICON_PADDING=none + typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false + typeset -g POWERLEVEL9K_BACKGROUND= + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_{LEFT,RIGHT}_WHITESPACE= + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SUBSEGMENT_SEPARATOR=' ' + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= + + typeset -g POWERLEVEL9K_DIR_FOREGROUND=4 + typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=4 + typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=4 + typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=true + typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique + typeset -g POWERLEVEL9K_SHORTEN_DELIMITER= + + typeset -g POWERLEVEL9K_VCS_CLEAN_FOREGROUND=2 + typeset -g POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=3 + typeset -g POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=2 + typeset -g POWERLEVEL9K_VCS_BACKENDS=(git) + + typeset -g POWERLEVEL9K_STATUS_OK=false + typeset -g POWERLEVEL9K_STATUS_ERROR=true + typeset -g POWERLEVEL9K_STATUS_ERROR_FOREGROUND=1 + + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3 + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0 + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=3 + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s' + + typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=2 + typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=1 + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION='$' + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION='#' + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION='V' + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIOWR_CONTENT_EXPANSION='O' + typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=true + typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL= + + typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off + typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet + typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true + + (( ! $+functions[p10k] )) || p10k reload +} + +(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]} +'builtin' 'unset' 'p10k_config_opts' +PORTABLE_EOF + +# ============================================================================= +# 7. Write .zshrc +# ============================================================================= +info "Writing ~/.zshrc..." + +# Back up existing .zshrc if present +if [[ -f "${ZDOTDIR}/.zshrc" ]]; then + cp "${ZDOTDIR}/.zshrc" "${ZDOTDIR}/.zshrc.bak" + warn "Existing .zshrc backed up to ~/.zshrc.bak" +fi + +cat > "${ZDOTDIR}/.zshrc" << EOF +USE_POWERLINE="true" +HAS_WIDECHARS="false" + +source "\${HOME}/.zsh-config" +source "\${HOME}/.zsh-prompt" + +# nvm +export NVM_DIR="\${HOME}/.nvm" +[ -s "\${NVM_DIR}/nvm.sh" ] && source "\${NVM_DIR}/nvm.sh" +[ -s "\${NVM_DIR}/bash_completion" ] && source "\${NVM_DIR}/bash_completion" + +# pnpm +export PNPM_HOME="\${HOME}/.local/share/pnpm" +case ":\$PATH:" in + *":\$PNPM_HOME:"*) ;; + *) export PATH="\$PNPM_HOME:\$PATH" ;; +esac + +# Java +export JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto +export PATH=\$JAVA_HOME/bin:\$PATH + +# Android +export ANDROID_HOME=\$HOME/Android/Sdk +export ANDROID_SDK_ROOT=\$ANDROID_HOME +export PATH=\$ANDROID_HOME/emulator:\$PATH +export PATH=\$ANDROID_HOME/platform-tools:\$PATH +export PATH=\$ANDROID_HOME/cmdline-tools/latest/bin:\$PATH +EOF + +# ============================================================================= +# 8. Set zsh as default shell +# ============================================================================= +if [[ "$SHELL" != "$(which zsh)" ]]; then + info "Setting zsh as default shell..." + chsh -s "$(which zsh)" +fi + +# ============================================================================= +# Done +# ============================================================================= +echo "" +info "Setup complete! Start a new terminal or run: exec zsh" +warn "Note: Update JAVA_HOME in ~/.zshrc if your JDK path differs on Kali." +warn "Note: Install a Nerd Font for the full powerline prompt (https://www.nerdfonts.com/)." +warn " Then set it in your terminal emulator's font settings."