public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Ashley E Desimone" <ashley.e.desimone@intel.com>
To: "Desimone, Nathaniel L" <nathaniel.l.desimone@intel.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Pandya, Puja" <puja.pandya@intel.com>,
	"Bjorge, Erik C" <erik.c.bjorge@intel.com>,
	"Agyeman, Prince" <prince.agyeman@intel.com>,
	"Bret Barkelew" <Bret.Barkelew@microsoft.com>,
	Philippe Mathieu-Daude <philmd@redhat.com>
Subject: Re: [edk2-staging/EdkRepo] [PATCH V1 1/3] EdkRepo: Generate command completion scripts
Date: Fri, 3 Apr 2020 21:33:20 +0000	[thread overview]
Message-ID: <DM6PR11MB3628BB822763FAC0429063F8B2C70@DM6PR11MB3628.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20200401223452.4805-2-nathaniel.l.desimone@intel.com>

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@intel.com> 
Sent: Wednesday, April 1, 2020 3:35 PM
To: devel@edk2.groups.io
Cc: Desimone, Ashley E <ashley.e.desimone@intel.com>; Pandya, Puja <puja.pandya@intel.com>; Bjorge, Erik C <erik.c.bjorge@intel.com>; Agyeman, Prince <prince.agyeman@intel.com>; Bret Barkelew <Bret.Barkelew@microsoft.com>; Philippe Mathieu-Daude <philmd@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@intel.com>
Cc: Puja Pandya <puja.pandya@intel.com>
Cc: Erik Bjorge <erik.c.bjorge@intel.com>
Cc: Prince Agyeman <prince.agyeman@intel.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Philippe Mathieu-Daude <philmd@redhat.com>
Signed-off-by: Nate DeSimone <nathaniel.l.desimone@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


  reply	other threads:[~2020-04-03 21:33 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-01 22:34 [edk2-staging/EdkRepo] [PATCH V1 0/3] EdkRepo: Command completion in bash/zsh Nate DeSimone
2020-04-01 22:34 ` [edk2-staging/EdkRepo] [PATCH V1 1/3] EdkRepo: Generate command completion scripts Nate DeSimone
2020-04-03 21:33   ` Ashley E Desimone [this message]
2020-04-01 22:34 ` [edk2-staging/EdkRepo] [PATCH V1 2/3] EdkRepo: Add command completion setup to install.py Nate DeSimone
2020-04-03 21:51   ` Ashley E Desimone
2020-04-01 22:34 ` [edk2-staging/EdkRepo] [PATCH V1 3/3] EdkRepo: Add command completion setup to Windows installer Nate DeSimone
2020-04-03 21:55   ` Ashley E Desimone

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM6PR11MB3628BB822763FAC0429063F8B2C70@DM6PR11MB3628.namprd11.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox