Files
NetworkManager/clients/cli/nmcli-completion
Dan Winship 721e917cb6 wimax: drop WiMAX support (bgo #747846)
Even Fedora is no longer shipping the WiMAX SDK, so it's likely we'll
eventually accidentally break some of the code in src/devices/wimax/
(if we haven't already). Discussion on the list showed a consensus for
dropping support for WiMAX.

So, remove the SDK checks from configure.ac, remove the WiMAX device
plugin and associated manager support, and deprecate all the APIs.

For compatibility reasons, it is still possible to create and save
WiMAX connections, to toggle the software WiMAX rfkill state, and to
change the "WIMAX" log level, although none of these have any effect,
since no NMDeviceWimax will ever be created.

nmcli was only compiling in support for most WiMAX operations when NM
as a whole was built with WiMAX support, so that code has been removed
now as well. (It is still possible to use nmcli to create and edit
WiMAX connections, but those connections will never be activatable.)
2015-04-17 12:42:23 -04:00

1313 lines
55 KiB
Bash

# nmcli(1) completion -*- shell-script -*-
# Originally based on
# https://github.com/GArik/bash-completion/blob/master/completions/nmcli
_nmcli_list()
{
COMPREPLY=( $( compgen -W '$1' -- $cur ) )
}
_nmcli_list_nl()
{
local IFS=$'\n'
COMPREPLY=( $( compgen -W '$1' -- $cur ) )
# Now escape special characters (spaces, single and double quotes),
# so that the argument is really regarded a single argument by bash.
# See http://stackoverflow.com/questions/1146098/properly-handling-spaces-and-quotes-in-bash-completion
local escaped_single_quote="'\''"
local i=0
local entry
for entry in ${COMPREPLY[*]}
do
if [[ "${cur:0:1}" == "'" ]]; then
# started with single quote, escaping only other single quotes
# [']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 and all backslashes
# ["]bla'bla"bla\bla bla --> ["]bla'bla\"bla\\bla bla
entry="${entry//\\/\\\\}"
entry="${entry//\"/\\\"}"
COMPREPLY[$i]="$entry"
else
# no quotes in front, escaping _everything_
# [ ]bla'bla"bla\bla bla --> [ ]bla\'bla\"bla\\bla\ bla
entry="${entry//\\/\\\\}"
entry="${entry//\'/\'}"
entry="${entry//\"/\\\"}"
entry="${entry// /\\ }"
COMPREPLY[$i]="$entry"
fi
(( 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}"
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
;;
nocheck)
_nmcli_array_delete_at words 0
;;
ask)
_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
;;
show-secrets)
_nmcli_array_delete_at words 0
;;
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
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 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]}")
case "${words[0]}" in
level)
if [[ "${#words[@]}" -eq 2 ]]; then
_nmcli_list "ERR WARN INFO DEBUG TRACE"
return 0
fi
;;
domains)
if [[ "${#words[@]}" -eq 2 ]]; then
local OPTIONS_DOM=(ALL DEFAULT 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)
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 bond-slave bridge bridge-slave team team-slave pppoe"
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"
;;
"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 ssh l2tp iodine"
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
;;
autoconnect| \
stp| \
hairpin| \
save| \
private)
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| \
passwd-file)
if [[ "${#words[@]}" -eq 2 ]]; then
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
;;
*)
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
unset OPTIONS[$i]
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.
_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()
{
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_UNKNOWN_OPTION OPTIONS_TYPE OPTIONS_TYPED OPTIONS OPTIONS_MANDATORY COMMAND_ARGS_WAIT_OPTIONS OPTIONS_IP OPTIONS_MANDATORY OPTIONS_NEXT_GROUP
local COMMAND_CONNECTION_TYPE COMMAND_CONNECTION_ID OPTIONS_MANDATORY_IFNAME HELP_ONLY_AS_FIRST
local COMMAND_CONNECTION_ACTIVE=""
HELP_ONLY_AS_FIRST=
local LONG_OPTIONS=(terse pretty mode fields colors escape nocheck ask wait version help)
_nmcli_compl_OPTIONS
i=$?
if [[ "$HELP_ONLY_AS_FIRST" == '0' ]]; then
# got a --help. No more completion.
return 0
fi
case $i in
0)
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)
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 edit delete reload load
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 show-secrets order
elif [[ ${#words[@]} -gt 3 ]]; then
_nmcli_array_delete_at words 0 1
LONG_OPTIONS=(help active show-secrets 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 "${words[2]}" type ifname con-name autoconnect
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 "${words[2]}" type ifname con-name autoconnect
fi
return 0
;;
esac
OPTIONS_TYPE=
OPTIONS=(type ifname con-name autoconnect save)
OPTIONS_MANDATORY=(type ifname)
COMMAND_ARGS_WAIT_OPTIONS=1
OPTIONS_MANDATORY_IFNAME=1
_nmcli_compl_ARGS && return 0
OPTIONS_MANDATORY_IFNAME=
if _nmcli_array_has_value OPTIONS "${OPTIONS_MANDATORY[@]}"; then
# we still have some missing mandatory options...
if [[ "$OPTIONS_UNKNOWN_OPTION" != '' ]]; then
if ! _nmcli_array_has_value OPTIONS "${OPTIONS_UNKNOWN_OPTION:1}"; then
# if we encountered an unknown option while having mandatory
# options, just return.
return 0
fi
fi
_nmcli_list "$(echo "${OPTIONS[@]}")"
return 0
fi
OPTIONS_IP=(ip4 ip6 gw4 gw6)
OPTIONS_MANDATORY=()
case "$OPTIONS_TYPE" in
802-3|802-3-|802-3-e|802-3-et|802-3-eth|802-3-ethe|802-3-ether|802-3-ethern|802-3-etherne|802-3-ethernet| \
e|et|eth|ethe|ether|ethern|etherne|ethernet)
OPTIONS_TYPE=ethernet
OPTIONS_TYPED=(mac cloned-mac mtu)
;;
802-11-w|802-11-wi|802-11-wir|802-11-wire|802-11-wirel|802-11-wirele|802-11-wireles|802-11-wireless| \
wif|wifi)
OPTIONS_TYPE=wifi
OPTIONS_TYPED=(ssid mac cloned-mac mtu mode)
OPTIONS_MANDATORY=(ssid)
;;
wim|wima|wimax)
OPTIONS_TYPE=wimax
OPTIONS_TYPED=(mac nsp)
;;
g|gs|gsm)
OPTIONS_TYPE=gsm
OPTIONS_TYPED=(apn user password)
OPTIONS_MANDATORY=(apn)
;;
c|cd|cdm|cdma)
OPTIONS_TYPE=cdma
OPTIONS_TYPED=(user password)
;;
i|in|inf|infi|infin|infini|infinib|infiniba|infiniban|infiniband)
OPTIONS_TYPE=infiniband
OPTIONS_TYPED=(mac mtu transport-mode parent p-key)
;;
bl|blu|blue|bluet|blueto|bluetoo|bluetoot|bluetooth)
OPTIONS_TYPE=bluetooth
OPTIONS_TYPED=(addr bt-type)
;;
vl|vla|vlan)
OPTIONS_TYPE=vlan
OPTIONS_TYPED=(dev id flags ingress egress mtu)
OPTIONS_MANDATORY=(dev)
;;
bond)
OPTIONS_TYPE=bond
OPTIONS_TYPED=(mode miimon downdelay updelay arp-interval arp-ip-target primary lacp-rate)
;;
bond-|bond-s|bond-sl|bond-sla|bond-slav|bond-slave)
OPTIONS_TYPE=bond-slave
OPTIONS_TYPED=(master)
OPTIONS_MANDATORY=(master)
OPTIONS_IP=()
;;
team)
OPTIONS_TYPE=team
OPTIONS_TYPED=(config)
;;
team-|team-s|team-sl|team-sla|team-slav|team-slave)
OPTIONS_TYPE=team-slave
OPTIONS_TYPED=(master config)
OPTIONS_MANDATORY=(master)
OPTIONS_IP=()
;;
bridge)
OPTIONS_TYPE=bridge
OPTIONS_TYPED=(stp priority forward-delay hello-time max-age ageing-time mac)
;;
bridge-|bridge-s|bridge-sl|bridge-sla|bridge-slav|bridge-slave)
OPTIONS_TYPE=bridge-slave
OPTIONS_TYPED=(master priority path-cost hairpin)
OPTIONS_MANDATORY=(master)
OPTIONS_IP=()
;;
vp|vpn)
OPTIONS_TYPE=vpn
OPTIONS_TYPED=(vpn-type user)
OPTIONS_MANDATORY=(vpn-type)
;;
802-11-o|802-11-ol|802-11-olp|802-11-olpc|802-11-olpc-|802-11-olpc-m|802-11-olpc-me|802-11-olpc-mes|802-11-olpc-mesh| \
o|ol|olp|olpc|olpc-|olpc-m|olpc-me|olpc-mes|olpc-mesh)
OPTIONS_TYPE=olpc-mesh
OPTIONS_TYPED=(ssid channel dhcp-anycast)
OPTIONS_MANDATORY=(ssid)
;;
p|pp|ppp|pppo|pppoe)
OPTIONS_TYPE=pppoe
OPTIONS_TYPED=(username password service mtu mac)
OPTIONS_MANDATORY=(username)
;;
*)
# for an unknown connection type, we stop completion here
return 0
;;
esac
if [[ "$COMMAND_ARGS_WAIT_OPTIONS" -ne 1 ]]; then
# means, we are at the end of options. Nothing more to parse, just show
# what are the options now.
if [[ "${#OPTIONS_MANDATORY[@]}" -gt 0 ]]; then
_nmcli_list "$(echo "${OPTIONS[@]}") $(echo "${OPTIONS_TYPED[@]}")"
else
_nmcli_list "$(echo "${OPTIONS[@]}") $(echo "${OPTIONS_TYPED[@]}") $(echo "${OPTIONS_IP[@]}")"
fi
return 0
fi
if [[ "${#OPTIONS[@]}" -gt 0 ]]; then
# we still have some options from before, but no mandatory ones. Mix them with OPTIONS_TYPED
# and continue parsing the options...
OPTIONS=("${OPTIONS[@]}" "${OPTIONS_TYPED[@]}")
OPTIONS_NEXT_GROUP=("${OPTIONS_TYPED[@]}")
_nmcli_compl_ARGS && return 0
if [[ "$COMMAND_ARGS_WAIT_OPTIONS" -ne 1 ]]; then
# means, we are at the end of options. Nothing more to parse, just show
# what are the options now.
if [[ "${#OPTIONS_MANDATORY[@]}" -gt 0 ]]; then
_nmcli_list "$(echo "${OPTIONS[@]}")"
else
_nmcli_list "$(echo "${OPTIONS[@]}") $(echo "${OPTIONS_IP[@]}")"
fi
return 0
fi
if [[ "$OPTIONS_UNKNOWN_OPTION" != "" ]]; then
# there was an unknown option specified. Maybe we have to stop with the completion.
if [[ "${#OPTIONS_MANDATORY[@]}" -gt 0 ]]; then
# we have an unknown option, but still mandatory ones that must be fullfiled first.
return 0
fi
if ! _nmcli_array_has_value OPTIONS_IP "${OPTIONS_UNKNOWN_OPTION:1}"; then
# the unknown option is NOT an IP option.
return 0
fi
# The unknown option is an IP option, which is fine... continue...
fi
fi
OPTIONS=("${OPTIONS_TYPED[@]}")
OPTIONS_NEXT_GROUP=()
if [[ "${#OPTIONS_MANDATORY[@]}" -ge 1 ]]; then
# we have some mandatory options... don't check for IP options yet...
_nmcli_compl_ARGS && return 0
if _nmcli_array_has_value OPTIONS "${OPTIONS_MANDATORY[@]}"; then
_nmcli_list "$(echo "${OPTIONS[@]}")"
return 0
fi
if [[ "$OPTIONS_UNKNOWN_OPTION" != "" ]]; then
if ! _nmcli_array_has_value OPTIONS_IP "${OPTIONS_UNKNOWN_OPTION:1}"; then
# the unknown option is NOT an IP option.
return 0
fi
fi
fi
# no mandatory options... do final completion including IP options
OPTIONS=("${OPTIONS[@]}" "${OPTIONS_IP[@]}")
OPTIONS_NEXT_GROUP=("${OPTIONS_IP[@]}")
_nmcli_compl_ARGS && return 0
if [[ "$OPTIONS_UNKNOWN_OPTION" != "" ]]; then
return 0
fi
if [[ "$COMMAND_ARGS_WAIT_OPTIONS" -ne 1 ]]; then
# means, we are at the end of options. Nothing more to parse, just show
# what are the options now.
_nmcli_list "$(echo "${OPTIONS[@]}")"
return 0
fi
# process the last group of options, as the OPTIONS_TYPED are already handled...
OPTIONS=("${OPTIONS_IP[@]}")
OPTIONS_NEXT_GROUP=()
COMMAND_ARGS_WAIT_OPTIONS=0
_nmcli_compl_ARGS && return 0
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
while [[ "${#words[@]}" -gt 0 ]]; do
if [[ ${#words[@]} -le 1 ]]; then
local PREFIX=""
if [[ "${words[0]:0:1}" == [+-] ]]; then
PREFIX="${words[0]:0:1}"
fi
_nmcli_list_nl "$(nmcli --fields profile connection show ${COMMAND_CONNECTION_TYPE} "$COMMAND_CONNECTION_ID" 2>/dev/null | sed -n 's/^\([^:]\+\):.*/'$PREFIX'\1/p')"
return 0
elif [[ ${#words[@]} -le 2 ]]; then
return 0
fi
_nmcli_array_delete_at words 0 1
done
_nmcli_list_nl "$(nmcli --fields profile connection show ${COMMAND_CONNECTION_TYPE} "$COMMAND_CONNECTION_ID" 2>/dev/null | sed -n 's/^\([^:]\+\):.*/\1/p')"
return 0
fi
;;
de|del|dele|delet|delete)
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
;;
esac
fi
;;
d|de|dev|devi|devic|device)
if [[ ${#words[@]} -eq 2 ]]; then
_nmcli_compl_COMMAND "$command" status show connect disconnect delete wifi
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| \
c|co|con|conn|conne|connec|connect)
if [[ ${#words[@]} -eq 3 ]]; then
_nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
fi
;;
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect| \
de|del|dele|delet|delete)
if [[ ${#words[@]} -ge 3 ]]; then
_nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
fi
;;
w|wi|wif|wifi)
if [[ ${#words[@]} -eq 3 ]]; then
_nmcli_compl_COMMAND "${words[2]}" list connect 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)
_nmcli_compl_ARGS
fi
;;
r|re|res|resc|resca|rescan)
_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
;;
esac
return 0
} &&
complete -F _nmcli nmcli
# ex: ts=4 sw=4 et filetype=sh