mirror of
https://github.com/ohmyzsh/ohmyzsh.git
synced 2026-06-16 11:36:16 +08:00
Merge 8c079e8160 into 3f6f72010f
This commit is contained in:
commit
901f1f02b9
40
plugins/iw/README.md
Normal file
40
plugins/iw/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# iw plugin
|
||||
|
||||
This plugin adds tab completion for [`iw`](https://wireless.wiki.kernel.org/en/users/documentation/iw),
|
||||
the standard Linux command-line tool for configuring wireless network interfaces.
|
||||
|
||||
To use it, add `iw` to the plugins array in your zshrc file:
|
||||
|
||||
```zsh
|
||||
plugins=(... iw)
|
||||
```
|
||||
|
||||
## Completion
|
||||
|
||||
Completion is generated dynamically by parsing the output of `iw help` and cached for
|
||||
performance. The cache is stored in `$ZSH_CACHE_DIR/_iw_cache` and is automatically
|
||||
regenerated when the installed version of `iw` changes.
|
||||
|
||||
The following command structure is completed:
|
||||
|
||||
| Level | Examples |
|
||||
| ----- | -------- |
|
||||
| Top-level commands | `dev`, `phy`, `wdev`, `reg`, `list`, `event`, … (discovered dynamically) |
|
||||
| Interface / phy names | `wlan0`, `phy0` (discovered from `/sys/class/net` and `/sys/class/ieee80211`) |
|
||||
| Subcommands | `dev <if> scan`, `dev <if> station`, `phy <phy> set`, … |
|
||||
| Sub-subcommands | `dev <if> scan dump`, `dev <if> station get`, `phy <phy> set txpower`, … |
|
||||
|
||||
## Functions
|
||||
|
||||
| Function | Description |
|
||||
| -------- | ----------- |
|
||||
| `iw-clear-cache` | Delete the cached completion data (useful after upgrading `iw`) |
|
||||
|
||||
## Requirements
|
||||
|
||||
- `iw` must be installed and in `$PATH`
|
||||
- Completion for a differently-named `iw` binary can be enabled with:
|
||||
|
||||
```zsh
|
||||
compdef _iw my-iw-binary
|
||||
```
|
||||
220
plugins/iw/_iw
Normal file
220
plugins/iw/_iw
Normal file
@ -0,0 +1,220 @@
|
||||
#compdef iw
|
||||
#
|
||||
|
||||
# ZSH completion for iw (Linux wireless configuration utility).
|
||||
# Parses 'iw help' output to discover commands and caches the result.
|
||||
#
|
||||
# $service is used as the iw binary name. This allows this completion to work
|
||||
# for differently-named iw binaries: compdef _iw my-iw-binary
|
||||
|
||||
# Parse 'iw help' output and write a sourceable cache file.
|
||||
_iw_build_cache() {
|
||||
local iw_cmd="$1"
|
||||
local version="$2"
|
||||
local cache_file="$3"
|
||||
local help_output
|
||||
|
||||
help_output=$($iw_cmd help 2>&1) || return 1
|
||||
|
||||
local -a top_cmds dev_subcmds phy_subcmds wdev_subcmds reg_subcmds
|
||||
local -A dev_subs phy_subs wdev_subs
|
||||
local line
|
||||
local -a words lines
|
||||
|
||||
# Single pass: collect top-level commands, subcmds, and sub-subcommands.
|
||||
# words[4] entries starting with '<', '[', or '-' are placeholders, not completions.
|
||||
lines=(${(f)help_output})
|
||||
for line in $lines; do
|
||||
words=(${=line})
|
||||
[[ $line == $'\t'[a-z]* && $line != $'\t\t'* ]] && top_cmds+=($words[1])
|
||||
case $words[1] in
|
||||
dev)
|
||||
if [[ $words[2] == '<devname>' && $words[3] == [a-z]* ]]; then
|
||||
dev_subcmds+=($words[3])
|
||||
if (( ${#words} > 3 )); then
|
||||
case $words[4] in
|
||||
'<'*|'['*|'-'*) ;;
|
||||
*) dev_subs[$words[3]]+=" $words[4]" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
phy)
|
||||
if [[ $words[2] == '<phyname>' && $words[3] == [a-z]* ]]; then
|
||||
phy_subcmds+=($words[3])
|
||||
if (( ${#words} > 3 )); then
|
||||
case $words[4] in
|
||||
'<'*|'['*|'-'*) ;;
|
||||
*) phy_subs[$words[3]]+=" $words[4]" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
wdev)
|
||||
if [[ $words[2] == '<idx>' && $words[3] == [a-z]* ]]; then
|
||||
wdev_subcmds+=($words[3])
|
||||
if (( ${#words} > 3 )); then
|
||||
case $words[4] in
|
||||
'<'*|'['*|'-'*) ;;
|
||||
*) wdev_subs[$words[3]]+=" $words[4]" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
reg)
|
||||
[[ $words[2] == [a-z]* ]] && reg_subcmds+=($words[2])
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# (ou): sorted + unique, replacing sort -u
|
||||
top_cmds=(${(ou)top_cmds})
|
||||
dev_subcmds=(${(ou)dev_subcmds})
|
||||
phy_subcmds=(${(ou)phy_subcmds})
|
||||
wdev_subcmds=(${(ou)wdev_subcmds})
|
||||
reg_subcmds=(${(ou)reg_subcmds})
|
||||
|
||||
local subcmd subs_str
|
||||
local -a subs_arr tmp_arr
|
||||
|
||||
{
|
||||
print "# iw completion cache"
|
||||
print "# version: ${version}"
|
||||
|
||||
print "_iw_top_cmds=(${top_cmds[*]})"
|
||||
print "_iw_dev_subcmds=(${dev_subcmds[*]})"
|
||||
for subcmd in $dev_subcmds; do
|
||||
if [[ -n "${dev_subs[$subcmd]}" ]]; then
|
||||
tmp_arr=(${=dev_subs[$subcmd]})
|
||||
subs_arr=(${(ou)tmp_arr})
|
||||
subs_str="${(j: :)subs_arr}"
|
||||
print "_iw_dev_subsubcmds[${subcmd}]=${(qq)subs_str}"
|
||||
fi
|
||||
done
|
||||
|
||||
print "_iw_phy_subcmds=(${phy_subcmds[*]})"
|
||||
for subcmd in $phy_subcmds; do
|
||||
if [[ -n "${phy_subs[$subcmd]}" ]]; then
|
||||
tmp_arr=(${=phy_subs[$subcmd]})
|
||||
subs_arr=(${(ou)tmp_arr})
|
||||
subs_str="${(j: :)subs_arr}"
|
||||
print "_iw_phy_subsubcmds[${subcmd}]=${(qq)subs_str}"
|
||||
fi
|
||||
done
|
||||
|
||||
print "_iw_wdev_subcmds=(${wdev_subcmds[*]})"
|
||||
for subcmd in $wdev_subcmds; do
|
||||
if [[ -n "${wdev_subs[$subcmd]}" ]]; then
|
||||
tmp_arr=(${=wdev_subs[$subcmd]})
|
||||
subs_arr=(${(ou)tmp_arr})
|
||||
subs_str="${(j: :)subs_arr}"
|
||||
print "_iw_wdev_subsubcmds[${subcmd}]=${(qq)subs_str}"
|
||||
fi
|
||||
done
|
||||
|
||||
print "_iw_reg_subcmds=(${reg_subcmds[*]})"
|
||||
|
||||
} >| "$cache_file"
|
||||
}
|
||||
|
||||
_iw() {
|
||||
local context state line curcontext="$curcontext"
|
||||
integer ret=1
|
||||
|
||||
# Declare cache variables; populated by sourcing the cache file below.
|
||||
local -a _iw_top_cmds _iw_dev_subcmds _iw_phy_subcmds _iw_wdev_subcmds _iw_reg_subcmds
|
||||
local -A _iw_dev_subsubcmds _iw_phy_subsubcmds _iw_wdev_subsubcmds
|
||||
|
||||
local cache_file="${ZSH_CACHE_DIR:-${HOME}/.cache}/_iw_cache"
|
||||
local current_version ver_output
|
||||
ver_output=$(${service} --version 2>&1)
|
||||
[[ $ver_output =~ '([0-9]+\.[0-9]+)' ]] && current_version=$match[1] || current_version=""
|
||||
|
||||
local cache_ver="" _l1 _l2
|
||||
if [[ -f "$cache_file" ]]; then
|
||||
{ IFS= read -r _l1; IFS= read -r _l2; } < "$cache_file" 2>/dev/null
|
||||
cache_ver=${_l2#\# version: }
|
||||
fi
|
||||
|
||||
if [[ $cache_ver != $current_version ]]; then
|
||||
_iw_build_cache "${service}" "$current_version" "$cache_file"
|
||||
fi
|
||||
|
||||
source "$cache_file" 2>/dev/null
|
||||
|
||||
_arguments -C \
|
||||
'--debug[enable netlink debugging]' \
|
||||
'(- 1 2 3 4)--version[show version]' \
|
||||
'1:: :->cmd' \
|
||||
'2:: :->arg2' \
|
||||
'3:: :->arg3' \
|
||||
'4:: :->arg4' \
|
||||
&& return 0
|
||||
|
||||
case "$state" in
|
||||
cmd)
|
||||
local -A _iw_cmd_descs
|
||||
_iw_cmd_descs=(
|
||||
dev 'network interface commands'
|
||||
phy 'wireless hardware commands'
|
||||
wdev 'wireless device commands'
|
||||
reg 'regulatory domain commands'
|
||||
list 'list all wireless devices and their capabilities'
|
||||
event 'monitor kernel events'
|
||||
features 'list supported features'
|
||||
commands 'list all known commands'
|
||||
help 'show command usage'
|
||||
)
|
||||
local -a top_cmds
|
||||
local _cmd
|
||||
for _cmd in $_iw_top_cmds; do
|
||||
if [[ -n "${_iw_cmd_descs[$_cmd]}" ]]; then
|
||||
top_cmds+=("${_cmd}:${_iw_cmd_descs[$_cmd]}")
|
||||
else
|
||||
top_cmds+=("$_cmd")
|
||||
fi
|
||||
done
|
||||
_describe -t commands 'iw command' top_cmds && ret=0
|
||||
;;
|
||||
|
||||
arg2)
|
||||
case "$line[1]" in
|
||||
dev)
|
||||
local -a wlan_devs
|
||||
wlan_devs=(/sys/class/net/*/phy80211(N:h:t))
|
||||
compadd -a wlan_devs && ret=0
|
||||
;;
|
||||
phy)
|
||||
local -a phy_devs
|
||||
phy_devs=(/sys/class/ieee80211/*(N:t))
|
||||
compadd -a phy_devs && ret=0
|
||||
;;
|
||||
reg)
|
||||
compadd -a _iw_reg_subcmds && ret=0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
arg3)
|
||||
case "$line[1]" in
|
||||
dev) compadd -a _iw_dev_subcmds && ret=0 ;;
|
||||
phy) compadd -a _iw_phy_subcmds && ret=0 ;;
|
||||
wdev) compadd -a _iw_wdev_subcmds && ret=0 ;;
|
||||
esac
|
||||
;;
|
||||
|
||||
arg4)
|
||||
local -a subs
|
||||
case "$line[1]" in
|
||||
dev) subs=(${=_iw_dev_subsubcmds[$line[3]]}) ;;
|
||||
phy) subs=(${=_iw_phy_subsubcmds[$line[3]]}) ;;
|
||||
wdev) subs=(${=_iw_wdev_subsubcmds[$line[3]]}) ;;
|
||||
esac
|
||||
(( ${#subs} > 0 )) && compadd -a subs && ret=0
|
||||
;;
|
||||
esac
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
_iw "$@"
|
||||
17
plugins/iw/iw.plugin.zsh
Normal file
17
plugins/iw/iw.plugin.zsh
Normal file
@ -0,0 +1,17 @@
|
||||
# iw Oh-My-ZSH plugin
|
||||
# Provides tab completion for iw (Linux wireless configuration utility).
|
||||
|
||||
if (( ! $+commands[iw] )); then
|
||||
return
|
||||
fi
|
||||
|
||||
# Remove the cached iw completion data (useful after upgrading iw).
|
||||
iw-clear-cache() {
|
||||
local cache_file="${ZSH_CACHE_DIR:-${HOME}/.cache}/_iw_cache"
|
||||
if [[ -f "$cache_file" ]]; then
|
||||
rm -f "$cache_file"
|
||||
print "iw completion cache cleared."
|
||||
else
|
||||
print "No iw completion cache found."
|
||||
fi
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user