RE: [PATCH] mmc-utils: Add bash completion

Avri Altman <[email protected]> Mon, 10 Aug 2026 06:22:51 +0000
Newsgroups org.kernel.vger.linux-mmc
Message-ID <DS1PR16MB675305B57F157ACDBCBB5D7CE5DE2@DS1PR16MB6753.namprd16.prod.outlook.com>
> Add a bash completion script in completion/mmc that completes
> subcommands and /dev/mmcblkN device paths for all mmc commands.
> 
> Subcommand completion is driven by parsing 'mmc help' output rather than
> maintaining a parallel hardcoded verb list, so it stays in sync as commands are
> added or removed.
> 
> The completion directory is named 'completion/' rather than 'bash-
> completion/' so shell-specific scripts for other shells (zsh, fish, etc.) can be
> placed alongside it without renaming.
> 
> Add bashcompletiondir variable to the Makefile (defaulting to the standard
> /usr/share/bash-completion/completions) and install the script as part of
> 'make install'. The install path can be overridden at build time with make
> bashcompletiondir=<path>.
> 
> Signed-off-by: Torstein Eide <[email protected]>
> ---
>  Makefile       |  5 ++++-
>  completion/mmc | 53
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  docs/HOWTO.rst |  6 ++++++
>  3 files changed, 63 insertions(+), 1 deletion(-)  create mode 100644
> completion/mmc
> 
> diff --git a/Makefile b/Makefile
> index bf8c006..607d372 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -7,6 +7,8 @@ AM_CFLAGS = -D_FILE_OFFSET_BITS=64 -
> D_FORTIFY_SOURCE=2 \
>             -DSD_IDS_PATH=\"$(idsdir)/sdcard.ids\" \
>             -DMMC_IDS_PATH=\"$(idsdir)/multimediacard.ids\"
I guess you are assuming here that the lsmmc series is applied first - which is fine IMHO.

>  CFLAGS ?= -g -O2
> +idsdir = /usr/share/misc
Ditto.
'?=' is perfectly fine.  I would just leave it

> +bashcompletiondir = /usr/share/bash-completion/completions
better '?=' Here also

>  objects = \
>         mmc.o \
>         mmc_cmds.o \
> @@ -23,7 +25,6 @@ override CFLAGS := $(CHECKFLAGS) $(AM_CFLAGS)
> $(CFLAGS)  INSTALL = install  prefix ?= /usr/local  bindir = $(prefix)/bin -idsdir
> ?= /usr/share/misc  LIBS=  RESTORE_LIBS=  mandir = /usr/share/man @@ -
> 63,6 +64,8 @@ install: $(progs)
>         $(INSTALL) -m755 -d $(DESTDIR)$(idsdir)
>         $(INSTALL) -m 644 sdcard.ids $(DESTDIR)$(idsdir)
>         $(INSTALL) -m 644 multimediacard.ids $(DESTDIR)$(idsdir)
> +       $(INSTALL) -m755 -d $(DESTDIR)$(bashcompletiondir)
> +       $(INSTALL) -m 644 completion/mmc
> + $(DESTDIR)$(bashcompletiondir)/mmc
> 
>  -include $(foreach obj,$(objects), $(dir $(obj))/.$(notdir $(obj)).d)
> 
> diff --git a/completion/mmc b/completion/mmc new file mode 100644 index
> 0000000..0a93bb1
> --- /dev/null
> +++ b/completion/mmc
> @@ -0,0 +1,53 @@
> +_mmc_complete() {
> +       local cur prev words cword
> +       _init_completion || return
> +
> +       local devices
> +       devices=$(compgen -G "/dev/mmcblk*" 2>/dev/null | grep -E
> + '^/dev/mmcblk[0-9]+$')
I think you are excluding rpmb nodes such as /dev/mmcblk0rpmb.

Thanks,
Avri
> +
> +       local mmcbin
> +       mmcbin=$(type -P "${words[0]}") || return
> +
> +       # "mmc help" prints one "Usage for command\t<verb words...> <args...>"
> +       # line per command. Argument placeholders always start with '<', so
> +       # stripping from the first '<' onward leaves just the verb words.
> +       local verbs
> +       verbs=$("$mmcbin" help 2>/dev/null | sed -n 's/^Usage for
> command[[:space:]]*//p' | sed 's/<.*//')
> +       [[ -z $verbs ]] && return
> +
> +       local -a typed=("${words[@]:1:cword-1}")
> +       local -A next_words=()
> +       local have_leaf=
> +
> +       local line i match
> +       while IFS= read -r line; do
> +               [[ -z $line ]] && continue
> +               local -a w
> +               read -ra w <<<"$line"
> +               [[ ${#w[@]} -lt ${#typed[@]} ]] && continue
> +
> +               match=1
> +               for ((i = 0; i < ${#typed[@]}; i++)); do
> +                       if [[ ${w[i]} != "${typed[i]}" ]]; then
> +                               match=0
> +                               break
> +                       fi
> +               done
> +               [[ $match -eq 0 ]] && continue
> +
> +               if [[ ${#w[@]} -gt ${#typed[@]} ]]; then
> +                       next_words[${w[${#typed[@]}]}]=1
> +               else
> +                       have_leaf=1
> +               fi
> +       done <<<"$verbs"
> +
> +       if [[ ${#next_words[@]} -gt 0 ]]; then
> +               COMPREPLY=($(compgen -W "${!next_words[*]}" -- "$cur"))
> +       elif [[ -n $have_leaf ]]; then
> +               COMPREPLY=($(compgen -W "$devices" -- "$cur"))
> +       fi
> +}
> +
> +complete -F _mmc_complete mmc
> +complete -F _mmc_complete ./mmc
> diff --git a/docs/HOWTO.rst b/docs/HOWTO.rst index 0b486e4..3aba86f
> 100644
> --- a/docs/HOWTO.rst
> +++ b/docs/HOWTO.rst
> @@ -2,6 +2,12 @@
> 
>  Running mmc-utils
>  -----------------
> +**Bash completion**
> +    Source ``completion/mmc`` to enable tab-completion for all subcommands
> and
> +    device paths. When installed via ``make install``, the file is placed in
> +    ``$(bashcompletiondir)`` (default: ``/usr/share/bash-
> completion/completions/mmc``)
> +    and loaded automatically by bash-completion.
> +
>  **Name**
>      mmc - a tool for configuring MMC storage devices
>  **Synopsis**
> --
> 2.53.0
>