summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2016-08-01 14:22:11 +0200
committerLubomir Rintel <lkundrak@v3.sk>2017-02-13 16:32:15 +0100
commit9d2290135ce50fca1e2d1ef4a724bb23d2ea4f53 (patch)
tree779809e37df825f4d14422e5fd4bd728a62382e3
parentb2146a43e5591c1ae6fd94379749781858f4d057 (diff)
downloadNetworkManager-9d2290135ce50fca1e2d1ef4a724bb23d2ea4f53.tar.gz
cli: make nmcli do its own command completionlr/completion-3
https://bugzilla.gnome.org/show_bug.cgi?id=777328
-rw-r--r--clients/cli/nmcli-completion1297
1 files changed, 57 insertions, 1240 deletions
diff --git a/clients/cli/nmcli-completion b/clients/cli/nmcli-completion
index e1716f6024..45dfe89c34 100644
--- a/clients/cli/nmcli-completion
+++ b/clients/cli/nmcli-completion
@@ -1,16 +1,65 @@
-# nmcli(1) completion -*- shell-script -*-
-# Originally based on
-# https://github.com/GArik/bash-completion/blob/master/completions/nmcli
+# nmcli(1) completion
-_nmcli_list()
+_nmcli_array_delete_at()
{
- COMPREPLY=( $( compgen -W '$1' -- $cur ) )
+ eval "local ARRAY=(\"\${$1[@]}\")"
+ local i
+ local tmp=()
+ local lower=$2
+ local upper=${3:-$lower}
+
+ # for some reason the following fails. So this clumsy workaround...
+ # A=(a "")
+ # echo " >> ${#A[@]}"
+ # >> 2
+ # A=("${A[@]:1}")
+ # echo " >> ${#A[@]}"
+ # >> 0
+ # ... seriously???
+
+ for i in "${!ARRAY[@]}"; do
+ if [[ "$i" -lt "$2" || "$i" -gt "${3-$2}" ]]; then
+ tmp=("${tmp[@]}" "${ARRAY[$i]}")
+ fi
+ done
+ eval "$1=(\"\${tmp[@]}\")"
}
-_nmcli_list_nl()
+_nmcli()
{
+ local cur words cword i output
+ _init_completion || return
+
+ # we don't care about any arguments after the current cursor position
+ # because we only parse from left to right. So, if there are some arguments
+ # right of the cursor, just ignore them. Also don't care about ${words[0]}.
+ _nmcli_array_delete_at words $((cword+1)) ${#words[@]}
+ _nmcli_array_delete_at words 0
+
+ # _init_completion returns the words with all the quotes and escaping
+ # characters. We don't care about them, drop them at first.
+ for i in ${!words[@]}; do
+ words[i]="$(printf '%s' "${words[i]}" | xargs printf '%s\n' 2>/dev/null || true)"
+ done
+
+ # In case the cursor is not at the end of the line,
+ # $cur consists of spaces that we want do remove.
+ # For example: `nmcli connection modify id <TAB> lo`
+ if [[ "$cur" =~ ^[[:space:]]+ ]]; then
+ cur=''
+ fi
+
+ output="$(nmcli --complete-args "${words[@]}" 2>/dev/null)"
+
+ # Bail out early if we're completing a file name
+ if [ $? = 65 ]; then
+ compopt -o default
+ COMPREPLY=()
+ return 0
+ fi
+
local IFS=$'\n'
- COMPREPLY=( $( compgen -W '$1' -- $cur ) )
+ COMPREPLY=( $( compgen -W '$output' -- $cur ) )
# Now escape special characters (spaces, single and double quotes),
# so that the argument is really regarded a single argument by bash.
@@ -25,7 +74,7 @@ _nmcli_list_nl()
# [']bla'bla"bla\bla bla --> [']bla'\''bla"bla\bla bla
COMPREPLY[$i]="${entry//\'/${escaped_single_quote}}"
elif [[ "${cur:0:1}" == '"' ]]; then
- # started with double quote, escaping all double quotes, backslashes and !
+ # started with double quote, escaping all double quotes and all backslashes
# ["]bla'bla"bla\bla bla --> ["]bla'bla\"bla\\bla bla
entry="${entry//\\/\\\\}"
entry="${entry//\"/\\\"}"
@@ -60,1239 +109,7 @@ _nmcli_list_nl()
COMPREPLY[$i]=${entry}
(( i++ ))
done
-}
-
-_nmcli_con_show()
-{
- nmcli -t -f "$1" connection show $2 2> /dev/null
-}
-
-_nmcli_wifi_list()
-{
- nmcli -t -f "$1" device wifi list 2>/dev/null
-}
-
-_nmcli_dev_status()
-{
- nmcli -t -f "$1" device status 2>/dev/null
-}
-
-_nmcli_array_has_value() {
- # expects the name of an array as first parameter and
- # returns true if if one of the remaining arguments is
- # contained in the array ${$1[@]}
- eval "local ARRAY=(\"\${$1[@]}\")"
- local arg a
- shift
- for arg; do
- for a in "${ARRAY[@]}"; do
- if [[ "$a" = "$arg" ]]; then
- return 0
- fi
- done
- done
- return 1
-}
-
-_nmcli_array_delete_at()
-{
- eval "local ARRAY=(\"\${$1[@]}\")"
- local i
- local tmp=()
- local lower=$2
- local upper=${3:-$lower}
-
- # for some reason the following fails. So this clumsy workaround...
- # A=(a "")
- # echo " >> ${#A[@]}"
- # >> 2
- # A=("${A[@]:1}")
- # echo " >> ${#A[@]}"
- # >> 0
- # ... seriously???
-
- for i in "${!ARRAY[@]}"; do
- if [[ "$i" -lt "$2" || "$i" -gt "${3-$2}" ]]; then
- tmp=("${tmp[@]}" "${ARRAY[$i]}")
- fi
- done
- eval "$1=(\"\${tmp[@]}\")"
-}
-
-_nmcli_compl_match_option()
-{
- local S="$1"
- local V
- shift
- if [[ "${S:0:2}" == "--" ]]; then
- S="${S:2}"
- elif [[ "${S:0:1}" == "-" ]]; then
- S="${S:1}"
- else
- return 1
- fi
- for V; do
- case "$V" in
- "$S"*)
- printf "%s" "$V"
- return 0
- ;;
- esac
- done
- return 1
-}
-
-# OPTIONS appear first at the command line (before the OBJECT).
-# This iterates over the argument list and tries to complete
-# the options. If there are options that are to be completed,
-# zero is returned and completion will be performed.
-# Otherwise it will remove all the option parameters from the ${words[@]}
-# array and return with zero (so that completion of OBJECT can continue).
-_nmcli_compl_OPTIONS()
-{
- local i W
-
- for (( ; ; )); do
- if [[ "${#words[@]}" -le 1 ]]; then
- return 1
- fi
- W="$(_nmcli_compl_match_option "${words[0]}" "${LONG_OPTIONS[@]}")"
- if [[ $? != 0 ]]; then
- return 2
- fi
-
- # remove the options already seen.
- for i in ${!LONG_OPTIONS[@]}; do
- if [[ "${LONG_OPTIONS[$i]}" == "$W" ]]; then
- _nmcli_array_delete_at LONG_OPTIONS $i
- break
- fi
- done
-
- if [[ "$HELP_ONLY_AS_FIRST" == '1' ]]; then
- for i in ${!LONG_OPTIONS[@]}; do
- if [[ "${LONG_OPTIONS[$i]}" == "help" ]]; then
- _nmcli_array_delete_at LONG_OPTIONS $i
- break
- fi
- done
- fi
-
- case "$W" in
- terse)
- _nmcli_array_delete_at words 0
- ;;
- pretty)
- _nmcli_array_delete_at words 0
- ;;
- ask)
- _nmcli_array_delete_at words 0
- ;;
- show-secrets)
- _nmcli_array_delete_at words 0
- ;;
- order)
- if [[ "${#words[@]}" -eq 2 ]]; then
- local ord="${words[1]}"
- local ord_sta=""
- local i
- local c=()
-
- # FIXME: currently the completion considers colon as separator
- # for words. Hence the following doesn't work as $ord will
- # not contain any colons at this point.
- # See https://bugzilla.gnome.org/show_bug.cgi?id=745157
-
- if [[ $ord = *":"* ]]; then
- ord_sta="${ord%:*}:"
- ord="${ord##*:}"
- fi
- if [[ $ord = [-+]* ]]; then
- ord_sta="$ord_sta${ord:0:1}"
- fi
- for i in active name type path; do
- c=("${c[@]}" "$ord_sta$i")
- done
- _nmcli_list "${c[*]}"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- active)
- _nmcli_array_delete_at words 0
- ;;
- version)
- _nmcli_array_delete_at words 0
- ;;
- help)
- _nmcli_array_delete_at words 0
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- HELP_ONLY_AS_FIRST=0
- return 0
- fi
- HELP_ONLY_AS_FIRST=0
- ;;
- temporary)
- _nmcli_array_delete_at words 0
- ;;
- mode)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "tabular multiline"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- colors)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "yes no auto"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- fields)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "all common
- NAME UUID TYPE TIMESTAMP TIMESTAMP-REAL AUTOCONNECT READONLY DBUS-PATH ACTIVE DEVICE STATE ACTIVE-PATH
- connection 802-3-ethernet 802-1x 802-11-wireless 802-11-wireless-security ipv4 ipv6 serial ppp pppoe gsm cdma bluetooth 802-11-olpc-mesh vpn wimax infiniband bond vlan adsl bridge bridge-port team team-port dcb tun ip-tunnel macvlan vxlan
- GENERAL IP4 DHCP4 IP6 DHCP6 VPN
- profile active"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- escape)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "no yes"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- wait)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list ""
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- *)
- # something unexpected. We are finished with parsing the OPTIONS.
- return 2
- ;;
- esac
- done
-}
-
-# after the OPTIONS, the OBJECT, the COMMAND and possible the COMMAND_CONNECTION, the syntax for nmcli
-# expects several options with parameters. This function can parse them and remove them from the words array.
-_nmcli_compl_ARGS()
-{
- local aliases=${@}
- local OPTIONS_ALL N_REMOVE_WORDS REMOVE_OPTIONS OPTIONS_HAS_MANDATORY i
- OPTIONS_ALL=("${OPTIONS[@]}")
- OPTIONS_UNKNOWN_OPTION=
-
- OPTIONS_HAS_MANDATORY=0
- if [[ "${#OPTIONS_MANDATORY[@]}" -ge 1 ]]; then
- OPTIONS_HAS_MANDATORY=1
- fi
-
- for (( ; ; )); do
- if [[ "${#words[@]}" -le 1 ]]; then
- # we have no more words left...
- if [[ ${#OPTIONS[@]} -eq 0 ]]; then
- return 1;
- fi
- if [[ "$COMMAND_ARGS_WAIT_OPTIONS" -ne 1 ]]; then
- _nmcli_list "$(echo "${OPTIONS[@]}")"
- return 0
- fi
- COMMAND_ARGS_WAIT_OPTIONS=0
- return 1
- fi
- if ! _nmcli_array_has_value OPTIONS_ALL "${words[0]}"; then
- # This is an entirely unknown option.
- OPTIONS_UNKNOWN_OPTION="?${words[0]}"
- return 1
- fi
- if [[ "$OPTIONS_HAS_MANDATORY" -eq 1 && "${#OPTIONS_MANDATORY[@]}" -eq 0 ]]; then
- # we had some mandatory options, but they are all satisfied... stop here...
- # This means, that we can continue with more additional options from the NEXT_GROUP.
- return 1
- fi
-
- N_REMOVE_WORDS=2
- REMOVE_OPTIONS=("${words[0]}")
-
- # change option name to alias
- WORD0="${words[0]}"
- for alias in "${aliases[@]}" ; do
- if [[ "${WORD0}" == ${alias%%:*} ]]; then
- WORD0=${alias#*:}
- break
- fi
- done
-
- case "${WORD0}" in
- level)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "OFF ERR WARN INFO DEBUG TRACE KEEP"
- return 0
- fi
- ;;
- domains)
- if [[ "${#words[@]}" -eq 2 ]]; then
- local OPTIONS_DOM=(ALL DEFAULT DHCP IP PLATFORM RFKILL ETHER WIFI BT MB DHCP4 DHCP6 PPP WIFI_SCAN IP4 IP6 AUTOIP4 DNS VPN SHARING SUPPLICANT AGENTS SETTINGS SUSPEND CORE DEVICE OLPC WIMAX INFINIBAND FIREWALL ADSL BOND VLAN BRIDGE DBUS_PROPS TEAM CONCHECK DCB DISPATCH AUDIT SYSTEMD VPN_PLUGIN)
- if [[ "${words[1]}" != "" ]]; then
-
- # split the comma separaeted domain string into its parts LOGD
- local oIFS="$IFS"
- IFS=","
- local LOGD=($(printf '%s' "${words[1]}" | sed 's/\(^\|,\)/,#/g'))
- IFS="$oIFS"
- unset oIFS
-
- local LOGDLAST LOGDLAST_IS_OPTION LOGDI i
- # first we iterate over all present domains and remove them from OPTIONS_DOM
- for LOGDI in ${LOGD[@]}; do
- LOGDI="${LOGDI:1}"
- LOGDLAST="$LOGDI"
- LOGDLAST_IS_OPTION=0
- for i in ${!OPTIONS_DOM[*]}; do
- if [[ "${OPTIONS_DOM[$i]}" = "$LOGDI" ]]; then
- LOGDLAST_IS_OPTION=1
- unset OPTIONS_DOM[$i]
- fi
- done
- done
-
- local OPTIONS_DOM2=()
- if [[ "$LOGDLAST" = "" ]]; then
- # we have a word that ends with ','. Just append all remaining options.
- for i in ${!OPTIONS_DOM[*]}; do
- OPTIONS_DOM2[${#OPTIONS_DOM2[@]}]="${words[1]}${OPTIONS_DOM[$i]}"
- done
- else
- # if the last option is not "" we keep only those option with the same prefix
- # as the last domain (LOGDLAST)
- for i in ${!OPTIONS_DOM[*]}; do
- if [[ "${OPTIONS_DOM[$i]:0:${#LOGDLAST}}" == "$LOGDLAST" ]]; then
- # modify the option with the present prefix
- OPTIONS_DOM2[${#OPTIONS_DOM2[@]}]="${words[1]}${OPTIONS_DOM[$i]:${#LOGDLAST}}"
- fi
- done
-
- if [[ $LOGDLAST_IS_OPTION -eq 1 ]]; then
- # if the last logd itself was a valid iption, ${words[1]} is itself a valid match
- OPTIONS_DOM2[${#OPTIONS_DOM2[@]}]="${words[1]}"
-
- # also, add all remaining options by comma separated to the word.
- for i in ${!OPTIONS_DOM[*]}; do
- OPTIONS_DOM2[${#OPTIONS_DOM2[@]}]="${words[1]},${OPTIONS_DOM[$i]}"
- done
- fi
- if [[ ${#OPTIONS_DOM2[@]} -eq 1 ]]; then
- for i in ${!OPTIONS_DOM[*]}; do
- if [[ "$LOGDLAST" != "${OPTIONS_DOM[$i]:0:${#LOGDLAST}}" ]]; then
- OPTIONS_DOM2[${#OPTIONS_DOM2[@]}]="${OPTIONS_DOM2[0]},${OPTIONS_DOM[$i]}"
- fi
- done
- fi
-
- fi
- OPTIONS_DOM=(${OPTIONS_DOM2[@]})
- fi
-
- _nmcli_list "$(echo "${OPTIONS_DOM[@]}")"
- return 0
- fi
- ;;
- type)
- if [[ "$OPTIONS_TYPE" != "" ]]; then
- return 1
- fi
- if [[ "${#words[@]}" -eq 2 ]]; then
- if [[ "${words[1]:0:1}" = "8" ]]; then
- # usually we don't want to show the 802-x types (because the shorter aliases are more
- # user friendly. Only complete them, if the current word already starts with an "8".
- _nmcli_list "802-3-ethernet 802-11-wireless 802-11-olpc-mesh"
- else
- _nmcli_list "ethernet wifi wimax gsm cdma infiniband bluetooth vpn olpc-mesh vlan bond bridge team pppoe adsl tun ip-tunnel macvlan vxlan"
- fi
- return 0
- fi
- OPTIONS_TYPE="${words[1]}"
-
- if [[ "x$OPTIONS_MANDATORY_IFNAME" != x ]]; then
- # the ifname is not a mandatory option for a few connection types...
- # Check, if we have such a 'type' and remove the 'ifname' from the list
- # of mandatory options.
- case "$OPTIONS_TYPE" in
- vl|vla|vlan| \
- bond| \
- team| \
- bridge)
- for i in ${!OPTIONS_MANDATORY[*]}; do
- if [[ "${OPTIONS_MANDATORY[$i]}" = "ifname" ]]; then
- unset OPTIONS_MANDATORY[$i]
- fi
- done
- ;;
- *)
- ;;
-
- esac
- OPTIONS_MANDATORY_IFNAME=
- fi
- ;;
- master)
- if [[ "${#words[@]}" -eq 2 ]]; then
- if [[ "${words[1]}" = "" ]]; then
- _nmcli_list_nl "$(_nmcli_dev_status DEVICE)"
- else
- _nmcli_list_nl "$(printf "%s\n%s\n%s" "$(_nmcli_dev_status DEVICE)" "$(_nmcli_con_show UUID)")"
- fi
- return 0
- fi
- ;;
- dev)
- if [[ "${#words[@]}" -eq 2 ]]; then
- if [[ "${words[1]}" = "" ]]; then
- _nmcli_list_nl "$(_nmcli_dev_status DEVICE)"
- else
- _nmcli_list_nl "$(printf "%s\n%s\n%s" "$(_nmcli_dev_status DEVICE)" "$(_nmcli_wifi_list BSSID)" "$(_nmcli_con_show UUID)")"
- fi
- return 0
- fi
- ;;
- primary| \
- ifname)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list_nl "$(_nmcli_dev_status DEVICE)"
- return 0
- fi
- ;;
- mode)
- if [[ "${#words[@]}" -eq 2 ]]; then
- case "$OPTIONS_TYPE" in
- "wifi")
- _nmcli_list "infrastructure ap adhoc"
- ;;
- "tun")
- _nmcli_list "tun tap"
- ;;
- "ip-tunnel")
- _nmcli_list "ipip gre sit isatap vti ip6ip6 ipip6 ip6gre vti6"
- ;;
- "macvlan")
- _nmcli_list "vepa bridge private passthru source"
- ;;
- "bond"| \
- *)
- _nmcli_list "balance-rr active-backup balance-xor broadcast 802.3ad balance-tlb balance-alb"
- esac
- return 0
- fi
- ;;
- transport-mode)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "datagram connected"
- return 0
- fi
- ;;
- vpn-type)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "vpnc openvpn pptp openconnect openswan libreswan strongswan ssh l2tp iodine fortisslvpn"
- return 0
- fi
- ;;
- slave-type)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "bond team bridge"
- return 0
- fi
- ;;
- lacp-rate)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "slow fast"
- return 0
- fi
- ;;
- bt-type)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "panu dun-gsm dun-cdma"
- return 0
- fi
- ;;
- wep-key-type)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "key phrase"
- return 0
- fi
- ;;
- managed| \
- autoconnect| \
- stp| \
- hairpin| \
- save| \
- hidden| \
- private| \
- pi| \
- vnet-hdr| \
- multi-queue|\
- tap)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "yes no"
- return 0
- fi
- ;;
- config)
- if [[ "${#words[@]}" -eq 2 ]]; then
- compopt -o default
- COMPREPLY=()
- return 0
- fi
- ;;
- ip4| \
- ip6| \
- gw4| \
- gw6| \
- priority| \
- forward-delay| \
- hello-time| \
- max-age| \
- ageing-time| \
- nsp| \
- path-cost| \
- name| \
- mtu| \
- cloned-mac| \
- addr| \
- parent| \
- miimon| \
- arp-interval| \
- arp-ip-target| \
- downdelay| \
- updelay| \
- p-key| \
- mac| \
- id| \
- flags| \
- ingress| \
- dhcp-anycast| \
- channel| \
- egress| \
- apn| \
- con-name| \
- user| \
- username| \
- service| \
- password)
- if [[ "${#words[@]}" -eq 2 ]]; then
- return 0
- fi
- ;;
- passwd-file| \
- file)
- if [[ "${#words[@]}" -eq 2 ]]; then
- compopt -o default
- COMPREPLY=()
- return 0
- fi
- ;;
- ssid)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list_nl "$(_nmcli_wifi_list SSID)"
- return 0
- fi
- ;;
- ap| \
- bssid)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list_nl "$(_nmcli_wifi_list BSSID)"
- return 0
- fi
- ;;
- encapsulation)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "vcmux llc"
- return 0
- fi
- ;;
- protocol)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "pppoa pppoe ipoatm"
- return 0
- fi
- ;;
- band)
- if [[ "${#words[@]}" -eq 2 ]]; then
- _nmcli_list "a bg"
- return 0
- fi
- ;;
- *)
- return 1
- ;;
- esac
-
-
- if [[ "${#OPTIONS_NEXT_GROUP[@]}" -gt 0 ]]; then
- if _nmcli_array_has_value OPTIONS_NEXT_GROUP "${words[0]}"; then
- # the current value is from the next group...
- # We back off, because the current group is complete.
- return 1
- fi
- fi
-
- _nmcli_array_delete_at words 0 $((N_REMOVE_WORDS-1))
- # remove the options already seen.
- for i in ${!OPTIONS[*]}; do
- if [[ "${OPTIONS[$i]}" = "${REMOVE_OPTIONS[0]}" || "${OPTIONS[$i]}" = "${REMOVE_OPTIONS[1]}" ]]; then
- if ! _nmcli_array_has_value OPTIONS_REPEATABLE "${OPTIONS[$i]}" ; then
- unset OPTIONS[$i]
- fi
- fi
- done
- for i in ${!OPTIONS_MANDATORY[*]}; do
- if [[ "${OPTIONS_MANDATORY[$i]}" = "${REMOVE_OPTIONS[0]}" || "${OPTIONS_MANDATORY[$i]}" = "${REMOVE_OPTIONS[1]}" ]]; then
- unset OPTIONS_MANDATORY[$i]
- fi
- done
- done
-}
-
-# some commands expect a connection as parameter. This connection can either be given
-# as id|uuid|path|apath. Parse that connection parameter.
-# Actually, it can also ask for a device name, like `nmcli device set [ifname] <ifname>`
-_nmcli_compl_ARGS_CONNECTION()
-{
- if ! _nmcli_array_has_value OPTIONS "${words[0]}"; then
- COMMAND_CONNECTION_TYPE=
- COMMAND_CONNECTION_ID="${words[0]}"
- _nmcli_array_delete_at words 0
- return 1
- fi
- COMMAND_CONNECTION_TYPE="${words[0]}"
- COMMAND_CONNECTION_ID="${words[1]}"
- local CON_TYPE=
- if [[ "x$COMMAND_CONNECTION_ACTIVE" != x ]]; then
- CON_TYPE=--active
- fi
- case "${words[0]}" in
- id)
- if [[ ${#words[@]} -le 2 ]]; then
- _nmcli_list_nl "$(_nmcli_con_show NAME $CON_TYPE)"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- uuid)
- if [[ ${#words[@]} -le 2 ]]; then
- _nmcli_list_nl "$(_nmcli_con_show UUID $CON_TYPE)"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- path)
- if [[ ${#words[@]} -le 2 ]]; then
- _nmcli_list_nl "$(_nmcli_con_show DBUS-PATH $CON_TYPE)"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- apath)
- if [[ ${#words[@]} -le 2 ]]; then
- _nmcli_list_nl "$(_nmcli_con_show ACTIVE-PATH --active)"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- ifname)
- if [[ ${#words[@]} -le 2 ]]; then
- _nmcli_list_nl "$(_nmcli_dev_status DEVICE)"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- ;;
- *)
- COMMAND_CONNECTION_TYPE=
- COMMAND_CONNECTION_ID="${words[0]}"
- _nmcli_array_delete_at words 0
- ;;
- esac
- return 1
-}
-
-_nmcli_compl_COMMAND() {
- local command="$1"
- shift
- local V=("$@")
- local H=
- if [[ "${command[0]:0:1}" != '-' ]]; then
- H=help
- elif [[ "${command[0]:1:1}" == '-' || "${command[0]}" == "-" ]]; then
- H=--help
- else
- H=-help
- fi
- if [[ "x$COMPL_COMMAND_NO_HELP" == x ]]; then
- V=("${V[@]}" "$H")
- fi
- _nmcli_list "${V[*]}"
-}
-
-_nmcli_compl_COMMAND_nl() {
- local command="$1"
- local a="$2"
- shift
- shift
- local V=("$@")
- local H=
- if [[ "${command[0]:0:1}" != '-' ]]; then
- V=("${V[@]/#/--}")
- H=help
- elif [[ "${command[0]:1:1}" == '-' || "${command[0]}" == "-" ]]; then
- V=("${V[@]/#/--}")
- H=--help
- else
- V=("${V[@]/#/-}")
- H=-help
- fi
- if [[ "x$COMPL_COMMAND_NO_HELP" == x ]]; then
- V=("${V[@]}" "$H")
- fi
- local IFS=$'\n'
- V="${V[*]}"
- _nmcli_list_nl "$(printf "%s%s\n%s" "" "$V" "$a")"
-}
-
-_nmcli_compl_PROPERTIES()
-{
- while [[ ${#words[@]} -gt 0 ]]; do
- if [[ ${#words[@]} -eq 1 ]]; then
- _nmcli_list_nl "$(nmcli --complete-args connection modify "$@" "${words[@]}" 2>/dev/null)"
- return 0
- fi
- _nmcli_array_delete_at words 0 1
- done
- return 0
-}
-
-_nmcli()
-{
- local cur prev words cword i
- _init_completion || return
-
- # we don't care about any arguments after the current cursor position
- # because we only parse from left to right. So, if there are some arguments
- # right of the cursor, just ignore them. Also don't care about ${words[0]}.
- _nmcli_array_delete_at words $((cword+1)) ${#words[@]}
- _nmcli_array_delete_at words 0
-
- # _init_completion returns the words with all the quotes and escaping
- # characters. We don't care about them, drop them at first.
- for i in ${!words[@]}; do
- words[i]="$(printf '%s' "${words[i]}" | xargs printf '%s\n' 2>/dev/null || true)"
- done
-
- # In case the cursor is not at the end of the line,
- # $cur consists of spaces that we want do remove.
- # For example: `nmcli connection modify id <TAB> lo`
- if [[ "$cur" =~ ^[[:space:]]+ ]]; then
- cur=''
- fi
-
- local OPTIONS OPTIONS_UNKNOWN_OPTION OPTIONS_TYPE OPTIONS_TYPED OPTIONS_IP OPTIONS_NEXT_GROUP \
- OPTIONS_SEP OPTIONS_REPEATABLE OPTIONS_MANDATORY OPTIONS_MANDATORY_IFNAME \
- COMMAND_ARGS_WAIT_OPTIONS COMMAND_CONNECTION_TYPE COMMAND_CONNECTION_ID \
- COMMAND_CONNECTION_ACTIVE="" HELP_ONLY_AS_FIRST="" \
- LONG_OPTIONS=(terse pretty mode fields colors escape ask show-secrets wait version help)
-
- _nmcli_compl_OPTIONS
- i=$?
-
- case $i in
- 0)
- # We have just completed an option or got an --help: terminate.
- return 0
- ;;
- 1)
- # we show for completion either the (remaining) OPTIONS
- # (if the current word starts with a dash) or the OBJECT list
- # otherwise.
- if [[ "${words[0]:0:1}" != '-' ]]; then
- OPTIONS=(help general networking radio connection device agent monitor)
- elif [[ "${words[0]:1:1}" == '-' || "${words[0]}" == "-" ]]; then
- OPTIONS=("${LONG_OPTIONS[@]/#/--}")
- else
- OPTIONS=("${LONG_OPTIONS[@]/#/-}")
- fi
- _nmcli_list "${OPTIONS[*]}"
- return 0
- ;;
- esac
-
- local command="${words[1]}"
- case "${words[0]}" in
- h|he|hel|help)
- ;;
- g|ge|gen|gene|gener|genera|general)
- if [[ ${#words[@]} -eq 2 ]]; then
- _nmcli_compl_COMMAND "$command" status permissions logging hostname
- elif [[ ${#words[@]} -gt 2 ]]; then
- case "$command" in
- ho|hos|host|hostn|hostna|hostnam|hostname)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" \
- "$(printf '%s\n%s\n%s\n' \
- "$(nmcli general hostname 2>/dev/null)" \
- "$(cat /etc/hostname 2>/dev/null)" \
- "$(hostnamectl status 2>/dev/null | sed -n '1s/^.\+hostname: \(.\+\)$/\1/p')" \
- "$HOSTNAME")"
- fi
- ;;
- l|lo|log|logg|loggi|loggin|logging)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND "${words[2]}" level domains
- else
- _nmcli_array_delete_at words 0 1
- OPTIONS=(level domains)
- _nmcli_compl_ARGS
- fi
- ;;
- s|st|sta|stat|statu|status| \
- p|pe|per|perm|permi|permis|permiss|permissi|permissio|permission|permissions)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND "${words[2]}"
- fi
- ;;
- esac
- fi
- ;;
- n|ne|net|netw|netwo|networ|network|networki|networkin|networking)
- if [[ ${#words[@]} -eq 2 ]]; then
- _nmcli_compl_COMMAND "$command" on off connectivity
- elif [[ ${#words[@]} -eq 3 ]]; then
- case "$command" in
- c|co|con|conn|conne|connec|connect|connecti|connectiv|connectivi|connectivit|connectivity)
- _nmcli_compl_COMMAND "${words[2]}" "check"
- ;;
- esac
- fi
- ;;
- r|ra|rad|radi|radio)
- if [[ ${#words[@]} -eq 2 ]]; then
- _nmcli_compl_COMMAND "$command" all wifi wwan
- elif [[ ${#words[@]} -eq 3 ]]; then
- case "$command" in
- a|al|all | w|wi|wif|wifi | ww|wwa|wwan)
- _nmcli_compl_COMMAND "${words[2]}" "on off"
- ;;
- esac
- fi
- ;;
- c|co|con|conn|conne|connec|connect|connecti|connectio|connection)
- if [[ ${#words[@]} -eq 2 ]]; then
- _nmcli_compl_COMMAND "$command" show up down add modify clone edit delete monitor reload load import export
- elif [[ ${#words[@]} -gt 2 ]]; then
- case "$command" in
- s|sh|sho|show)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_show NAME)")" active order
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help active order)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
- i=$?
-
- if ! _nmcli_array_has_value LONG_OPTIONS active; then
- COMMAND_CONNECTION_ACTIVE=1
- fi
-
- case $i in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- if [[ "x$COMMAND_CONNECTION_ACTIVE" = x ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_show NAME)")" "${LONG_OPTIONS[@]}"
-
- else
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_show NAME --active)")" "${LONG_OPTIONS[@]}"
- fi
- fi
- return 0
- ;;
- esac
-
- OPTIONS=(id uuid path apath)
- while [[ ${#words[@]} -gt 0 ]]; do
- _nmcli_compl_ARGS_CONNECTION && return 0
- done
- if [[ "x$COMMAND_CONNECTION_ACTIVE" = x ]]; then
- _nmcli_list_nl "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_show NAME)")"
- else
- _nmcli_list_nl "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_show NAME --active)")"
- fi
- fi
- ;;
- u|up)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "ifname\nid\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")"
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
-
- case $? in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "ifname\nid\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")" "${LONG_OPTIONS[@]}"
- fi
- return 0
- ;;
- esac
-
- local COMMAND_CONNECTION_TYPE=''
- OPTIONS=(ifname id uuid path)
- _nmcli_compl_ARGS_CONNECTION && return 0
-
- if [[ "$COMMAND_CONNECTION_TYPE" = "ifname" ]]; then
- OPTIONS=(ap nsp passwd-file)
- else
- OPTIONS=(ifname ap nsp passwd-file)
- fi
- _nmcli_compl_ARGS
- fi
- ;;
- d|do|dow|down)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_show NAME --active)")"
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
- case $? in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_show NAME --active)")" "${LONG_OPTIONS[@]}"
- fi
- return 0
- ;;
- esac
-
- OPTIONS=(id uuid path apath)
- COMMAND_CONNECTION_ACTIVE=1
- _nmcli_compl_ARGS_CONNECTION && return 0
- fi
- ;;
- a|ad|add)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(nmcli --complete-args connection add "" 2>/dev/null)"
- else
- _nmcli_array_delete_at words 0 1
- _nmcli_list_nl "$(nmcli --complete-args connection add "${words[@]}" 2>/dev/null)"
- fi
- ;;
- e|ed|edi|edit)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\ntype\ncon-name\n%s" "$(_nmcli_con_show NAME)")"
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
-
- case $? in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\ntype\ncon-name\n%s" "$(_nmcli_con_show NAME)")" "${LONG_OPTIONS[@]}"
- fi
- return 0
- ;;
- esac
-
- if [[ "${words[0]}" = 'type' || "${words[0]}" = 'con-name' ]]; then
- OPTIONS=(type con-name)
- _nmcli_compl_ARGS
- else
- OPTIONS=(id uuid path apath)
- _nmcli_compl_ARGS_CONNECTION
- fi
- fi
- ;;
- m|mo|mod|modi|modif|modify)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")" temporary
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help temporary)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
- case $? in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")" "${LONG_OPTIONS[@]}"
- fi
- return 0
- ;;
- esac
-
- OPTIONS=(id uuid path)
- _nmcli_compl_ARGS_CONNECTION && return 0
-
- _nmcli_compl_PROPERTIES ${COMMAND_CONNECTION_TYPE} "$COMMAND_CONNECTION_ID"
-
- return 0
- fi
- ;;
- c|cl|clo|clon|clone)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")" temporary
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help temporary)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
- case $? in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")" "${LONG_OPTIONS[@]}"
- fi
- return 0
- ;;
- esac
-
- OPTIONS=(id uuid path)
- _nmcli_compl_ARGS_CONNECTION && return 0
-
- return 0
- fi
- ;;
-
- de|del|dele|delet|delete| \
- mon|moni|monit|monito|monitor)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")"
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help)
- _nmcli_compl_OPTIONS
- case $? in
- 0)
- return 0
- ;;
- 1)
- if ! _nmcli_array_has_value LONG_OPTIONS "help"; then
- return 0
- fi
- ;;
- esac
-
- OPTIONS=(id uuid path apath)
- while [[ ${#words[@]} -gt 0 ]]; do
- _nmcli_compl_ARGS_CONNECTION && return 0
- done
- _nmcli_list_nl "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")"
- fi
- ;;
- l|lo|loa|load)
- if [[ ${#words[@]} -gt 2 ]]; then
- # we should also complete for help/--help, but who to mix that
- # with file name completion?
- compopt -o default
- COMPREPLY=()
- fi
- ;;
- i|im|imp|impo|impor|import)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND "${words[2]}" type file --temporary
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help temporary)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
- case $? in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- _nmcli_compl_COMMAND "${words[2]}" type file
- fi
- return 0
- ;;
- esac
-
- OPTIONS=(type file)
- OPTIONS_MANDATORY=(type file)
- _nmcli_compl_ARGS type:vpn-type
- return 0
- fi
- ;;
- e|ex|exp|expo|expor|export)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")"
- elif [[ ${#words[@]} -gt 3 ]]; then
- _nmcli_array_delete_at words 0 1
-
- LONG_OPTIONS=(help)
- HELP_ONLY_AS_FIRST=1
- _nmcli_compl_OPTIONS
- case $? in
- 0)
- return 0
- ;;
- 1)
- if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")" "${LONG_OPTIONS[@]}"
- fi
- return 0
- ;;
- esac
-
- OPTIONS=(id uuid path)
- _nmcli_compl_ARGS_CONNECTION && return 0
- return 0
- fi
- ;;
-
- esac
- fi
- ;;
- d|de|dev|devi|devic|device)
- if [[ ${#words[@]} -eq 2 ]]; then
- _nmcli_compl_COMMAND "$command" status show connect reapply modify disconnect delete monitor wifi set lldp
- elif [[ ${#words[@]} -gt 2 ]]; then
- case "$command" in
- s|st|sta|stat|statu|status)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND "${words[2]}"
- fi
- ;;
- sh|sho|show| \
- r|re|rea|reap|reapp|reappl|reapply| \
- c|co|con|conn|conne|connec|connect)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
- fi
- ;;
- mod|modi|modif|modify)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(nmcli --complete-args device modify "" 2>/dev/null)"
- else
- _nmcli_array_delete_at words 0 1
- _nmcli_list_nl "$(nmcli --complete-args device modify "${words[@]}" 2>/dev/null)"
- fi
- ;;
- d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect| \
- de|del|dele|delet|delete| \
- m|mo|mon|moni|monit|monito|monitor)
- if [[ ${#words[@]} -ge 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
- fi
- ;;
- se|set)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "ifname\n%s" "$(_nmcli_dev_status DEVICE)")"
- else
- _nmcli_array_delete_at words 0 1
- OPTIONS=(ifname)
- _nmcli_compl_ARGS_CONNECTION && return 0
- OPTIONS=(autoconnect managed)
- _nmcli_compl_ARGS
- fi
- ;;
- w|wi|wif|wifi)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND "${words[2]}" list connect hotspot rescan
- else
- case "${words[2]}" in
- l|li|lis|list)
- _nmcli_array_delete_at words 0 2
- OPTIONS=(ifname bssid)
- _nmcli_compl_ARGS
- ;;
- c|co|con|conn|conne|connec|connect)
- if [[ ${#words[@]} -eq 4 ]]; then
- if [[ "${words[3]}" = "" ]]; then
- _nmcli_list_nl "$(_nmcli_wifi_list SSID)"
- else
- _nmcli_list_nl "$(printf "%s\n%s" "$(_nmcli_wifi_list SSID)" "$(_nmcli_wifi_list BSSID)")"
- fi
- else
- _nmcli_array_delete_at words 0 3
- local OPTIONS=(password wep-key-type ifname bssid name private hidden)
- _nmcli_compl_ARGS
- fi
- ;;
- h|ho|hot|hots|hotsp|hotspo|hotspot)
- _nmcli_array_delete_at words 0 2
- OPTIONS=(ifname con-name ssid band channel password)
- _nmcli_compl_ARGS
- ;;
- r|re|res|resc|resca|rescan)
- _nmcli_array_delete_at words 0 2
- OPTIONS_REPEATABLE=(ssid)
- OPTIONS=(ifname ssid)
- _nmcli_compl_ARGS
- ;;
- esac
- fi
- ;;
- l|ll|lld|lldp)
- if [[ ${#words[@]} -eq 3 ]]; then
- _nmcli_compl_COMMAND "${words[2]}" list
- else
- case "${words[2]}" in
- l|li|lis|list)
- _nmcli_array_delete_at words 0 2
- OPTIONS=(ifname)
- _nmcli_compl_ARGS
- ;;
- esac
- fi
- ;;
- esac
- fi
- ;;
- a|ag|age|agen|agent)
- if [[ ${#words[@]} -eq 2 ]]; then
- _nmcli_compl_COMMAND "$command" secret polkit all
- fi
- ;;
- m|mo|mon|moni|monit|monito|monitor)
- ;;
- esac
- return 0
} &&
complete -F _nmcli nmcli