prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Bash completion for MultiCommands returns subcommands twice until it stops.
  Python 2.7.10
  broken in click >= 6
  ok in click (5.1)
  
  ```
  manage hello hello world world
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `click/_bashcomplete.py`
  Content:
  ```
  1 import os
  2 import re
  3 from .utils import echo
  4 from .parser import split_arg_string
  5 from .core import MultiCommand, Option
  6 
  7 
  8 COMPLETION_SCRIPT = '''
  9 %(complete_func)s() {
  10     COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \\
  11                    COMP_CWORD=$COMP_CWORD \\
  12                    %(autocomplete_var)s=complete $1 ) )
  13     return 0
  14 }
  15 
  16 complete -F %(complete_func)s -o default %(script_names)s
  17 '''
  18 
  19 _invalid_ident_char_re = re.compile(r'[^a-zA-Z0-9_]')
  20 
  21 
  22 def get_completion_script(prog_name, complete_var):
  23     cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_'))
  24     return (COMPLETION_SCRIPT % {
  25         'complete_func': '_%s_completion' % cf_name,
  26         'script_names': prog_name,
  27         'autocomplete_var': complete_var,
  28     }).strip() + ';'
  29 
  30 
  31 def resolve_ctx(cli, prog_name, args):
  32     ctx = cli.make_context(prog_name, args, resilient_parsing=True)
  33     while ctx.args and isinstance(ctx.command, MultiCommand):
  34         cmd = ctx.command.get_command(ctx, ctx.args[0])
  35         if cmd is None:
  36             return None
  37         ctx = cmd.make_context(ctx.args[0], ctx.args[1:], parent=ctx,
  38                                resilient_parsing=True)
  39     return ctx
  40 
  41 
  42 def do_complete(cli, prog_name):
  43     cwords = split_arg_string(os.environ['COMP_WORDS'])
  44     cword = int(os.environ['COMP_CWORD'])
  45     args = cwords[1:cword]
  46     try:
  47         incomplete = cwords[cword]
  48     except IndexError:
  49         incomplete = ''
  50 
  51     ctx = resolve_ctx(cli, prog_name, args)
  52     if ctx is None:
  53         return True
  54 
  55     choices = []
  56     if incomplete and not incomplete[:1].isalnum():
  57         for param in ctx.command.params:
  58             if not isinstance(param, Option):
  59                 continue
  60             choices.extend(param.opts)
  61             choices.extend(param.secondary_opts)
  62     elif isinstance(ctx.command, MultiCommand):
  63         choices.extend(ctx.command.list_commands(ctx))
  64 
  65     for item in choices:
  66         if item.startswith(incomplete):
  67             echo(item)
  68 
  69     return True
  70 
  71 
  72 def bashcomplete(cli, prog_name, complete_var, complete_instr):
  73     if complete_instr == 'source':
  74         echo(get_completion_script(prog_name, complete_var))
  75         return True
  76     elif complete_instr == 'complete':
  77         return do_complete(cli, prog_name)
  78     return False
  79
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/click/_bashcomplete.py b/click/_bashcomplete.py
  --- a/click/_bashcomplete.py
  +++ b/click/_bashcomplete.py
  @@ -30,27 +30,19 @@
   
   def resolve_ctx(cli, prog_name, args):
       ctx = cli.make_context(prog_name, args, resilient_parsing=True)
  -    while ctx.args and isinstance(ctx.command, MultiCommand):
  -        cmd = ctx.command.get_command(ctx, ctx.args[0])
  +    while ctx.args + ctx.protected_args and isinstance(ctx.command, MultiCommand):
  +        a = ctx.args + ctx.protected_args
  +        cmd = ctx.command.get_command(ctx, a[0])
           if cmd is None:
               return None
  -        ctx = cmd.make_context(ctx.args[0], ctx.args[1:], parent=ctx,
  -                               resilient_parsing=True)
  +        ctx = cmd.make_context(a[0], a[1:], parent=ctx, resilient_parsing=True)
       return ctx
   
   
  -def do_complete(cli, prog_name):
  -    cwords = split_arg_string(os.environ['COMP_WORDS'])
  -    cword = int(os.environ['COMP_CWORD'])
  -    args = cwords[1:cword]
  -    try:
  -        incomplete = cwords[cword]
  -    except IndexError:
  -        incomplete = ''
  -
  +def get_choices(cli, prog_name, args, incomplete):
       ctx = resolve_ctx(cli, prog_name, args)
       if ctx is None:
  -        return True
  +        return
   
       choices = []
       if incomplete and not incomplete[:1].isalnum():
  @@ -64,7 +56,20 @@
   
       for item in choices:
           if item.startswith(incomplete):
  -            echo(item)
  +            yield item
  +
  +
  +def do_complete(cli, prog_name):
  +    cwords = split_arg_string(os.environ['COMP_WORDS'])
  +    cword = int(os.environ['COMP_CWORD'])
  +    args = cwords[1:cword]
  +    try:
  +        incomplete = cwords[cword]
  +    except IndexError:
  +        incomplete = ''
  +
  +    for item in get_choices(cli, prog_name, args, incomplete):
  +        echo(item)
   
       return True
  
verification_info: {"golden_diff": "diff --git a/click/_bashcomplete.py b/click/_bashcomplete.py\n--- a/click/_bashcomplete.py\n+++ b/click/_bashcomplete.py\n@@ -30,27 +30,19 @@\n \n def resolve_ctx(cli, prog_name, args):\n     ctx = cli.make_context(prog_name, args, resilient_parsing=True)\n-    while ctx.args and isinstance(ctx.command, MultiCommand):\n-        cmd = ctx.command.get_command(ctx, ctx.args[0])\n+    while ctx.args + ctx.protected_args and isinstance(ctx.command, MultiCommand):\n+        a = ctx.args + ctx.protected_args\n+        cmd = ctx.command.get_command(ctx, a[0])\n         if cmd is None:\n             return None\n-        ctx = cmd.make_context(ctx.args[0], ctx.args[1:], parent=ctx,\n-                               resilient_parsing=True)\n+        ctx = cmd.make_context(a[0], a[1:], parent=ctx, resilient_parsing=True)\n     return ctx\n \n \n-def do_complete(cli, prog_name):\n-    cwords = split_arg_string(os.environ['COMP_WORDS'])\n-    cword = int(os.environ['COMP_CWORD'])\n-    args = cwords[1:cword]\n-    try:\n-        incomplete = cwords[cword]\n-    except IndexError:\n-        incomplete = ''\n-\n+def get_choices(cli, prog_name, args, incomplete):\n     ctx = resolve_ctx(cli, prog_name, args)\n     if ctx is None:\n-        return True\n+        return\n \n     choices = []\n     if incomplete and not incomplete[:1].isalnum():\n@@ -64,7 +56,20 @@\n \n     for item in choices:\n         if item.startswith(incomplete):\n-            echo(item)\n+            yield item\n+\n+\n+def do_complete(cli, prog_name):\n+    cwords = split_arg_string(os.environ['COMP_WORDS'])\n+    cword = int(os.environ['COMP_CWORD'])\n+    args = cwords[1:cword]\n+    try:\n+        incomplete = cwords[cword]\n+    except IndexError:\n+        incomplete = ''\n+\n+    for item in get_choices(cli, prog_name, args, incomplete):\n+        echo(item)\n \n     return True\n", "issue": "Bash completion for MultiCommands returns subcommands twice until it stops.\nPython 2.7.10\nbroken in click >= 6\nok in click (5.1)\n\n```\nmanage hello hello world world\n```\n\n", "before_files": [{"content": "import os\nimport re\nfrom .utils import echo\nfrom .parser import split_arg_string\nfrom .core import MultiCommand, Option\n\n\nCOMPLETION_SCRIPT = '''\n%(complete_func)s() {\n    COMPREPLY=( $( env COMP_WORDS=\"${COMP_WORDS[*]}\" \\\\\n                   COMP_CWORD=$COMP_CWORD \\\\\n                   %(autocomplete_var)s=complete $1 ) )\n    return 0\n}\n\ncomplete -F %(complete_func)s -o default %(script_names)s\n'''\n\n_invalid_ident_char_re = re.compile(r'[^a-zA-Z0-9_]')\n\n\ndef get_completion_script(prog_name, complete_var):\n    cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_'))\n    return (COMPLETION_SCRIPT % {\n        'complete_func': '_%s_completion' % cf_name,\n        'script_names': prog_name,\n        'autocomplete_var': complete_var,\n    }).strip() + ';'\n\n\ndef resolve_ctx(cli, prog_name, args):\n    ctx = cli.make_context(prog_name, args, resilient_parsing=True)\n    while ctx.args and isinstance(ctx.command, MultiCommand):\n        cmd = ctx.command.get_command(ctx, ctx.args[0])\n        if cmd is None:\n            return None\n        ctx = cmd.make_context(ctx.args[0], ctx.args[1:], parent=ctx,\n                               resilient_parsing=True)\n    return ctx\n\n\ndef do_complete(cli, prog_name):\n    cwords = split_arg_string(os.environ['COMP_WORDS'])\n    cword = int(os.environ['COMP_CWORD'])\n    args = cwords[1:cword]\n    try:\n        incomplete = cwords[cword]\n    except IndexError:\n        incomplete = ''\n\n    ctx = resolve_ctx(cli, prog_name, args)\n    if ctx is None:\n        return True\n\n    choices = []\n    if incomplete and not incomplete[:1].isalnum():\n        for param in ctx.command.params:\n            if not isinstance(param, Option):\n                continue\n            choices.extend(param.opts)\n            choices.extend(param.secondary_opts)\n    elif isinstance(ctx.command, MultiCommand):\n        choices.extend(ctx.command.list_commands(ctx))\n\n    for item in choices:\n        if item.startswith(incomplete):\n            echo(item)\n\n    return True\n\n\ndef bashcomplete(cli, prog_name, complete_var, complete_instr):\n    if complete_instr == 'source':\n        echo(get_completion_script(prog_name, complete_var))\n        return True\n    elif complete_instr == 'complete':\n        return do_complete(cli, prog_name)\n    return False\n", "path": "click/_bashcomplete.py"}], "after_files": [{"content": "import os\nimport re\nfrom .utils import echo\nfrom .parser import split_arg_string\nfrom .core import MultiCommand, Option\n\n\nCOMPLETION_SCRIPT = '''\n%(complete_func)s() {\n    COMPREPLY=( $( env COMP_WORDS=\"${COMP_WORDS[*]}\" \\\\\n                   COMP_CWORD=$COMP_CWORD \\\\\n                   %(autocomplete_var)s=complete $1 ) )\n    return 0\n}\n\ncomplete -F %(complete_func)s -o default %(script_names)s\n'''\n\n_invalid_ident_char_re = re.compile(r'[^a-zA-Z0-9_]')\n\n\ndef get_completion_script(prog_name, complete_var):\n    cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_'))\n    return (COMPLETION_SCRIPT % {\n        'complete_func': '_%s_completion' % cf_name,\n        'script_names': prog_name,\n        'autocomplete_var': complete_var,\n    }).strip() + ';'\n\n\ndef resolve_ctx(cli, prog_name, args):\n    ctx = cli.make_context(prog_name, args, resilient_parsing=True)\n    while ctx.args + ctx.protected_args and isinstance(ctx.command, MultiCommand):\n        a = ctx.args + ctx.protected_args\n        cmd = ctx.command.get_command(ctx, a[0])\n        if cmd is None:\n            return None\n        ctx = cmd.make_context(a[0], a[1:], parent=ctx, resilient_parsing=True)\n    return ctx\n\n\ndef get_choices(cli, prog_name, args, incomplete):\n    ctx = resolve_ctx(cli, prog_name, args)\n    if ctx is None:\n        return\n\n    choices = []\n    if incomplete and not incomplete[:1].isalnum():\n        for param in ctx.command.params:\n            if not isinstance(param, Option):\n                continue\n            choices.extend(param.opts)\n            choices.extend(param.secondary_opts)\n    elif isinstance(ctx.command, MultiCommand):\n        choices.extend(ctx.command.list_commands(ctx))\n\n    for item in choices:\n        if item.startswith(incomplete):\n            yield item\n\n\ndef do_complete(cli, prog_name):\n    cwords = split_arg_string(os.environ['COMP_WORDS'])\n    cword = int(os.environ['COMP_CWORD'])\n    args = cwords[1:cword]\n    try:\n        incomplete = cwords[cword]\n    except IndexError:\n        incomplete = ''\n\n    for item in get_choices(cli, prog_name, args, incomplete):\n        echo(item)\n\n    return True\n\n\ndef bashcomplete(cli, prog_name, complete_var, complete_instr):\n    if complete_instr == 'source':\n        echo(get_completion_script(prog_name, complete_var))\n        return True\n    elif complete_instr == 'complete':\n        return do_complete(cli, prog_name)\n    return False\n", "path": "click/_bashcomplete.py"}]}