#!/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."