about summary refs log tree commit diff
path: root/Completion/Base/Widget/_next_tags
blob: eaf7e3ace3d577e588aab7356c11ca871f95aa42 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#compdef -k complete-word \C-xn

# Main widget.

_next_tags() {
  eval "$_comp_setup"

  local ins ops="$PREFIX$SUFFIX"

  unfunction _all_labels _next_label

  _all_labels() {
    local __gopt __len __tmp __pre __suf __ret=1 __descr __spec __prev

    if [[ "$1" = - ]]; then
      __prev=-
      shift
    fi

    __gopt=()
    zparseopts -D -a __gopt 1 2 V J x

    __tmp=${argv[(ib:4:)-]}
    __len=$#
    if [[ __tmp -lt __len ]]; then
      __pre=$(( __tmp-1 ))
      __suf=$__tmp
    elif [[ __tmp -eq $# ]]; then
      __pre=-2
      __suf=$(( __len+1 ))
    else
      __pre=4
      __suf=5
    fi

    while comptags "-A$__prev" "$1" curtag __spec; do
      [[ "$_next_tags_not" = *\ ${__spec}\ * ]] && continue
      _comp_tags="$_comp_tags $__spec "
      if [[ "$curtag" = *[^\\]:* ]]; then
        zformat -f __descr "${curtag#*:}" "d:$3"
        _description "$__gopt[@]" "${curtag%:*}" "$2" "$__descr"
        curtag="${curtag%:*}"

        "$4" "${(P@)2}" "${(@)argv[5,-1]}" && __ret=0
      else
        _description "$__gopt[@]" "$curtag" "$2" "$3"

        "${(@)argv[4,__pre]}" "${(P@)2}" "${(@)argv[__suf,-1]}" && __ret=0
      fi
    done

    return __ret
  }

  _next_label() {
    local __gopt __descr __spec

    __gopt=()
    zparseopts -D -a __gopt 1 2 V J x

    if comptags -A "$1" curtag __spec; then
      [[ "$_next_tags_not" = *\ ${__spec}\ * ]] && continue
      _comp_tags="$_comp_tags $__spec "
      if [[ "$curtag" = *[^\\]:* ]]; then
        zformat -f __descr "${curtag#*:}" "d:$3"
        _description "$__gopt[@]" "${curtag%:*}" "$2" "$__descr"
        curtag="${curtag%:*}"
	set -A $2 "${(P@)2}" "${(@)argv[4,-1]}"
      else
        _description "$__gopt[@]" "$curtag" "$2" "$3"
	set -A $2 "${(@)argv[4,-1]}" "${(P@)2}"
      fi

      return 0
    fi

    return 1
  }

  if [[ "${LBUFFER%${PREFIX}}" = "$_next_tags_pre" ]]; then
    PREFIX="$_next_tags_pfx"
    SUFFIX="$_next_tags_sfx"
  else
    _next_tags_pre="${LBUFFER%${PREFIX}}"
    if [[ "$LASTWIDGET" = (_next_tags|list-*|*complete*) ]]; then
      PREFIX="$_lastcomp[prefix]"
      SUFFIX="$_lastcomp[suffix]"
    fi
  fi

  _next_tags_not="$_next_tags_not $_lastcomp[tags]"
  _next_tags_pfx="$PREFIX"
  _next_tags_sfx="$SUFFIX"

  if [[ -n "$compstate[old_insert]" ]]; then
    ins=1
  else
    ins=unambiguous
  fi

  _main_complete _complete _next_tags_completer

  [[ $compstate[insert] = automenu ]] && compstate[insert]=automenu-unambiguous
  [[ $compstate[insert] = *unambiguous && -n "$ops" &&
     -z "$_lastcomp[unambiguous]" ]] && compadd -Uns "$SUFFIX" - "$PREFIX"

  compstate[insert]="$ins"
  compstate[list]='list force'

  compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
}

# Completer, for wrap-around.

_next_tags_completer() {
  _next_tags_not=

  _complete
}

# Pre-completion function.

_next_tags_pre() {

  # Probably `remove' our label functions. A better test would be nice, but
  # I think one should still be able to edit the current word between
  # attempts to complete it.

  if [[ -n $compstate[old_insert] && $WIDGET != _next_tags ]]; then
    compstate[old_list]=keep
    compstate[insert]=menu:2
    return 0
  elif [[ ${LBUFFER%${PREFIX}} != ${_next_tags_pre}* ]]; then
    unfunction _all_labels _next_label
    autoload -U _all_labels _next_label
  else
    compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
  fi
}

_next_tags "$@"