#!/bin/zsh
zmodload -Fa zsh/zutil b:zstyle

typeset -g ZLE_REMOVE_SUFFIX_CHARS=$' /;\n\r\t'
typeset -g ZLE_SPACE_SUFFIX_CHARS='|&<>-+'

builtin zstyle ':completion:*' use-cache yes
builtin zstyle -e ':completion:*' cache-path autocomplete:config:cache-path
autocomplete:config:cache-path() {
  reply=( "${XDG_CACHE_HOME:-$HOME/.cache}/zsh/compcache" )
}

builtin zstyle ':completion:*' completer _expand _complete _prefix _ignored _correct _approximate

builtin zstyle    ':completion:*:expand:*' tag-order '! expansions original' -
builtin zstyle    ':completion:*:expand:*' accept-exact continue
builtin zstyle -e ':completion:*:expand:*' glob _autocomplete__is_glob
builtin zstyle    ':completion:*:expand:*' keep-prefix no  # Needed for file type highlighting
builtin zstyle    ':completion:*:expand:*' add-space subst
builtin zstyle -e ':completion:*:expand:*' substitute autocomplete:config:substitute:expand
autocomplete:config:substitute:expand() {
  local -P __word__=$PREFIX$SUFFIX
  if [[ ${(Q)__word__} == *(\`*\`|\$\(*\))* ]]; then
    reply=( false )
  else
    reply=( true )
  fi
}


builtin zstyle -e ':completion:*:-command-:*' tag-order autocomplete:config:tag-order:command
autocomplete:config:tag-order:command() {
  if [[ $PREFIX == (|.|*/*) ]]; then
    reply=( 'suffix-aliases (|*-)directories executables (|*-)files' - )
  else
    reply=( aliases suffix-aliases functions 'reserved-words builtins' )
    if [[ -n $path[(r).] ]]; then
      reply+=( '(|*-)directories executables (|*-)files' commands )
    else
      reply+=( commands '(|*-)directories executables (|*-)files' )
    fi
  fi
}
builtin zstyle ':completion:*:-tilde-:*' tag-order directory-stack named-directories

builtin zstyle ':completion:*:(approximate|correct):*' tag-order '! original' -

# Complete options rather than directory stack. You can get directory stack by typing `~-` (tilde plus dash).
builtin zstyle ':completion:*:cd:*' complete-options yes
builtin zstyle ':completion:*:cd:*' tag-order '! directory-stack' -

# Don't show the giant list of history lines.
builtin zstyle ':completion:*:fc:*' tag-order options -

builtin zstyle ':completion:*:git-*:(|*-)argument-*:*' tag-order \
    '! (|cached-)files *-remote remote-* (|*-)tags' \
    '! *-remote remote-* tags'

# Order of matchers matters: m should come before r, which should come before l.
# Otherwise, the results are not as expected.
builtin zstyle ':completion:*' matcher-list \
    'm:{[:lower:]-}={[:upper:]_} r:|[.]=**' \
    '+l:|=*' \
    'm:{[:lower:]-}={[:upper:]_} r:|[.]=** l:?|=[-_\\ ] r:?||[-_]=*' \
    'm:{[:lower:]-}={[:upper:]_} r:|?=**'

builtin zstyle ':completion:*:options' matcher 'b:-=+'

builtin zstyle ':completion:*' prefix-needed yes
builtin zstyle ':completion:*:functions'  ignored-patterns '*.*' '*:*' '+*'
builtin zstyle ':completion:*:users'      ignored-patterns '_*'
builtin zstyle ':completion:*:widgets'    ignored-patterns '*.*' '*:*'
builtin zstyle ':completion:*' single-ignored ''

builtin zstyle ':completion:*:expand-alias:*' complete yes

# Complete only the tail of a path.
builtin zstyle ':completion:*' ignore-parents 'parent pwd directory'
builtin zstyle ':completion:*:paths' expand suffix
builtin zstyle ':completion:*:paths' list-suffixes yes
builtin zstyle ':completion:*:paths' path-completion no
builtin zstyle ':completion:*:paths' special-dirs no

builtin zstyle ':completion:*' group-name ''
builtin zstyle ':completion:*' group-order \
    all-expansions expansions options \
    aliases suffix-aliases functions reserved-words builtins commands \
    local-directories directories executables

builtin zstyle    ':completion:*'               file-patterns '*(-/):directories:directory %p(#q^-/):globbed-files'
builtin zstyle -e ':completion:*:-command-:*'   file-patterns autocomplete:config:file-patterns:command
autocomplete:config:file-patterns:command() {
  [[ $PREFIX$SUFFIX != */* ]] &&
      reply=( '*(-/):directories:directory ./*(-*^/):executables:"executable file"' )
}
builtin zstyle    ':completion:*:(.|source):*'  file-patterns \
    '%p(#q-/):directories:directory %p~*.zwc(-.^*):globbed-files' '%p~*.zwc(-^/):globbed-files'

# Don't combine parameters with same values.
builtin zstyle ':completion:*:parameters' list-grouped no

builtin zstyle ':completion:*:descriptions'   format $'%{\e[0;1;2m%}%d%{\e[0m%}'
builtin zstyle -e ':completion:*:warnings'    format autocomplete:config:format:warnings
autocomplete:config:format:warnings() {
  [[ $CURRENT == 1 && -z $PREFIX$SUFFIX ]] ||
      reply=( $'%{\e[0;2m%}'"no matching %d completions"$'%{\e[0m%}' )
}
builtin zstyle ':completion:*:messages'       format '%F{9}%d%f'
builtin zstyle ':completion:*:history-lines'  format ''

builtin zstyle ':completion:*' auto-description '%d'
builtin zstyle ':completion:*:parameters' extra-verbose yes
builtin zstyle ':completion:*:default' select-prompt '%F{black}%K{12}line %l %p%f%k'

builtin zstyle ':completion:*' insert-sections yes
builtin zstyle ':completion:*' separate-sections yes

# Needed for _gnu_generic to prevent descriptions from getting cropped.
is-at-least 5.9 ||
    builtin zstyle ':completion:*' command '- COLUMNS=999'

.autocomplete:config:precmd() {
  typeset -g _comp_setup="$_comp_setup"';
      [[ $_comp_caller_options[globdots] == yes ]] && setopt globdots'

  # Remove incompatible settings.
  local -P key= setting=
  for key in menu list-prompt; do
    for setting in ${(f)"$( zstyle -L '*' $key )"}; do
      eval "${setting/zstyle(| -e)/zstyle -d}"
    done
  done
  builtin zstyle ':completion:*:*:*:*:default' menu no no-select
  unset LISTPROMPT
}
