about summary refs log tree commit diff
path: root/Completion/Base/Widget/_next_tags
blob: 0620a1f99e3496b27cee1653e6babe1548835487 (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
#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=-J len tmp pre suf ret=1 descr spec

    if [[ "$1" = -([12]|)[VJ] ]]; then
      gopt="$1"
      shift
    fi

    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 "$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]}"
      else
        _description "$gopt" "$curtag" "$2" "$3"

        "${(@)argv[4,pre]}" "${(P@)2}" "${(@)argv[suf,-1]}" && ret=0
      fi
    done

    return ret
  }

  _next_label() {
    local gopt=-J descr spec

    if [[ "$1" = -([12]|)[VJ] ]]; then
      gopt="$1"
      shift
    fi

    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 "$@"