We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bash completion understands options even after "--"
Click Bash Completion prints out `command`'s options for any string starting with a single dash even after the double dash separator.

I'm facing this problem because I'm trying to create a wrapper with Click and I would like to use Click's auto completion to print out options from my wrapped program.

So, supposing that I'm wrapping `git` and my program is called `logbuch`, my command line would be something like:
```sh
logbuch -g -- commit -<TAB>
```

Supposing I'm doing some workaround in-code to get the `git commit`'s options, I'm returning that as a list of strings from a callback to my `command` `argument` `autocompletion` param. Like this:
```sh
@click.argument('arg',nargs=-1,type=click.STRING,autocompletion=auto_comp_callback)
```

Is there any way to prevent Click from completing my `program`'s options instead of calling my `callback`? I have read this [code](https://github.com/pallets/click/blob/master/click/_bashcomplete.py#L246) and it sounds like that Click does not check for double dashes before calling the `start_of_option` at line 246.

Besides that, I think that this issue goes in opposite way to this statement at [Click docs](https://click.palletsprojects.com/en/7.x/arguments/#option-like-arguments): " After the `--` marker, all further parameters are accepted as arguments."

I'm using `python3.7` with Click installed by `python3.7 -m pip install click`.

--- 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 copy
2 import os
3 import re
4 
5 from .utils import echo
6 from .parser import split_arg_string
7 from .core import MultiCommand, Option, Argument
8 from .types import Choice
9 
10 try:
11     from collections import abc
12 except ImportError:
13     import collections as abc
14 
15 WORDBREAK = '='
16 
17 # Note, only BASH version 4.4 and later have the nosort option.
18 COMPLETION_SCRIPT_BASH = '''
19 %(complete_func)s() {
20     local IFS=$'\n'
21     COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \\
22                    COMP_CWORD=$COMP_CWORD \\
23                    %(autocomplete_var)s=complete $1 ) )
24     return 0
25 }
26 
27 %(complete_func)setup() {
28     local COMPLETION_OPTIONS=""
29     local BASH_VERSION_ARR=(${BASH_VERSION//./ })
30     # Only BASH version 4.4 and later have the nosort option.
31     if [ ${BASH_VERSION_ARR[0]} -gt 4 ] || ([ ${BASH_VERSION_ARR[0]} -eq 4 ] && [ ${BASH_VERSION_ARR[1]} -ge 4 ]); then
32         COMPLETION_OPTIONS="-o nosort"
33     fi
34 
35     complete $COMPLETION_OPTIONS -F %(complete_func)s %(script_names)s
36 }
37 
38 %(complete_func)setup
39 '''
40 
41 COMPLETION_SCRIPT_ZSH = '''
42 #compdef %(script_names)s
43 
44 %(complete_func)s() {
45     local -a completions
46     local -a completions_with_descriptions
47     local -a response
48     (( ! $+commands[%(script_names)s] )) && return 1
49 
50     response=("${(@f)$( env COMP_WORDS=\"${words[*]}\" \\
51                         COMP_CWORD=$((CURRENT-1)) \\
52                         %(autocomplete_var)s=\"complete_zsh\" \\
53                         %(script_names)s )}")
54 
55     for key descr in ${(kv)response}; do
56       if [[ "$descr" == "_" ]]; then
57           completions+=("$key")
58       else
59           completions_with_descriptions+=("$key":"$descr")
60       fi
61     done
62 
63     if [ -n "$completions_with_descriptions" ]; then
64         _describe -V unsorted completions_with_descriptions -U -Q
65     fi
66 
67     if [ -n "$completions" ]; then
68         compadd -U -V unsorted -Q -a completions
69     fi
70     compstate[insert]="automenu"
71 }
72 
73 compdef %(complete_func)s %(script_names)s
74 '''
75 
76 _invalid_ident_char_re = re.compile(r'[^a-zA-Z0-9_]')
77 
78 
79 def get_completion_script(prog_name, complete_var, shell):
80     cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_'))
81     script = COMPLETION_SCRIPT_ZSH if shell == 'zsh' else COMPLETION_SCRIPT_BASH
82     return (script % {
83         'complete_func': '_%s_completion' % cf_name,
84         'script_names': prog_name,
85         'autocomplete_var': complete_var,
86     }).strip() + ';'
87 
88 
89 def resolve_ctx(cli, prog_name, args):
90     """
91     Parse into a hierarchy of contexts. Contexts are connected through the parent variable.
92     :param cli: command definition
93     :param prog_name: the program that is running
94     :param args: full list of args
95     :return: the final context/command parsed
96     """
97     ctx = cli.make_context(prog_name, args, resilient_parsing=True)
98     args = ctx.protected_args + ctx.args
99     while args:
100         if isinstance(ctx.command, MultiCommand):
101             if not ctx.command.chain:
102                 cmd_name, cmd, args = ctx.command.resolve_command(ctx, args)
103                 if cmd is None:
104                     return ctx
105                 ctx = cmd.make_context(cmd_name, args, parent=ctx,
106                                        resilient_parsing=True)
107                 args = ctx.protected_args + ctx.args
108             else:
109                 # Walk chained subcommand contexts saving the last one.
110                 while args:
111                     cmd_name, cmd, args = ctx.command.resolve_command(ctx, args)
112                     if cmd is None:
113                         return ctx
114                     sub_ctx = cmd.make_context(cmd_name, args, parent=ctx,
115                                                allow_extra_args=True,
116                                                allow_interspersed_args=False,
117                                                resilient_parsing=True)
118                     args = sub_ctx.args
119                 ctx = sub_ctx
120                 args = sub_ctx.protected_args + sub_ctx.args
121         else:
122             break
123     return ctx
124 
125 
126 def start_of_option(param_str):
127     """
128     :param param_str: param_str to check
129     :return: whether or not this is the start of an option declaration (i.e. starts "-" or "--")
130     """
131     return param_str and param_str[:1] == '-'
132 
133 
134 def is_incomplete_option(all_args, cmd_param):
135     """
136     :param all_args: the full original list of args supplied
137     :param cmd_param: the current command paramter
138     :return: whether or not the last option declaration (i.e. starts "-" or "--") is incomplete and
139     corresponds to this cmd_param. In other words whether this cmd_param option can still accept
140     values
141     """
142     if not isinstance(cmd_param, Option):
143         return False
144     if cmd_param.is_flag:
145         return False
146     last_option = None
147     for index, arg_str in enumerate(reversed([arg for arg in all_args if arg != WORDBREAK])):
148         if index + 1 > cmd_param.nargs:
149             break
150         if start_of_option(arg_str):
151             last_option = arg_str
152 
153     return True if last_option and last_option in cmd_param.opts else False
154 
155 
156 def is_incomplete_argument(current_params, cmd_param):
157     """
158     :param current_params: the current params and values for this argument as already entered
159     :param cmd_param: the current command parameter
160     :return: whether or not the last argument is incomplete and corresponds to this cmd_param. In
161     other words whether or not the this cmd_param argument can still accept values
162     """
163     if not isinstance(cmd_param, Argument):
164         return False
165     current_param_values = current_params[cmd_param.name]
166     if current_param_values is None:
167         return True
168     if cmd_param.nargs == -1:
169         return True
170     if isinstance(current_param_values, abc.Iterable) \
171             and cmd_param.nargs > 1 and len(current_param_values) < cmd_param.nargs:
172         return True
173     return False
174 
175 
176 def get_user_autocompletions(ctx, args, incomplete, cmd_param):
177     """
178     :param ctx: context associated with the parsed command
179     :param args: full list of args
180     :param incomplete: the incomplete text to autocomplete
181     :param cmd_param: command definition
182     :return: all the possible user-specified completions for the param
183     """
184     results = []
185     if isinstance(cmd_param.type, Choice):
186         # Choices don't support descriptions.
187         results = [(c, None)
188                    for c in cmd_param.type.choices if str(c).startswith(incomplete)]
189     elif cmd_param.autocompletion is not None:
190         dynamic_completions = cmd_param.autocompletion(ctx=ctx,
191                                                        args=args,
192                                                        incomplete=incomplete)
193         results = [c if isinstance(c, tuple) else (c, None)
194                    for c in dynamic_completions]
195     return results
196 
197 
198 def get_visible_commands_starting_with(ctx, starts_with):
199     """
200     :param ctx: context associated with the parsed command
201     :starts_with: string that visible commands must start with.
202     :return: all visible (not hidden) commands that start with starts_with.
203     """
204     for c in ctx.command.list_commands(ctx):
205         if c.startswith(starts_with):
206             command = ctx.command.get_command(ctx, c)
207             if not command.hidden:
208                 yield command
209 
210 
211 def add_subcommand_completions(ctx, incomplete, completions_out):
212     # Add subcommand completions.
213     if isinstance(ctx.command, MultiCommand):
214         completions_out.extend(
215             [(c.name, c.get_short_help_str()) for c in get_visible_commands_starting_with(ctx, incomplete)])
216 
217     # Walk up the context list and add any other completion possibilities from chained commands
218     while ctx.parent is not None:
219         ctx = ctx.parent
220         if isinstance(ctx.command, MultiCommand) and ctx.command.chain:
221             remaining_commands = [c for c in get_visible_commands_starting_with(ctx, incomplete)
222                                   if c.name not in ctx.protected_args]
223             completions_out.extend([(c.name, c.get_short_help_str()) for c in remaining_commands])
224 
225 
226 def get_choices(cli, prog_name, args, incomplete):
227     """
228     :param cli: command definition
229     :param prog_name: the program that is running
230     :param args: full list of args
231     :param incomplete: the incomplete text to autocomplete
232     :return: all the possible completions for the incomplete
233     """
234     all_args = copy.deepcopy(args)
235 
236     ctx = resolve_ctx(cli, prog_name, args)
237     if ctx is None:
238         return []
239 
240     # In newer versions of bash long opts with '='s are partitioned, but it's easier to parse
241     # without the '='
242     if start_of_option(incomplete) and WORDBREAK in incomplete:
243         partition_incomplete = incomplete.partition(WORDBREAK)
244         all_args.append(partition_incomplete[0])
245         incomplete = partition_incomplete[2]
246     elif incomplete == WORDBREAK:
247         incomplete = ''
248 
249     completions = []
250     if start_of_option(incomplete):
251         # completions for partial options
252         for param in ctx.command.params:
253             if isinstance(param, Option) and not param.hidden:
254                 param_opts = [param_opt for param_opt in param.opts +
255                               param.secondary_opts if param_opt not in all_args or param.multiple]
256                 completions.extend([(o, param.help) for o in param_opts if o.startswith(incomplete)])
257         return completions
258     # completion for option values from user supplied values
259     for param in ctx.command.params:
260         if is_incomplete_option(all_args, param):
261             return get_user_autocompletions(ctx, all_args, incomplete, param)
262     # completion for argument values from user supplied values
263     for param in ctx.command.params:
264         if is_incomplete_argument(ctx.params, param):
265             return get_user_autocompletions(ctx, all_args, incomplete, param)
266 
267     add_subcommand_completions(ctx, incomplete, completions)
268     # Sort before returning so that proper ordering can be enforced in custom types.
269     return sorted(completions)
270 
271 
272 def do_complete(cli, prog_name, include_descriptions):
273     cwords = split_arg_string(os.environ['COMP_WORDS'])
274     cword = int(os.environ['COMP_CWORD'])
275     args = cwords[1:cword]
276     try:
277         incomplete = cwords[cword]
278     except IndexError:
279         incomplete = ''
280 
281     for item in get_choices(cli, prog_name, args, incomplete):
282         echo(item[0])
283         if include_descriptions:
284             # ZSH has trouble dealing with empty array parameters when returned from commands, so use a well defined character '_' to indicate no description is present.
285             echo(item[1] if item[1] else '_')
286 
287     return True
288 
289 
290 def bashcomplete(cli, prog_name, complete_var, complete_instr):
291     if complete_instr.startswith('source'):
292         shell = 'zsh' if complete_instr == 'source_zsh' else 'bash'
293         echo(get_completion_script(prog_name, complete_var, shell))
294         return True
295     elif complete_instr == 'complete' or complete_instr == 'complete_zsh':
296         return do_complete(cli, prog_name, complete_instr == 'complete_zsh')
297     return False
298
```
--- 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()

```

diff --git a/click/_bashcomplete.py b/click/_bashcomplete.py
--- a/click/_bashcomplete.py
+++ b/click/_bashcomplete.py
@@ -237,6 +237,8 @@
     if ctx is None:
         return []
 
+    has_double_dash = "--" in all_args
+
     # In newer versions of bash long opts with '='s are partitioned, but it's easier to parse
     # without the '='
     if start_of_option(incomplete) and WORDBREAK in incomplete:
@@ -247,7 +249,7 @@
         incomplete = ''
 
     completions = []
-    if start_of_option(incomplete):
+    if not has_double_dash and start_of_option(incomplete):
         # completions for partial options
         for param in ctx.command.params:
             if isinstance(param, Option) and not param.hidden:

{"golden_diff": "diff --git a/click/_bashcomplete.py b/click/_bashcomplete.py\n--- a/click/_bashcomplete.py\n+++ b/click/_bashcomplete.py\n@@ -237,6 +237,8 @@\n     if ctx is None:\n         return []\n \n+    has_double_dash = \"--\" in all_args\n+\n     # In newer versions of bash long opts with '='s are partitioned, but it's easier to parse\n     # without the '='\n     if start_of_option(incomplete) and WORDBREAK in incomplete:\n@@ -247,7 +249,7 @@\n         incomplete = ''\n \n     completions = []\n-    if start_of_option(incomplete):\n+    if not has_double_dash and start_of_option(incomplete):\n         # completions for partial options\n         for param in ctx.command.params:\n             if isinstance(param, Option) and not param.hidden:\n", "issue": "Bash completion understands options even after \"--\"\nClick Bash Completion prints out `command`'s options for any string starting with a single dash even after the double dash separator.\r\n\r\nI'm facing this problem because I'm trying to create a wrapper with Click and I would like to use Click's auto completion to print out options from my wrapped program.\r\n\r\nSo, supposing that I'm wrapping `git` and my program is called `logbuch`, my command line would be something like:\r\n```sh\r\nlogbuch -g -- commit -<TAB>\r\n```\r\n\r\nSupposing I'm doing some workaround in-code to get the `git commit`'s options, I'm returning that as a list of strings from a callback to my `command` `argument` `autocompletion` param. Like this:\r\n```sh\r\n@click.argument('arg',nargs=-1,type=click.STRING,autocompletion=auto_comp_callback)\r\n```\r\n\r\nIs there any way to prevent Click from completing my `program`'s options instead of calling my `callback`? I have read this [code](https://github.com/pallets/click/blob/master/click/_bashcomplete.py#L246) and it sounds like that Click does not check for double dashes before calling the `start_of_option` at line 246.\r\n\r\nBesides that, I think that this issue goes in opposite way to this statement at [Click docs](https://click.palletsprojects.com/en/7.x/arguments/#option-like-arguments): \" After the `--` marker, all further parameters are accepted as arguments.\"\r\n\r\nI'm using `python3.7` with Click installed by `python3.7 -m pip install click`.\n", "before_files": [{"content": "import copy\nimport os\nimport re\n\nfrom .utils import echo\nfrom .parser import split_arg_string\nfrom .core import MultiCommand, Option, Argument\nfrom .types import Choice\n\ntry:\n    from collections import abc\nexcept ImportError:\n    import collections as abc\n\nWORDBREAK = '='\n\n# Note, only BASH version 4.4 and later have the nosort option.\nCOMPLETION_SCRIPT_BASH = '''\n%(complete_func)s() {\n    local IFS=$'\\n'\n    COMPREPLY=( $( env COMP_WORDS=\"${COMP_WORDS[*]}\" \\\\\n                   COMP_CWORD=$COMP_CWORD \\\\\n                   %(autocomplete_var)s=complete $1 ) )\n    return 0\n}\n\n%(complete_func)setup() {\n    local COMPLETION_OPTIONS=\"\"\n    local BASH_VERSION_ARR=(${BASH_VERSION//./ })\n    # Only BASH version 4.4 and later have the nosort option.\n    if [ ${BASH_VERSION_ARR[0]} -gt 4 ] || ([ ${BASH_VERSION_ARR[0]} -eq 4 ] && [ ${BASH_VERSION_ARR[1]} -ge 4 ]); then\n        COMPLETION_OPTIONS=\"-o nosort\"\n    fi\n\n    complete $COMPLETION_OPTIONS -F %(complete_func)s %(script_names)s\n}\n\n%(complete_func)setup\n'''\n\nCOMPLETION_SCRIPT_ZSH = '''\n#compdef %(script_names)s\n\n%(complete_func)s() {\n    local -a completions\n    local -a completions_with_descriptions\n    local -a response\n    (( ! $+commands[%(script_names)s] )) && return 1\n\n    response=(\"${(@f)$( env COMP_WORDS=\\\"${words[*]}\\\" \\\\\n                        COMP_CWORD=$((CURRENT-1)) \\\\\n                        %(autocomplete_var)s=\\\"complete_zsh\\\" \\\\\n                        %(script_names)s )}\")\n\n    for key descr in ${(kv)response}; do\n      if [[ \"$descr\" == \"_\" ]]; then\n          completions+=(\"$key\")\n      else\n          completions_with_descriptions+=(\"$key\":\"$descr\")\n      fi\n    done\n\n    if [ -n \"$completions_with_descriptions\" ]; then\n        _describe -V unsorted completions_with_descriptions -U -Q\n    fi\n\n    if [ -n \"$completions\" ]; then\n        compadd -U -V unsorted -Q -a completions\n    fi\n    compstate[insert]=\"automenu\"\n}\n\ncompdef %(complete_func)s %(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, shell):\n    cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_'))\n    script = COMPLETION_SCRIPT_ZSH if shell == 'zsh' else COMPLETION_SCRIPT_BASH\n    return (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    \"\"\"\n    Parse into a hierarchy of contexts. Contexts are connected through the parent variable.\n    :param cli: command definition\n    :param prog_name: the program that is running\n    :param args: full list of args\n    :return: the final context/command parsed\n    \"\"\"\n    ctx = cli.make_context(prog_name, args, resilient_parsing=True)\n    args = ctx.protected_args + ctx.args\n    while args:\n        if isinstance(ctx.command, MultiCommand):\n            if not ctx.command.chain:\n                cmd_name, cmd, args = ctx.command.resolve_command(ctx, args)\n                if cmd is None:\n                    return ctx\n                ctx = cmd.make_context(cmd_name, args, parent=ctx,\n                                       resilient_parsing=True)\n                args = ctx.protected_args + ctx.args\n            else:\n                # Walk chained subcommand contexts saving the last one.\n                while args:\n                    cmd_name, cmd, args = ctx.command.resolve_command(ctx, args)\n                    if cmd is None:\n                        return ctx\n                    sub_ctx = cmd.make_context(cmd_name, args, parent=ctx,\n                                               allow_extra_args=True,\n                                               allow_interspersed_args=False,\n                                               resilient_parsing=True)\n                    args = sub_ctx.args\n                ctx = sub_ctx\n                args = sub_ctx.protected_args + sub_ctx.args\n        else:\n            break\n    return ctx\n\n\ndef start_of_option(param_str):\n    \"\"\"\n    :param param_str: param_str to check\n    :return: whether or not this is the start of an option declaration (i.e. starts \"-\" or \"--\")\n    \"\"\"\n    return param_str and param_str[:1] == '-'\n\n\ndef is_incomplete_option(all_args, cmd_param):\n    \"\"\"\n    :param all_args: the full original list of args supplied\n    :param cmd_param: the current command paramter\n    :return: whether or not the last option declaration (i.e. starts \"-\" or \"--\") is incomplete and\n    corresponds to this cmd_param. In other words whether this cmd_param option can still accept\n    values\n    \"\"\"\n    if not isinstance(cmd_param, Option):\n        return False\n    if cmd_param.is_flag:\n        return False\n    last_option = None\n    for index, arg_str in enumerate(reversed([arg for arg in all_args if arg != WORDBREAK])):\n        if index + 1 > cmd_param.nargs:\n            break\n        if start_of_option(arg_str):\n            last_option = arg_str\n\n    return True if last_option and last_option in cmd_param.opts else False\n\n\ndef is_incomplete_argument(current_params, cmd_param):\n    \"\"\"\n    :param current_params: the current params and values for this argument as already entered\n    :param cmd_param: the current command parameter\n    :return: whether or not the last argument is incomplete and corresponds to this cmd_param. In\n    other words whether or not the this cmd_param argument can still accept values\n    \"\"\"\n    if not isinstance(cmd_param, Argument):\n        return False\n    current_param_values = current_params[cmd_param.name]\n    if current_param_values is None:\n        return True\n    if cmd_param.nargs == -1:\n        return True\n    if isinstance(current_param_values, abc.Iterable) \\\n            and cmd_param.nargs > 1 and len(current_param_values) < cmd_param.nargs:\n        return True\n    return False\n\n\ndef get_user_autocompletions(ctx, args, incomplete, cmd_param):\n    \"\"\"\n    :param ctx: context associated with the parsed command\n    :param args: full list of args\n    :param incomplete: the incomplete text to autocomplete\n    :param cmd_param: command definition\n    :return: all the possible user-specified completions for the param\n    \"\"\"\n    results = []\n    if isinstance(cmd_param.type, Choice):\n        # Choices don't support descriptions.\n        results = [(c, None)\n                   for c in cmd_param.type.choices if str(c).startswith(incomplete)]\n    elif cmd_param.autocompletion is not None:\n        dynamic_completions = cmd_param.autocompletion(ctx=ctx,\n                                                       args=args,\n                                                       incomplete=incomplete)\n        results = [c if isinstance(c, tuple) else (c, None)\n                   for c in dynamic_completions]\n    return results\n\n\ndef get_visible_commands_starting_with(ctx, starts_with):\n    \"\"\"\n    :param ctx: context associated with the parsed command\n    :starts_with: string that visible commands must start with.\n    :return: all visible (not hidden) commands that start with starts_with.\n    \"\"\"\n    for c in ctx.command.list_commands(ctx):\n        if c.startswith(starts_with):\n            command = ctx.command.get_command(ctx, c)\n            if not command.hidden:\n                yield command\n\n\ndef add_subcommand_completions(ctx, incomplete, completions_out):\n    # Add subcommand completions.\n    if isinstance(ctx.command, MultiCommand):\n        completions_out.extend(\n            [(c.name, c.get_short_help_str()) for c in get_visible_commands_starting_with(ctx, incomplete)])\n\n    # Walk up the context list and add any other completion possibilities from chained commands\n    while ctx.parent is not None:\n        ctx = ctx.parent\n        if isinstance(ctx.command, MultiCommand) and ctx.command.chain:\n            remaining_commands = [c for c in get_visible_commands_starting_with(ctx, incomplete)\n                                  if c.name not in ctx.protected_args]\n            completions_out.extend([(c.name, c.get_short_help_str()) for c in remaining_commands])\n\n\ndef get_choices(cli, prog_name, args, incomplete):\n    \"\"\"\n    :param cli: command definition\n    :param prog_name: the program that is running\n    :param args: full list of args\n    :param incomplete: the incomplete text to autocomplete\n    :return: all the possible completions for the incomplete\n    \"\"\"\n    all_args = copy.deepcopy(args)\n\n    ctx = resolve_ctx(cli, prog_name, args)\n    if ctx is None:\n        return []\n\n    # In newer versions of bash long opts with '='s are partitioned, but it's easier to parse\n    # without the '='\n    if start_of_option(incomplete) and WORDBREAK in incomplete:\n        partition_incomplete = incomplete.partition(WORDBREAK)\n        all_args.append(partition_incomplete[0])\n        incomplete = partition_incomplete[2]\n    elif incomplete == WORDBREAK:\n        incomplete = ''\n\n    completions = []\n    if start_of_option(incomplete):\n        # completions for partial options\n        for param in ctx.command.params:\n            if isinstance(param, Option) and not param.hidden:\n                param_opts = [param_opt for param_opt in param.opts +\n                              param.secondary_opts if param_opt not in all_args or param.multiple]\n                completions.extend([(o, param.help) for o in param_opts if o.startswith(incomplete)])\n        return completions\n    # completion for option values from user supplied values\n    for param in ctx.command.params:\n        if is_incomplete_option(all_args, param):\n            return get_user_autocompletions(ctx, all_args, incomplete, param)\n    # completion for argument values from user supplied values\n    for param in ctx.command.params:\n        if is_incomplete_argument(ctx.params, param):\n            return get_user_autocompletions(ctx, all_args, incomplete, param)\n\n    add_subcommand_completions(ctx, incomplete, completions)\n    # Sort before returning so that proper ordering can be enforced in custom types.\n    return sorted(completions)\n\n\ndef do_complete(cli, prog_name, include_descriptions):\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[0])\n        if include_descriptions:\n            # ZSH has trouble dealing with empty array parameters when returned from commands, so use a well defined character '_' to indicate no description is present.\n            echo(item[1] if item[1] else '_')\n\n    return True\n\n\ndef bashcomplete(cli, prog_name, complete_var, complete_instr):\n    if complete_instr.startswith('source'):\n        shell = 'zsh' if complete_instr == 'source_zsh' else 'bash'\n        echo(get_completion_script(prog_name, complete_var, shell))\n        return True\n    elif complete_instr == 'complete' or complete_instr == 'complete_zsh':\n        return do_complete(cli, prog_name, complete_instr == 'complete_zsh')\n    return False\n", "path": "click/_bashcomplete.py"}], "after_files": [{"content": "import copy\nimport os\nimport re\n\nfrom .utils import echo\nfrom .parser import split_arg_string\nfrom .core import MultiCommand, Option, Argument\nfrom .types import Choice\n\ntry:\n    from collections import abc\nexcept ImportError:\n    import collections as abc\n\nWORDBREAK = '='\n\n# Note, only BASH version 4.4 and later have the nosort option.\nCOMPLETION_SCRIPT_BASH = '''\n%(complete_func)s() {\n    local IFS=$'\\n'\n    COMPREPLY=( $( env COMP_WORDS=\"${COMP_WORDS[*]}\" \\\\\n                   COMP_CWORD=$COMP_CWORD \\\\\n                   %(autocomplete_var)s=complete $1 ) )\n    return 0\n}\n\n%(complete_func)setup() {\n    local COMPLETION_OPTIONS=\"\"\n    local BASH_VERSION_ARR=(${BASH_VERSION//./ })\n    # Only BASH version 4.4 and later have the nosort option.\n    if [ ${BASH_VERSION_ARR[0]} -gt 4 ] || ([ ${BASH_VERSION_ARR[0]} -eq 4 ] && [ ${BASH_VERSION_ARR[1]} -ge 4 ]); then\n        COMPLETION_OPTIONS=\"-o nosort\"\n    fi\n\n    complete $COMPLETION_OPTIONS -F %(complete_func)s %(script_names)s\n}\n\n%(complete_func)setup\n'''\n\nCOMPLETION_SCRIPT_ZSH = '''\n#compdef %(script_names)s\n\n%(complete_func)s() {\n    local -a completions\n    local -a completions_with_descriptions\n    local -a response\n    (( ! $+commands[%(script_names)s] )) && return 1\n\n    response=(\"${(@f)$( env COMP_WORDS=\\\"${words[*]}\\\" \\\\\n                        COMP_CWORD=$((CURRENT-1)) \\\\\n                        %(autocomplete_var)s=\\\"complete_zsh\\\" \\\\\n                        %(script_names)s )}\")\n\n    for key descr in ${(kv)response}; do\n      if [[ \"$descr\" == \"_\" ]]; then\n          completions+=(\"$key\")\n      else\n          completions_with_descriptions+=(\"$key\":\"$descr\")\n      fi\n    done\n\n    if [ -n \"$completions_with_descriptions\" ]; then\n        _describe -V unsorted completions_with_descriptions -U -Q\n    fi\n\n    if [ -n \"$completions\" ]; then\n        compadd -U -V unsorted -Q -a completions\n    fi\n    compstate[insert]=\"automenu\"\n}\n\ncompdef %(complete_func)s %(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, shell):\n    cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_'))\n    script = COMPLETION_SCRIPT_ZSH if shell == 'zsh' else COMPLETION_SCRIPT_BASH\n    return (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    \"\"\"\n    Parse into a hierarchy of contexts. Contexts are connected through the parent variable.\n    :param cli: command definition\n    :param prog_name: the program that is running\n    :param args: full list of args\n    :return: the final context/command parsed\n    \"\"\"\n    ctx = cli.make_context(prog_name, args, resilient_parsing=True)\n    args = ctx.protected_args + ctx.args\n    while args:\n        if isinstance(ctx.command, MultiCommand):\n            if not ctx.command.chain:\n                cmd_name, cmd, args = ctx.command.resolve_command(ctx, args)\n                if cmd is None:\n                    return ctx\n                ctx = cmd.make_context(cmd_name, args, parent=ctx,\n                                       resilient_parsing=True)\n                args = ctx.protected_args + ctx.args\n            else:\n                # Walk chained subcommand contexts saving the last one.\n                while args:\n                    cmd_name, cmd, args = ctx.command.resolve_command(ctx, args)\n                    if cmd is None:\n                        return ctx\n                    sub_ctx = cmd.make_context(cmd_name, args, parent=ctx,\n                                               allow_extra_args=True,\n                                               allow_interspersed_args=False,\n                                               resilient_parsing=True)\n                    args = sub_ctx.args\n                ctx = sub_ctx\n                args = sub_ctx.protected_args + sub_ctx.args\n        else:\n            break\n    return ctx\n\n\ndef start_of_option(param_str):\n    \"\"\"\n    :param param_str: param_str to check\n    :return: whether or not this is the start of an option declaration (i.e. starts \"-\" or \"--\")\n    \"\"\"\n    return param_str and param_str[:1] == '-'\n\n\ndef is_incomplete_option(all_args, cmd_param):\n    \"\"\"\n    :param all_args: the full original list of args supplied\n    :param cmd_param: the current command paramter\n    :return: whether or not the last option declaration (i.e. starts \"-\" or \"--\") is incomplete and\n    corresponds to this cmd_param. In other words whether this cmd_param option can still accept\n    values\n    \"\"\"\n    if not isinstance(cmd_param, Option):\n        return False\n    if cmd_param.is_flag:\n        return False\n    last_option = None\n    for index, arg_str in enumerate(reversed([arg for arg in all_args if arg != WORDBREAK])):\n        if index + 1 > cmd_param.nargs:\n            break\n        if start_of_option(arg_str):\n            last_option = arg_str\n\n    return True if last_option and last_option in cmd_param.opts else False\n\n\ndef is_incomplete_argument(current_params, cmd_param):\n    \"\"\"\n    :param current_params: the current params and values for this argument as already entered\n    :param cmd_param: the current command parameter\n    :return: whether or not the last argument is incomplete and corresponds to this cmd_param. In\n    other words whether or not the this cmd_param argument can still accept values\n    \"\"\"\n    if not isinstance(cmd_param, Argument):\n        return False\n    current_param_values = current_params[cmd_param.name]\n    if current_param_values is None:\n        return True\n    if cmd_param.nargs == -1:\n        return True\n    if isinstance(current_param_values, abc.Iterable) \\\n            and cmd_param.nargs > 1 and len(current_param_values) < cmd_param.nargs:\n        return True\n    return False\n\n\ndef get_user_autocompletions(ctx, args, incomplete, cmd_param):\n    \"\"\"\n    :param ctx: context associated with the parsed command\n    :param args: full list of args\n    :param incomplete: the incomplete text to autocomplete\n    :param cmd_param: command definition\n    :return: all the possible user-specified completions for the param\n    \"\"\"\n    results = []\n    if isinstance(cmd_param.type, Choice):\n        # Choices don't support descriptions.\n        results = [(c, None)\n                   for c in cmd_param.type.choices if str(c).startswith(incomplete)]\n    elif cmd_param.autocompletion is not None:\n        dynamic_completions = cmd_param.autocompletion(ctx=ctx,\n                                                       args=args,\n                                                       incomplete=incomplete)\n        results = [c if isinstance(c, tuple) else (c, None)\n                   for c in dynamic_completions]\n    return results\n\n\ndef get_visible_commands_starting_with(ctx, starts_with):\n    \"\"\"\n    :param ctx: context associated with the parsed command\n    :starts_with: string that visible commands must start with.\n    :return: all visible (not hidden) commands that start with starts_with.\n    \"\"\"\n    for c in ctx.command.list_commands(ctx):\n        if c.startswith(starts_with):\n            command = ctx.command.get_command(ctx, c)\n            if not command.hidden:\n                yield command\n\n\ndef add_subcommand_completions(ctx, incomplete, completions_out):\n    # Add subcommand completions.\n    if isinstance(ctx.command, MultiCommand):\n        completions_out.extend(\n            [(c.name, c.get_short_help_str()) for c in get_visible_commands_starting_with(ctx, incomplete)])\n\n    # Walk up the context list and add any other completion possibilities from chained commands\n    while ctx.parent is not None:\n        ctx = ctx.parent\n        if isinstance(ctx.command, MultiCommand) and ctx.command.chain:\n            remaining_commands = [c for c in get_visible_commands_starting_with(ctx, incomplete)\n                                  if c.name not in ctx.protected_args]\n            completions_out.extend([(c.name, c.get_short_help_str()) for c in remaining_commands])\n\n\ndef get_choices(cli, prog_name, args, incomplete):\n    \"\"\"\n    :param cli: command definition\n    :param prog_name: the program that is running\n    :param args: full list of args\n    :param incomplete: the incomplete text to autocomplete\n    :return: all the possible completions for the incomplete\n    \"\"\"\n    all_args = copy.deepcopy(args)\n\n    ctx = resolve_ctx(cli, prog_name, args)\n    if ctx is None:\n        return []\n\n    has_double_dash = \"--\" in all_args\n\n    # In newer versions of bash long opts with '='s are partitioned, but it's easier to parse\n    # without the '='\n    if start_of_option(incomplete) and WORDBREAK in incomplete:\n        partition_incomplete = incomplete.partition(WORDBREAK)\n        all_args.append(partition_incomplete[0])\n        incomplete = partition_incomplete[2]\n    elif incomplete == WORDBREAK:\n        incomplete = ''\n\n    completions = []\n    if not has_double_dash and start_of_option(incomplete):\n        # completions for partial options\n        for param in ctx.command.params:\n            if isinstance(param, Option) and not param.hidden:\n                param_opts = [param_opt for param_opt in param.opts +\n                              param.secondary_opts if param_opt not in all_args or param.multiple]\n                completions.extend([(o, param.help) for o in param_opts if o.startswith(incomplete)])\n        return completions\n    # completion for option values from user supplied values\n    for param in ctx.command.params:\n        if is_incomplete_option(all_args, param):\n            return get_user_autocompletions(ctx, all_args, incomplete, param)\n    # completion for argument values from user supplied values\n    for param in ctx.command.params:\n        if is_incomplete_argument(ctx.params, param):\n            return get_user_autocompletions(ctx, all_args, incomplete, param)\n\n    add_subcommand_completions(ctx, incomplete, completions)\n    # Sort before returning so that proper ordering can be enforced in custom types.\n    return sorted(completions)\n\n\ndef do_complete(cli, prog_name, include_descriptions):\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[0])\n        if include_descriptions:\n            # ZSH has trouble dealing with empty array parameters when returned from commands, so use a well defined character '_' to indicate no description is present.\n            echo(item[1] if item[1] else '_')\n\n    return True\n\n\ndef bashcomplete(cli, prog_name, complete_var, complete_instr):\n    if complete_instr.startswith('source'):\n        shell = 'zsh' if complete_instr == 'source_zsh' else 'bash'\n        echo(get_completion_script(prog_name, complete_var, shell))\n        return True\n    elif complete_instr == 'complete' or complete_instr == 'complete_zsh':\n        return do_complete(cli, prog_name, complete_instr == 'complete_zsh')\n    return False\n", "path": "click/_bashcomplete.py"}]}