util-linux/bash-completion/eject
Kevin Locke 0c8865f843 bash-completion: Add non-canonical device fallback
It is desirable for bash-completion to complete block devices via
symlinks (e.g. under /dev/disk) and with non-canonical locations (e.g.
./sda if $PWD is /dev, and /chroot/dev/sda).

Unfortunately, this is a non-trivial task due to how bash-completion
works.  It is necessary to un-escape the last partial argument, search,
then escape the results, ideally handling tilde and variable
expansion/completion.  See [_get_comp_words_by_ref] and [_filedir] in
the bash-completion project for details.

Given the development costs of a complete and correct implementation,
the annoyance/frustration which would result from an incomplete/buggy
implementation, and the trade-offs between under- and over-completion,
this commit adds fallback to bash default completion if the argument
does not match any canonical device names.  This correctly completes in
the cases mentioned above, although it incorrectly completes on
non-block-device files as well.

[_filedir]: https://github.com/scop/bash-completion/blob/2.9/bash_completion#L552
[_get_comp_words_by_ref]: https://github.com/scop/bash-completion/blob/2.9/bash_completion#L365

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2019-09-19 08:17:09 -06:00

66 lines
1.2 KiB
Plaintext

_eject_module()
{
local cur prev OPTS
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case $prev in
'-a'|'--auto'|'-i'|'--manualeject')
COMPREPLY=( $(compgen -W "off on" -- $cur) )
return 0
;;
'-c'|'--changerslot')
# FIXME: there must be way to determine slots
COMPREPLY=( $(compgen -W "slot" -- $cur) )
return 0
;;
'-x'|'--cdspeed')
COMPREPLY=( $(compgen -W "$(eject --listspeed 2>/dev/null)" -- $cur) )
return 0
;;
'-h'|'--help'|'-V'|'--version')
return 0
;;
esac
case $cur in
-*)
OPTS="--auto
--changerslot
--default
--floppy
--force
--manualeject
--no-unmount
--no-partitions-unmount
--noop
--proc
--tape
--cdrom
--scsi
--trayclose
--traytoggle
--verbose
--cdspeed
--listspeed
--help
--version"
COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
return 0
;;
esac
local DEVS
DEVS="$(for I in /sys/class/block/*/removable; do
if [ $(cat $I) -ne 0 ]; then
OLD_IFS=$IFS
IFS='/';
ARR=($I)
echo "/dev/${ARR[4]}"
IFS=$OLD_IFS
fi
done)"
compopt -o bashdefault -o default
COMPREPLY=( $(compgen -W "$DEVS" $cur) )
return 0
}
complete -F _eject_module eject