[edk2-devel] [edk2-staging/EdkRepo] [PATCH V1 1/3] EdkRepo: Generate command completion scripts

Ashley E Desimone ashley.e.desimone at intel.com
Fri Apr 3 21:33:20 UTC 2020


The following section will need to be updated to take into account Erik's recent addition of support for archived combinations. 

+def checkout(parsed_args, config):
+    manifest = get_workspace_manifest()
+    print(' '.join([c.name for c in manifest.combinations]))

Thanks,
Ashley 

-----Original Message-----
From: Desimone, Nathaniel L <nathaniel.l.desimone at intel.com> 
Sent: Wednesday, April 1, 2020 3:35 PM
To: devel at edk2.groups.io
Cc: Desimone, Ashley E <ashley.e.desimone at intel.com>; Pandya, Puja <puja.pandya at intel.com>; Bjorge, Erik C <erik.c.bjorge at intel.com>; Agyeman, Prince <prince.agyeman at intel.com>; Bret Barkelew <Bret.Barkelew at microsoft.com>; Philippe Mathieu-Daude <philmd at redhat.com>
Subject: [edk2-staging/EdkRepo] [PATCH V1 1/3] EdkRepo: Generate command completion scripts

Adds code to edkrepo_cli.py to generate a bash/zsh compatible command completion script.

Add a new command_completion_edkrepo.py script which is callable by the shell when needed for dynamic completion data. For example, providing completion for "edkrepo checkout" requires the shell to know the list of possible branch combinations, this requires parsing the manifest XML. command_completion_edkrepo.py provides a means for the shell to get that type of data.

Cc: Ashley DeSimone <ashley.e.desimone at intel.com>
Cc: Puja Pandya <puja.pandya at intel.com>
Cc: Erik Bjorge <erik.c.bjorge at intel.com>
Cc: Prince Agyeman <prince.agyeman at intel.com>
Cc: Bret Barkelew <Bret.Barkelew at microsoft.com>
Cc: Philippe Mathieu-Daude <philmd at redhat.com>
Signed-off-by: Nate DeSimone <nathaniel.l.desimone at intel.com>
---
 edkrepo/command_completion_edkrepo.py | 86 +++++++++++++++++++++++++++
 edkrepo/edkrepo_cli.py                | 61 ++++++++++++++++++-
 setup.py                              |  8 +--
 3 files changed, 150 insertions(+), 5 deletions(-)  create mode 100644 edkrepo/command_completion_edkrepo.py

diff --git a/edkrepo/command_completion_edkrepo.py b/edkrepo/command_completion_edkrepo.py
new file mode 100644
index 0000000..05de9ca
--- /dev/null
+++ b/edkrepo/command_completion_edkrepo.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+#
+## @file
+# command_completion_edkrepo.py
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> # 
+SPDX-License-Identifier: BSD-2-Clause-Patent #
+
+import argparse
+import io
+import os
+import sys
+import traceback
+
+from edkrepo_manifest_parser.edk_manifest import ManifestXml from 
+edkrepo.config import config_factory from edkrepo.config.config_factory 
+import get_workspace_manifest
+
+def checkout(parsed_args, config):
+    manifest = get_workspace_manifest()
+    print(' '.join([c.name for c in manifest.combinations]))
+
+def current_combo(parsed_args, config):
+    manifest = get_workspace_manifest()
+    print(" [{}]".format(manifest.general_config.current_combo))
+
+def checkout_pin(parsed_args, config):
+    pins = []
+    manifest_directory = config['cfg_file'].manifest_repo_abs_local_path
+    manifest = get_workspace_manifest()
+    pin_folder = os.path.normpath(os.path.join(manifest_directory, manifest.general_config.pin_path))
+    for dirpath, _, filenames in os.walk(pin_folder):
+        for file in filenames:
+            pin_file = os.path.join(dirpath, file)
+            # Capture error output from manifest parser stdout so it is hidden unless verbose is enabled
+            stdout = sys.stdout
+            sys.stdout = io.StringIO()
+            pin = ManifestXml(pin_file)
+            parse_output = sys.stdout.getvalue()
+            sys.stdout = stdout
+            if parsed_args.verbose and parse_output.strip() != '':
+                print('Pin {} Parsing Errors: {}\n'.format(file, parse_output.strip()))
+            if pin.project_info.codename == manifest.project_info.codename:
+                pins.append(file)
+    print(' '.join(pins))
+
+# To add command completions for a new command, add an entry to this dictionary.
+command_completions = {
+    'current-combo': current_combo,
+    'checkout': checkout,
+    'checkout-pin': checkout_pin,
+    'chp': checkout_pin
+}
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("-v", "--verbose", action="store_true", help='Increases command verbosity')
+    subparsers = parser.add_subparsers(dest='subparser_name')
+    for command_completion in command_completions:
+        subparsers.add_parser(command_completion, formatter_class=argparse.RawTextHelpFormatter)
+    if len(sys.argv) <= 1:
+        return 0
+    parsed_args = parser.parse_args()
+    try:
+        command_name = parsed_args.subparser_name
+        config = {}
+        config["cfg_file"] = config_factory.GlobalConfig()
+        config["user_cfg_file"] = config_factory.GlobalUserConfig()
+        if command_name not in command_completions:
+            return 1
+        command_completions[command_name](parsed_args, config)
+        return 0
+    except Exception as e:
+        if parsed_args.verbose:
+            traceback.print_exc()
+            print("Error: {}".format(str(e)))
+        return 1
+    return 0
+
+if __name__ == "__main__":
+    try:
+        sys.exit(main())
+    except Exception as e:
+        traceback.print_exc()
+        sys.exit(1)
diff --git a/edkrepo/edkrepo_cli.py b/edkrepo/edkrepo_cli.py index 0b69860..03061c9 100644
--- a/edkrepo/edkrepo_cli.py
+++ b/edkrepo/edkrepo_cli.py
@@ -3,7 +3,7 @@
 ## @file
 # edkrepo_cli.py
 #
-# Copyright (c) 2017- 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2020, Intel Corporation. All rights 
+reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent  #
 
@@ -29,6 +29,7 @@ from edkrepo.common.edkrepo_exception import EdkrepoException, EdkrepoGlobalConf  from edkrepo.common.edkrepo_exception import EdkrepoWarningException  from edkrepo.common.edkrepo_exception import EdkrepoConfigFileInvalidException  from edkrepo.common.humble import KEYBOARD_INTERRUPT, GIT_CMD_ERROR
+from edkrepo.common.pathfix import get_actual_path
 
 def generate_command_line(command):
     parser = argparse.ArgumentParser()
@@ -100,6 +101,61 @@ def generate_command_line(command):
                 subparser_name.add_argument(('--' + arg.get('name')), action=arg_action, help=arg.get('help-text'))
     return parser
 
+command_completion_script_header='''#!/usr/bin/env bash # ## @file 
+edkrepo_completions.sh # # Automatically generated please DO NOT modify 
+!!!
+#
+
+'''
+def generate_command_completion_script(script_filename, parser):
+    import edkrepo.command_completion_edkrepo as completion
+    commands = []
+    for action in parser._positionals._group_actions:
+        if action.choices is not None:
+            commands = [c for c in action.choices]
+            break
+    commands = sorted(commands)
+    commands_with_3rd_param_completion = [c for c in completion.command_completions if c in commands]
+    commands_with_3rd_param_completion = sorted(commands_with_3rd_param_completion)
+    with open(script_filename, 'w') as f:
+        f.write(command_completion_script_header)
+        if sys.platform == "win32":
+            command_completion_path = os.path.dirname(sys.executable)
+            command_completion_path = os.path.join(command_completion_path, 'Scripts', "command_completion_edkrepo.exe")
+            if not os.path.isfile(command_completion_path):
+                print('command_completion_edkrepo.exe not found')
+                return
+            command_completion_path = get_actual_path(command_completion_path)
+            (drive, path) = os.path.splitdrive(command_completion_path)
+            command_completion_path = '/{}{}'.format(drive.replace(':','').lower(), path.replace('\\','/'))
+            f.write("export command_completion_edkrepo_file='{}'\n".format(command_completion_path))
+            f.write('alias command_completion_edkrepo="$command_completion_edkrepo_file"\n')
+        f.write('_edkrepo_completions() {\n    if [ "${#COMP_WORDS[@]}" -eq "2" ]; then\n')
+        f.write('        COMPREPLY=($(compgen -W "{}" -- "${{COMP_WORDS[1]}}"))\n'.format(' '.join(commands)))
+        if len(commands_with_3rd_param_completion) > 0:
+            f.write('    elif [ "${#COMP_WORDS[@]}" -eq "3" ]; then\n')
+        first_loop = True
+        for command in commands_with_3rd_param_completion:
+            if first_loop:
+                f.write('        if [ "${{COMP_WORDS[1]}}" == "{}" ]; then\n'.format(command))
+                first_loop = False
+            else:
+                f.write('        elif [ "${{COMP_WORDS[1]}}" == "{}" ]; then\n'.format(command))
+            f.write('            COMPREPLY=($(compgen -W "$(command_completion_edkrepo ${COMP_WORDS[1]})" -- "${COMP_WORDS[2]}"))\n')
+        if len(commands_with_3rd_param_completion) > 0:
+            f.write('        fi\n')
+        f.write('    fi\n}\n\n')
+        if len(commands_with_3rd_param_completion) > 0:
+            if sys.platform == "win32":
+                f.write('if [ -x "$(command -v edkrepo)" ] && [ -x "$(command -v $command_completion_edkrepo_file)" ]; then\n')
+            else:
+                f.write('if [ -x "$(command -v edkrepo)" ] && [ -x "$(command -v command_completion_edkrepo)" ]; then\n')
+        else:
+            f.write('if [ -x "$(command -v edkrepo)" ]; then\n')
+        f.write('    complete -F _edkrepo_completions edkrepo\nfi\n')
+
 def main():
     command = command_factory.create_composite_command()
     config = {}
@@ -117,6 +173,9 @@ def main():
     if len(sys.argv) <= 1:
         parser.print_help()
         return 1
+    if sys.argv[1] == 'generate-command-completion-script' and len(sys.argv) >= 3:
+        generate_command_completion_script(sys.argv[2], parser)
+        return 0
     parsed_args = parser.parse_args()
     command_name = parsed_args.subparser_name
     try:
diff --git a/setup.py b/setup.py
index e14aed1..e7e6ce8 100755
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,8 @@
 #!/usr/bin/env python3
 #
-## @file
-# setup.py
+## @file setup.py
 #
-# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2020, Intel Corporation. All rights 
+reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent  #
 
@@ -20,7 +19,8 @@ setup(name='edkrepo',
       include_package_data=True,
       entry_points={
           'console_scripts': [
-              'edkrepo = edkrepo.edkrepo_entry_point:main'
+              'edkrepo = edkrepo.edkrepo_entry_point:main',
+              'command_completion_edkrepo = edkrepo.command_completion_edkrepo:main'
               ]
           }
       )
--
2.24.0.windows.2


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#56952): https://edk2.groups.io/g/devel/message/56952
Mute This Topic: https://groups.io/mt/72713333/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list