We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[color] in .gitconfig should be stripped in the prompt branch functions
In clean install with no `.xonshrc`, when I change into a git repo, my prompt looks like:

![prompt](https://i.imgur.com/ZFOPSOj.png)

Is there some setting I'm missing somewhere?

## xonfig

<details>

```
+------------------+----------------------+
| xonsh            | 0.9.13.dev1          |
| Git SHA          | 9f7ccc65             |
| Commit Date      | Oct 15 17:14:50 2019 |
| Python           | 3.7.6                |
| PLY              | 3.11                 |
| have readline    | True                 |
| prompt toolkit   | 3.0.0                |
| shell type       | prompt_toolkit2      |
| pygments         | 2.5.2                |
| on posix         | True                 |
| on linux         | True                 |
| distro           | ubuntu               |
| on darwin        | False                |
| on windows       | False                |
| on cygwin        | False                |
| on msys2         | False                |
| is superuser     | False                |
| default encoding | utf-8                |
| xonsh encoding   | utf-8                |
| encoding errors  | surrogateescape      |
+------------------+----------------------+
```


</details>

## Expected Behavior
I think something like this (without the ansi escape codes):
```
mcrowe@mike-XPS-15-9560 ~/.dotfiles/bash_it [master] $
```


--- 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/prompt/vc.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 """Prompt formatter for simple version control branches"""
3 # pylint:disable=no-member, invalid-name
4 
5 import os
6 import sys
7 import queue
8 import builtins
9 import threading
10 import subprocess
11 
12 import xonsh.tools as xt
13 
14 
15 def _get_git_branch(q):
16     denv = builtins.__xonsh__.env.detype()
17     try:
18         branches = xt.decode_bytes(
19             subprocess.check_output(
20                 ["git", "branch"], env=denv, stderr=subprocess.DEVNULL
21             )
22         ).splitlines()
23     except (subprocess.CalledProcessError, OSError, FileNotFoundError):
24         q.put(None)
25     else:
26         for branch in branches:
27             if not branch.startswith("* "):
28                 continue
29             elif branch.endswith(")"):
30                 branch = branch.split()[-1][:-1]
31             else:
32                 branch = branch.split()[-1]
33 
34             q.put(branch)
35             break
36         else:
37             q.put(None)
38 
39 
40 def get_git_branch():
41     """Attempts to find the current git branch. If this could not
42     be determined (timeout, not in a git repo, etc.) then this returns None.
43     """
44     branch = None
45     timeout = builtins.__xonsh__.env.get("VC_BRANCH_TIMEOUT")
46     q = queue.Queue()
47 
48     t = threading.Thread(target=_get_git_branch, args=(q,))
49     t.start()
50     t.join(timeout=timeout)
51     try:
52         branch = q.get_nowait()
53     except queue.Empty:
54         branch = None
55     return branch
56 
57 
58 def _get_hg_root(q):
59     _curpwd = builtins.__xonsh__.env["PWD"]
60     while True:
61         if not os.path.isdir(_curpwd):
62             return False
63         try:
64             dot_hg_is_in_curwd = any([b.name == ".hg" for b in xt.scandir(_curpwd)])
65         except OSError:
66             return False
67         if dot_hg_is_in_curwd:
68             q.put(_curpwd)
69             break
70         else:
71             _oldpwd = _curpwd
72             _curpwd = os.path.split(_curpwd)[0]
73             if _oldpwd == _curpwd:
74                 return False
75 
76 
77 def get_hg_branch(root=None):
78     """Try to get the mercurial branch of the current directory,
79     return None if not in a repo or subprocess.TimeoutExpired if timed out.
80     """
81     env = builtins.__xonsh__.env
82     timeout = env["VC_BRANCH_TIMEOUT"]
83     q = queue.Queue()
84     t = threading.Thread(target=_get_hg_root, args=(q,))
85     t.start()
86     t.join(timeout=timeout)
87     try:
88         root = q.get_nowait()
89     except queue.Empty:
90         return None
91     if env.get("VC_HG_SHOW_BRANCH"):
92         # get branch name
93         branch_path = os.path.sep.join([root, ".hg", "branch"])
94         if os.path.exists(branch_path):
95             with open(branch_path, "r") as branch_file:
96                 branch = branch_file.read()
97         else:
98             branch = "default"
99     else:
100         branch = ""
101     # add bookmark, if we can
102     bookmark_path = os.path.sep.join([root, ".hg", "bookmarks.current"])
103     if os.path.exists(bookmark_path):
104         with open(bookmark_path, "r") as bookmark_file:
105             active_bookmark = bookmark_file.read()
106         if env.get("VC_HG_SHOW_BRANCH") is True:
107             branch = "{0}, {1}".format(
108                 *(b.strip(os.linesep) for b in (branch, active_bookmark))
109             )
110         else:
111             branch = active_bookmark.strip(os.linesep)
112     else:
113         branch = branch.strip(os.linesep)
114     return branch
115 
116 
117 _FIRST_BRANCH_TIMEOUT = True
118 
119 
120 def _first_branch_timeout_message():
121     global _FIRST_BRANCH_TIMEOUT
122     sbtm = builtins.__xonsh__.env["SUPPRESS_BRANCH_TIMEOUT_MESSAGE"]
123     if not _FIRST_BRANCH_TIMEOUT or sbtm:
124         return
125     _FIRST_BRANCH_TIMEOUT = False
126     print(
127         "xonsh: branch timeout: computing the branch name, color, or both "
128         "timed out while formatting the prompt. You may avoid this by "
129         "increasing the value of $VC_BRANCH_TIMEOUT or by removing branch "
130         "fields, like {curr_branch}, from your $PROMPT. See the FAQ "
131         "for more details. This message will be suppressed for the remainder "
132         "of this session. To suppress this message permanently, set "
133         "$SUPPRESS_BRANCH_TIMEOUT_MESSAGE = True in your xonshrc file.",
134         file=sys.stderr,
135     )
136 
137 
138 def current_branch():
139     """Gets the branch for a current working directory. Returns an empty string
140     if the cwd is not a repository.  This currently only works for git and hg
141     and should be extended in the future.  If a timeout occurred, the string
142     '<branch-timeout>' is returned.
143     """
144     branch = None
145     cmds = builtins.__xonsh__.commands_cache
146     # check for binary only once
147     if cmds.is_empty():
148         has_git = bool(cmds.locate_binary("git", ignore_alias=True))
149         has_hg = bool(cmds.locate_binary("hg", ignore_alias=True))
150     else:
151         has_git = bool(cmds.lazy_locate_binary("git", ignore_alias=True))
152         has_hg = bool(cmds.lazy_locate_binary("hg", ignore_alias=True))
153     if has_git:
154         branch = get_git_branch()
155     if not branch and has_hg:
156         branch = get_hg_branch()
157     if isinstance(branch, subprocess.TimeoutExpired):
158         branch = "<branch-timeout>"
159         _first_branch_timeout_message()
160     return branch or None
161 
162 
163 def _git_dirty_working_directory(q, include_untracked):
164     status = None
165     denv = builtins.__xonsh__.env.detype()
166     try:
167         cmd = ["git", "status", "--porcelain"]
168         if include_untracked:
169             cmd.append("--untracked-files=normal")
170         else:
171             cmd.append("--untracked-files=no")
172         status = subprocess.check_output(cmd, stderr=subprocess.DEVNULL, env=denv)
173     except (subprocess.CalledProcessError, OSError, FileNotFoundError):
174         q.put(None)
175     if status is not None:
176         return q.put(bool(status))
177 
178 
179 def git_dirty_working_directory(include_untracked=False):
180     """Returns whether or not the git directory is dirty. If this could not
181     be determined (timeout, file not found, etc.) then this returns None.
182     """
183     timeout = builtins.__xonsh__.env.get("VC_BRANCH_TIMEOUT")
184     q = queue.Queue()
185     t = threading.Thread(
186         target=_git_dirty_working_directory, args=(q, include_untracked)
187     )
188     t.start()
189     t.join(timeout=timeout)
190     try:
191         return q.get_nowait()
192     except queue.Empty:
193         return None
194 
195 
196 def hg_dirty_working_directory():
197     """Computes whether or not the mercurial working directory is dirty or not.
198     If this cannot be determined, None is returned.
199     """
200     env = builtins.__xonsh__.env
201     cwd = env["PWD"]
202     denv = env.detype()
203     vcbt = env["VC_BRANCH_TIMEOUT"]
204     # Override user configurations settings and aliases
205     denv["HGRCPATH"] = ""
206     try:
207         s = subprocess.check_output(
208             ["hg", "identify", "--id"],
209             stderr=subprocess.PIPE,
210             cwd=cwd,
211             timeout=vcbt,
212             universal_newlines=True,
213             env=denv,
214         )
215         return s.strip(os.linesep).endswith("+")
216     except (
217         subprocess.CalledProcessError,
218         subprocess.TimeoutExpired,
219         FileNotFoundError,
220     ):
221         return None
222 
223 
224 def dirty_working_directory():
225     """Returns a boolean as to whether there are uncommitted files in version
226     control repository we are inside. If this cannot be determined, returns
227     None. Currently supports git and hg.
228     """
229     dwd = None
230     cmds = builtins.__xonsh__.commands_cache
231     if cmds.lazy_locate_binary("git", ignore_alias=True):
232         dwd = git_dirty_working_directory()
233     if cmds.lazy_locate_binary("hg", ignore_alias=True) and dwd is None:
234         dwd = hg_dirty_working_directory()
235     return dwd
236 
237 
238 def branch_color():
239     """Return red if the current branch is dirty, yellow if the dirtiness can
240     not be determined, and green if it clean. These are bold, intense colors
241     for the foreground.
242     """
243     dwd = dirty_working_directory()
244     if dwd is None:
245         color = "{BOLD_INTENSE_YELLOW}"
246     elif dwd:
247         color = "{BOLD_INTENSE_RED}"
248     else:
249         color = "{BOLD_INTENSE_GREEN}"
250     return color
251 
252 
253 def branch_bg_color():
254     """Return red if the current branch is dirty, yellow if the dirtiness can
255     not be determined, and green if it clean. These are background colors.
256     """
257     dwd = dirty_working_directory()
258     if dwd is None:
259         color = "{BACKGROUND_YELLOW}"
260     elif dwd:
261         color = "{BACKGROUND_RED}"
262     else:
263         color = "{BACKGROUND_GREEN}"
264     return color
265
```
--- 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/prompt/vc.py b/xonsh/prompt/vc.py
--- a/xonsh/prompt/vc.py
+++ b/xonsh/prompt/vc.py
@@ -8,8 +8,16 @@
 import builtins
 import threading
 import subprocess
+import re
 
 import xonsh.tools as xt
+from xonsh.lazyasd import LazyObject
+
+RE_REMOVE_ANSI = LazyObject(
+    lambda: re.compile(r"(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]"),
+    globals(),
+    "RE_REMOVE_ANSI",
+)
 
 
 def _get_git_branch(q):
@@ -50,6 +58,9 @@
     t.join(timeout=timeout)
     try:
         branch = q.get_nowait()
+        # branch = RE_REMOVE_ANSI.sub("", branch or "")
+        if branch:
+            branch = RE_REMOVE_ANSI.sub("", branch)
     except queue.Empty:
         branch = None
     return branch

{"golden_diff": "diff --git a/xonsh/prompt/vc.py b/xonsh/prompt/vc.py\n--- a/xonsh/prompt/vc.py\n+++ b/xonsh/prompt/vc.py\n@@ -8,8 +8,16 @@\n import builtins\n import threading\n import subprocess\n+import re\n \n import xonsh.tools as xt\n+from xonsh.lazyasd import LazyObject\n+\n+RE_REMOVE_ANSI = LazyObject(\n+    lambda: re.compile(r\"(?:\\x1B[@-_]|[\\x80-\\x9F])[0-?]*[ -/]*[@-~]\"),\n+    globals(),\n+    \"RE_REMOVE_ANSI\",\n+)\n \n \n def _get_git_branch(q):\n@@ -50,6 +58,9 @@\n     t.join(timeout=timeout)\n     try:\n         branch = q.get_nowait()\n+        # branch = RE_REMOVE_ANSI.sub(\"\", branch or \"\")\n+        if branch:\n+            branch = RE_REMOVE_ANSI.sub(\"\", branch)\n     except queue.Empty:\n         branch = None\n     return branch\n", "issue": "[color] in .gitconfig should be stripped in the prompt branch functions\nIn clean install with no `.xonshrc`, when I change into a git repo, my prompt looks like:\r\n\r\n![prompt](https://i.imgur.com/ZFOPSOj.png)\r\n\r\nIs there some setting I'm missing somewhere?\r\n\r\n## xonfig\r\n\r\n<details>\r\n\r\n```\r\n+------------------+----------------------+\r\n| xonsh            | 0.9.13.dev1          |\r\n| Git SHA          | 9f7ccc65             |\r\n| Commit Date      | Oct 15 17:14:50 2019 |\r\n| Python           | 3.7.6                |\r\n| PLY              | 3.11                 |\r\n| have readline    | True                 |\r\n| prompt toolkit   | 3.0.0                |\r\n| shell type       | prompt_toolkit2      |\r\n| pygments         | 2.5.2                |\r\n| on posix         | True                 |\r\n| on linux         | True                 |\r\n| distro           | ubuntu               |\r\n| on darwin        | False                |\r\n| on windows       | False                |\r\n| on cygwin        | False                |\r\n| on msys2         | False                |\r\n| is superuser     | False                |\r\n| default encoding | utf-8                |\r\n| xonsh encoding   | utf-8                |\r\n| encoding errors  | surrogateescape      |\r\n+------------------+----------------------+\r\n```\r\n\r\n\r\n</details>\r\n\r\n## Expected Behavior\r\nI think something like this (without the ansi escape codes):\r\n```\r\nmcrowe@mike-XPS-15-9560 ~/.dotfiles/bash_it [master] $\r\n```\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"Prompt formatter for simple version control branches\"\"\"\n# pylint:disable=no-member, invalid-name\n\nimport os\nimport sys\nimport queue\nimport builtins\nimport threading\nimport subprocess\n\nimport xonsh.tools as xt\n\n\ndef _get_git_branch(q):\n    denv = builtins.__xonsh__.env.detype()\n    try:\n        branches = xt.decode_bytes(\n            subprocess.check_output(\n                [\"git\", \"branch\"], env=denv, stderr=subprocess.DEVNULL\n            )\n        ).splitlines()\n    except (subprocess.CalledProcessError, OSError, FileNotFoundError):\n        q.put(None)\n    else:\n        for branch in branches:\n            if not branch.startswith(\"* \"):\n                continue\n            elif branch.endswith(\")\"):\n                branch = branch.split()[-1][:-1]\n            else:\n                branch = branch.split()[-1]\n\n            q.put(branch)\n            break\n        else:\n            q.put(None)\n\n\ndef get_git_branch():\n    \"\"\"Attempts to find the current git branch. If this could not\n    be determined (timeout, not in a git repo, etc.) then this returns None.\n    \"\"\"\n    branch = None\n    timeout = builtins.__xonsh__.env.get(\"VC_BRANCH_TIMEOUT\")\n    q = queue.Queue()\n\n    t = threading.Thread(target=_get_git_branch, args=(q,))\n    t.start()\n    t.join(timeout=timeout)\n    try:\n        branch = q.get_nowait()\n    except queue.Empty:\n        branch = None\n    return branch\n\n\ndef _get_hg_root(q):\n    _curpwd = builtins.__xonsh__.env[\"PWD\"]\n    while True:\n        if not os.path.isdir(_curpwd):\n            return False\n        try:\n            dot_hg_is_in_curwd = any([b.name == \".hg\" for b in xt.scandir(_curpwd)])\n        except OSError:\n            return False\n        if dot_hg_is_in_curwd:\n            q.put(_curpwd)\n            break\n        else:\n            _oldpwd = _curpwd\n            _curpwd = os.path.split(_curpwd)[0]\n            if _oldpwd == _curpwd:\n                return False\n\n\ndef get_hg_branch(root=None):\n    \"\"\"Try to get the mercurial branch of the current directory,\n    return None if not in a repo or subprocess.TimeoutExpired if timed out.\n    \"\"\"\n    env = builtins.__xonsh__.env\n    timeout = env[\"VC_BRANCH_TIMEOUT\"]\n    q = queue.Queue()\n    t = threading.Thread(target=_get_hg_root, args=(q,))\n    t.start()\n    t.join(timeout=timeout)\n    try:\n        root = q.get_nowait()\n    except queue.Empty:\n        return None\n    if env.get(\"VC_HG_SHOW_BRANCH\"):\n        # get branch name\n        branch_path = os.path.sep.join([root, \".hg\", \"branch\"])\n        if os.path.exists(branch_path):\n            with open(branch_path, \"r\") as branch_file:\n                branch = branch_file.read()\n        else:\n            branch = \"default\"\n    else:\n        branch = \"\"\n    # add bookmark, if we can\n    bookmark_path = os.path.sep.join([root, \".hg\", \"bookmarks.current\"])\n    if os.path.exists(bookmark_path):\n        with open(bookmark_path, \"r\") as bookmark_file:\n            active_bookmark = bookmark_file.read()\n        if env.get(\"VC_HG_SHOW_BRANCH\") is True:\n            branch = \"{0}, {1}\".format(\n                *(b.strip(os.linesep) for b in (branch, active_bookmark))\n            )\n        else:\n            branch = active_bookmark.strip(os.linesep)\n    else:\n        branch = branch.strip(os.linesep)\n    return branch\n\n\n_FIRST_BRANCH_TIMEOUT = True\n\n\ndef _first_branch_timeout_message():\n    global _FIRST_BRANCH_TIMEOUT\n    sbtm = builtins.__xonsh__.env[\"SUPPRESS_BRANCH_TIMEOUT_MESSAGE\"]\n    if not _FIRST_BRANCH_TIMEOUT or sbtm:\n        return\n    _FIRST_BRANCH_TIMEOUT = False\n    print(\n        \"xonsh: branch timeout: computing the branch name, color, or both \"\n        \"timed out while formatting the prompt. You may avoid this by \"\n        \"increasing the value of $VC_BRANCH_TIMEOUT or by removing branch \"\n        \"fields, like {curr_branch}, from your $PROMPT. See the FAQ \"\n        \"for more details. This message will be suppressed for the remainder \"\n        \"of this session. To suppress this message permanently, set \"\n        \"$SUPPRESS_BRANCH_TIMEOUT_MESSAGE = True in your xonshrc file.\",\n        file=sys.stderr,\n    )\n\n\ndef current_branch():\n    \"\"\"Gets the branch for a current working directory. Returns an empty string\n    if the cwd is not a repository.  This currently only works for git and hg\n    and should be extended in the future.  If a timeout occurred, the string\n    '<branch-timeout>' is returned.\n    \"\"\"\n    branch = None\n    cmds = builtins.__xonsh__.commands_cache\n    # check for binary only once\n    if cmds.is_empty():\n        has_git = bool(cmds.locate_binary(\"git\", ignore_alias=True))\n        has_hg = bool(cmds.locate_binary(\"hg\", ignore_alias=True))\n    else:\n        has_git = bool(cmds.lazy_locate_binary(\"git\", ignore_alias=True))\n        has_hg = bool(cmds.lazy_locate_binary(\"hg\", ignore_alias=True))\n    if has_git:\n        branch = get_git_branch()\n    if not branch and has_hg:\n        branch = get_hg_branch()\n    if isinstance(branch, subprocess.TimeoutExpired):\n        branch = \"<branch-timeout>\"\n        _first_branch_timeout_message()\n    return branch or None\n\n\ndef _git_dirty_working_directory(q, include_untracked):\n    status = None\n    denv = builtins.__xonsh__.env.detype()\n    try:\n        cmd = [\"git\", \"status\", \"--porcelain\"]\n        if include_untracked:\n            cmd.append(\"--untracked-files=normal\")\n        else:\n            cmd.append(\"--untracked-files=no\")\n        status = subprocess.check_output(cmd, stderr=subprocess.DEVNULL, env=denv)\n    except (subprocess.CalledProcessError, OSError, FileNotFoundError):\n        q.put(None)\n    if status is not None:\n        return q.put(bool(status))\n\n\ndef git_dirty_working_directory(include_untracked=False):\n    \"\"\"Returns whether or not the git directory is dirty. If this could not\n    be determined (timeout, file not found, etc.) then this returns None.\n    \"\"\"\n    timeout = builtins.__xonsh__.env.get(\"VC_BRANCH_TIMEOUT\")\n    q = queue.Queue()\n    t = threading.Thread(\n        target=_git_dirty_working_directory, args=(q, include_untracked)\n    )\n    t.start()\n    t.join(timeout=timeout)\n    try:\n        return q.get_nowait()\n    except queue.Empty:\n        return None\n\n\ndef hg_dirty_working_directory():\n    \"\"\"Computes whether or not the mercurial working directory is dirty or not.\n    If this cannot be determined, None is returned.\n    \"\"\"\n    env = builtins.__xonsh__.env\n    cwd = env[\"PWD\"]\n    denv = env.detype()\n    vcbt = env[\"VC_BRANCH_TIMEOUT\"]\n    # Override user configurations settings and aliases\n    denv[\"HGRCPATH\"] = \"\"\n    try:\n        s = subprocess.check_output(\n            [\"hg\", \"identify\", \"--id\"],\n            stderr=subprocess.PIPE,\n            cwd=cwd,\n            timeout=vcbt,\n            universal_newlines=True,\n            env=denv,\n        )\n        return s.strip(os.linesep).endswith(\"+\")\n    except (\n        subprocess.CalledProcessError,\n        subprocess.TimeoutExpired,\n        FileNotFoundError,\n    ):\n        return None\n\n\ndef dirty_working_directory():\n    \"\"\"Returns a boolean as to whether there are uncommitted files in version\n    control repository we are inside. If this cannot be determined, returns\n    None. Currently supports git and hg.\n    \"\"\"\n    dwd = None\n    cmds = builtins.__xonsh__.commands_cache\n    if cmds.lazy_locate_binary(\"git\", ignore_alias=True):\n        dwd = git_dirty_working_directory()\n    if cmds.lazy_locate_binary(\"hg\", ignore_alias=True) and dwd is None:\n        dwd = hg_dirty_working_directory()\n    return dwd\n\n\ndef branch_color():\n    \"\"\"Return red if the current branch is dirty, yellow if the dirtiness can\n    not be determined, and green if it clean. These are bold, intense colors\n    for the foreground.\n    \"\"\"\n    dwd = dirty_working_directory()\n    if dwd is None:\n        color = \"{BOLD_INTENSE_YELLOW}\"\n    elif dwd:\n        color = \"{BOLD_INTENSE_RED}\"\n    else:\n        color = \"{BOLD_INTENSE_GREEN}\"\n    return color\n\n\ndef branch_bg_color():\n    \"\"\"Return red if the current branch is dirty, yellow if the dirtiness can\n    not be determined, and green if it clean. These are background colors.\n    \"\"\"\n    dwd = dirty_working_directory()\n    if dwd is None:\n        color = \"{BACKGROUND_YELLOW}\"\n    elif dwd:\n        color = \"{BACKGROUND_RED}\"\n    else:\n        color = \"{BACKGROUND_GREEN}\"\n    return color\n", "path": "xonsh/prompt/vc.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"Prompt formatter for simple version control branches\"\"\"\n# pylint:disable=no-member, invalid-name\n\nimport os\nimport sys\nimport queue\nimport builtins\nimport threading\nimport subprocess\nimport re\n\nimport xonsh.tools as xt\nfrom xonsh.lazyasd import LazyObject\n\nRE_REMOVE_ANSI = LazyObject(\n    lambda: re.compile(r\"(?:\\x1B[@-_]|[\\x80-\\x9F])[0-?]*[ -/]*[@-~]\"),\n    globals(),\n    \"RE_REMOVE_ANSI\",\n)\n\n\ndef _get_git_branch(q):\n    denv = builtins.__xonsh__.env.detype()\n    try:\n        branches = xt.decode_bytes(\n            subprocess.check_output(\n                [\"git\", \"branch\"], env=denv, stderr=subprocess.DEVNULL\n            )\n        ).splitlines()\n    except (subprocess.CalledProcessError, OSError, FileNotFoundError):\n        q.put(None)\n    else:\n        for branch in branches:\n            if not branch.startswith(\"* \"):\n                continue\n            elif branch.endswith(\")\"):\n                branch = branch.split()[-1][:-1]\n            else:\n                branch = branch.split()[-1]\n\n            q.put(branch)\n            break\n        else:\n            q.put(None)\n\n\ndef get_git_branch():\n    \"\"\"Attempts to find the current git branch. If this could not\n    be determined (timeout, not in a git repo, etc.) then this returns None.\n    \"\"\"\n    branch = None\n    timeout = builtins.__xonsh__.env.get(\"VC_BRANCH_TIMEOUT\")\n    q = queue.Queue()\n\n    t = threading.Thread(target=_get_git_branch, args=(q,))\n    t.start()\n    t.join(timeout=timeout)\n    try:\n        branch = q.get_nowait()\n        # branch = RE_REMOVE_ANSI.sub(\"\", branch or \"\")\n        if branch:\n            branch = RE_REMOVE_ANSI.sub(\"\", branch)\n    except queue.Empty:\n        branch = None\n    return branch\n\n\ndef _get_hg_root(q):\n    _curpwd = builtins.__xonsh__.env[\"PWD\"]\n    while True:\n        if not os.path.isdir(_curpwd):\n            return False\n        try:\n            dot_hg_is_in_curwd = any([b.name == \".hg\" for b in xt.scandir(_curpwd)])\n        except OSError:\n            return False\n        if dot_hg_is_in_curwd:\n            q.put(_curpwd)\n            break\n        else:\n            _oldpwd = _curpwd\n            _curpwd = os.path.split(_curpwd)[0]\n            if _oldpwd == _curpwd:\n                return False\n\n\ndef get_hg_branch(root=None):\n    \"\"\"Try to get the mercurial branch of the current directory,\n    return None if not in a repo or subprocess.TimeoutExpired if timed out.\n    \"\"\"\n    env = builtins.__xonsh__.env\n    timeout = env[\"VC_BRANCH_TIMEOUT\"]\n    q = queue.Queue()\n    t = threading.Thread(target=_get_hg_root, args=(q,))\n    t.start()\n    t.join(timeout=timeout)\n    try:\n        root = q.get_nowait()\n    except queue.Empty:\n        return None\n    if env.get(\"VC_HG_SHOW_BRANCH\"):\n        # get branch name\n        branch_path = os.path.sep.join([root, \".hg\", \"branch\"])\n        if os.path.exists(branch_path):\n            with open(branch_path, \"r\") as branch_file:\n                branch = branch_file.read()\n        else:\n            branch = \"default\"\n    else:\n        branch = \"\"\n    # add bookmark, if we can\n    bookmark_path = os.path.sep.join([root, \".hg\", \"bookmarks.current\"])\n    if os.path.exists(bookmark_path):\n        with open(bookmark_path, \"r\") as bookmark_file:\n            active_bookmark = bookmark_file.read()\n        if env.get(\"VC_HG_SHOW_BRANCH\") is True:\n            branch = \"{0}, {1}\".format(\n                *(b.strip(os.linesep) for b in (branch, active_bookmark))\n            )\n        else:\n            branch = active_bookmark.strip(os.linesep)\n    else:\n        branch = branch.strip(os.linesep)\n    return branch\n\n\n_FIRST_BRANCH_TIMEOUT = True\n\n\ndef _first_branch_timeout_message():\n    global _FIRST_BRANCH_TIMEOUT\n    sbtm = builtins.__xonsh__.env[\"SUPPRESS_BRANCH_TIMEOUT_MESSAGE\"]\n    if not _FIRST_BRANCH_TIMEOUT or sbtm:\n        return\n    _FIRST_BRANCH_TIMEOUT = False\n    print(\n        \"xonsh: branch timeout: computing the branch name, color, or both \"\n        \"timed out while formatting the prompt. You may avoid this by \"\n        \"increasing the value of $VC_BRANCH_TIMEOUT or by removing branch \"\n        \"fields, like {curr_branch}, from your $PROMPT. See the FAQ \"\n        \"for more details. This message will be suppressed for the remainder \"\n        \"of this session. To suppress this message permanently, set \"\n        \"$SUPPRESS_BRANCH_TIMEOUT_MESSAGE = True in your xonshrc file.\",\n        file=sys.stderr,\n    )\n\n\ndef current_branch():\n    \"\"\"Gets the branch for a current working directory. Returns an empty string\n    if the cwd is not a repository.  This currently only works for git and hg\n    and should be extended in the future.  If a timeout occurred, the string\n    '<branch-timeout>' is returned.\n    \"\"\"\n    branch = None\n    cmds = builtins.__xonsh__.commands_cache\n    # check for binary only once\n    if cmds.is_empty():\n        has_git = bool(cmds.locate_binary(\"git\", ignore_alias=True))\n        has_hg = bool(cmds.locate_binary(\"hg\", ignore_alias=True))\n    else:\n        has_git = bool(cmds.lazy_locate_binary(\"git\", ignore_alias=True))\n        has_hg = bool(cmds.lazy_locate_binary(\"hg\", ignore_alias=True))\n    if has_git:\n        branch = get_git_branch()\n    if not branch and has_hg:\n        branch = get_hg_branch()\n    if isinstance(branch, subprocess.TimeoutExpired):\n        branch = \"<branch-timeout>\"\n        _first_branch_timeout_message()\n    return branch or None\n\n\ndef _git_dirty_working_directory(q, include_untracked):\n    status = None\n    denv = builtins.__xonsh__.env.detype()\n    try:\n        cmd = [\"git\", \"status\", \"--porcelain\"]\n        if include_untracked:\n            cmd.append(\"--untracked-files=normal\")\n        else:\n            cmd.append(\"--untracked-files=no\")\n        status = subprocess.check_output(cmd, stderr=subprocess.DEVNULL, env=denv)\n    except (subprocess.CalledProcessError, OSError, FileNotFoundError):\n        q.put(None)\n    if status is not None:\n        return q.put(bool(status))\n\n\ndef git_dirty_working_directory(include_untracked=False):\n    \"\"\"Returns whether or not the git directory is dirty. If this could not\n    be determined (timeout, file not found, etc.) then this returns None.\n    \"\"\"\n    timeout = builtins.__xonsh__.env.get(\"VC_BRANCH_TIMEOUT\")\n    q = queue.Queue()\n    t = threading.Thread(\n        target=_git_dirty_working_directory, args=(q, include_untracked)\n    )\n    t.start()\n    t.join(timeout=timeout)\n    try:\n        return q.get_nowait()\n    except queue.Empty:\n        return None\n\n\ndef hg_dirty_working_directory():\n    \"\"\"Computes whether or not the mercurial working directory is dirty or not.\n    If this cannot be determined, None is returned.\n    \"\"\"\n    env = builtins.__xonsh__.env\n    cwd = env[\"PWD\"]\n    denv = env.detype()\n    vcbt = env[\"VC_BRANCH_TIMEOUT\"]\n    # Override user configurations settings and aliases\n    denv[\"HGRCPATH\"] = \"\"\n    try:\n        s = subprocess.check_output(\n            [\"hg\", \"identify\", \"--id\"],\n            stderr=subprocess.PIPE,\n            cwd=cwd,\n            timeout=vcbt,\n            universal_newlines=True,\n            env=denv,\n        )\n        return s.strip(os.linesep).endswith(\"+\")\n    except (\n        subprocess.CalledProcessError,\n        subprocess.TimeoutExpired,\n        FileNotFoundError,\n    ):\n        return None\n\n\ndef dirty_working_directory():\n    \"\"\"Returns a boolean as to whether there are uncommitted files in version\n    control repository we are inside. If this cannot be determined, returns\n    None. Currently supports git and hg.\n    \"\"\"\n    dwd = None\n    cmds = builtins.__xonsh__.commands_cache\n    if cmds.lazy_locate_binary(\"git\", ignore_alias=True):\n        dwd = git_dirty_working_directory()\n    if cmds.lazy_locate_binary(\"hg\", ignore_alias=True) and dwd is None:\n        dwd = hg_dirty_working_directory()\n    return dwd\n\n\ndef branch_color():\n    \"\"\"Return red if the current branch is dirty, yellow if the dirtiness can\n    not be determined, and green if it clean. These are bold, intense colors\n    for the foreground.\n    \"\"\"\n    dwd = dirty_working_directory()\n    if dwd is None:\n        color = \"{BOLD_INTENSE_YELLOW}\"\n    elif dwd:\n        color = \"{BOLD_INTENSE_RED}\"\n    else:\n        color = \"{BOLD_INTENSE_GREEN}\"\n    return color\n\n\ndef branch_bg_color():\n    \"\"\"Return red if the current branch is dirty, yellow if the dirtiness can\n    not be determined, and green if it clean. These are background colors.\n    \"\"\"\n    dwd = dirty_working_directory()\n    if dwd is None:\n        color = \"{BACKGROUND_YELLOW}\"\n    elif dwd:\n        color = \"{BACKGROUND_RED}\"\n    else:\n        color = \"{BACKGROUND_GREEN}\"\n    return color\n", "path": "xonsh/prompt/vc.py"}]}