From 6b839159a53b7c94c70d7541ed4c9aa264f1d631 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Sun, 3 Oct 2021 19:59:21 +0100 Subject: [PATCH 1/4] use `string.Template` --- shtab/__init__.py | 62 ++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/shtab/__init__.py b/shtab/__init__.py index b18b71d..557543b 100644 --- a/shtab/__init__.py +++ b/shtab/__init__.py @@ -14,6 +14,7 @@ _VersionAction, ) from functools import total_ordering +from string import Template # version detector. Precedence: installed dist, git, 'UNKNOWN' try: @@ -129,13 +130,6 @@ def complete2pattern(opt_complete, shell, choice_type2fn): ) -def replace_format(string, **fmt): - """Similar to `string.format(**fmt)` but ignores unknown `{key}`s.""" - for k, v in fmt.items(): - string = string.replace("{" + k + "}", v) - return string - - def wordify(string): """Replace non-word chars [-. ] with underscores [_]""" return string.replace("-", "_").replace(".", " ").replace(" ", "_") @@ -362,22 +356,22 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): # Programmable-Completion.html # - https://opensource.com/article/18/3/creating-bash-completion-script # - https://stackoverflow.com/questions/12933362 - return replace_format( + return Template( """\ #!/usr/bin/env bash # AUTOMATCALLY GENERATED by `shtab` -{subparsers} +${subparsers} -{option_strings} +${option_strings} -{compgens} +${compgens} -{choices} +${choices} -{nargs} +${nargs} -{preamble} +${preamble} # $1=COMP_WORDS[1] _shtab_compgen_files() { compgen -f -- $1 # files @@ -396,7 +390,7 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): # set default values (called for the initial parser & any subparsers) _set_parser_defaults() { local subparsers_var="${prefix}_subparsers[@]" - subparsers=${!subparsers_var} + sub_parsers=${!subparsers_var} local current_option_strings_var="${prefix}_option_strings[@]" current_option_strings=${!current_option_strings_var} @@ -437,11 +431,11 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): # hello="world" # x="hello" # ${!x} -> ${hello} -> "world" -{root_prefix}() { +${root_prefix}() { local completing_word="${COMP_WORDS[COMP_CWORD]}" COMPREPLY=() - prefix={root_prefix} + prefix=${root_prefix} word_index=0 _set_parser_defaults word_index=1 @@ -451,7 +445,7 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): while [ $word_index -ne $COMP_CWORD ]; do local this_word="${COMP_WORDS[$word_index]}" - if [[ -n $subparsers && " ${subparsers[@]} " =~ " ${this_word} " ]]; then + if [[ -n $sub_parsers && " ${sub_parsers[@]} " =~ " ${this_word} " ]]; then # valid subcommand: add it to the prefix & reset the current action prefix="${prefix}_$(_shtab_replace_nonword $this_word)" _set_parser_defaults @@ -491,7 +485,8 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): return 0 } -complete -o filenames -F {root_prefix} {prog}""", +complete -o filenames -F ${root_prefix} ${prog}""" + ).safe_substitute( subparsers="\n".join(subparsers), option_strings="\n".join(option_strings), compgens="\n".join(compgens), @@ -632,37 +627,38 @@ def format_positional(opt): # - https://mads-hartmann.com/2017/08/06/ # writing-zsh-completion-scripts.html # - http://www.linux-mag.com/id/1106/ - return replace_format( + return Template( """\ -#compdef {prog} +#compdef ${prog} # AUTOMATCALLY GENERATED by `shtab` -{root_prefix}_options_=( - {root_options} +${root_prefix}_options_=( + ${root_options} ) -{root_prefix}_commands_() { +${root_prefix}_commands_() { local _commands=( - {commands} + ${commands} ) - _describe '{prog} commands' _commands + _describe '${prog} commands' _commands } -{subcommands} -{preamble} +${subcommands} +${preamble} typeset -A opt_args local context state line curcontext="$curcontext" _arguments \\ - ${root_prefix}_options_ \\ - {root_arguments} \\ - ': :{root_prefix}_commands_' \\ + $$${root_prefix}_options_ \\ + ${root_arguments} \\ + ': :${root_prefix}_commands_' \\ '*::args:->args' case $words[1] in - {commands_case} -esac""", + ${commands_case} +esac""" + ).safe_substitute( root_prefix=root_prefix, prog=parser.prog, commands="\n ".join( From 67257209699a804d41ec05df0c2c6acbeb11bb9e Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Sun, 3 Oct 2021 20:00:03 +0100 Subject: [PATCH 2/4] minor pre-commit updates --- .pre-commit-config.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a65a323..fd50db5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,12 +31,14 @@ repos: - id: flake8 args: [-j8] additional_dependencies: + - flake8-broken-line - flake8-bugbear - flake8-comprehensions - flake8-debugger + - flake8-isort - flake8-string-format - repo: https://github.com/psf/black - rev: 21.8b0 + rev: 21.9b0 hooks: - id: black - repo: https://github.com/PyCQA/isort From d626220147a801ed43ef32ee0e09139c95177f2f Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 11 Oct 2021 13:20:04 +0100 Subject: [PATCH 3/4] fix py2.7 tests --- .github/workflows/test.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 64eeb11..845b6ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,7 +50,13 @@ jobs: - uses: actions/setup-python@v2 with: python-version: ${{ matrix.python }} - - run: pip install -U -r requirements-dev.txt + - name: Install + run: | + if [[ ${{ matrix.python }} == '2.7' ]]; then + pip install -U pytest-cov 'pytest-timeout<2' + else + pip install -U -r requirements-dev.txt + fi - run: pytest - uses: codecov/codecov-action@v1 deploy: From 2a4b49887c1f3572eb2be8c90d377ecea1582085 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Tue, 12 Oct 2021 00:32:05 +0100 Subject: [PATCH 4/4] examples: fix subparser completion hiding - fixes #54 --- examples/customcomplete.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/customcomplete.py b/examples/customcomplete.py index 1c7a6ff..f90343e 100755 --- a/examples/customcomplete.py +++ b/examples/customcomplete.py @@ -39,12 +39,12 @@ def get_main_parser(): subparsers.required = True subparsers.dest = "subcommand" - parser = subparsers.add_parser("completion") + parser = subparsers.add_parser("completion", help="print tab completion") shtab.add_argument_to( parser, "shell", parent=main_parser, preamble=PREAMBLE ) # magic! - parser = subparsers.add_parser("process") + parser = subparsers.add_parser("process", help="parse files") # `*.txt` file tab completion parser.add_argument("input_txt", nargs="?").complete = TXT_FILE # file tab completion builtin shortcut