Skip to content

Add iwctl completion#1616

Open
cladmi wants to merge 3 commits intoscop:mainfrom
cladmi:feat/iwctl
Open

Add iwctl completion#1616
cladmi wants to merge 3 commits intoscop:mainfrom
cladmi:feat/iwctl

Conversation

@cladmi
Copy link
Copy Markdown

@cladmi cladmi commented Apr 13, 2026

Complete commands/subcommands, devices, networks, SSID with spaces.

No handling of set-property and debug connect|roam completions.
Not tested with ap/ad-hoc devices as my device does not handle it.

Implementation of hidden-networks completion using quotes to handle completion on :`.

Split commits

In separate commits, as I am not sure if it is wanted, I added support to not show any completion when nothing should be displayed, and some testing using a mock command to show parsing of real command outputs to find devices/networks.

These could be squashed together in the same commit, just thought it would be easier to review and remove them if needed.

#### Inspiration

I did look at ip.bash as an inspiration.

Style

If any implementation style is not found appropriate, and there is a better file to look into/change this, please tell and I'll adapt it.

Testing

I did interactively test everything supported at some point.
Added plenty of unit tests to try validating what I did. I did not work in TDD with these though as was more learning how to write things, read documentation and testing multiple things at once. So there might be tests that at the end do not test correctly as not finding a completion for other reasons.

pytest -q -- test/t/test_iwctl.py 
............................s.......s.................................................. [ 56%]
..................................................................                      [100%]
151 passed, 2 skipped in 0.84s

With skipped tests being the one I cannot run on my machine, hoping they would work elsewhere.

test/t/test_iwctl.py::TestIwctl::test_ad_hoc_with_interfaces SKIPPED (iwctl ad-hoc list
| command grep -q 'No devices in') 
test/t/test_iwctl.py::TestIwctl::test_ap_with_interfaces SKIPPED (iwctl ap list |
command grep -q 'No devices in')

Commit-hooks

It seems that the hook for mypy just always fails, no information on why.
When run manually it seems happy. Not sure what to do here.

I did try resetting and re-committing everything at once, and only this did fail.
Each of the commit might not pass hooks as I do not know how to re-execute hooks on a git commit --amend and all.

cladmi added 3 commits April 13, 2026 14:56
Complete commands/subcommands, devices, networks, SSID with spaces.

No handling of `set-property` and `debug connect|roam` completions.
Not tested with `ap/ad-hoc` devices as my device does not handle it.

Implementation of `hidden-networks completion using quotes to
handle completion on `:`.
Use a mocked implementation to test network/interfaces completion.
station)
[[ $subcmd == list ]] && return
# All arguments except $prev and trailing empty argument
local iwctl_args=("${words[@]::${#words[@]}-2}")
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I need to call iwctl station wlan0 get-networks so try to get rely on words to get everything except the connect in iwctl station wlan0 connect.

There might be options provided in here, as long as the option are given just after iwctl all this will work well, but if not, I know this might break but not sure what would be the correct way of handling it. I thought about generating a whole new array with options removed, but was not sure if it it was necessary to add it, or if there was already a preferred way of handling it.

@scop
Copy link
Copy Markdown
Owner

scop commented Apr 14, 2026

Thank you for working on making bash completions better. But to verify, did you notice the two few paragraphs of CONTRIBUTING.md as linked in the PR creation view, in particular:

However, before submitting a completion to us, first consider submitting it to the project that ships the commands your completion is for.

If you considered submitting it upstream, let's include the explanation why submit it here instead. If it was asked upstream and rejected there, let's add a link to the response.

@cladmi
Copy link
Copy Markdown
Author

cladmi commented Apr 14, 2026

No I did not submit it upstream indeed. I'll try.
Anything that seems obviously wrong before I should submit it upstream?
One thing they would not have I guess is the test infrastructure.

I did notice that it was submitted for fish-shell separately though: fish-shell/fish-shell#9932

{
local offset="$1"
shift
local remove_colors="s/\x1B\[[0-9;]\+m//g"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
local remove_colors="s/\x1B\[[0-9;]\+m//g"
local remove_colors="s/\x1B\[[0-9:;]\{1,\}m//g"
  • \+ is a GNU extension.
  • SGR may also contain :.

local offset="$1"
shift
local format_network="s/^\(.\{32\}\) .*/\1/"
local format_rstrip="s/\([^ ]\) *$/\1/g"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
local format_rstrip="s/\([^ ]\) *$/\1/g"
local format_rstrip="s/ *$//"

Comment on lines +83 to +84
[[ $subcmd == list ]] && break
[[ $subcmd ]] && subcmd=${words[subcword]} && break
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what situation does subcmd become non-empty in this context? In this loop, subcmd is set only by line 85, but that line performs break, so isn't subcmd inside the loop always empty?

local iwctl="$1"
local device_mode="$2"
"${iwctl}" "${device_mode}" list | _comp_cmd_iwctl__filter_first_column
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called only in the following form.

                    _comp_compgen_split -l -- \
                        "$(_comp_cmd_iwctl__list_devices "$1" "$cmd")"

Then, shouldn't the entire _comp_compgen_split ... be made a function instead of only making the command-substitution part a function?

Also, _comp_compgen -a -- -W "list" can be included.

{
local i
for i in "${!COMPREPLY[@]}"; do
COMPREPLY[i]=${COMPREPLY[i]//* */\"${COMPREPLY[i]}\"}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
COMPREPLY[i]=${COMPREPLY[i]//* */\"${COMPREPLY[i]}\"}
COMPREPLY[i]=${COMPREPLY[i]//* */\""${COMPREPLY[i]}"\"}

See the description here. Even if you know that & will never be included in the values in this context, it is unclear just by looking at the line, so it's not readable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants