We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Allow sorting of completions based on custom types
Currently completion candidates returned by click are sorted in ZSH based on alphanumeric rules. This means that completions ['1', '2', '10'] would be displayed out of natural sort order as ['1', '10', '2']. Update the completion script to bring the sorting into Python where custom types can be sorted more appropriately. Note that the version of bash that ships with OS X is v3.2. The nosort option for `complete` was introduced in v4.4 This change should support both.

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

Path: `examples/bashcompletion/bashcompletion.py`
Content:
```
1 import click
2 import os
3 
4 
5 @click.group()
6 def cli():
7     pass
8 
9 
10 def get_env_vars(ctx, args, incomplete):
11     for key in os.environ.keys():
12         if incomplete in key:
13             yield key
14 
15 
16 @cli.command(help='A command to print environment variables')
17 @click.argument("envvar", type=click.STRING, autocompletion=get_env_vars)
18 def cmd1(envvar):
19     click.echo('Environment variable: %s' % envvar)
20     click.echo('Value: %s' % os.environ[envvar])
21 
22 
23 @click.group(help='A group that holds a subcommand')
24 def group():
25     pass
26 
27 
28 def list_users(ctx, args, incomplete):
29     # Here you can generate completions dynamically
30     users = ['bob', 'alice']
31     for user in users:
32         if user.startswith(incomplete):
33             yield user
34 
35 
36 @group.command(help='Choose a user')
37 @click.argument("user", type=click.STRING, autocompletion=list_users)
38 def subcmd(user):
39     click.echo('Chosen user is %s' % user)
40 
41 cli.add_command(group)
42
```
--- 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
@@ -10,6 +10,7 @@
 
 WORDBREAK = '='
 
+# Note, only BASH version 4.4 and later have the nosort option.
 COMPLETION_SCRIPT_BASH = '''
 %(complete_func)s() {
     local IFS=$'\n'
@@ -19,7 +20,17 @@
     return 0
 }
 
-complete -F %(complete_func)s %(script_names)s
+%(complete_func)setup() {
+    local COMPLETION_OPTIONS=""
+    local BASH_VERSION_ARR=(${BASH_VERSION//./ })
+    if [ ${BASH_VERSION_ARR[0]} -ge 4 ] && [ ${BASH_VERSION_ARR[1]} -ge 4 ];then
+        COMPLETION_OPTIONS="-o nosort"
+    fi
+
+    complete $COMPLETION_OPTIONS -F %(complete_func)s %(script_names)s
+}
+
+%(complete_func)setup
 '''
 
 COMPLETION_SCRIPT_ZSH = '''
@@ -41,11 +52,13 @@
     done
 
     if [ -n "$completions_with_descriptions" ]; then
-        _describe '' completions_with_descriptions
+        _describe -V unsorted completions_with_descriptions -U -Q
     fi
+
     if [ -n "$completions" ]; then
-        compadd -M 'r:|=* l:|=* r:|=*' -a completions
+        compadd -U -V unsorted -Q -a completions
     fi
+    compstate[insert]="automenu"
 }
 
 compdef %(complete_func)s %(script_names)s
@@ -232,7 +245,8 @@
             return get_user_autocompletions(ctx, all_args, incomplete, param)
 
     add_subcommand_completions(ctx, incomplete, completions)
-    return completions
+    # Sort before returning so that proper ordering can be enforced in custom types.
+    return sorted(completions)
 
 
 def do_complete(cli, prog_name, include_descriptions):
diff --git a/examples/bashcompletion/bashcompletion.py b/examples/bashcompletion/bashcompletion.py
--- a/examples/bashcompletion/bashcompletion.py
+++ b/examples/bashcompletion/bashcompletion.py
@@ -8,6 +8,7 @@
 
 
 def get_env_vars(ctx, args, incomplete):
+    # Completions returned as strings do not have a description displayed.
     for key in os.environ.keys():
         if incomplete in key:
             yield key
@@ -26,11 +27,13 @@
 
 
 def list_users(ctx, args, incomplete):
-    # Here you can generate completions dynamically
-    users = ['bob', 'alice']
-    for user in users:
-        if user.startswith(incomplete):
-            yield user
+    # You can generate completions with descriptions by returning
+    # tuples in the form (completion, description).
+    users = [('bob', 'butcher'),
+             ('alice', 'baker'),
+             ('jerry', 'candlestick maker')]
+    # Ths will allow completion matches based on matches within the description string too!
+    return [user for user in users if incomplete in user[0] or incomplete in user[1]]
 
 
 @group.command(help='Choose a user')
@@ -38,4 +41,5 @@
 def subcmd(user):
     click.echo('Chosen user is %s' % user)
 
+
 cli.add_command(group)

{"golden_diff": "diff --git a/click/_bashcomplete.py b/click/_bashcomplete.py\n--- a/click/_bashcomplete.py\n+++ b/click/_bashcomplete.py\n@@ -10,6 +10,7 @@\n \n WORDBREAK = '='\n \n+# Note, only BASH version 4.4 and later have the nosort option.\n COMPLETION_SCRIPT_BASH = '''\n %(complete_func)s() {\n     local IFS=$'\\n'\n@@ -19,7 +20,17 @@\n     return 0\n }\n \n-complete -F %(complete_func)s %(script_names)s\n+%(complete_func)setup() {\n+    local COMPLETION_OPTIONS=\"\"\n+    local BASH_VERSION_ARR=(${BASH_VERSION//./ })\n+    if [ ${BASH_VERSION_ARR[0]} -ge 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 \n COMPLETION_SCRIPT_ZSH = '''\n@@ -41,11 +52,13 @@\n     done\n \n     if [ -n \"$completions_with_descriptions\" ]; then\n-        _describe '' completions_with_descriptions\n+        _describe -V unsorted completions_with_descriptions -U -Q\n     fi\n+\n     if [ -n \"$completions\" ]; then\n-        compadd -M 'r:|=* l:|=* r:|=*' -a completions\n+        compadd -U -V unsorted -Q -a completions\n     fi\n+    compstate[insert]=\"automenu\"\n }\n \n compdef %(complete_func)s %(script_names)s\n@@ -232,7 +245,8 @@\n             return get_user_autocompletions(ctx, all_args, incomplete, param)\n \n     add_subcommand_completions(ctx, incomplete, completions)\n-    return completions\n+    # Sort before returning so that proper ordering can be enforced in custom types.\n+    return sorted(completions)\n \n \n def do_complete(cli, prog_name, include_descriptions):\ndiff --git a/examples/bashcompletion/bashcompletion.py b/examples/bashcompletion/bashcompletion.py\n--- a/examples/bashcompletion/bashcompletion.py\n+++ b/examples/bashcompletion/bashcompletion.py\n@@ -8,6 +8,7 @@\n \n \n def get_env_vars(ctx, args, incomplete):\n+    # Completions returned as strings do not have a description displayed.\n     for key in os.environ.keys():\n         if incomplete in key:\n             yield key\n@@ -26,11 +27,13 @@\n \n \n def list_users(ctx, args, incomplete):\n-    # Here you can generate completions dynamically\n-    users = ['bob', 'alice']\n-    for user in users:\n-        if user.startswith(incomplete):\n-            yield user\n+    # You can generate completions with descriptions by returning\n+    # tuples in the form (completion, description).\n+    users = [('bob', 'butcher'),\n+             ('alice', 'baker'),\n+             ('jerry', 'candlestick maker')]\n+    # Ths will allow completion matches based on matches within the description string too!\n+    return [user for user in users if incomplete in user[0] or incomplete in user[1]]\n \n \n @group.command(help='Choose a user')\n@@ -38,4 +41,5 @@\n def subcmd(user):\n     click.echo('Chosen user is %s' % user)\n \n+\n cli.add_command(group)\n", "issue": "Allow sorting of completions based on custom types\nCurrently completion candidates returned by click are sorted in ZSH based on alphanumeric rules. This means that completions ['1', '2', '10'] would be displayed out of natural sort order as ['1', '10', '2']. Update the completion script to bring the sorting into Python where custom types can be sorted more appropriately. Note that the version of bash that ships with OS X is v3.2. The nosort option for `complete` was introduced in v4.4 This change should support both.\n", "before_files": [{"content": "import collections\nimport 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\nWORDBREAK = '='\n\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\ncomplete -F %(complete_func)s %(script_names)s\n'''\n\nCOMPLETION_SCRIPT_ZSH = '''\n%(complete_func)s() {\n    local -a completions\n    local -a completions_with_descriptions\n    local -a response\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 '' completions_with_descriptions\n    fi\n    if [ -n \"$completions\" ]; then\n        compadd -M 'r:|=* l:|=* r:|=*' -a completions\n    fi\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, collections.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 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 add_subcommand_completions(ctx, incomplete, completions_out):\n    # Add subcommand completions.\n    if isinstance(ctx.command, MultiCommand):\n        completions_out.extend(\n            [(c, ctx.command.get_command(ctx, c).get_short_help_str()) for c in ctx.command.list_commands(ctx) if c.startswith(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 = sorted(\n                set(ctx.command.list_commands(ctx)) - set(ctx.protected_args))\n            completions_out.extend(\n                [(c, ctx.command.get_command(ctx, c).get_short_help_str()) for c in remaining_commands if c.startswith(incomplete)])\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):\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(\n                    [(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    return 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"}, {"content": "import click\nimport os\n\n\n@click.group()\ndef cli():\n    pass\n\n\ndef get_env_vars(ctx, args, incomplete):\n    for key in os.environ.keys():\n        if incomplete in key:\n            yield key\n\n\n@cli.command(help='A command to print environment variables')\n@click.argument(\"envvar\", type=click.STRING, autocompletion=get_env_vars)\ndef cmd1(envvar):\n    click.echo('Environment variable: %s' % envvar)\n    click.echo('Value: %s' % os.environ[envvar])\n\n\n@click.group(help='A group that holds a subcommand')\ndef group():\n    pass\n\n\ndef list_users(ctx, args, incomplete):\n    # Here you can generate completions dynamically\n    users = ['bob', 'alice']\n    for user in users:\n        if user.startswith(incomplete):\n            yield user\n\n\n@group.command(help='Choose a user')\n@click.argument(\"user\", type=click.STRING, autocompletion=list_users)\ndef subcmd(user):\n    click.echo('Chosen user is %s' % user)\n\ncli.add_command(group)\n", "path": "examples/bashcompletion/bashcompletion.py"}], "after_files": [{"content": "import collections\nimport 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\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    if [ ${BASH_VERSION_ARR[0]} -ge 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%(complete_func)s() {\n    local -a completions\n    local -a completions_with_descriptions\n    local -a response\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, collections.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 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 add_subcommand_completions(ctx, incomplete, completions_out):\n    # Add subcommand completions.\n    if isinstance(ctx.command, MultiCommand):\n        completions_out.extend(\n            [(c, ctx.command.get_command(ctx, c).get_short_help_str()) for c in ctx.command.list_commands(ctx) if c.startswith(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 = sorted(\n                set(ctx.command.list_commands(ctx)) - set(ctx.protected_args))\n            completions_out.extend(\n                [(c, ctx.command.get_command(ctx, c).get_short_help_str()) for c in remaining_commands if c.startswith(incomplete)])\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):\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(\n                    [(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"}, {"content": "import click\nimport os\n\n\n@click.group()\ndef cli():\n    pass\n\n\ndef get_env_vars(ctx, args, incomplete):\n    # Completions returned as strings do not have a description displayed.\n    for key in os.environ.keys():\n        if incomplete in key:\n            yield key\n\n\n@cli.command(help='A command to print environment variables')\n@click.argument(\"envvar\", type=click.STRING, autocompletion=get_env_vars)\ndef cmd1(envvar):\n    click.echo('Environment variable: %s' % envvar)\n    click.echo('Value: %s' % os.environ[envvar])\n\n\n@click.group(help='A group that holds a subcommand')\ndef group():\n    pass\n\n\ndef list_users(ctx, args, incomplete):\n    # You can generate completions with descriptions by returning\n    # tuples in the form (completion, description).\n    users = [('bob', 'butcher'),\n             ('alice', 'baker'),\n             ('jerry', 'candlestick maker')]\n    # Ths will allow completion matches based on matches within the description string too!\n    return [user for user in users if incomplete in user[0] or incomplete in user[1]]\n\n\n@group.command(help='Choose a user')\n@click.argument(\"user\", type=click.STRING, autocompletion=list_users)\ndef subcmd(user):\n    click.echo('Chosen user is %s' % user)\n\n\ncli.add_command(group)\n", "path": "examples/bashcompletion/bashcompletion.py"}]}