xref: /llvm-project/clang/utils/bash-autocomplete.sh (revision 8c000110cf3a858aa34bff1ea63f17daba4f41bb)
1# Please add "source /path/to/bash-autocomplete.sh" to your .bashrc to use this.
2
3_clang_filedir()
4{
5  # _filedir function provided by recent versions of bash-completion package is
6  # better than "compgen -f" because the former honors spaces in pathnames while
7  # the latter doesn't. So we use compgen only when _filedir is not provided.
8  _filedir 2> /dev/null || COMPREPLY=( $( compgen -f ) )
9}
10
11_clang()
12{
13  local cur prev words cword arg flags w1 w2
14  # If latest bash-completion is not supported just initialize COMPREPLY and
15  # initialize variables by setting manualy.
16  _init_completion -n 2> /dev/null
17  if [[ "$?" != 0 ]]; then
18    COMPREPLY=()
19    cword=$COMP_CWORD
20    cur="${COMP_WORDS[$cword]}"
21  fi
22
23  w1="${COMP_WORDS[$cword - 1]}"
24  if [[ $cword > 1 ]]; then
25    w2="${COMP_WORDS[$cword - 2]}"
26  fi
27
28  # Clang want to know if -cc1 or -Xclang option is specified or not, because we don't want to show
29  # cc1 options otherwise.
30  if [[ "${COMP_WORDS[1]}" == "-cc1" || "$w1" == "-Xclang" ]]; then
31    arg="#"
32  fi
33
34  # bash always separates '=' as a token even if there's no space before/after '='.
35  # On the other hand, '=' is just a regular character for clang options that
36  # contain '='. For example, "-stdlib=" is defined as is, instead of "-stdlib" and "=".
37  # So, we need to partially undo bash tokenization here for integrity.
38  if [[ "$cur" == -* ]]; then
39    # -foo<tab>
40    arg="$arg$cur"
41  elif [[ "$w1" == -*  && "$cur" == '=' ]]; then
42    # -foo=<tab>
43    arg="$arg$w1=,"
44  elif [[ "$cur" == -*= ]]; then
45    # -foo=<tab>
46    arg="$arg$cur,"
47  elif [[ "$w1" == -* ]]; then
48    # -foo <tab> or -foo bar<tab>
49    arg="$arg$w1,$cur"
50  elif [[ "$w2" == -* && "$w1" == '=' ]]; then
51    # -foo=bar<tab>
52    arg="$arg$w2=,$cur"
53  elif [[ ${cur: -1} != '=' && ${cur/=} != $cur ]]; then
54    # -foo=bar<tab>
55    arg="$arg${cur%=*}=,${cur#*=}"
56  fi
57
58  # expand ~ to $HOME
59  eval local path=${COMP_WORDS[0]}
60  flags=$( "$path" --autocomplete="$arg" 2>/dev/null )
61  # If clang is old that it does not support --autocomplete,
62  # fall back to the filename completion.
63  if [[ "$?" != 0 ]]; then
64    _clang_filedir
65    return
66  fi
67
68  # When clang does not emit any possible autocompletion, or user pushed tab after " ",
69  # just autocomplete files.
70  if [[ "$flags" == "$(echo -e '\n')" || "$arg" == "" ]]; then
71    # If -foo=<tab> and there was no possible values, autocomplete files.
72    [[ "$cur" == '=' || "$cur" == -*= ]] && cur=""
73    _clang_filedir
74  elif [[ "$cur" == '=' ]]; then
75    COMPREPLY=( $( compgen -W "$flags" -- "") )
76  else
77    # Bash automatically appends a space after '=' by default.
78    # Disable it so that it works nicely for options in the form of -foo=bar.
79    [[ "${flags: -1}" == '=' ]] && compopt -o nospace 2> /dev/null
80    COMPREPLY=( $( compgen -W "$flags" -- "$cur" ) )
81  fi
82}
83complete -F _clang clang
84