On 11.11.21 11:59, Michael Adler wrote:
> With the plethora of new command-line options, it is starting to get
> difficult to remember them all. This commit introduces shell completions
> for bash and zsh for the convenience of the user.
> 
> Instead of writing the completion files by hand (a tedious task), the
> files are generated automatically from a Python spec using shtab [1].
> To ease the integration into the main Makefile (automake), the generated
> completions are stored in git as well. This has the advantage that 'make
> install' will install the completion files. A CI job ensures that the
> generated files are in sync with the spec (i.e. python files).
> 
> [1] https://github.com/iterative/shtab
> 
> Signed-off-by: Michael Adler <[email protected]>
> ---
>  .github/workflows/main.yaml                   |   9 ++
>  .gitignore                                    |   4 +
>  Makefile.am                                   |   6 +
>  share/completion/.gitignore                   |   2 +
>  share/completion/Makefile                     |  38 +++++
>  share/completion/bg_printenv/cli.py           |  31 ++++
>  share/completion/bg_printenv/common.py        |   1 +
>  share/completion/bg_setenv/cli.py             |  47 ++++++
>  share/completion/bg_setenv/common.py          |   1 +
>  share/completion/common.py                    |  23 +++
>  .../generated/bash/bg_printenv.bash           | 139 +++++++++++++++++
>  .../completion/generated/bash/bg_setenv.bash  | 142 ++++++++++++++++++
>  share/completion/generated/zsh/_bg_printenv   |  37 +++++
>  share/completion/generated/zsh/_bg_setenv     |  43 ++++++

Why "share/"? Can't we just use completion/ as subfolder?

>  14 files changed, 523 insertions(+)
>  create mode 100644 share/completion/.gitignore
>  create mode 100644 share/completion/Makefile
>  create mode 100644 share/completion/bg_printenv/cli.py
>  create mode 120000 share/completion/bg_printenv/common.py
>  create mode 100644 share/completion/bg_setenv/cli.py
>  create mode 120000 share/completion/bg_setenv/common.py
>  create mode 100644 share/completion/common.py
>  create mode 100644 share/completion/generated/bash/bg_printenv.bash
>  create mode 100644 share/completion/generated/bash/bg_setenv.bash
>  create mode 100644 share/completion/generated/zsh/_bg_printenv
>  create mode 100644 share/completion/generated/zsh/_bg_setenv
> 
> diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
> index 10b2a2d..78f6ce4 100644
> --- a/.github/workflows/main.yaml
> +++ b/.github/workflows/main.yaml
> @@ -160,3 +160,12 @@ jobs:
>            # files are provided. Compare 'cppcheck --help'.
>            cppcheck -f -q --error-exitcode=2 $enable $suppress $ignore \
>                $cpp_conf $includes .
> +
> +      - name: Generate shell completions
> +        if: ${{ matrix.target == 'amd64' }}
> +        run: |
> +          sudo apt-get install -y --no-install-recommends make python3 pip 
> git
> +          sudo pip install shtab

Given that Python is a standard package and we only need that single
shtab thing from pip, why not doing the generation during build in a
virtual env, using a pinned version of shtab that is fetched on demand,
maybe with the option to run in the host env if the user prefers to
install shtab manually?

> +          rm -rf share/completion/generated

There should be a clean target for this in [share/]completion/Makefile

> +          make -C share/completion
> +          git diff --exit-code share/completion
> diff --git a/.gitignore b/.gitignore
> index 1943fe0..f472f03 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -92,3 +92,7 @@ test_ebgenv_api
>  test_ebgenv_api_internal
>  test_probe_config_file
>  test_probe_config_partitions
> +
> +### Python ###
> +__pycache__
> +*.pyc
> diff --git a/Makefile.am b/Makefile.am
> index 8081839..9351488 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -218,6 +218,12 @@ efibootguard_DATA = $(efi_loadername)
>  CLEANFILES += $(efi_objects) $(efi_solib) $(efi_loadername)
>  EXTRA_DIST += $(efi_sources)
>  
> +bashcompletiondir = ${datarootdir}/efibootguard/completion/bash
> +bashcompletion_DATA = share/completion/generated/bash/bg_setenv.bash 
> share/completion/generated/bash/bg_printenv.bash
> +
> +zshcompletiondir = ${datarootdir}/efibootguard/completion/zsh
> +zshcompletion_DATA = share/completion/generated/zsh/_bg_setenv 
> share/completion/generated/zsh/_bg_printenv
> +
>  $(top_builddir)/%.o: $(top_srcdir)/%.c
>       @$(MKDIR_P) $(shell dirname $@)/
>       $(AM_V_CC)$(GNUEFI_CC) $(efi_cppflags) $(efi_cflags) -c $< -o $@
> diff --git a/share/completion/.gitignore b/share/completion/.gitignore
> new file mode 100644
> index 0000000..b731cd1
> --- /dev/null
> +++ b/share/completion/.gitignore
> @@ -0,0 +1,2 @@
> +!bg_printenv
> +!bg_setenv
> diff --git a/share/completion/Makefile b/share/completion/Makefile
> new file mode 100644
> index 0000000..21105bb
> --- /dev/null
> +++ b/share/completion/Makefile
> @@ -0,0 +1,38 @@
> +# Copyright (c) Siemens AG, 2021
> +#
> +# Authors:
> +#  Michael Adler <[email protected]>
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2.  See
> +# the COPYING file in the top-level directory.
> +#
> +# SPDX-License-Identifier:   GPL-2.0
> +PYTHON ?= python3
> +
> +all: bash-completion zsh-completion
> +
> +bash-completion: generated/bash/bg_setenv.bash 
> generated/bash/bg_printenv.bash
> +
> +zsh-completion: generated/zsh/_bg_setenv generated/zsh/_bg_printenv
> +
> +generated/bash/bg_setenv.bash: bg_setenv/cli.py
> +     @echo "Generating $@"
> +     @mkdir -p $(@D)
> +     @$(PYTHON) -m shtab --shell=bash -u "bg_setenv.cli.bg_setenv" >$@
> +
> +generated/bash/bg_printenv.bash: bg_printenv/cli.py
> +     @echo "Generating $@"
> +     @mkdir -p $(@D)
> +     @-$(PYTHON) -m shtab --shell=bash -u "bg_printenv.cli.bg_printenv" >$@
> +
> +generated/zsh/_bg_setenv: bg_setenv/cli.py
> +     @echo "Generating $@"
> +     @mkdir -p $(@D)
> +     @-$(PYTHON) -m shtab --shell=zsh -u "bg_setenv.cli.bg_setenv" >$@
> +
> +generated/zsh/_bg_printenv: bg_printenv/cli.py
> +     @echo "Generating $@"
> +     @mkdir -p $(@D)
> +     @-$(PYTHON) -m shtab --shell=zsh -u "bg_printenv.cli.bg_printenv" >$@
> +
> +.PHONY: all bash-completion zsh-completion

clean is missing, see above.

> diff --git a/share/completion/bg_printenv/cli.py 
> b/share/completion/bg_printenv/cli.py
> new file mode 100644
> index 0000000..570faf9
> --- /dev/null
> +++ b/share/completion/bg_printenv/cli.py
> @@ -0,0 +1,31 @@
> +#
> +# Copyright (c) Siemens AG, 2021
> +#
> +# Authors:
> +#  Michael Adler <[email protected]>
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2.  See
> +# the COPYING file in the top-level directory.
> +#
> +# SPDX-License-Identifier:   GPL-2.0
> +
> +import argparse
> +
> +from .common import add_common_opts
> +
> +
> +def bg_printenv():
> +    parser = argparse.ArgumentParser(prog="bg_printenv", add_help=False)
> +    add_common_opts(parser)
> +    parser.add_argument("-c", "--current", action="store_true", help="Only 
> print values from the current environment")
> +    parser.add_argument(
> +        "-o",
> +        "--output",
> +        choices=["in_progress", "revision", "kernel", "kernelargs", 
> "watchdog_timeout", "ustate", "user"],
> +        help="Comma-separated list of fields which are printed",
> +    )
> +    parser.add_argument("-r", "--raw", action="store_true", help="Raw output 
> mode")
> +    parser.add_argument("--usage", action="store_true", help="Give a short 
> usage message")
> +    return parser
> +
> +
> diff --git a/share/completion/bg_printenv/common.py 
> b/share/completion/bg_printenv/common.py
> new file mode 120000
> index 0000000..a11703e
> --- /dev/null
> +++ b/share/completion/bg_printenv/common.py
> @@ -0,0 +1 @@
> +../common.py
> \ No newline at end of file
> diff --git a/share/completion/bg_setenv/cli.py 
> b/share/completion/bg_setenv/cli.py
> new file mode 100644
> index 0000000..9698882
> --- /dev/null
> +++ b/share/completion/bg_setenv/cli.py
> @@ -0,0 +1,47 @@
> +#
> +# Copyright (c) Siemens AG, 2021
> +#
> +# Authors:
> +#  Michael Adler <[email protected]>
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2.  See
> +# the COPYING file in the top-level directory.
> +#
> +# SPDX-License-Identifier:   GPL-2.0
> +
> +import argparse
> +
> +from .common import add_common_opts
> +
> +
> +def bg_setenv():
> +    parser = argparse.ArgumentParser(prog="bg_setenv", add_help=False)
> +    add_common_opts(parser)
> +    parser.add_argument("-P", "--preserve", action="store_true", 
> help="Preserve existing entries")
> +    parser.add_argument("-k", "--kernel", metavar="KERNEL", help="Set kernel 
> to load")
> +    parser.add_argument("-a", "--args", metavar="KERNEL_ARGS", help="Set 
> kernel arguments")
> +    parser.add_argument("-r", "--revision", metavar="REVISION", help="Set 
> revision value")
> +    parser.add_argument(
> +        "-s",
> +        "--ustate",
> +        choices=["OK", "INSTALLED", "TESTING", "FAILED", "UNKNOWN"],
> +        metavar="USTATE",
> +        help="Set update status for environment",
> +    )
> +    parser.add_argument("-w", "--watchdog", metavar="WATCHDOG_TIMEOUT", 
> help="Watchdog timeout in seconds")
> +    parser.add_argument("-c", "--confirm", action="store_true", 
> help="Confirm working environment")
> +    parser.add_argument("-u", "--update", action="store_true", 
> help="Automatically update oldest revision")
> +    parser.add_argument(
> +        "-x",
> +        "--uservar",
> +        metavar="KEY=VAL",
> +        help="Set user-defined string variable. For setting multiple 
> variables, use this option multiple times.",
> +    )
> +    parser.add_argument(
> +        "-i",
> +        "--in_progress",
> +        metavar="IN_PROGRESS",
> +        choices=["0", "1"],
> +        help="Set in_progress variable to simulate a running update 
> process.",
> +    )
> +    return parser
> diff --git a/share/completion/bg_setenv/common.py 
> b/share/completion/bg_setenv/common.py
> new file mode 120000
> index 0000000..a11703e
> --- /dev/null
> +++ b/share/completion/bg_setenv/common.py
> @@ -0,0 +1 @@
> +../common.py
> \ No newline at end of file
> diff --git a/share/completion/common.py b/share/completion/common.py
> new file mode 100644
> index 0000000..8134aef
> --- /dev/null
> +++ b/share/completion/common.py
> @@ -0,0 +1,23 @@
> +#
> +# Copyright (c) Siemens AG, 2021
> +#
> +# Authors:
> +#  Michael Adler <[email protected]>
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2.  See
> +# the COPYING file in the top-level directory.
> +#
> +# SPDX-License-Identifier:   GPL-2.0
> +
> +import shtab
> +
> +
> +def add_common_opts(parser):
> +    parser.add_argument(
> +        "-f", "--filepath", metavar="ENVFILE", help="Environment to use. 
> Expects a file name, usually called BGENV.DAT."
> +    ).complete = shtab.FILE
> +    parser.add_argument("-p", "--part", metavar="ENV_PART", type=int, 
> help="Set environment partition to update")
> +    parser.add_argument("-v", "--verbose", action="store_true", help="Be 
> verbose")
> +    parser.add_argument("-V", "--version", action="store_true", help="Print 
> version")
> +    # there is a bug in shtab which currently prohibits "-?"
> +    parser.add_argument("--help", action="store_true", help="Show help")

So we are replicating the command line options from the C tools in
Python stubs - ok. But please leave a comment in the affected C files
where the Python files should be updated as well when changing options.

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux

-- 
You received this message because you are subscribed to the Google Groups "EFI 
Boot Guard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/efibootguard-dev/86b93e59-839a-8bf3-522d-cb9a8f569b98%40siemens.com.

Reply via email to