about summary refs log tree commit diff
path: root/Completion/Core/_display
blob: 5bddeaac13cf55dab52a6e5ac5e86f6bea060134 (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
#autoload

# This builds a display-list for the `-y' option of `compadd' and
# `compgen' out of the arguments it gets. The first argument is
# taken as the name of a parameter and the string built is stored
# into it.
# The second argument is the name of an array whose elements each
# contains a string to complete, optionally followed by a colon
# and a description. The display list created will contain one
# line per string with the description after it, all nicely
# aligned. Strings without descriptions are put at the end in a
# column-oriented fashion.
# All arguments after the second one are given as arguments to
# `compadd'.
# This function will also do the matching required to find out
# which strings will be included in the list. All elements that
# don't match will be removed from the array. This means that the
# special parameters `PREFI' and `SUFFIX' have to be set up 
# correctly before this function is called.

local _param="$1" _arr _len _i _tmp _simple

# Remove all descriptions not matched by the string on the line.

if [[ "${2[1]}" = \( ]]; then
  _arr=( ${(o)=2[2,-2]} )
else
  _arr=( "${(@Po)2}" )
fi

compadd -D _arr "${(@)argv[3,-1]}" - "${(@)_arr%%:*}"

[[ "${2[1]}" != \( ]] && eval "${2}=( \"\$_arr[@]\" )"

if (( $#_arr )); then

  # There are strings left, first get the length of the longest of
  # them (to be able to align them) and collect all strings without
  # descriptions.

  _simple=()
  _len=1
  for _i in "$_arr[@]";  do
    _tmp="${#_i%%:*}"
    if [[ "$_i" = *:?* ]]; then
      [[ _tmp -gt _len ]] && _len="$_tmp"
    else
      _simple=( "$_simple[@]" "${_i%:}" )
    fi
  done

  # Now we build the list in `_tmp', adding one line per string.

  _tmp=''
  for _i in "$_arr[@]"; do
    [[ "$_i" = *:?* ]] && _tmp="$_tmp
${(r:_len:: :)_i%%:*} -- ${_i#*:}"
  done

  # If there were strings without descriptions, we just add them by
  # calling `print -c'.

  (( $#_simple )) && _tmp="${_tmp}
$(print -c - $_simple)"

  eval "${_param}=${(q)_tmp[2,-1]}"

  return 0
else

  # None of the strings matches what's on the line, signal this by
  # setting the parameter to an empty string and by the return value.

  eval "${_param}=''"
  return 1
fi