986 lines
41 KiB
Bash
986 lines
41 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 ) )
|
|
}
|
|
|
|
_nmcli_con_id()
|
|
{
|
|
echo "$(nmcli -t -f NAME con show c 2>/dev/null)"
|
|
}
|
|
|
|
_nmcli_con_id_active()
|
|
{
|
|
echo "$(nmcli -t -f NAME con show a 2>/dev/null)"
|
|
}
|
|
|
|
_nmcli_con_uuid()
|
|
{
|
|
echo "$(nmcli -t -f UUID con show c 2>/dev/null)"
|
|
}
|
|
|
|
_nmcli_con_path()
|
|
{
|
|
echo "$(nmcli -t -f DBUS-PATH con show c 2>/dev/null)"
|
|
}
|
|
|
|
_nmcli_con_apath()
|
|
{
|
|
echo "$(nmcli -t -f DBUS-PATH con show a 2>/dev/null)"
|
|
}
|
|
|
|
_nmcli_ap_ssid()
|
|
{
|
|
echo "$(nmcli -t -f SSID dev wifi list 2>/dev/null)"
|
|
|
|
# without quotes
|
|
#ssids="$(nmcli -t -f SSID dev wifi list 2>/dev/null)"
|
|
#local IFS=$'\n'
|
|
#for ssid in $ssids; do
|
|
# temp="${ssid%\'}"
|
|
# temp="${temp#\'}"
|
|
# echo "$temp"
|
|
#done
|
|
}
|
|
|
|
_nmcli_device_wifi_list_SSID()
|
|
{
|
|
echo "$(nmcli -t -f SSID device wifi list 2>/dev/null | sort | uniq)"
|
|
}
|
|
|
|
_nmcli_ap_bssid()
|
|
{
|
|
echo "$(nmcli -e no -t -f BSSID dev wifi list 2>/dev/null)"
|
|
}
|
|
|
|
_nmcli_NM_devices()
|
|
{
|
|
echo "$(nmcli -t -f DEVICE dev status 2>/dev/null)"
|
|
}
|
|
|
|
_nmcli_NM_dev_MAC()
|
|
{
|
|
echo "$(nmcli -t dev show | grep HWADDR | cut -d':' -f2- | sort | uniq)"
|
|
}
|
|
|
|
_nmcli_array_has_value() {
|
|
# expects an array variable ARRAY defined and returns true
|
|
# if one of the arguments $@ is contained in ${ARRAY[@]}
|
|
local arg a
|
|
for arg; do
|
|
for a in "${ARRAY[@]}"; do
|
|
if [[ "$a" = "$arg" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
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_complete_OPTIONS()
|
|
{
|
|
local OPTIONS=( -t --terse -p --pretty -m --mode -f --fields -e --escape -n --nocheck -a --ask -w --wait -v --version -h --help )
|
|
local i REMOVE_OPTIONS
|
|
|
|
for (( ; ; )); do
|
|
if [[ "${#words[@]}" -le 1 ]]; then
|
|
# 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)
|
|
fi
|
|
_nmcli_list "$(echo "${OPTIONS[@]}")"
|
|
return 0
|
|
fi
|
|
case "${words[0]}" in
|
|
-t|--terse)
|
|
REMOVE_OPTIONS=(-t --terse)
|
|
words=("${words[@]:1}")
|
|
;;
|
|
-p|--pretty)
|
|
REMOVE_OPTIONS=(-p --pretty)
|
|
words=("${words[@]:1}")
|
|
;;
|
|
-n|--nocheck)
|
|
REMOVE_OPTIONS=(-n --nocheck)
|
|
words=("${words[@]:1}")
|
|
;;
|
|
-a|--ask)
|
|
REMOVE_OPTIONS=(-a --ask)
|
|
words=("${words[@]:1}")
|
|
;;
|
|
-v|--version)
|
|
REMOVE_OPTIONS=(-v --version)
|
|
words=("${words[@]:1}")
|
|
;;
|
|
-h|--help)
|
|
REMOVE_OPTIONS=(-h --help)
|
|
words=("${words[@]:1}")
|
|
;;
|
|
-m|--mode)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list "tabular multiline"
|
|
return 0
|
|
fi
|
|
REMOVE_OPTIONS=(-m --mode)
|
|
words=("${words[@]:2}")
|
|
;;
|
|
-f|--fields)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list "all common"
|
|
return 0
|
|
fi
|
|
REMOVE_OPTIONS=(-f --fields)
|
|
words=("${words[@]:2}")
|
|
;;
|
|
-e|--escape)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list "no yes"
|
|
return 0
|
|
fi
|
|
REMOVE_OPTIONS=(-e --escape)
|
|
words=("${words[@]:2}")
|
|
;;
|
|
-w|--wait)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list ""
|
|
return 0
|
|
fi
|
|
REMOVE_OPTIONS=(-w --wait)
|
|
words=("${words[@]:2}")
|
|
;;
|
|
*)
|
|
# something unexpected. We are finished with parsing the OPTIONS.
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
# 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
|
|
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_complete_COMMAND_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
|
|
ARRAY=("${OPTIONS_ALL[@]}")
|
|
if ! _nmcli_array_has_value "${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 "ERROR WARN INFO DEBUG"
|
|
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_MESH WIMAX INFINIBAND FIREWALL ADSL BOND VLAN BRIDGE DBUS_PROPS TEAM CONCHECK)
|
|
if [[ "${words[1]}" != "" ]]; then
|
|
|
|
# split the comma separaeted domain string into its parts LOGD
|
|
local oIFS="$IFS"
|
|
IFS=","
|
|
local LOGD=($(echo "${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 adsl bluetooth vpn olpc-mesh vlan bond bond-slave bridge bridge-slave team team-slave"
|
|
fi
|
|
return 0
|
|
fi
|
|
OPTIONS_TYPE="${words[1]}"
|
|
;;
|
|
master)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
if [[ "${words[1]}" = "" ]]; then
|
|
_nmcli_list_nl "$(_nmcli_NM_devices)"
|
|
else
|
|
_nmcli_list_nl "$(printf "%s\n%s\n%s" "$(_nmcli_NM_devices)" "$(_nmcli_con_uuid)")"
|
|
fi
|
|
return 0
|
|
fi
|
|
;;
|
|
dev)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
if [[ "${words[1]}" = "" ]]; then
|
|
_nmcli_list_nl "$(_nmcli_NM_devices)"
|
|
else
|
|
_nmcli_list_nl "$(printf "%s\n%s\n%s" "$(_nmcli_NM_devices)" "$(_nmcli_ap_bssid)" "$(_nmcli_con_uuid)")"
|
|
fi
|
|
return 0
|
|
fi
|
|
;;
|
|
primary| \
|
|
ifname)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_NM_devices)"
|
|
return 0
|
|
fi
|
|
;;
|
|
mode)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list "balance-rr active-backup balance-xor broadcast 802.3ad balance-tlb balance-alb"
|
|
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"
|
|
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| \
|
|
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| \
|
|
password)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
return 0
|
|
fi
|
|
;;
|
|
ssid)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_device_wifi_list_SSID)"
|
|
return 0
|
|
fi
|
|
;;
|
|
ap| \
|
|
bssid)
|
|
if [[ "${#words[@]}" -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_ap_bssid)"
|
|
return 0
|
|
fi
|
|
;;
|
|
*)
|
|
echo
|
|
echo "unexpected option. This is a bug in the completion. Check for \"${words[0]}\""
|
|
echo
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
|
|
if [[ "${#OPTIONS_NEXT_GROUP[@]}" -gt 0 ]]; then
|
|
ARRAY=("${OPTIONS_NEXT_GROUP[@]}")
|
|
if _nmcli_array_has_value "${words[0]}"; then
|
|
# the current value is from the next group...
|
|
# We back off, because the current group is complete.
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
words=("${words[@]:$N_REMOVE_WORDS}")
|
|
# 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_complete_COMMAND_CONNECTION()
|
|
{
|
|
ARRAY=("${OPTIONS[@]}")
|
|
if ! _nmcli_array_has_value "${words[0]}"; then
|
|
COMMAND_CONNECTION_TYPE=
|
|
COMMAND_CONNECTION_ID="${words[0]}"
|
|
words=("${words[@]:1}")
|
|
return 1
|
|
fi
|
|
COMMAND_CONNECTION_TYPE="${words[0]}"
|
|
COMMAND_CONNECTION_ID="${words[1]}"
|
|
case "${words[0]}" in
|
|
id)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_con_id)"
|
|
return 0
|
|
fi
|
|
words=("${words[@]:2}")
|
|
;;
|
|
uuid)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_con_uuid)"
|
|
return 0
|
|
fi
|
|
words=("${words[@]:2}")
|
|
;;
|
|
path)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_con_path)"
|
|
return 0
|
|
fi
|
|
words=("${words[@]:2}")
|
|
;;
|
|
apath)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_con_apath)"
|
|
return 0
|
|
fi
|
|
words=("${words[@]:2}")
|
|
;;
|
|
ifname)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_NM_devices)"
|
|
return 0
|
|
fi
|
|
words=("${words[@]:2}")
|
|
;;
|
|
*)
|
|
COMMAND_CONNECTION_TYPE=
|
|
COMMAND_CONNECTION_ID="${words[0]}"
|
|
words=("${words[@]:1}")
|
|
;;
|
|
esac
|
|
return 1
|
|
}
|
|
|
|
_nmcli_complete_commands() {
|
|
local command="$1"
|
|
shift
|
|
if [[ "x${command:0:1}" == 'x-' ]]; then
|
|
_nmcli_list "-h --help"
|
|
else
|
|
_nmcli_list "help $*"
|
|
fi
|
|
}
|
|
|
|
_nmcli()
|
|
{
|
|
local cur prev words cword
|
|
_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]}.
|
|
words=("${words[@]:1:$cword}")
|
|
|
|
# _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]="$(echo "${words[i]}" | xargs 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
|
|
|
|
_nmcli_complete_OPTIONS && return 0
|
|
|
|
local command="${words[1]}"
|
|
local OPTIONS_UNKNOWN_OPTION OPTIONS_TYPE OPTIONS_TYPED OPTIONS OPTIONS_MANDATORY COMMAND_ARGS_WAIT_OPTIONS ARRAY OPTIONS_IP OPTIONS_MANDATORY OPTIONS_NEXT_GROUP
|
|
local COMMAND_CONNECTION_TYPE COMMAND_CONNECTION_ID
|
|
|
|
case "${words[0]}" in
|
|
h|he|hel|help)
|
|
;;
|
|
g|ge|gen|gene|gener|genera|general)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_complete_commands "$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_list_nl "$(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)
|
|
words=("${words[@]:2}")
|
|
OPTIONS=(level domains)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
n|ne|net|netw|netwo|networ|network|networki|networkin|networking)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_complete_commands "$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_list "check"
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
r|ra|rad|radi|radio)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_complete_commands "$command" all wifi wwan wimax
|
|
elif [[ ${#words[@]} -eq 3 ]]; then
|
|
case "$command" in
|
|
a|al|all | w|wi|wif|wifi | ww|wwa|wwan | wim|wima|wimax)
|
|
_nmcli_list "on off"
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
c|co|con|conn|conne|connec|connect|connecti|connectio|connection)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_complete_commands "$command" show up down add modify edit delete reload
|
|
elif [[ ${#words[@]} -gt 2 ]]; then
|
|
case "$command" in
|
|
s|sh|sho|show)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list "configured active"
|
|
elif [[ ${#words[@]} -gt 3 ]]; then
|
|
case "${words[2]}" in
|
|
c|co|con|conf|confi|config|configu|configur|configure|configured)
|
|
if [[ ${#words[@]} -eq 4 ]]; then
|
|
_nmcli_list_nl "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_id)")"
|
|
else
|
|
words=("${words[@]:3}")
|
|
OPTIONS=(id uuid path)
|
|
_nmcli_complete_COMMAND_CONNECTION
|
|
fi
|
|
;;
|
|
a|ac|act|acti|activ|active)
|
|
if [[ ${#words[@]} -eq 4 ]]; then
|
|
_nmcli_list_nl "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_id_active)")"
|
|
else
|
|
words=("${words[@]:3}")
|
|
OPTIONS=(id uuid path apath)
|
|
_nmcli_complete_COMMAND_CONNECTION
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
u|up)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list_nl "$(printf "ifname\nid\nuuid\npath\n%s" "$(_nmcli_con_id)")"
|
|
elif [[ ${#words[@]} -gt 3 ]]; then
|
|
local COMMAND_CONNECTION_TYPE=''
|
|
words=("${words[@]:2}")
|
|
OPTIONS=(ifname id uuid path)
|
|
_nmcli_complete_COMMAND_CONNECTION && return 0
|
|
|
|
if [[ "$COMMAND_CONNECTION_TYPE" = "ifname" ]]; then
|
|
OPTIONS=(ap nsp)
|
|
else
|
|
OPTIONS=(ifname ap nsp)
|
|
fi
|
|
_nmcli_complete_COMMAND_ARGS
|
|
fi
|
|
;;
|
|
d|do|dow|down)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list_nl "$(printf "id\nuuid\npath\napath\n%s" "$(_nmcli_con_id_active)")"
|
|
elif [[ ${#words[@]} -gt 3 ]]; then
|
|
words=("${words[@]:2}")
|
|
OPTIONS=(id uuid path apath)
|
|
_nmcli_complete_COMMAND_CONNECTION
|
|
fi
|
|
;;
|
|
a|ad|add)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_complete_commands "${words[2]}" type ifname con-name autoconnect
|
|
elif [[ ${#words[@]} -gt 3 ]]; then
|
|
words=("${words[@]:2}")
|
|
OPTIONS_TYPE=
|
|
OPTIONS=(type ifname con-name autoconnect)
|
|
OPTIONS_MANDATORY=(type)
|
|
COMMAND_ARGS_WAIT_OPTIONS=1
|
|
_nmcli_complete_COMMAND_ARGS && return 0
|
|
|
|
ARRAY=("${OPTIONS[@]}")
|
|
if _nmcli_array_has_value "${OPTIONS_MANDATORY[@]}"; then
|
|
# we still have some missing mandatory options...
|
|
if [[ "$OPTIONS_UNKNOWN_OPTION" != '' ]]; then
|
|
ARRAY="${OPTIONS[@]}"
|
|
if ! _nmcli_array_has_value "${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_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_TYPED=(ssid mac cloned-mac mtu)
|
|
OPTIONS_MANDATORY=(ssid)
|
|
;;
|
|
wim|wima|wimax)
|
|
OPTIONS_TYPED=(mac nsp)
|
|
;;
|
|
g|gs|gsm)
|
|
OPTIONS_TYPED=(apn user password)
|
|
OPTIONS_MANDATORY=(apn)
|
|
;;
|
|
c|cd|cdm|cdma)
|
|
OPTIONS_TYPED=(user password)
|
|
;;
|
|
i|in|inf|infi|infin|infini|infinib|infiniba|infiniban|infiniband)
|
|
OPTIONS_TYPED=(mac mtu transport-mode parent p-key)
|
|
;;
|
|
bl|blu|blue|bluet|blueto|bluetoo|bluetoot|bluetooth)
|
|
OPTIONS_TYPED=(addr bt-type)
|
|
;;
|
|
vl|vla|vlan)
|
|
OPTIONS_TYPED=(dev id flags ingress egress mtu)
|
|
OPTIONS_MANDATORY=(dev)
|
|
;;
|
|
bond)
|
|
OPTIONS_TYPED=(mode miimon downdelay updelay arp-interval arp-ip-target primary)
|
|
;;
|
|
bond-|bond-s|bond-sl|bond-sla|bond-slav|bond-slave)
|
|
OPTIONS_TYPED=(master)
|
|
OPTIONS_MANDATORY=(master)
|
|
OPTIONS_IP=()
|
|
;;
|
|
team)
|
|
OPTIONS_TYPED=(config)
|
|
;;
|
|
team-|team-s|team-sl|team-sla|team-slav|team-slave)
|
|
OPTIONS_TYPED=(master config)
|
|
OPTIONS_MANDATORY=(master)
|
|
OPTIONS_IP=()
|
|
;;
|
|
bridge)
|
|
OPTIONS_TYPED=(stp priority forward-delay hello-time max-age ageing-time)
|
|
;;
|
|
bridge-|bridge-s|bridge-sl|bridge-sla|bridge-slav|bridge-slave)
|
|
OPTIONS_TYPED=(master priority path-cost hairpin)
|
|
OPTIONS_MANDATORY=(master)
|
|
OPTIONS_IP=()
|
|
;;
|
|
vp|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_TYPED=(ssid channel dhcp-anycast)
|
|
OPTIONS_MANDATORY=(ssid)
|
|
;;
|
|
*)
|
|
# 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_complete_COMMAND_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
|
|
ARRAY=("${OPTIONS_IP[@]}")
|
|
if ! _nmcli_array_has_value "${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_complete_COMMAND_ARGS && return 0
|
|
|
|
ARRAY=("${OPTIONS[@]}")
|
|
if _nmcli_array_has_value "${OPTIONS_MANDATORY[@]}"; then
|
|
_nmcli_list "$(echo "${OPTIONS[@]}")"
|
|
return 0
|
|
fi
|
|
|
|
if [[ "$OPTIONS_UNKNOWN_OPTION" != "" ]]; then
|
|
ARRAY=("${OPTIONS_IP[@]}")
|
|
if ! _nmcli_array_has_value "${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_complete_COMMAND_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_complete_COMMAND_ARGS && return 0
|
|
fi
|
|
;;
|
|
e|ed|edi|edit)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list_nl "$(printf "id\nuuid\npath\ntype\ncon-name\n%s" "$(_nmcli_con_id)")"
|
|
elif [[ ${#words[@]} -gt 3 ]]; then
|
|
words=("${words[@]:2}")
|
|
if [[ "${words[0]}" = 'type' || "${words[0]}" = 'con-name' ]]; then
|
|
OPTIONS=(type con-name)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
else
|
|
OPTIONS=(id uuid path apath)
|
|
_nmcli_complete_COMMAND_CONNECTION
|
|
fi
|
|
fi
|
|
;;
|
|
m|mo|mod|modi|modif|modify)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list_nl "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_id)")"
|
|
elif [[ ${#words[@]} -gt 3 ]]; then
|
|
words=("${words[@]:2}")
|
|
OPTIONS=(id uuid path apath)
|
|
_nmcli_complete_COMMAND_CONNECTION && return 0
|
|
if [[ ${#words[@]} -le 1 ]]; then
|
|
_nmcli_list_nl "$(nmcli connection show configured "${COMMAND_CONNECTION_TYPE:-id}" "$COMMAND_CONNECTION_ID" 2>/dev/null | sed -n 's/^\([^:]\+\):.*/\1/p')"
|
|
fi
|
|
fi
|
|
;;
|
|
de|del|dele|delet|delete)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list_nl "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_id)")"
|
|
elif [[ ${#words[@]} -gt 3 ]]; then
|
|
words=("${words[@]:2}")
|
|
OPTIONS=(id uuid path apath)
|
|
_nmcli_complete_COMMAND_CONNECTION
|
|
fi
|
|
;;
|
|
l|lo|loa|load)
|
|
if [[ ${#words[@]} -gt 2 ]]; then
|
|
compopt -o default
|
|
COMPREPLY=()
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
d|de|dev|devi|devic|device)
|
|
if [[ ${#words[@]} -eq 2 ]]; then
|
|
_nmcli_complete_commands "$command" status show connect disconnect wifi wimax
|
|
elif [[ ${#words[@]} -gt 2 ]]; then
|
|
case "$command" in
|
|
s|st|sta|stat|statu|status)
|
|
;;
|
|
sh|sho|show| \
|
|
c|co|con|conn|conne|connec|connect| \
|
|
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list_nl "$(_nmcli_NM_devices)"
|
|
fi
|
|
;;
|
|
w|wi|wif|wifi)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list "list connect rescan"
|
|
else
|
|
case "${words[2]}" in
|
|
l|li|lis|list)
|
|
words=("${words[@]:3}")
|
|
OPTIONS=(ifname bssid)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
;;
|
|
c|co|con|conn|conne|connec|connect)
|
|
if [[ ${#words[@]} -eq 4 ]]; then
|
|
if [[ "${words[3]}" = "" ]]; then
|
|
_nmcli_list_nl "$(_nmcli_ap_ssid)"
|
|
else
|
|
_nmcli_list_nl "$(printf "%s\n%s" "$(_nmcli_ap_ssid)" "$(_nmcli_ap_bssid)")"
|
|
fi
|
|
else
|
|
words=("${words[@]:4}")
|
|
local OPTIONS=(password wep-key-type ifname bssid name private)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
fi
|
|
;;
|
|
r|re|res|resc|resca|rescan)
|
|
words=("${words[@]:3}")
|
|
OPTIONS=(ifname)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
wim|wima|wimax)
|
|
if [[ ${#words[@]} -eq 3 ]]; then
|
|
_nmcli_list "list"
|
|
else
|
|
case "${words[2]}" in
|
|
l|li|lis|list)
|
|
words=("${words[@]:3}")
|
|
OPTIONS=(ifname nsp)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
;;
|
|
c|co|con|conn|conne|connec|connect)
|
|
if [[ ${#words[@]} -eq 4 ]]; then
|
|
if [[ "${words[3]}" = "" ]]; then
|
|
_nmcli_list_nl "$(_nmcli_ap_ssid)"
|
|
else
|
|
_nmcli_list_nl "$(_nmcli_ap_ssid) $(_nmcli_ap_bssid)"
|
|
fi
|
|
else
|
|
words=("${words[@]:4}")
|
|
OPTIONS=(password wep-key-type ifname bssid name private)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
fi
|
|
;;
|
|
r|re|res|resc|resca|rescan)
|
|
words=("${words[@]:3}")
|
|
OPTIONS=(ifname)
|
|
_nmcli_complete_COMMAND_ARGS
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
|
|
esac
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
return 0
|
|
} &&
|
|
complete -F _nmcli nmcli
|
|
|
|
# ex: ts=4 sw=4 et filetype=sh
|