We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Autocomplete doesn't understand multi-space in name of a file
xonsh autocomplete can't understand multi-space (more than one space) in name of a file and consider it as one space the following gif will show it: [bug gif](https://ibb.co/eVno7x)  

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `xonsh/completers/bash_completion.py`
Content:
```
1 """This module provides the implementation for the retrieving completion results
2 from bash.
3 """
4 # developer note: this file should not perform any action on import.
5 import os
6 import re
7 import sys
8 import shlex
9 import shutil
10 import pathlib
11 import platform
12 import functools
13 import subprocess
14 
15 __version__ = '0.1.0'
16 
17 
18 @functools.lru_cache(1)
19 def _git_for_windows_path():
20     """Returns the path to git for windows, if available and None otherwise."""
21     import winreg
22     try:
23         key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
24                              'SOFTWARE\\GitForWindows')
25         gfwp, _ = winreg.QueryValueEx(key, "InstallPath")
26     except FileNotFoundError:
27         gfwp = None
28     return gfwp
29 
30 
31 @functools.lru_cache(1)
32 def _windows_bash_command(env=None):
33     """Determines the command for Bash on windows."""
34     wbc = 'bash'
35     path = None if env is None else env.get('PATH', None)
36     bash_on_path = shutil.which('bash', path=path)
37     if bash_on_path:
38         try:
39             out = subprocess.check_output([bash_on_path, '--version'],
40                                           stderr=subprocess.PIPE,
41                                           universal_newlines=True)
42         except subprocess.CalledProcessError:
43             bash_works = False
44         else:
45             # Check if Bash is from the "Windows Subsystem for Linux" (WSL)
46             # which can't be used by xonsh foreign-shell/completer
47             bash_works = out and 'pc-linux-gnu' not in out.splitlines()[0]
48 
49         if bash_works:
50             wbc = bash_on_path
51         else:
52             gfwp = _git_for_windows_path()
53             if gfwp:
54                 bashcmd = os.path.join(gfwp, 'bin\\bash.exe')
55                 if os.path.isfile(bashcmd):
56                     wbc = bashcmd
57     return wbc
58 
59 
60 def _bash_command(env=None):
61     """Determines the command for Bash on the current plaform."""
62     if platform.system() == 'Windows':
63         bc = _windows_bash_command(env=None)
64     else:
65         bc = 'bash'
66     return bc
67 
68 
69 def _bash_completion_paths_default():
70     """A possibly empty tuple with default paths to Bash completions known for
71     the current platform.
72     """
73     platform_sys = platform.system()
74     if platform_sys == 'Linux' or sys.platform == 'cygwin':
75         bcd = ('/usr/share/bash-completion/bash_completion', )
76     elif platform_sys == 'Darwin':
77         bcd = ('/usr/local/share/bash-completion/bash_completion',  # v2.x
78                '/usr/local/etc/bash_completion')  # v1.x
79     elif platform_sys == 'Windows':
80         gfwp = _git_for_windows_path()
81         if gfwp:
82             bcd = (os.path.join(gfwp, 'usr\\share\\bash-completion\\'
83                                       'bash_completion'),
84                    os.path.join(gfwp, 'mingw64\\share\\git\\completion\\'
85                                       'git-completion.bash'))
86         else:
87             bcd = ()
88     else:
89         bcd = ()
90     return bcd
91 
92 
93 _BASH_COMPLETIONS_PATHS_DEFAULT = None
94 
95 
96 def _get_bash_completions_source(paths=None):
97     global _BASH_COMPLETIONS_PATHS_DEFAULT
98     if paths is None:
99         if _BASH_COMPLETIONS_PATHS_DEFAULT is None:
100             _BASH_COMPLETIONS_PATHS_DEFAULT = _bash_completion_paths_default()
101         paths = _BASH_COMPLETIONS_PATHS_DEFAULT
102     for path in map(pathlib.Path, paths):
103         if path.is_file():
104             return 'source "{}"'.format(path.as_posix())
105     return None
106 
107 
108 def _bash_get_sep():
109     """ Returns the appropriate filepath separator char depending on OS and
110     xonsh options set
111     """
112     if platform.system() == 'Windows':
113         return os.altsep
114     else:
115         return os.sep
116 
117 
118 _BASH_PATTERN_NEED_QUOTES = None
119 
120 
121 def _bash_pattern_need_quotes():
122     global _BASH_PATTERN_NEED_QUOTES
123     if _BASH_PATTERN_NEED_QUOTES is not None:
124         return _BASH_PATTERN_NEED_QUOTES
125     pattern = r'\s`\$\{\}\,\*\(\)"\'\?&'
126     if platform.system() == 'Windows':
127         pattern += '%'
128     pattern = '[' + pattern + ']' + r'|\band\b|\bor\b'
129     _BASH_PATTERN_NEED_QUOTES = re.compile(pattern)
130     return _BASH_PATTERN_NEED_QUOTES
131 
132 
133 def _bash_expand_path(s):
134     """Takes a string path and expands ~ to home and environment vars."""
135     # expand ~ according to Bash unquoted rules "Each variable assignment is
136     # checked for unquoted tilde-prefixes immediately following a ':' or the
137     # first '='". See the following for more details.
138     # https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html
139     pre, char, post = s.partition('=')
140     if char:
141         s = os.path.expanduser(pre) + char
142         s += os.pathsep.join(map(os.path.expanduser, post.split(os.pathsep)))
143     else:
144         s = os.path.expanduser(s)
145     return s
146 
147 
148 def _bash_quote_to_use(x):
149     single = "'"
150     double = '"'
151     if single in x and double not in x:
152         return double
153     else:
154         return single
155 
156 
157 def _bash_quote_paths(paths, start, end):
158     out = set()
159     space = ' '
160     backslash = '\\'
161     double_backslash = '\\\\'
162     slash = _bash_get_sep()
163     orig_start = start
164     orig_end = end
165     # quote on all or none, to make readline completes to max prefix
166     need_quotes = any(
167         re.search(_bash_pattern_need_quotes(), x) or
168         (backslash in x and slash != backslash)
169         for x in paths)
170 
171     for s in paths:
172         start = orig_start
173         end = orig_end
174         if start == '' and need_quotes:
175             start = end = _bash_quote_to_use(s)
176         if os.path.isdir(_bash_expand_path(s)):
177             _tail = slash
178         elif end == '':
179             _tail = space
180         else:
181             _tail = ''
182         if start != '' and 'r' not in start and backslash in s:
183             start = 'r%s' % start
184         s = s + _tail
185         if end != '':
186             if "r" not in start.lower():
187                 s = s.replace(backslash, double_backslash)
188             if s.endswith(backslash) and not s.endswith(double_backslash):
189                 s += backslash
190         if end in s:
191             s = s.replace(end, ''.join('\\%s' % i for i in end))
192         out.add(start + s + end)
193     return out
194 
195 
196 BASH_COMPLETE_SCRIPT = r"""
197 {source}
198 
199 # Override some functions in bash-completion, do not quote for readline
200 quote_readline()
201 {{
202     echo "$1"
203 }}
204 
205 _quote_readline_by_ref()
206 {{
207     if [[ $1 == \'* ]]; then
208         # Leave out first character
209         printf -v $2 %s "${{1:1}}"
210     else
211         printf -v $2 %s "$1"
212     fi
213 
214     [[ ${{!2}} == \$* ]] && eval $2=${{!2}}
215 }}
216 
217 
218 function _get_complete_statement {{
219     complete -p {cmd} 2> /dev/null || echo "-F _minimal"
220 }}
221 
222 _complete_stmt=$(_get_complete_statement)
223 if echo "$_complete_stmt" | grep --quiet -e "_minimal"
224 then
225     declare -f _completion_loader > /dev/null && _completion_loader {cmd}
226     _complete_stmt=$(_get_complete_statement)
227 fi
228 
229 _func=$(echo "$_complete_stmt" | grep -o -e '-F \w\+' | cut -d ' ' -f 2)
230 declare -f "$_func" > /dev/null || exit 1
231 
232 echo "$_complete_stmt"
233 COMP_WORDS=({line})
234 COMP_LINE={comp_line}
235 COMP_POINT=${{#COMP_LINE}}
236 COMP_COUNT={end}
237 COMP_CWORD={n}
238 $_func {cmd} {prefix} {prev}
239 
240 for ((i=0;i<${{#COMPREPLY[*]}};i++)) do echo ${{COMPREPLY[i]}}; done
241 """
242 
243 
244 def bash_completions(prefix, line, begidx, endidx, env=None, paths=None,
245                      command=None, quote_paths=_bash_quote_paths, **kwargs):
246     """Completes based on results from BASH completion.
247 
248     Parameters
249     ----------
250     prefix : str
251         The string to match
252     line : str
253         The line that prefix appears on.
254     begidx : int
255         The index in line that prefix starts on.
256     endidx : int
257         The index in line that prefix ends on.
258     env : Mapping, optional
259         The environment dict to execute the Bash subprocess in.
260     paths : list or tuple of str or None, optional
261         This is a list (or tuple) of strings that specifies where the
262         ``bash_completion`` script may be found. The first valid path will
263         be used. For better performance, bash-completion v2.x is recommended
264         since it lazy-loads individual completion scripts. For both
265         bash-completion v1.x and v2.x, paths of individual completion scripts
266         (like ``.../completes/ssh``) do not need to be included here. The
267         default values are platform dependent, but sane.
268     command : str or None, optional
269         The /path/to/bash to use. If None, it will be selected based on the
270         from the environment and platform.
271     quote_paths : callable, optional
272         A functions that quotes file system paths. You shouldn't normally need
273         this as the default is acceptable 99+% of the time.
274 
275     Returns
276     -------
277     rtn : list of str
278         Possible completions of prefix, sorted alphabetically.
279     lprefix : int
280         Length of the prefix to be replaced in the completion.
281     """
282     source = _get_bash_completions_source(paths) or set()
283 
284     if prefix.startswith('$'):  # do not complete env variables
285         return set(), 0
286 
287     splt = line.split()
288     cmd = splt[0]
289     idx = n = 0
290     prev = ''
291     for n, tok in enumerate(splt):
292         if tok == prefix:
293             idx = line.find(prefix, idx)
294             if idx >= begidx:
295                 break
296         prev = tok
297 
298     if len(prefix) == 0:
299         prefix_quoted = '""'
300         n += 1
301     else:
302         prefix_quoted = shlex.quote(prefix)
303 
304     script = BASH_COMPLETE_SCRIPT.format(
305         source=source, line=' '.join(shlex.quote(p) for p in splt),
306         comp_line=shlex.quote(line), n=n, cmd=shlex.quote(cmd),
307         end=endidx + 1, prefix=prefix_quoted, prev=shlex.quote(prev),
308     )
309 
310     if command is None:
311         command = _bash_command(env=env)
312     try:
313         out = subprocess.check_output(
314             [command, '-c', script], universal_newlines=True,
315             stderr=subprocess.PIPE, env=env)
316         if not out:
317             raise ValueError
318     except (subprocess.CalledProcessError, FileNotFoundError,
319             UnicodeDecodeError, ValueError):
320         return set(), 0
321 
322     out = out.splitlines()
323     complete_stmt = out[0]
324     out = set(out[1:])
325 
326     # From GNU Bash document: The results of the expansion are prefix-matched
327     # against the word being completed
328 
329     # Ensure input to `commonprefix` is a list (now required by Python 3.6)
330     commprefix = os.path.commonprefix(list(out))
331     strip_len = 0
332     while strip_len < len(prefix):
333         if commprefix.startswith(prefix[strip_len:]):
334             break
335         strip_len += 1
336 
337     if '-o noquote' not in complete_stmt:
338         out = quote_paths(out, '', '')
339     if '-o nospace' in complete_stmt:
340         out = set([x.rstrip() for x in out])
341 
342     return out, len(prefix) - strip_len
343
```
--- 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/xonsh/completers/bash_completion.py b/xonsh/completers/bash_completion.py
--- a/xonsh/completers/bash_completion.py
+++ b/xonsh/completers/bash_completion.py
@@ -2,6 +2,8 @@
 from bash.
 """
 # developer note: this file should not perform any action on import.
+#                 This file comes from https://github.com/xonsh/py-bash-completion
+#                 and should be edited there!
 import os
 import re
 import sys
@@ -237,7 +239,7 @@
 COMP_CWORD={n}
 $_func {cmd} {prefix} {prev}
 
-for ((i=0;i<${{#COMPREPLY[*]}};i++)) do echo ${{COMPREPLY[i]}}; done
+for ((i=0;i<${{#COMPREPLY[*]}};i++)) do echo "${{COMPREPLY[i]}}"; done
 """
 
 
@@ -274,8 +276,8 @@
 
     Returns
     -------
-    rtn : list of str
-        Possible completions of prefix, sorted alphabetically.
+    rtn : set of str
+        Possible completions of prefix
     lprefix : int
         Length of the prefix to be replaced in the completion.
     """
@@ -340,3 +342,60 @@
         out = set([x.rstrip() for x in out])
 
     return out, len(prefix) - strip_len
+
+
+def bash_complete_line(line, return_line=True, **kwargs):
+    """Provides the completion from the end of the line.
+
+    Parameters
+    ----------
+    line : str
+        Line to complete
+    return_line : bool, optional
+        If true (default), will return the entire line, with the completion added.
+        If false, this will instead return the strings to append to the original line.
+    kwargs : optional
+        All other keyword arguments are passed to the bash_completions() function.
+
+    Returns
+    -------
+    rtn : set of str
+        Possible completions of prefix
+    """
+    # set up for completing from the end of the line
+    split = line.split()
+    if len(split) > 1 and not line.endswith(' '):
+        prefix = split[-1]
+        begidx = len(line.rsplit(prefix)[0])
+    else:
+        prefix = ''
+        begidx = len(line)
+    endidx = len(line)
+    # get completions
+    out, lprefix = bash_completions(prefix, line, begidx, endidx, **kwargs)
+    # reformat output
+    if return_line:
+        preline = line[:-lprefix]
+        rtn = {preline + o for o in out}
+    else:
+        rtn = {o[lprefix:] for o in out}
+    return rtn
+
+
+def _bc_main(args=None):
+    """Runs complete_line() and prints the output."""
+    from argparse import ArgumentParser
+    p = ArgumentParser('bash_completions')
+    p.add_argument('--return-line', action='store_true', dest='return_line', default=True,
+                   help='will return the entire line, with the completion added')
+    p.add_argument('--no-return-line', action='store_false', dest='return_line',
+                   help='will instead return the strings to append to the original line')
+    p.add_argument('line', help='line to complete')
+    ns = p.parse_args(args=args)
+    out = bash_complete_line(ns.line, return_line=ns.return_line)
+    for o in sorted(out):
+        print(o)
+
+
+if __name__ == '__main__':
+    _bc_main()

{"golden_diff": "diff --git a/xonsh/completers/bash_completion.py b/xonsh/completers/bash_completion.py\n--- a/xonsh/completers/bash_completion.py\n+++ b/xonsh/completers/bash_completion.py\n@@ -2,6 +2,8 @@\n from bash.\n \"\"\"\n # developer note: this file should not perform any action on import.\n+#                 This file comes from https://github.com/xonsh/py-bash-completion\n+#                 and should be edited there!\n import os\n import re\n import sys\n@@ -237,7 +239,7 @@\n COMP_CWORD={n}\n $_func {cmd} {prefix} {prev}\n \n-for ((i=0;i<${{#COMPREPLY[*]}};i++)) do echo ${{COMPREPLY[i]}}; done\n+for ((i=0;i<${{#COMPREPLY[*]}};i++)) do echo \"${{COMPREPLY[i]}}\"; done\n \"\"\"\n \n \n@@ -274,8 +276,8 @@\n \n     Returns\n     -------\n-    rtn : list of str\n-        Possible completions of prefix, sorted alphabetically.\n+    rtn : set of str\n+        Possible completions of prefix\n     lprefix : int\n         Length of the prefix to be replaced in the completion.\n     \"\"\"\n@@ -340,3 +342,60 @@\n         out = set([x.rstrip() for x in out])\n \n     return out, len(prefix) - strip_len\n+\n+\n+def bash_complete_line(line, return_line=True, **kwargs):\n+    \"\"\"Provides the completion from the end of the line.\n+\n+    Parameters\n+    ----------\n+    line : str\n+        Line to complete\n+    return_line : bool, optional\n+        If true (default), will return the entire line, with the completion added.\n+        If false, this will instead return the strings to append to the original line.\n+    kwargs : optional\n+        All other keyword arguments are passed to the bash_completions() function.\n+\n+    Returns\n+    -------\n+    rtn : set of str\n+        Possible completions of prefix\n+    \"\"\"\n+    # set up for completing from the end of the line\n+    split = line.split()\n+    if len(split) > 1 and not line.endswith(' '):\n+        prefix = split[-1]\n+        begidx = len(line.rsplit(prefix)[0])\n+    else:\n+        prefix = ''\n+        begidx = len(line)\n+    endidx = len(line)\n+    # get completions\n+    out, lprefix = bash_completions(prefix, line, begidx, endidx, **kwargs)\n+    # reformat output\n+    if return_line:\n+        preline = line[:-lprefix]\n+        rtn = {preline + o for o in out}\n+    else:\n+        rtn = {o[lprefix:] for o in out}\n+    return rtn\n+\n+\n+def _bc_main(args=None):\n+    \"\"\"Runs complete_line() and prints the output.\"\"\"\n+    from argparse import ArgumentParser\n+    p = ArgumentParser('bash_completions')\n+    p.add_argument('--return-line', action='store_true', dest='return_line', default=True,\n+                   help='will return the entire line, with the completion added')\n+    p.add_argument('--no-return-line', action='store_false', dest='return_line',\n+                   help='will instead return the strings to append to the original line')\n+    p.add_argument('line', help='line to complete')\n+    ns = p.parse_args(args=args)\n+    out = bash_complete_line(ns.line, return_line=ns.return_line)\n+    for o in sorted(out):\n+        print(o)\n+\n+\n+if __name__ == '__main__':\n+    _bc_main()\n", "issue": "Autocomplete doesn't understand multi-space in name of a file\nxonsh autocomplete can't understand multi-space (more than one space) in name of a file and consider it as one space the following gif will show it: [bug gif](https://ibb.co/eVno7x)  \n", "before_files": [{"content": "\"\"\"This module provides the implementation for the retrieving completion results\nfrom bash.\n\"\"\"\n# developer note: this file should not perform any action on import.\nimport os\nimport re\nimport sys\nimport shlex\nimport shutil\nimport pathlib\nimport platform\nimport functools\nimport subprocess\n\n__version__ = '0.1.0'\n\n\n@functools.lru_cache(1)\ndef _git_for_windows_path():\n    \"\"\"Returns the path to git for windows, if available and None otherwise.\"\"\"\n    import winreg\n    try:\n        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                             'SOFTWARE\\\\GitForWindows')\n        gfwp, _ = winreg.QueryValueEx(key, \"InstallPath\")\n    except FileNotFoundError:\n        gfwp = None\n    return gfwp\n\n\n@functools.lru_cache(1)\ndef _windows_bash_command(env=None):\n    \"\"\"Determines the command for Bash on windows.\"\"\"\n    wbc = 'bash'\n    path = None if env is None else env.get('PATH', None)\n    bash_on_path = shutil.which('bash', path=path)\n    if bash_on_path:\n        try:\n            out = subprocess.check_output([bash_on_path, '--version'],\n                                          stderr=subprocess.PIPE,\n                                          universal_newlines=True)\n        except subprocess.CalledProcessError:\n            bash_works = False\n        else:\n            # Check if Bash is from the \"Windows Subsystem for Linux\" (WSL)\n            # which can't be used by xonsh foreign-shell/completer\n            bash_works = out and 'pc-linux-gnu' not in out.splitlines()[0]\n\n        if bash_works:\n            wbc = bash_on_path\n        else:\n            gfwp = _git_for_windows_path()\n            if gfwp:\n                bashcmd = os.path.join(gfwp, 'bin\\\\bash.exe')\n                if os.path.isfile(bashcmd):\n                    wbc = bashcmd\n    return wbc\n\n\ndef _bash_command(env=None):\n    \"\"\"Determines the command for Bash on the current plaform.\"\"\"\n    if platform.system() == 'Windows':\n        bc = _windows_bash_command(env=None)\n    else:\n        bc = 'bash'\n    return bc\n\n\ndef _bash_completion_paths_default():\n    \"\"\"A possibly empty tuple with default paths to Bash completions known for\n    the current platform.\n    \"\"\"\n    platform_sys = platform.system()\n    if platform_sys == 'Linux' or sys.platform == 'cygwin':\n        bcd = ('/usr/share/bash-completion/bash_completion', )\n    elif platform_sys == 'Darwin':\n        bcd = ('/usr/local/share/bash-completion/bash_completion',  # v2.x\n               '/usr/local/etc/bash_completion')  # v1.x\n    elif platform_sys == 'Windows':\n        gfwp = _git_for_windows_path()\n        if gfwp:\n            bcd = (os.path.join(gfwp, 'usr\\\\share\\\\bash-completion\\\\'\n                                      'bash_completion'),\n                   os.path.join(gfwp, 'mingw64\\\\share\\\\git\\\\completion\\\\'\n                                      'git-completion.bash'))\n        else:\n            bcd = ()\n    else:\n        bcd = ()\n    return bcd\n\n\n_BASH_COMPLETIONS_PATHS_DEFAULT = None\n\n\ndef _get_bash_completions_source(paths=None):\n    global _BASH_COMPLETIONS_PATHS_DEFAULT\n    if paths is None:\n        if _BASH_COMPLETIONS_PATHS_DEFAULT is None:\n            _BASH_COMPLETIONS_PATHS_DEFAULT = _bash_completion_paths_default()\n        paths = _BASH_COMPLETIONS_PATHS_DEFAULT\n    for path in map(pathlib.Path, paths):\n        if path.is_file():\n            return 'source \"{}\"'.format(path.as_posix())\n    return None\n\n\ndef _bash_get_sep():\n    \"\"\" Returns the appropriate filepath separator char depending on OS and\n    xonsh options set\n    \"\"\"\n    if platform.system() == 'Windows':\n        return os.altsep\n    else:\n        return os.sep\n\n\n_BASH_PATTERN_NEED_QUOTES = None\n\n\ndef _bash_pattern_need_quotes():\n    global _BASH_PATTERN_NEED_QUOTES\n    if _BASH_PATTERN_NEED_QUOTES is not None:\n        return _BASH_PATTERN_NEED_QUOTES\n    pattern = r'\\s`\\$\\{\\}\\,\\*\\(\\)\"\\'\\?&'\n    if platform.system() == 'Windows':\n        pattern += '%'\n    pattern = '[' + pattern + ']' + r'|\\band\\b|\\bor\\b'\n    _BASH_PATTERN_NEED_QUOTES = re.compile(pattern)\n    return _BASH_PATTERN_NEED_QUOTES\n\n\ndef _bash_expand_path(s):\n    \"\"\"Takes a string path and expands ~ to home and environment vars.\"\"\"\n    # expand ~ according to Bash unquoted rules \"Each variable assignment is\n    # checked for unquoted tilde-prefixes immediately following a ':' or the\n    # first '='\". See the following for more details.\n    # https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html\n    pre, char, post = s.partition('=')\n    if char:\n        s = os.path.expanduser(pre) + char\n        s += os.pathsep.join(map(os.path.expanduser, post.split(os.pathsep)))\n    else:\n        s = os.path.expanduser(s)\n    return s\n\n\ndef _bash_quote_to_use(x):\n    single = \"'\"\n    double = '\"'\n    if single in x and double not in x:\n        return double\n    else:\n        return single\n\n\ndef _bash_quote_paths(paths, start, end):\n    out = set()\n    space = ' '\n    backslash = '\\\\'\n    double_backslash = '\\\\\\\\'\n    slash = _bash_get_sep()\n    orig_start = start\n    orig_end = end\n    # quote on all or none, to make readline completes to max prefix\n    need_quotes = any(\n        re.search(_bash_pattern_need_quotes(), x) or\n        (backslash in x and slash != backslash)\n        for x in paths)\n\n    for s in paths:\n        start = orig_start\n        end = orig_end\n        if start == '' and need_quotes:\n            start = end = _bash_quote_to_use(s)\n        if os.path.isdir(_bash_expand_path(s)):\n            _tail = slash\n        elif end == '':\n            _tail = space\n        else:\n            _tail = ''\n        if start != '' and 'r' not in start and backslash in s:\n            start = 'r%s' % start\n        s = s + _tail\n        if end != '':\n            if \"r\" not in start.lower():\n                s = s.replace(backslash, double_backslash)\n            if s.endswith(backslash) and not s.endswith(double_backslash):\n                s += backslash\n        if end in s:\n            s = s.replace(end, ''.join('\\\\%s' % i for i in end))\n        out.add(start + s + end)\n    return out\n\n\nBASH_COMPLETE_SCRIPT = r\"\"\"\n{source}\n\n# Override some functions in bash-completion, do not quote for readline\nquote_readline()\n{{\n    echo \"$1\"\n}}\n\n_quote_readline_by_ref()\n{{\n    if [[ $1 == \\'* ]]; then\n        # Leave out first character\n        printf -v $2 %s \"${{1:1}}\"\n    else\n        printf -v $2 %s \"$1\"\n    fi\n\n    [[ ${{!2}} == \\$* ]] && eval $2=${{!2}}\n}}\n\n\nfunction _get_complete_statement {{\n    complete -p {cmd} 2> /dev/null || echo \"-F _minimal\"\n}}\n\n_complete_stmt=$(_get_complete_statement)\nif echo \"$_complete_stmt\" | grep --quiet -e \"_minimal\"\nthen\n    declare -f _completion_loader > /dev/null && _completion_loader {cmd}\n    _complete_stmt=$(_get_complete_statement)\nfi\n\n_func=$(echo \"$_complete_stmt\" | grep -o -e '-F \\w\\+' | cut -d ' ' -f 2)\ndeclare -f \"$_func\" > /dev/null || exit 1\n\necho \"$_complete_stmt\"\nCOMP_WORDS=({line})\nCOMP_LINE={comp_line}\nCOMP_POINT=${{#COMP_LINE}}\nCOMP_COUNT={end}\nCOMP_CWORD={n}\n$_func {cmd} {prefix} {prev}\n\nfor ((i=0;i<${{#COMPREPLY[*]}};i++)) do echo ${{COMPREPLY[i]}}; done\n\"\"\"\n\n\ndef bash_completions(prefix, line, begidx, endidx, env=None, paths=None,\n                     command=None, quote_paths=_bash_quote_paths, **kwargs):\n    \"\"\"Completes based on results from BASH completion.\n\n    Parameters\n    ----------\n    prefix : str\n        The string to match\n    line : str\n        The line that prefix appears on.\n    begidx : int\n        The index in line that prefix starts on.\n    endidx : int\n        The index in line that prefix ends on.\n    env : Mapping, optional\n        The environment dict to execute the Bash subprocess in.\n    paths : list or tuple of str or None, optional\n        This is a list (or tuple) of strings that specifies where the\n        ``bash_completion`` script may be found. The first valid path will\n        be used. For better performance, bash-completion v2.x is recommended\n        since it lazy-loads individual completion scripts. For both\n        bash-completion v1.x and v2.x, paths of individual completion scripts\n        (like ``.../completes/ssh``) do not need to be included here. The\n        default values are platform dependent, but sane.\n    command : str or None, optional\n        The /path/to/bash to use. If None, it will be selected based on the\n        from the environment and platform.\n    quote_paths : callable, optional\n        A functions that quotes file system paths. You shouldn't normally need\n        this as the default is acceptable 99+% of the time.\n\n    Returns\n    -------\n    rtn : list of str\n        Possible completions of prefix, sorted alphabetically.\n    lprefix : int\n        Length of the prefix to be replaced in the completion.\n    \"\"\"\n    source = _get_bash_completions_source(paths) or set()\n\n    if prefix.startswith('$'):  # do not complete env variables\n        return set(), 0\n\n    splt = line.split()\n    cmd = splt[0]\n    idx = n = 0\n    prev = ''\n    for n, tok in enumerate(splt):\n        if tok == prefix:\n            idx = line.find(prefix, idx)\n            if idx >= begidx:\n                break\n        prev = tok\n\n    if len(prefix) == 0:\n        prefix_quoted = '\"\"'\n        n += 1\n    else:\n        prefix_quoted = shlex.quote(prefix)\n\n    script = BASH_COMPLETE_SCRIPT.format(\n        source=source, line=' '.join(shlex.quote(p) for p in splt),\n        comp_line=shlex.quote(line), n=n, cmd=shlex.quote(cmd),\n        end=endidx + 1, prefix=prefix_quoted, prev=shlex.quote(prev),\n    )\n\n    if command is None:\n        command = _bash_command(env=env)\n    try:\n        out = subprocess.check_output(\n            [command, '-c', script], universal_newlines=True,\n            stderr=subprocess.PIPE, env=env)\n        if not out:\n            raise ValueError\n    except (subprocess.CalledProcessError, FileNotFoundError,\n            UnicodeDecodeError, ValueError):\n        return set(), 0\n\n    out = out.splitlines()\n    complete_stmt = out[0]\n    out = set(out[1:])\n\n    # From GNU Bash document: The results of the expansion are prefix-matched\n    # against the word being completed\n\n    # Ensure input to `commonprefix` is a list (now required by Python 3.6)\n    commprefix = os.path.commonprefix(list(out))\n    strip_len = 0\n    while strip_len < len(prefix):\n        if commprefix.startswith(prefix[strip_len:]):\n            break\n        strip_len += 1\n\n    if '-o noquote' not in complete_stmt:\n        out = quote_paths(out, '', '')\n    if '-o nospace' in complete_stmt:\n        out = set([x.rstrip() for x in out])\n\n    return out, len(prefix) - strip_len\n", "path": "xonsh/completers/bash_completion.py"}], "after_files": [{"content": "\"\"\"This module provides the implementation for the retrieving completion results\nfrom bash.\n\"\"\"\n# developer note: this file should not perform any action on import.\n#                 This file comes from https://github.com/xonsh/py-bash-completion\n#                 and should be edited there!\nimport os\nimport re\nimport sys\nimport shlex\nimport shutil\nimport pathlib\nimport platform\nimport functools\nimport subprocess\n\n__version__ = '0.1.0'\n\n\n@functools.lru_cache(1)\ndef _git_for_windows_path():\n    \"\"\"Returns the path to git for windows, if available and None otherwise.\"\"\"\n    import winreg\n    try:\n        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                             'SOFTWARE\\\\GitForWindows')\n        gfwp, _ = winreg.QueryValueEx(key, \"InstallPath\")\n    except FileNotFoundError:\n        gfwp = None\n    return gfwp\n\n\n@functools.lru_cache(1)\ndef _windows_bash_command(env=None):\n    \"\"\"Determines the command for Bash on windows.\"\"\"\n    wbc = 'bash'\n    path = None if env is None else env.get('PATH', None)\n    bash_on_path = shutil.which('bash', path=path)\n    if bash_on_path:\n        try:\n            out = subprocess.check_output([bash_on_path, '--version'],\n                                          stderr=subprocess.PIPE,\n                                          universal_newlines=True)\n        except subprocess.CalledProcessError:\n            bash_works = False\n        else:\n            # Check if Bash is from the \"Windows Subsystem for Linux\" (WSL)\n            # which can't be used by xonsh foreign-shell/completer\n            bash_works = out and 'pc-linux-gnu' not in out.splitlines()[0]\n\n        if bash_works:\n            wbc = bash_on_path\n        else:\n            gfwp = _git_for_windows_path()\n            if gfwp:\n                bashcmd = os.path.join(gfwp, 'bin\\\\bash.exe')\n                if os.path.isfile(bashcmd):\n                    wbc = bashcmd\n    return wbc\n\n\ndef _bash_command(env=None):\n    \"\"\"Determines the command for Bash on the current plaform.\"\"\"\n    if platform.system() == 'Windows':\n        bc = _windows_bash_command(env=None)\n    else:\n        bc = 'bash'\n    return bc\n\n\ndef _bash_completion_paths_default():\n    \"\"\"A possibly empty tuple with default paths to Bash completions known for\n    the current platform.\n    \"\"\"\n    platform_sys = platform.system()\n    if platform_sys == 'Linux' or sys.platform == 'cygwin':\n        bcd = ('/usr/share/bash-completion/bash_completion', )\n    elif platform_sys == 'Darwin':\n        bcd = ('/usr/local/share/bash-completion/bash_completion',  # v2.x\n               '/usr/local/etc/bash_completion')  # v1.x\n    elif platform_sys == 'Windows':\n        gfwp = _git_for_windows_path()\n        if gfwp:\n            bcd = (os.path.join(gfwp, 'usr\\\\share\\\\bash-completion\\\\'\n                                      'bash_completion'),\n                   os.path.join(gfwp, 'mingw64\\\\share\\\\git\\\\completion\\\\'\n                                      'git-completion.bash'))\n        else:\n            bcd = ()\n    else:\n        bcd = ()\n    return bcd\n\n\n_BASH_COMPLETIONS_PATHS_DEFAULT = None\n\n\ndef _get_bash_completions_source(paths=None):\n    global _BASH_COMPLETIONS_PATHS_DEFAULT\n    if paths is None:\n        if _BASH_COMPLETIONS_PATHS_DEFAULT is None:\n            _BASH_COMPLETIONS_PATHS_DEFAULT = _bash_completion_paths_default()\n        paths = _BASH_COMPLETIONS_PATHS_DEFAULT\n    for path in map(pathlib.Path, paths):\n        if path.is_file():\n            return 'source \"{}\"'.format(path.as_posix())\n    return None\n\n\ndef _bash_get_sep():\n    \"\"\" Returns the appropriate filepath separator char depending on OS and\n    xonsh options set\n    \"\"\"\n    if platform.system() == 'Windows':\n        return os.altsep\n    else:\n        return os.sep\n\n\n_BASH_PATTERN_NEED_QUOTES = None\n\n\ndef _bash_pattern_need_quotes():\n    global _BASH_PATTERN_NEED_QUOTES\n    if _BASH_PATTERN_NEED_QUOTES is not None:\n        return _BASH_PATTERN_NEED_QUOTES\n    pattern = r'\\s`\\$\\{\\}\\,\\*\\(\\)\"\\'\\?&'\n    if platform.system() == 'Windows':\n        pattern += '%'\n    pattern = '[' + pattern + ']' + r'|\\band\\b|\\bor\\b'\n    _BASH_PATTERN_NEED_QUOTES = re.compile(pattern)\n    return _BASH_PATTERN_NEED_QUOTES\n\n\ndef _bash_expand_path(s):\n    \"\"\"Takes a string path and expands ~ to home and environment vars.\"\"\"\n    # expand ~ according to Bash unquoted rules \"Each variable assignment is\n    # checked for unquoted tilde-prefixes immediately following a ':' or the\n    # first '='\". See the following for more details.\n    # https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html\n    pre, char, post = s.partition('=')\n    if char:\n        s = os.path.expanduser(pre) + char\n        s += os.pathsep.join(map(os.path.expanduser, post.split(os.pathsep)))\n    else:\n        s = os.path.expanduser(s)\n    return s\n\n\ndef _bash_quote_to_use(x):\n    single = \"'\"\n    double = '\"'\n    if single in x and double not in x:\n        return double\n    else:\n        return single\n\n\ndef _bash_quote_paths(paths, start, end):\n    out = set()\n    space = ' '\n    backslash = '\\\\'\n    double_backslash = '\\\\\\\\'\n    slash = _bash_get_sep()\n    orig_start = start\n    orig_end = end\n    # quote on all or none, to make readline completes to max prefix\n    need_quotes = any(\n        re.search(_bash_pattern_need_quotes(), x) or\n        (backslash in x and slash != backslash)\n        for x in paths)\n\n    for s in paths:\n        start = orig_start\n        end = orig_end\n        if start == '' and need_quotes:\n            start = end = _bash_quote_to_use(s)\n        if os.path.isdir(_bash_expand_path(s)):\n            _tail = slash\n        elif end == '':\n            _tail = space\n        else:\n            _tail = ''\n        if start != '' and 'r' not in start and backslash in s:\n            start = 'r%s' % start\n        s = s + _tail\n        if end != '':\n            if \"r\" not in start.lower():\n                s = s.replace(backslash, double_backslash)\n            if s.endswith(backslash) and not s.endswith(double_backslash):\n                s += backslash\n        if end in s:\n            s = s.replace(end, ''.join('\\\\%s' % i for i in end))\n        out.add(start + s + end)\n    return out\n\n\nBASH_COMPLETE_SCRIPT = r\"\"\"\n{source}\n\n# Override some functions in bash-completion, do not quote for readline\nquote_readline()\n{{\n    echo \"$1\"\n}}\n\n_quote_readline_by_ref()\n{{\n    if [[ $1 == \\'* ]]; then\n        # Leave out first character\n        printf -v $2 %s \"${{1:1}}\"\n    else\n        printf -v $2 %s \"$1\"\n    fi\n\n    [[ ${{!2}} == \\$* ]] && eval $2=${{!2}}\n}}\n\n\nfunction _get_complete_statement {{\n    complete -p {cmd} 2> /dev/null || echo \"-F _minimal\"\n}}\n\n_complete_stmt=$(_get_complete_statement)\nif echo \"$_complete_stmt\" | grep --quiet -e \"_minimal\"\nthen\n    declare -f _completion_loader > /dev/null && _completion_loader {cmd}\n    _complete_stmt=$(_get_complete_statement)\nfi\n\n_func=$(echo \"$_complete_stmt\" | grep -o -e '-F \\w\\+' | cut -d ' ' -f 2)\ndeclare -f \"$_func\" > /dev/null || exit 1\n\necho \"$_complete_stmt\"\nCOMP_WORDS=({line})\nCOMP_LINE={comp_line}\nCOMP_POINT=${{#COMP_LINE}}\nCOMP_COUNT={end}\nCOMP_CWORD={n}\n$_func {cmd} {prefix} {prev}\n\nfor ((i=0;i<${{#COMPREPLY[*]}};i++)) do echo \"${{COMPREPLY[i]}}\"; done\n\"\"\"\n\n\ndef bash_completions(prefix, line, begidx, endidx, env=None, paths=None,\n                     command=None, quote_paths=_bash_quote_paths, **kwargs):\n    \"\"\"Completes based on results from BASH completion.\n\n    Parameters\n    ----------\n    prefix : str\n        The string to match\n    line : str\n        The line that prefix appears on.\n    begidx : int\n        The index in line that prefix starts on.\n    endidx : int\n        The index in line that prefix ends on.\n    env : Mapping, optional\n        The environment dict to execute the Bash subprocess in.\n    paths : list or tuple of str or None, optional\n        This is a list (or tuple) of strings that specifies where the\n        ``bash_completion`` script may be found. The first valid path will\n        be used. For better performance, bash-completion v2.x is recommended\n        since it lazy-loads individual completion scripts. For both\n        bash-completion v1.x and v2.x, paths of individual completion scripts\n        (like ``.../completes/ssh``) do not need to be included here. The\n        default values are platform dependent, but sane.\n    command : str or None, optional\n        The /path/to/bash to use. If None, it will be selected based on the\n        from the environment and platform.\n    quote_paths : callable, optional\n        A functions that quotes file system paths. You shouldn't normally need\n        this as the default is acceptable 99+% of the time.\n\n    Returns\n    -------\n    rtn : set of str\n        Possible completions of prefix\n    lprefix : int\n        Length of the prefix to be replaced in the completion.\n    \"\"\"\n    source = _get_bash_completions_source(paths) or set()\n\n    if prefix.startswith('$'):  # do not complete env variables\n        return set(), 0\n\n    splt = line.split()\n    cmd = splt[0]\n    idx = n = 0\n    prev = ''\n    for n, tok in enumerate(splt):\n        if tok == prefix:\n            idx = line.find(prefix, idx)\n            if idx >= begidx:\n                break\n        prev = tok\n\n    if len(prefix) == 0:\n        prefix_quoted = '\"\"'\n        n += 1\n    else:\n        prefix_quoted = shlex.quote(prefix)\n\n    script = BASH_COMPLETE_SCRIPT.format(\n        source=source, line=' '.join(shlex.quote(p) for p in splt),\n        comp_line=shlex.quote(line), n=n, cmd=shlex.quote(cmd),\n        end=endidx + 1, prefix=prefix_quoted, prev=shlex.quote(prev),\n    )\n\n    if command is None:\n        command = _bash_command(env=env)\n    try:\n        out = subprocess.check_output(\n            [command, '-c', script], universal_newlines=True,\n            stderr=subprocess.PIPE, env=env)\n        if not out:\n            raise ValueError\n    except (subprocess.CalledProcessError, FileNotFoundError,\n            UnicodeDecodeError, ValueError):\n        return set(), 0\n\n    out = out.splitlines()\n    complete_stmt = out[0]\n    out = set(out[1:])\n\n    # From GNU Bash document: The results of the expansion are prefix-matched\n    # against the word being completed\n\n    # Ensure input to `commonprefix` is a list (now required by Python 3.6)\n    commprefix = os.path.commonprefix(list(out))\n    strip_len = 0\n    while strip_len < len(prefix):\n        if commprefix.startswith(prefix[strip_len:]):\n            break\n        strip_len += 1\n\n    if '-o noquote' not in complete_stmt:\n        out = quote_paths(out, '', '')\n    if '-o nospace' in complete_stmt:\n        out = set([x.rstrip() for x in out])\n\n    return out, len(prefix) - strip_len\n\n\ndef bash_complete_line(line, return_line=True, **kwargs):\n    \"\"\"Provides the completion from the end of the line.\n\n    Parameters\n    ----------\n    line : str\n        Line to complete\n    return_line : bool, optional\n        If true (default), will return the entire line, with the completion added.\n        If false, this will instead return the strings to append to the original line.\n    kwargs : optional\n        All other keyword arguments are passed to the bash_completions() function.\n\n    Returns\n    -------\n    rtn : set of str\n        Possible completions of prefix\n    \"\"\"\n    # set up for completing from the end of the line\n    split = line.split()\n    if len(split) > 1 and not line.endswith(' '):\n        prefix = split[-1]\n        begidx = len(line.rsplit(prefix)[0])\n    else:\n        prefix = ''\n        begidx = len(line)\n    endidx = len(line)\n    # get completions\n    out, lprefix = bash_completions(prefix, line, begidx, endidx, **kwargs)\n    # reformat output\n    if return_line:\n        preline = line[:-lprefix]\n        rtn = {preline + o for o in out}\n    else:\n        rtn = {o[lprefix:] for o in out}\n    return rtn\n\n\ndef _bc_main(args=None):\n    \"\"\"Runs complete_line() and prints the output.\"\"\"\n    from argparse import ArgumentParser\n    p = ArgumentParser('bash_completions')\n    p.add_argument('--return-line', action='store_true', dest='return_line', default=True,\n                   help='will return the entire line, with the completion added')\n    p.add_argument('--no-return-line', action='store_false', dest='return_line',\n                   help='will instead return the strings to append to the original line')\n    p.add_argument('line', help='line to complete')\n    ns = p.parse_args(args=args)\n    out = bash_complete_line(ns.line, return_line=ns.return_line)\n    for o in sorted(out):\n        print(o)\n\n\nif __name__ == '__main__':\n    _bc_main()\n", "path": "xonsh/completers/bash_completion.py"}]}