#!/bin/zsh
# Blake's ZSH config file

### Basic shell configuration >>>
### Environment variables >>>
{
   # Intelligently set $EDITOR
   if command -v nvim > /dev/null;then
      export EDITOR=nvim
   elif command -v vim > /dev/null;then
      export EDITOR=vim
   elif command -v vi > /dev/null;then
      export EDITOR=vi
   fi

   export PATH="$PATH:${XDG_DATA_HOME:-$HOME/.local/bin}"
   export SYSTEMD_EDITOR="$EDITOR"

   export LSCOLORS="Gxfxcxdxbxegedabagacad"
   export ZSH_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/zsh"

   export ZINIT_HOME_DIR=""

   WORKING_DIR_SAVE_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/zsh/last-working-dir"
   # make the dir for the file if needed
   ! test -d "$(dirname "$WORKING_DIR_SAVE_FILE")" && mkdir -p "$(dirname "$WORKING_DIR_SAVE_FILE")"

   # (I know this shouldn't go here, but I needed it to happen early)
   # change cursor to beam by default
   echo -ne '\e[5 q'

   # Plugin setting >>>
   {
      # ZSH Vi Mode
      ZVM_VI_HIGHLIGHT_FOREGROUND=#BBC2CF
      ZVM_VI_HIGHLIGHT_BACKGROUND=#515860
      # ZVM_VI_HIGHLIGHT_EXTRASTYLE=bold,underline    # bold and underline

      # OMZ Completion
      COMPLETION_WAITING_DOTS=true
   }
   # <<<

   # optionally source an external environment variable file
   [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/envrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/envrc"
}
# <<<
### Aliases >>>
{
   ## Short hand programs (ex: sc = shellcheck) >>>
   # use nvim rather than vim if the command exists
   [ -x "$(command -v nvim)" ] && alias vim='nvim' vimdiff='nvim -d'

   alias vv="$EDITOR"
   alias sedit='sudoedit'

   # I do this too much by accident smh my head
   alias :q='exit' \
         q='exit' \

   alias vim=nvim
   alias sc=shellcheck
   # rmdir is long
   alias \
      rmd='rmdir' \
      rd='rmdir' \

   alias \
      mkd=mkdir \
      g=git \
      sctl='sudo systemctl' \

   # <<<
   ## Program improvements (ex: ls = ls -h) >>>
   alias sudo='sudo '      # allow using aliases in sudo commands
   alias df='df -h'        # Human-readable sizes
   alias free='free -m'    # Show sizes in MB
   alias bc='bc -ql'       # Make bc usable for fast math
   [ -z "$VIMRUNTIME" ] &&
      alias glow='glow -p' # force Glow to preview with `less` if not in vim

   # I hate it when I get ghost script instead of git status. this will be removed
   alias gs="echo 'you don'\''t really want ghost script, do you?'"

   # Colors
   alias \
      ls='ls -hN --color=auto --group-directories-first' \
      grep='grep --color=auto' \
      diff='diff --color=auto' \
      pacman='pacman --color=auto' \
      paru='paru --color=auto --sudoloop --newsonupgrade --pgpfetch --upgrademenu --bottomup --skipreview' \

   command -v lsd > /dev/null && alias \
      ls=lsd \
      lsd='lsd --group-dirs=first' \

   # <<<
   ## Mini short-hand scripts (ex: la = ls -a) >>>
   # dotfile management
   alias dot='git --git-dir="$HOME/git/dotfiles" --work-tree="$HOME"'
   alias   d='git --git-dir="$HOME/git/dotfiles" --work-tree="$HOME"' # duplicate for auto-complete

   # quicker shutdown
   alias sdn='shutdown now'

   # open a new session called 0, but if there is already a session called 0, connect to it
   alias tm='tmux new -As0' 

   # List available X displays. Useful for finding what display to export when connected over ssh.
   alias lsx='ls /tmp/.X11-unix | tr "X" ":"'

   # Edit config files
   alias \
      nvc='(cd ~/.config/nvim/lua/blake && nvim ../../init.lua)' \
      zshrc='$EDITOR ~/.zshrc' \
      fstab='sudoedit /etc/fstab' \

   # Git cLONE
   alias glone="git clone"

   # Docker
   alias \
      logs='docker-compose logs --tail=200 -f' \
      dupd='docker-compose up -d' \
      ddwn='docker-compose down' \
      dc='docker-compose' \
      occ='docker exec -it -u www-data nextcloud php occ' \

   # file copying with a progress bar
   alias cpv="rsync -ah --info=progress2"

   # lists all open ports, along with some other info
   alias ls-ports='netstat -tulpn' 

   # list all disks and their mount points
   alias mnt="mount | awk -F' ' '{ printf \"%s\t%s\n\",\$1,\$3; }' | column -t | grep -E '^/dev/' | sort"

   # backs up list of packages
   alias packback='comm -23 <(paru -Qqett | sort) <(paru -Qqg base -g base-devel | sort | uniq) > ~/pkglist.txt'

   # thoroughly reset the terminal
   alias rce='reset && clear && exec zsh'

   # find pretty much any file, quickly
   alias fds='fd --hidden --exclude /run'

   # smart plug things
   SMART_PLUG_IP='192.168.1.250'
   alias light='tplink_smartplug.py -t $SMART_PLUG_IP -c'

   # Common ls  aliases
   alias \
      l=ls \
      la='ls -ah' \
      ll='ls -lh' \
      lla='ls -lah' \

   # <<<
   # optionally source an external alias file
   [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc"
}
# <<<
### Functions >>>
{
   # cd search: cd to a directory, given part of its name
   # (also can take arguments for an `fd` commnd)
   cds() {
      if ! [ -z "$1" ];then
         cd "$(fd --max-results=1 -t d $@)" && pwd
      else
         echo "$0: no arguments provided"
         return 1
      fi
   }

   # toggles whether a file or group of files is executable
   chx() {
      for FILE in "$@";do
         if [  -x "$FILE" ];then
            chmod -x "$FILE" &&
            echo -e "$FILE: -x"
         elif ! [ -x "$FILE" ];then
            chmod +x "$FILE" &&
            echo -e "$FILE: +x"
         else
            echo "error: file $FILE does not exist" >&2
         fi
      done
   }

   # a simple way to manage your todo list
   # Usage:
   #  todo                    -- pull latest repo version and edit ~/todo
   #  todo [any git command]  -- manage todo for easy syncing, assuming ~/todo is
   #                                a symlink that points to a file in a git repo
   #
   # Suggested use: make a git repo for holding your todo list, then make
   # a symlink called 'todo' that points to your todo list in your home directory
   #
   todo() {
      todo_dir="$(dirname "$(realpath ~/todo)")"
      todo_file="$(realpath ~/todo)"
      if [ -z "$@" ];then
         ( # subshell to protect against directory changes
         cd "$todo_dir"

         # pull the latest commits
         git rev-parse &&
            git pull

         # open the file
         "$EDITOR" "$todo_file"

         # commit and push the file if it's in a git repo and the file has changed
         if git rev-parse && ! git diff --exit-code "$todo_file"; then
            git commit "$todo_file" -m 'todo' &&
               git push
         fi
         )

      elif [ "$@" = "cd" ]; then
         cd "$todo_dir"

      else
         git -C "$todo_dir" $@

      fi
   }

   # Simple extraction script. Taken from manjaro's .bashrc
   ex() {
      if [ -f $1 ] ; then
         case $1 in
            *.tar.bz2)   tar xjf $1   ;;
            *.tar.gz)    tar xzf $1   ;;
            *.bz2)       bunzip2 $1   ;;
            *.rar)       unrar x $1   ;;
            *.gz)        gunzip $1    ;;
            *.tar)       tar xf $1    ;;
            *.tbz2)      tar xjf $1   ;;
            *.tgz)       tar xzf $1   ;;
            *.zip)       unzip $1     ;;
            *.Z)         uncompress $1;;
            *.7z)        7z x $1      ;;
            *)           echo "'$1' cannot be extracted via ex()" ;;
         esac
      else
         echo "'$1' is not a valid file"
      fi
   }

   # TODO: encode the url to fix things like spaces using something like https://stackoverflow.com/a/10660730/11162605
   # usage: sitepath <path to file>
   # usage: sitepath <file to find>
   # usage: sitepath
   # usage: sitepath <fd commands> -- you can search with 'fd' if you put in a command
   sitepath() {
      # If there is no input, make the input the current directory
      [ -z ${1+x} ] && 1="$(pwd)"
      FILEPATH="$(([ -e "$1" ] && readlink -f "$1") || fd $@ /home/blake/docker/blakenorth.net/site)"

      echo "$FILEPATH" | grep -o 'site.*' | sed 's+^site+https://blakenorth.net+g'
   }

   # for sending error messages from functions and whatnot
   error() {
      ERROR_CODE="$?"
      >&2 echo "An error occurred within a function in the .zshrc on line number ${1}"
      return $ERROR_CODE
   } 

   # prcolors(): Display all colors in a few different ways >>>
   # TODO: change this to make it not just a few scripts smashed together
   prcolors() {
      [ -z "$1" ] && 1=0
      if [ $1 -eq '1' ];then
      # Taken from manjaro's bashrc >>>
      local fgc bgc vals seq0

      printf "Color escapes are %s\n" '\e[${value};...;${value}m'
      printf "Values 30..37 are \e[33mforeground colors\e[m\n"
      printf "Values 40..47 are \e[43mbackground colors\e[m\n"
      printf "Value  1 gives a  \e[1mbold-faced look\e[m\n\n"

      # foreground colors
      for fgc in {30..37}; do
         # background colors
         for bgc in {40..47}; do
            fgc=${fgc#37} # white
            bgc=${bgc#40} # black
            
            vals="${fgc:+$fgc;}${bgc}"
            vals=${vals%%;}

            seq0="${vals:+\e[${vals}m}"
            printf "  %-9s" "${seq0:-(default)}"
            printf " ${seq0}TEXT\e[m"
            printf " \e[${vals:+${vals+$vals;}}1mBOLD\e[m"
         done
         echo; echo
      done
      # <<<
   elif [ $1 -eq '2' ];then
      # from base16shell >>>
      ansi_mappings=(
         Red               Green        
         Yellow            Blue
         Magenta           Cyan
         White             Black
         Bright_Red        Bright_Green 
         Bright_Yellow     Bright_Blue
         Bright_Magenta    Bright_Cyan
         Bright_White      Bright_Black 
      )
      colors=(
         base00 base08
         base0B base0A
         base0D base0E
         base0C base05
         base03 base08
         base0B base0A
         base0D base0E
         base0C base07
         base09 base0F
         base01 base02
         base04 base06
      )
      for padded_value in `seq -w 0 21`; do
         color_variable="color${padded_value}"
         eval current_color=\$${color_variable}
         current_color=$(echo ${current_color//\//} | tr '[:lower:]' '[:upper:]') # get rid of slashes, and uppercase
         non_padded_value=$((10#$padded_value))
         base16_color_name=${colors[$non_padded_value]}
         current_color_label=${current_color:-unknown}
         ansi_label=${ansi_mappings[$non_padded_value]} 
         block=$(printf "\x1b[48;5;${non_padded_value}m___________________________")
         foreground=$(printf "\x1b[38;5;${non_padded_value}m$color_variable")
         printf "%s %s %s %-30s %s\x1b[0m\n" $foreground $base16_color_name $current_color_label ${ansi_label:-""} $block
      done;
      #if [ $# -eq 1 ]; then
      #   printf "To restore current theme, source ~/.base16_theme or reopen your terminal\n"
      #fi
      # <<<
   elif [ $1 -eq '3' ];then
      # Similar to above, but does 256-bit colors. >>>
      # Taken from this: https://github.com/romkatv/powerlevel10k#set-colors-through-Powerlevel10k-configuration-parameters
      for i in {0..255}; do
         print -Pn "%K{$i}  %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$'\n'}
      done
      # <<<
   else
      cat <<-EOF
			Usage: prcolors <printing method number>
			   1: Manjaro bashrc -- for checking text readability
			   2: base26shell    -- for seeing the 16 set terminal colors
			   3: 256            -- for testing 256 color output
		EOF
      fi
   }
   # <<<

   # shellcheck disable=SC2016
   mkcd() {
      mkdir -p "$1" || error $LINENO
      cd "$1" || error $LINENO
   }
   
   # shellcheck disable=SC2086
   random-mac() {
      interfaces=(enp5s0 wlp4s0)
      for interface in "${interfaces[@]}";do
         echo " Changing interface: $interface"
         sudo ip link set dev $interface down
         sudo macchanger -r $interface
         sudo ip link set dev $interface up
      done
   }

   # Git cLONE cD
   gloned() {
      git clone "$1"
      if ! cd "$(echo "$1" | sed 's/\.git//g' | rev | cut -d '/' -f 1 | rev)";then
         echo 'Error: Could not `cd` into the repo'
         return 1
      fi
      echo
      ls --color=auto
   }

   # believe it or not, zsh makes for a fine calculator
   calc() {
      echo $(($*))
   }

   # Makes a swapfile at /swapfile of a given size (ex: mkswp 4G)
   mkswp() {
      sudo fallocate -l "$1" /swapfile &&
      sudo chmod 600 /swapfile
      sudo mkswap /swapfile &&
      sudo swapon /swapfile
   }

   # Deletes the swapfile created by mkswp()
   rmswp() {
      sudo swapoff -v /swapfile &&
      sudo rm /swapfile
   }

   # optionally source an external function file
   [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/fnrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/fnrc"
}
# <<<
# <<<
### Plugins >>>
{
   # plugin config >>>
   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
   # vim-mode cursor
   # syntax: "[color] [blinking] [style]" see: https://github.com/softmoth/zsh-vim-mode#mode-in-prompt
   MODE_CURSOR_VIINS="blinking bar"
   MODE_CURSOR_REPLACE="steady bar"
   MODE_CURSOR_VICMD="steady block"
   MODE_CURSOR_SEARCH="blinking underline"
   MODE_CURSOR_VISUAL="steady block"
   MODE_CURSOR_VLINE="steady block"
   # <<<
   # Load zinit >>>
   {
      # Install zinit if not installed
      if [[ ! -f $HOME/.zinit/bin/zinit.zsh ]]; then
         print -P "%F{33}▓▒░ %F{220}Installing %F{33}DHARMA%F{220} Initiative Plugin Manager (%F{33}zdharma/zinit%F{220})…%f"
         command mkdir -p "$HOME/.zinit" && command chmod g-rwX "$HOME/.zinit"
         command git clone https://github.com/zdharma/zinit "$HOME/.zinit/bin" && \
            print -P "%F{33}▓▒░ %F{34}Installation successful.%f%b" || \
            print -P "%F{160}▓▒░ The clone has failed.%f%b"
      fi

      # Source zinit
      source "$HOME/.zinit/bin/zinit.zsh"
      autoload -Uz _zinit
      (( ${+_comps} )) && _comps[zinit]=_zinit

      # Load a few important annexes, without Turbo
      # (this is currently required for annexes)
      zinit light-mode for \
         zinit-zsh/z-a-rust \
         zinit-zsh/z-a-as-monitor \
         zinit-zsh/z-a-patch-dl \
         zinit-zsh/z-a-bin-gem-node
   }
   # <<<
   # Plugins to install >>>
   {
      zinit ice wait'!0' # Enable turbo mode
      zinit ice depth"1" # git clone depth
      zinit snippet OMZ::lib/history.zsh
      # Some better completion options
      zinit snippet OMZ::lib/completion.zsh

      # Quality of life
      zinit load "zsh-users/zsh-autosuggestions"
      zinit load "zdharma/fast-syntax-highlighting"
      # zinit load "softmoth/zsh-vim-mode"
      zinit load "jeffreytse/zsh-vi-mode"
      zinit load "zsh-users/zsh-history-substring-search"
      zinit load "zsh-users/zsh-completions"

      ## Themes
      # terminal colors
      if [[ -f ~/.config/shell/colors.sh ]];then
         source ~/.config/shell/colors.sh 
      else
         zinit snippet 'https://github.com/chriskempson/base16-shell/blob/master/scripts/base16-onedark.sh' # onedark shell colors
      fi
      zinit load "romkatv/powerlevel10k"
      zinit ice atclone"dircolors -b ./src/dir_colors > colors.zsh" \
         atpull'%atclone' pick"colors.zsh" nocompile'!' \
         atload'zstyle ":completion:*" list-colors “${(s.:.)LS_COLORS}”'
      zinit light arcticicestudio/nord-dircolors
      [[ -f ~/.p10k.zsh ]] && source ~/.p10k.zsh
   }
   # <<<
}
# <<<
### General ZSH configuration >>> 
# This section is (mostly) From manjaro's "manjaro-zsh-config" (/usr/share/zsh/manjaro-zsh-config)

[ -z "$HISTFILE" ] && HISTFILE="$HOME/.zsh_history"

## ZSH Options >>>
{
   # setopt correct                                                 # Auto correct mistakes
   setopt extendedglob                                            # Extended globbing. Allows using regular expressions with *
   setopt nocaseglob                                              # Case insensitive globbing
   setopt rcexpandparam                                           # Array expension with parameters
   setopt checkjobs                                               # Warn about running processes when exiting
   setopt numericglobsort                                         # Sort filenames numerically when it makes sense
   setopt nobeep                                                  # Most important option
   setopt appendhistory                                           # Immediately append history instead of overwriting
   setopt inc_append_history                                      # save commands are added to the history immediately, otherwise only when shell exits.
   setopt histfindnodups                                          # If a new command is a duplicate, remove the older one
   setopt histignorealldups                                       # If a new command is a duplicate, remove the older one
   setopt autocd                                                  # if only directory path is entered, cd there.
   setopt interactive_comments                                    # allow typing comments in line
   setopt no_rm_star_silent                                       # Ensure the user wants to execute 'rm *'
   setopt rm_star_wait                                            # Wait before accepting 'rm *' or 'rm /path/*'
   setopt short_loops                                             # allow things like 'if [ 1=1 ] { echo "okay"}' < https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#Alternate-Forms-For-Complex-Commands
   setopt pipe_fail                                               # When a pipe fails, show the non-0 exit code for the exit code
}
# <<<
## ZSH Completion Options >>>
{
   # Mine
   zstyle ':completion:*' completer _expand _complete _ignored _prefix
   zstyle ':completion:*' expand prefix suffix
   zstyle ':completion:*' file-sort access
   zstyle ':completion:*' ignore-parents parent pwd directory
   zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
   zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s
   zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|[._-]=** r:|=**'
   zstyle ':completion:*' menu select=long
   zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s
   zstyle :compinstall filename '/home/blake/.zshrc'

   # Manjaro's
   # zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'      # Case insensitive tab completion
   # zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"        # Colored completion (different colors for dirs/files/etc)
   # zstyle ':completion:*' rehash true                             # automatically find new executables in path
   # # Speed up completions
   zstyle ':completion:*' accept-exact '*(N)'
   zstyle ':completion:*' use-cache on
   zstyle ':completion:*' cache-path $ZSH_CACHE_DIR
   WORDCHARS=${WORDCHARS//\/[&.;]}                                 # Don't consider certain characters part of the word

   # just gonna sneak this in here, too
   unalias zi zpl zini zplg which-command run-help
}
# <<<
## Keybindings >>>
bindkey -v                                                     # Enable Vi mode
bindkey '^[[7~' beginning-of-line                              # Home key
bindkey '^[[H' beginning-of-line                               # Home key
if [[ "${terminfo[khome]}" != "" ]]; then
   bindkey "${terminfo[khome]}" beginning-of-line              # [Home] - Go to beginning of line
fi
bindkey '^[[8~' end-of-line                                    # End key
bindkey '^[[F' end-of-line                                     # End key
if [[ "${terminfo[kend]}" != "" ]]; then
   bindkey "${terminfo[kend]}" end-of-line                     # [End] - Go to end of line
fi
bindkey '^[[2~' overwrite-mode                                 # Insert key
bindkey '^[[3~' delete-char                                    # Delete key
bindkey '^[[C'  forward-char                                   # Right key
bindkey '^[[D'  backward-char                                  # Left key
bindkey '^[[5~' history-beginning-search-backward              # Page up key
bindkey '^[[6~' history-beginning-search-forward               # Page down key

# Navigate words with ctrl+arrow keys
bindkey '^[Oc' forward-word                                    #
bindkey '^[Od' backward-word                                   #
bindkey '^[[1;5D' backward-word                                #
bindkey '^[[1;5C' forward-word                                 #
# Delete words with ctrl+bksp/del
bindkey '^H' backward-kill-word                                # delete previous word with ctrl+backspace
bindkey '^[[3;5~' kill-word                                    # delete next word with ctrl+delete
bindkey '^[[Z' undo                                            # Shift+tab undo last action

# bind UP and DOWN arrow keys to history substring search
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
bindkey -M vicmd 'k' history-substring-search-up
bindkey -M vicmd 'j' history-substring-search-down
# <<<

# Colors and compinit >>>
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
autoload -U compinit colors zcalc
compinit -d 2>&1 > /dev/null
colors
# <<<
### Various manjaro ZSH functions >>>
# Set terminal window and tab/icon title >>>
# usage: title short_tab_title [long_window_title]
# See: http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#ss3.1
# Fully supports screen and probably most modern xterm and rxvt
# (In screen, only short_tab_title is used)
function title {
   emulate -L zsh
   setopt prompt_subst

   [[ "$EMACS" == *term* ]] && return

  # if $2 is unset use $1 as default
  # if it is set and empty, leave it as is
  : ${2=$1}

  case "$TERM" in
     xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty|st*)
        print -Pn "\e]2;${2:q}\a" # set window name
        print -Pn "\e]1;${1:q}\a" # set tab name
        ;;
     screen*|tmux*)
        print -Pn "\ek${1:q}\e\\" # set screen hardstatus
        ;;
     *)
        # Try to use terminfo to set the title
        # If the feature is available set title
        if [[ -n "$terminfo[fsl]" ]] && [[ -n "$terminfo[tsl]" ]]; then
           echoti tsl
           print -Pn "$1"
           echoti fsl
        fi
        ;;
  esac
}
# <<<

ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" # 15 char left truncated PWD
ZSH_THEME_TERM_TITLE_IDLE="%n@%m:%~"

# Runs before showing the prompt >>>
function mzc_termsupport_precmd {
   [[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return
   title $ZSH_THEME_TERM_TAB_TITLE_IDLE $ZSH_THEME_TERM_TITLE_IDLE
}
# <<<

# Runs before executing the command >>>
function mzc_termsupport_preexec {
   [[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return

   emulate -L zsh

  # split command into array of arguments
  local -a cmdargs
  cmdargs=("${(z)2}") # " <- syntax highlighting fix
  
  # if running fg, extract the command from the job description
  if [[ "${cmdargs[1]}" = fg ]]; then
     # get the job id from the first argument passed to the fg command
     local job_id jobspec="${cmdargs[2]#%}"
     # logic based on jobs arguments:
     # http://zsh.sourceforge.net/Doc/Release/Jobs-_0026-Signals.html#Jobs
     # https://www.zsh.org/mla/users/2007/msg00704.html
     case "$jobspec" in
        <->) # %number argument:
           # use the same <number> passed as an argument
           job_id=${jobspec} ;;
        ""|%|+) # empty, %% or %+ argument:
           # use the current job, which appears with a + in $jobstates:
           # suspended:+:5071=suspended (tty output)
           job_id=${(k)jobstates[(r)*:+:*]} ;;
        -) # %- argument:
           # use the previous job, which appears with a - in $jobstates:
           # suspended:-:6493=suspended (signal)
           job_id=${(k)jobstates[(r)*:-:*]} ;;
        [?]*) # %?string argument:
           # use $jobtexts to match for a job whose command *contains* <string>
           job_id=${(k)jobtexts[(r)*${(Q)jobspec}*]} ;;
        *) # %string argument:
           # use $jobtexts to match for a job whose command *starts with* <string>
           job_id=${(k)jobtexts[(r)${(Q)jobspec}*]} ;;
     esac

    # override preexec function arguments with job command
    if [[ -n "${jobtexts[$job_id]}" ]]; then
       1="${jobtexts[$job_id]}"
       2="${jobtexts[$job_id]}"
    fi
  fi

  # cmd name only, or if this is sudo or ssh, the next cmd
  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
# <<<
# auto save and load working dir (allow `cd -` on start) >>>
# Load the last working directory
load_working_dir() {
   # load the directory  (and do validation to make sure it's actually a directory)
   if test -f "$WORKING_DIR_SAVE_FILE"; then
      local PREVIOUS_WORKING_DIR="$(cat "$WORKING_DIR_SAVE_FILE")"
      if test -d "$(cat "$WORKING_DIR_SAVE_FILE")"; then
         cd "$PREVIOUS_WORKING_DIR" || error $LINENO
      else
         echo "Invalid saved working directory ($PREVIOUS_WORKING_DIR)" > /dev/null
         return 1
      fi
   else
      echo "Invalid working directory save file ($WORKING_DIR_SAVE_FILE)" > /dev/null
      return 1
   fi
}

save_working_dir() {
   pwd > "$WORKING_DIR_SAVE_FILE"
}

autoload -U add-zsh-hook
add-zsh-hook chpwd save_working_dir

load_working_dir &&
   cd - > /dev/null
# <<<
# <<<

# Optionally source the user's customized .zshrc
[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/zshrc.local" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/zshrc.local" || return 0

# vim:fdm=marker:fmr=>>>,<<<:et:ft=sh:sw=3