Просмотр исходного кода

completion: add support for borg help

Thomas Waldmann 1 месяц назад
Родитель
Сommit
03b0cf0b9b
2 измененных файлов с 44 добавлено и 2 удалено
  1. 41 1
      src/borg/archiver/completion_cmd.py
  2. 3 1
      src/borg/archiver/help_cmd.py

+ 41 - 1
src/borg/archiver/completion_cmd.py

@@ -192,6 +192,12 @@ _borg_complete_filescachemode() {
     printf '%s\n' "${prefix_eq}${head}${k}"
     printf '%s\n' "${prefix_eq}${head}${k}"
   done
   done
 }
 }
+
+_borg_help_topics() {
+    local choices="{HELP_CHOICES}"
+    local IFS=$' \t\n'
+    compgen -W "${choices}" -- "$1"
+}
 """
 """
 
 
 
 
@@ -353,6 +359,11 @@ _borg_complete_filescachemode() {
   compadd -Q -- $candidates
   compadd -Q -- $candidates
   return 0
   return 0
 }
 }
+
+_borg_help_topics() {
+    local choices=({HELP_CHOICES})
+    _describe 'help topics' choices
+}
 """
 """
 
 
 
 
@@ -403,6 +414,18 @@ def _attach_filescachemode_completion(parser: argparse.ArgumentParser):
             action.complete = {"bash": FCM_BASH_FN_NAME, "zsh": FCM_ZSH_FN_NAME}  # type: ignore[attr-defined]
             action.complete = {"bash": FCM_BASH_FN_NAME, "zsh": FCM_ZSH_FN_NAME}  # type: ignore[attr-defined]
 
 
 
 
+def _attach_help_completion(parser: argparse.ArgumentParser, completion_dict: dict):
+    """Tag the 'topic' argument of the 'help' command with static completion choices."""
+    for action in parser._actions:
+        if isinstance(action, argparse._SubParsersAction):
+            for sub in action.choices.values():
+                _attach_help_completion(sub, completion_dict)
+            continue
+
+        if action.dest == "topic":
+            action.complete = completion_dict  # type: ignore[attr-defined]
+
+
 class CompletionMixIn:
 class CompletionMixIn:
     def do_completion(self, args):
     def do_completion(self, args):
         """Output shell completion script for the given shell."""
         """Output shell completion script for the given shell."""
@@ -415,10 +438,27 @@ class CompletionMixIn:
         _attach_sortby_completion(parser)
         _attach_sortby_completion(parser)
         _attach_filescachemode_completion(parser)
         _attach_filescachemode_completion(parser)
 
 
+        # Collect all commands and help topics for "borg help" completion
+        help_choices = list(self.helptext.keys())
+        for action in parser._actions:
+            if isinstance(action, argparse._SubParsersAction):
+                help_choices.extend(action.choices.keys())
+
+        help_completion_fn = "_borg_help_topics"
+        _attach_help_completion(parser, {"bash": help_completion_fn, "zsh": help_completion_fn})
+
         # Build preambles using partial_format to avoid escaping braces etc.
         # Build preambles using partial_format to avoid escaping braces etc.
         sort_keys = " ".join(AI_HUMAN_SORT_KEYS)
         sort_keys = " ".join(AI_HUMAN_SORT_KEYS)
         fcm_keys = " ".join(["ctime", "mtime", "size", "inode", "rechunk", "disabled"])  # keep in sync with parser
         fcm_keys = " ".join(["ctime", "mtime", "size", "inode", "rechunk", "disabled"])  # keep in sync with parser
-        mapping = {"SORT_KEYS": sort_keys, "FCM_KEYS": fcm_keys}
+
+        # Help completion templates
+        help_choices = " ".join(sorted(help_choices))
+
+        mapping = {
+            "SORT_KEYS": sort_keys,
+            "FCM_KEYS": fcm_keys,
+            "HELP_CHOICES": help_choices,
+        }
         bash_preamble = partial_format(BASH_PREAMBLE_TMPL, mapping)
         bash_preamble = partial_format(BASH_PREAMBLE_TMPL, mapping)
         zsh_preamble = partial_format(ZSH_PREAMBLE_TMPL, mapping)
         zsh_preamble = partial_format(ZSH_PREAMBLE_TMPL, mapping)
         preamble = {"bash": bash_preamble, "zsh": zsh_preamble}
         preamble = {"bash": bash_preamble, "zsh": zsh_preamble}

+ 3 - 1
src/borg/archiver/help_cmd.py

@@ -536,7 +536,9 @@ class HelpMixIn:
     do_maincommand_help = do_subcommand_help
     do_maincommand_help = do_subcommand_help
 
 
     def build_parser_help(self, subparsers, common_parser, mid_common_parser, parser):
     def build_parser_help(self, subparsers, common_parser, mid_common_parser, parser):
-        subparser = subparsers.add_parser("help", parents=[common_parser], add_help=False, description="Extra help")
+        subparser = subparsers.add_parser(
+            "help", parents=[common_parser], add_help=False, description="Extra help", help="Extra help"
+        )
         subparser.add_argument("--epilog-only", dest="epilog_only", action="store_true")
         subparser.add_argument("--epilog-only", dest="epilog_only", action="store_true")
         subparser.add_argument("--usage-only", dest="usage_only", action="store_true")
         subparser.add_argument("--usage-only", dest="usage_only", action="store_true")
         subparser.set_defaults(func=functools.partial(self.do_help, parser, subparsers.choices))
         subparser.set_defaults(func=functools.partial(self.do_help, parser, subparsers.choices))