We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
No shortcut for replacements editor
##### Steps to reproduce the problem:

1. run `mitmproxy`
2. type `O` to open the options editor
3. move the cursor down to `replacements` and press Enter
4. type `a` then `/~s/foo/bar` to add a replacement, and press Esc to commit
5. type `q` and again `q` to return to the flows list
6. the status bar now says “[Replacing]” with the ‘R’ highlighted, as if it were a shortcut
7. however, typing `R` doesn’t do anything

##### Any other comments? What have you tried so far?

It seems like `R` was intended to be a shortcut for the replacements editor (which would be very convenient), but left out. It’s not listed in the online help, either.

If it wasn’t intended to be a shortcut, it shouldn’t be highlighted in the status bar.

##### System information

Mitmproxy: 3.0.3 binary
Python:    3.5.2
OpenSSL:   OpenSSL 1.1.0g  2 Nov 2017
Platform:  Linux-4.4.0-116-generic-x86_64-with-debian-stretch-sid

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mitmproxy/tools/console/statusbar.py`
Content:
```
1 import os.path
2 
3 import urwid
4 
5 from mitmproxy.tools.console import common
6 from mitmproxy.tools.console import signals
7 from mitmproxy.tools.console import commandexecutor
8 import mitmproxy.tools.console.master # noqa
9 from mitmproxy.tools.console.commander import commander
10 
11 
12 class PromptPath:
13     def __init__(self, callback, args):
14         self.callback, self.args = callback, args
15 
16     def __call__(self, pth):
17         if not pth:
18             return
19         pth = os.path.expanduser(pth)
20         try:
21             return self.callback(pth, *self.args)
22         except IOError as v:
23             signals.status_message.send(message=v.strerror)
24 
25 
26 class PromptStub:
27     def __init__(self, callback, args):
28         self.callback, self.args = callback, args
29 
30     def __call__(self, txt):
31         return self.callback(txt, *self.args)
32 
33 
34 class ActionBar(urwid.WidgetWrap):
35 
36     def __init__(self, master):
37         self.master = master
38         urwid.WidgetWrap.__init__(self, None)
39         self.clear()
40         signals.status_message.connect(self.sig_message)
41         signals.status_prompt.connect(self.sig_prompt)
42         signals.status_prompt_onekey.connect(self.sig_prompt_onekey)
43         signals.status_prompt_command.connect(self.sig_prompt_command)
44 
45         self.prompting = None
46 
47         self.onekey = False
48 
49     def sig_message(self, sender, message, expire=1):
50         if self.prompting:
51             return
52         cols, _ = self.master.ui.get_cols_rows()
53         w = urwid.Text(self.shorten_message(message, cols))
54         self._w = w
55         if expire:
56             def cb(*args):
57                 if w == self._w:
58                     self.clear()
59             signals.call_in.send(seconds=expire, callback=cb)
60 
61     def prep_prompt(self, p):
62         return p.strip() + ": "
63 
64     def shorten_message(self, msg, max_width):
65         """
66         Shorten message so that it fits into a single line in the statusbar.
67         """
68         if isinstance(msg, tuple):
69             disp_attr, msg_text = msg
70         elif isinstance(msg, str):
71             disp_attr, msg_text = None, msg
72         else:
73             return msg
74         msg_end = "\u2026"  # unicode ellipsis for the end of shortened message
75         prompt = "(more in eventlog)"
76 
77         msg_lines = msg_text.split("\n")
78         first_line = msg_lines[0]
79         if len(msg_lines) > 1:
80             # First line of messages with a few lines must end with prompt.
81             line_length = len(first_line) + len(prompt)
82         else:
83             line_length = len(first_line)
84 
85         if line_length > max_width:
86             shortening_index = max(0, max_width - len(prompt) - len(msg_end))
87             first_line = first_line[:shortening_index] + msg_end
88         else:
89             if len(msg_lines) == 1:
90                 prompt = ""
91 
92         return [(disp_attr, first_line), ("warn", prompt)]
93 
94     def sig_prompt(self, sender, prompt, text, callback, args=()):
95         signals.focus.send(self, section="footer")
96         self._w = urwid.Edit(self.prep_prompt(prompt), text or "")
97         self.prompting = PromptStub(callback, args)
98 
99     def sig_prompt_command(self, sender, partial=""):
100         signals.focus.send(self, section="footer")
101         self._w = commander.CommandEdit(self.master, partial)
102         self.prompting = commandexecutor.CommandExecutor(self.master)
103 
104     def sig_prompt_onekey(self, sender, prompt, keys, callback, args=()):
105         """
106             Keys are a set of (word, key) tuples. The appropriate key in the
107             word is highlighted.
108         """
109         signals.focus.send(self, section="footer")
110         prompt = [prompt, " ("]
111         mkup = []
112         for i, e in enumerate(keys):
113             mkup.extend(common.highlight_key(e[0], e[1]))
114             if i < len(keys) - 1:
115                 mkup.append(",")
116         prompt.extend(mkup)
117         prompt.append(")? ")
118         self.onekey = set(i[1] for i in keys)
119         self._w = urwid.Edit(prompt, "")
120         self.prompting = PromptStub(callback, args)
121 
122     def selectable(self):
123         return True
124 
125     def keypress(self, size, k):
126         if self.prompting:
127             if k == "esc":
128                 self.prompt_done()
129             elif self.onekey:
130                 if k == "enter":
131                     self.prompt_done()
132                 elif k in self.onekey:
133                     self.prompt_execute(k)
134             elif k == "enter":
135                 self.prompt_execute(self._w.get_edit_text())
136             else:
137                 if common.is_keypress(k):
138                     self._w.keypress(size, k)
139                 else:
140                     return k
141 
142     def clear(self):
143         self._w = urwid.Text("")
144         self.prompting = None
145 
146     def prompt_done(self):
147         self.prompting = None
148         self.onekey = False
149         signals.status_message.send(message="")
150         signals.focus.send(self, section="body")
151 
152     def prompt_execute(self, txt):
153         p = self.prompting
154         self.prompt_done()
155         msg = p(txt)
156         if msg:
157             signals.status_message.send(message=msg, expire=1)
158 
159 
160 class StatusBar(urwid.WidgetWrap):
161     keyctx = ""
162 
163     def __init__(
164         self, master: "mitmproxy.tools.console.master.ConsoleMaster"
165     ) -> None:
166         self.master = master
167         self.ib = urwid.WidgetWrap(urwid.Text(""))
168         self.ab = ActionBar(self.master)
169         super().__init__(urwid.Pile([self.ib, self.ab]))
170         signals.update_settings.connect(self.sig_update)
171         signals.flowlist_change.connect(self.sig_update)
172         master.options.changed.connect(self.sig_update)
173         master.view.focus.sig_change.connect(self.sig_update)
174         master.view.sig_view_add.connect(self.sig_update)
175         self.redraw()
176 
177     def sig_update(self, sender, flow=None, updated=None):
178         self.redraw()
179 
180     def keypress(self, *args, **kwargs):
181         return self.ab.keypress(*args, **kwargs)
182 
183     def get_status(self):
184         r = []
185 
186         sreplay = self.master.addons.get("serverplayback")
187         creplay = self.master.addons.get("clientplayback")
188 
189         if len(self.master.options.setheaders):
190             r.append("[")
191             r.append(("heading_key", "H"))
192             r.append("eaders]")
193         if len(self.master.options.replacements):
194             r.append("[")
195             r.append(("heading_key", "R"))
196             r.append("eplacing]")
197         if creplay.count():
198             r.append("[")
199             r.append(("heading_key", "cplayback"))
200             r.append(":%s]" % creplay.count())
201         if sreplay.count():
202             r.append("[")
203             r.append(("heading_key", "splayback"))
204             r.append(":%s]" % sreplay.count())
205         if self.master.options.ignore_hosts:
206             r.append("[")
207             r.append(("heading_key", "I"))
208             r.append("gnore:%d]" % len(self.master.options.ignore_hosts))
209         if self.master.options.tcp_hosts:
210             r.append("[")
211             r.append(("heading_key", "T"))
212             r.append("CP:%d]" % len(self.master.options.tcp_hosts))
213         if self.master.options.intercept:
214             r.append("[")
215             if not self.master.options.intercept_active:
216                 r.append("X")
217             r.append(("heading_key", "i"))
218             r.append(":%s]" % self.master.options.intercept)
219         if self.master.options.view_filter:
220             r.append("[")
221             r.append(("heading_key", "f"))
222             r.append(":%s]" % self.master.options.view_filter)
223         if self.master.options.stickycookie:
224             r.append("[")
225             r.append(("heading_key", "t"))
226             r.append(":%s]" % self.master.options.stickycookie)
227         if self.master.options.stickyauth:
228             r.append("[")
229             r.append(("heading_key", "u"))
230             r.append(":%s]" % self.master.options.stickyauth)
231         if self.master.options.console_default_contentview != 'auto':
232             r.append("[contentview:%s]" % (self.master.options.console_default_contentview))
233         if self.master.options.has_changed("view_order"):
234             r.append("[")
235             r.append(("heading_key", "o"))
236             r.append(":%s]" % self.master.options.view_order)
237 
238         opts = []
239         if self.master.options.anticache:
240             opts.append("anticache")
241         if self.master.options.anticomp:
242             opts.append("anticomp")
243         if self.master.options.showhost:
244             opts.append("showhost")
245         if not self.master.options.server_replay_refresh:
246             opts.append("norefresh")
247         if self.master.options.server_replay_kill_extra:
248             opts.append("killextra")
249         if not self.master.options.upstream_cert:
250             opts.append("no-upstream-cert")
251         if self.master.options.console_focus_follow:
252             opts.append("following")
253         if self.master.options.stream_large_bodies:
254             opts.append(self.master.options.stream_large_bodies)
255 
256         if opts:
257             r.append("[%s]" % (":".join(opts)))
258 
259         if self.master.options.mode != "regular":
260             r.append("[%s]" % self.master.options.mode)
261         if self.master.options.scripts:
262             r.append("[scripts:%s]" % len(self.master.options.scripts))
263 
264         if self.master.options.save_stream_file:
265             r.append("[W:%s]" % self.master.options.save_stream_file)
266 
267         return r
268 
269     def redraw(self):
270         fc = len(self.master.view)
271         if self.master.view.focus.flow is None:
272             offset = 0
273         else:
274             offset = self.master.view.focus.index + 1
275 
276         if self.master.options.view_order_reversed:
277             arrow = common.SYMBOL_UP
278         else:
279             arrow = common.SYMBOL_DOWN
280 
281         marked = ""
282         if self.master.view.show_marked:
283             marked = "M"
284 
285         t = [
286             ('heading', ("%s %s [%s/%s]" % (arrow, marked, offset, fc)).ljust(11)),
287         ]
288 
289         if self.master.options.server:
290             host = self.master.options.listen_host
291             if host == "0.0.0.0" or host == "":
292                 host = "*"
293             boundaddr = "[%s:%s]" % (host, self.master.options.listen_port)
294         else:
295             boundaddr = ""
296         t.extend(self.get_status())
297         status = urwid.AttrWrap(urwid.Columns([
298             urwid.Text(t),
299             urwid.Text(boundaddr, align="right"),
300         ]), "heading")
301         self.ib._w = status
302 
303     def selectable(self):
304         return True
305
```
--- 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/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py
--- a/mitmproxy/tools/console/statusbar.py
+++ b/mitmproxy/tools/console/statusbar.py
@@ -191,9 +191,7 @@
             r.append(("heading_key", "H"))
             r.append("eaders]")
         if len(self.master.options.replacements):
-            r.append("[")
-            r.append(("heading_key", "R"))
-            r.append("eplacing]")
+            r.append("[%d replacements]" % len(self.master.options.replacements))
         if creplay.count():
             r.append("[")
             r.append(("heading_key", "cplayback"))

{"golden_diff": "diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py\n--- a/mitmproxy/tools/console/statusbar.py\n+++ b/mitmproxy/tools/console/statusbar.py\n@@ -191,9 +191,7 @@\n             r.append((\"heading_key\", \"H\"))\n             r.append(\"eaders]\")\n         if len(self.master.options.replacements):\n-            r.append(\"[\")\n-            r.append((\"heading_key\", \"R\"))\n-            r.append(\"eplacing]\")\n+            r.append(\"[%d replacements]\" % len(self.master.options.replacements))\n         if creplay.count():\n             r.append(\"[\")\n             r.append((\"heading_key\", \"cplayback\"))\n", "issue": "No shortcut for replacements editor\n##### Steps to reproduce the problem:\r\n\r\n1. run `mitmproxy`\r\n2. type `O` to open the options editor\r\n3. move the cursor down to `replacements` and press Enter\r\n4. type `a` then `/~s/foo/bar` to add a replacement, and press Esc to commit\r\n5. type `q` and again `q` to return to the flows list\r\n6. the status bar now says \u201c[Replacing]\u201d with the \u2018R\u2019 highlighted, as if it were a shortcut\r\n7. however, typing `R` doesn\u2019t do anything\r\n\r\n##### Any other comments? What have you tried so far?\r\n\r\nIt seems like `R` was intended to be a shortcut for the replacements editor (which would be very convenient), but left out. It\u2019s not listed in the online help, either.\r\n\r\nIf it wasn\u2019t intended to be a shortcut, it shouldn\u2019t be highlighted in the status bar.\r\n\r\n##### System information\r\n\r\nMitmproxy: 3.0.3 binary\r\nPython:    3.5.2\r\nOpenSSL:   OpenSSL 1.1.0g  2 Nov 2017\r\nPlatform:  Linux-4.4.0-116-generic-x86_64-with-debian-stretch-sid\n", "before_files": [{"content": "import os.path\n\nimport urwid\n\nfrom mitmproxy.tools.console import common\nfrom mitmproxy.tools.console import signals\nfrom mitmproxy.tools.console import commandexecutor\nimport mitmproxy.tools.console.master # noqa\nfrom mitmproxy.tools.console.commander import commander\n\n\nclass PromptPath:\n    def __init__(self, callback, args):\n        self.callback, self.args = callback, args\n\n    def __call__(self, pth):\n        if not pth:\n            return\n        pth = os.path.expanduser(pth)\n        try:\n            return self.callback(pth, *self.args)\n        except IOError as v:\n            signals.status_message.send(message=v.strerror)\n\n\nclass PromptStub:\n    def __init__(self, callback, args):\n        self.callback, self.args = callback, args\n\n    def __call__(self, txt):\n        return self.callback(txt, *self.args)\n\n\nclass ActionBar(urwid.WidgetWrap):\n\n    def __init__(self, master):\n        self.master = master\n        urwid.WidgetWrap.__init__(self, None)\n        self.clear()\n        signals.status_message.connect(self.sig_message)\n        signals.status_prompt.connect(self.sig_prompt)\n        signals.status_prompt_onekey.connect(self.sig_prompt_onekey)\n        signals.status_prompt_command.connect(self.sig_prompt_command)\n\n        self.prompting = None\n\n        self.onekey = False\n\n    def sig_message(self, sender, message, expire=1):\n        if self.prompting:\n            return\n        cols, _ = self.master.ui.get_cols_rows()\n        w = urwid.Text(self.shorten_message(message, cols))\n        self._w = w\n        if expire:\n            def cb(*args):\n                if w == self._w:\n                    self.clear()\n            signals.call_in.send(seconds=expire, callback=cb)\n\n    def prep_prompt(self, p):\n        return p.strip() + \": \"\n\n    def shorten_message(self, msg, max_width):\n        \"\"\"\n        Shorten message so that it fits into a single line in the statusbar.\n        \"\"\"\n        if isinstance(msg, tuple):\n            disp_attr, msg_text = msg\n        elif isinstance(msg, str):\n            disp_attr, msg_text = None, msg\n        else:\n            return msg\n        msg_end = \"\\u2026\"  # unicode ellipsis for the end of shortened message\n        prompt = \"(more in eventlog)\"\n\n        msg_lines = msg_text.split(\"\\n\")\n        first_line = msg_lines[0]\n        if len(msg_lines) > 1:\n            # First line of messages with a few lines must end with prompt.\n            line_length = len(first_line) + len(prompt)\n        else:\n            line_length = len(first_line)\n\n        if line_length > max_width:\n            shortening_index = max(0, max_width - len(prompt) - len(msg_end))\n            first_line = first_line[:shortening_index] + msg_end\n        else:\n            if len(msg_lines) == 1:\n                prompt = \"\"\n\n        return [(disp_attr, first_line), (\"warn\", prompt)]\n\n    def sig_prompt(self, sender, prompt, text, callback, args=()):\n        signals.focus.send(self, section=\"footer\")\n        self._w = urwid.Edit(self.prep_prompt(prompt), text or \"\")\n        self.prompting = PromptStub(callback, args)\n\n    def sig_prompt_command(self, sender, partial=\"\"):\n        signals.focus.send(self, section=\"footer\")\n        self._w = commander.CommandEdit(self.master, partial)\n        self.prompting = commandexecutor.CommandExecutor(self.master)\n\n    def sig_prompt_onekey(self, sender, prompt, keys, callback, args=()):\n        \"\"\"\n            Keys are a set of (word, key) tuples. The appropriate key in the\n            word is highlighted.\n        \"\"\"\n        signals.focus.send(self, section=\"footer\")\n        prompt = [prompt, \" (\"]\n        mkup = []\n        for i, e in enumerate(keys):\n            mkup.extend(common.highlight_key(e[0], e[1]))\n            if i < len(keys) - 1:\n                mkup.append(\",\")\n        prompt.extend(mkup)\n        prompt.append(\")? \")\n        self.onekey = set(i[1] for i in keys)\n        self._w = urwid.Edit(prompt, \"\")\n        self.prompting = PromptStub(callback, args)\n\n    def selectable(self):\n        return True\n\n    def keypress(self, size, k):\n        if self.prompting:\n            if k == \"esc\":\n                self.prompt_done()\n            elif self.onekey:\n                if k == \"enter\":\n                    self.prompt_done()\n                elif k in self.onekey:\n                    self.prompt_execute(k)\n            elif k == \"enter\":\n                self.prompt_execute(self._w.get_edit_text())\n            else:\n                if common.is_keypress(k):\n                    self._w.keypress(size, k)\n                else:\n                    return k\n\n    def clear(self):\n        self._w = urwid.Text(\"\")\n        self.prompting = None\n\n    def prompt_done(self):\n        self.prompting = None\n        self.onekey = False\n        signals.status_message.send(message=\"\")\n        signals.focus.send(self, section=\"body\")\n\n    def prompt_execute(self, txt):\n        p = self.prompting\n        self.prompt_done()\n        msg = p(txt)\n        if msg:\n            signals.status_message.send(message=msg, expire=1)\n\n\nclass StatusBar(urwid.WidgetWrap):\n    keyctx = \"\"\n\n    def __init__(\n        self, master: \"mitmproxy.tools.console.master.ConsoleMaster\"\n    ) -> None:\n        self.master = master\n        self.ib = urwid.WidgetWrap(urwid.Text(\"\"))\n        self.ab = ActionBar(self.master)\n        super().__init__(urwid.Pile([self.ib, self.ab]))\n        signals.update_settings.connect(self.sig_update)\n        signals.flowlist_change.connect(self.sig_update)\n        master.options.changed.connect(self.sig_update)\n        master.view.focus.sig_change.connect(self.sig_update)\n        master.view.sig_view_add.connect(self.sig_update)\n        self.redraw()\n\n    def sig_update(self, sender, flow=None, updated=None):\n        self.redraw()\n\n    def keypress(self, *args, **kwargs):\n        return self.ab.keypress(*args, **kwargs)\n\n    def get_status(self):\n        r = []\n\n        sreplay = self.master.addons.get(\"serverplayback\")\n        creplay = self.master.addons.get(\"clientplayback\")\n\n        if len(self.master.options.setheaders):\n            r.append(\"[\")\n            r.append((\"heading_key\", \"H\"))\n            r.append(\"eaders]\")\n        if len(self.master.options.replacements):\n            r.append(\"[\")\n            r.append((\"heading_key\", \"R\"))\n            r.append(\"eplacing]\")\n        if creplay.count():\n            r.append(\"[\")\n            r.append((\"heading_key\", \"cplayback\"))\n            r.append(\":%s]\" % creplay.count())\n        if sreplay.count():\n            r.append(\"[\")\n            r.append((\"heading_key\", \"splayback\"))\n            r.append(\":%s]\" % sreplay.count())\n        if self.master.options.ignore_hosts:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"I\"))\n            r.append(\"gnore:%d]\" % len(self.master.options.ignore_hosts))\n        if self.master.options.tcp_hosts:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"T\"))\n            r.append(\"CP:%d]\" % len(self.master.options.tcp_hosts))\n        if self.master.options.intercept:\n            r.append(\"[\")\n            if not self.master.options.intercept_active:\n                r.append(\"X\")\n            r.append((\"heading_key\", \"i\"))\n            r.append(\":%s]\" % self.master.options.intercept)\n        if self.master.options.view_filter:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"f\"))\n            r.append(\":%s]\" % self.master.options.view_filter)\n        if self.master.options.stickycookie:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"t\"))\n            r.append(\":%s]\" % self.master.options.stickycookie)\n        if self.master.options.stickyauth:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"u\"))\n            r.append(\":%s]\" % self.master.options.stickyauth)\n        if self.master.options.console_default_contentview != 'auto':\n            r.append(\"[contentview:%s]\" % (self.master.options.console_default_contentview))\n        if self.master.options.has_changed(\"view_order\"):\n            r.append(\"[\")\n            r.append((\"heading_key\", \"o\"))\n            r.append(\":%s]\" % self.master.options.view_order)\n\n        opts = []\n        if self.master.options.anticache:\n            opts.append(\"anticache\")\n        if self.master.options.anticomp:\n            opts.append(\"anticomp\")\n        if self.master.options.showhost:\n            opts.append(\"showhost\")\n        if not self.master.options.server_replay_refresh:\n            opts.append(\"norefresh\")\n        if self.master.options.server_replay_kill_extra:\n            opts.append(\"killextra\")\n        if not self.master.options.upstream_cert:\n            opts.append(\"no-upstream-cert\")\n        if self.master.options.console_focus_follow:\n            opts.append(\"following\")\n        if self.master.options.stream_large_bodies:\n            opts.append(self.master.options.stream_large_bodies)\n\n        if opts:\n            r.append(\"[%s]\" % (\":\".join(opts)))\n\n        if self.master.options.mode != \"regular\":\n            r.append(\"[%s]\" % self.master.options.mode)\n        if self.master.options.scripts:\n            r.append(\"[scripts:%s]\" % len(self.master.options.scripts))\n\n        if self.master.options.save_stream_file:\n            r.append(\"[W:%s]\" % self.master.options.save_stream_file)\n\n        return r\n\n    def redraw(self):\n        fc = len(self.master.view)\n        if self.master.view.focus.flow is None:\n            offset = 0\n        else:\n            offset = self.master.view.focus.index + 1\n\n        if self.master.options.view_order_reversed:\n            arrow = common.SYMBOL_UP\n        else:\n            arrow = common.SYMBOL_DOWN\n\n        marked = \"\"\n        if self.master.view.show_marked:\n            marked = \"M\"\n\n        t = [\n            ('heading', (\"%s %s [%s/%s]\" % (arrow, marked, offset, fc)).ljust(11)),\n        ]\n\n        if self.master.options.server:\n            host = self.master.options.listen_host\n            if host == \"0.0.0.0\" or host == \"\":\n                host = \"*\"\n            boundaddr = \"[%s:%s]\" % (host, self.master.options.listen_port)\n        else:\n            boundaddr = \"\"\n        t.extend(self.get_status())\n        status = urwid.AttrWrap(urwid.Columns([\n            urwid.Text(t),\n            urwid.Text(boundaddr, align=\"right\"),\n        ]), \"heading\")\n        self.ib._w = status\n\n    def selectable(self):\n        return True\n", "path": "mitmproxy/tools/console/statusbar.py"}], "after_files": [{"content": "import os.path\n\nimport urwid\n\nfrom mitmproxy.tools.console import common\nfrom mitmproxy.tools.console import signals\nfrom mitmproxy.tools.console import commandexecutor\nimport mitmproxy.tools.console.master # noqa\nfrom mitmproxy.tools.console.commander import commander\n\n\nclass PromptPath:\n    def __init__(self, callback, args):\n        self.callback, self.args = callback, args\n\n    def __call__(self, pth):\n        if not pth:\n            return\n        pth = os.path.expanduser(pth)\n        try:\n            return self.callback(pth, *self.args)\n        except IOError as v:\n            signals.status_message.send(message=v.strerror)\n\n\nclass PromptStub:\n    def __init__(self, callback, args):\n        self.callback, self.args = callback, args\n\n    def __call__(self, txt):\n        return self.callback(txt, *self.args)\n\n\nclass ActionBar(urwid.WidgetWrap):\n\n    def __init__(self, master):\n        self.master = master\n        urwid.WidgetWrap.__init__(self, None)\n        self.clear()\n        signals.status_message.connect(self.sig_message)\n        signals.status_prompt.connect(self.sig_prompt)\n        signals.status_prompt_onekey.connect(self.sig_prompt_onekey)\n        signals.status_prompt_command.connect(self.sig_prompt_command)\n\n        self.prompting = None\n\n        self.onekey = False\n\n    def sig_message(self, sender, message, expire=1):\n        if self.prompting:\n            return\n        cols, _ = self.master.ui.get_cols_rows()\n        w = urwid.Text(self.shorten_message(message, cols))\n        self._w = w\n        if expire:\n            def cb(*args):\n                if w == self._w:\n                    self.clear()\n            signals.call_in.send(seconds=expire, callback=cb)\n\n    def prep_prompt(self, p):\n        return p.strip() + \": \"\n\n    def shorten_message(self, msg, max_width):\n        \"\"\"\n        Shorten message so that it fits into a single line in the statusbar.\n        \"\"\"\n        if isinstance(msg, tuple):\n            disp_attr, msg_text = msg\n        elif isinstance(msg, str):\n            disp_attr, msg_text = None, msg\n        else:\n            return msg\n        msg_end = \"\\u2026\"  # unicode ellipsis for the end of shortened message\n        prompt = \"(more in eventlog)\"\n\n        msg_lines = msg_text.split(\"\\n\")\n        first_line = msg_lines[0]\n        if len(msg_lines) > 1:\n            # First line of messages with a few lines must end with prompt.\n            line_length = len(first_line) + len(prompt)\n        else:\n            line_length = len(first_line)\n\n        if line_length > max_width:\n            shortening_index = max(0, max_width - len(prompt) - len(msg_end))\n            first_line = first_line[:shortening_index] + msg_end\n        else:\n            if len(msg_lines) == 1:\n                prompt = \"\"\n\n        return [(disp_attr, first_line), (\"warn\", prompt)]\n\n    def sig_prompt(self, sender, prompt, text, callback, args=()):\n        signals.focus.send(self, section=\"footer\")\n        self._w = urwid.Edit(self.prep_prompt(prompt), text or \"\")\n        self.prompting = PromptStub(callback, args)\n\n    def sig_prompt_command(self, sender, partial=\"\"):\n        signals.focus.send(self, section=\"footer\")\n        self._w = commander.CommandEdit(self.master, partial)\n        self.prompting = commandexecutor.CommandExecutor(self.master)\n\n    def sig_prompt_onekey(self, sender, prompt, keys, callback, args=()):\n        \"\"\"\n            Keys are a set of (word, key) tuples. The appropriate key in the\n            word is highlighted.\n        \"\"\"\n        signals.focus.send(self, section=\"footer\")\n        prompt = [prompt, \" (\"]\n        mkup = []\n        for i, e in enumerate(keys):\n            mkup.extend(common.highlight_key(e[0], e[1]))\n            if i < len(keys) - 1:\n                mkup.append(\",\")\n        prompt.extend(mkup)\n        prompt.append(\")? \")\n        self.onekey = set(i[1] for i in keys)\n        self._w = urwid.Edit(prompt, \"\")\n        self.prompting = PromptStub(callback, args)\n\n    def selectable(self):\n        return True\n\n    def keypress(self, size, k):\n        if self.prompting:\n            if k == \"esc\":\n                self.prompt_done()\n            elif self.onekey:\n                if k == \"enter\":\n                    self.prompt_done()\n                elif k in self.onekey:\n                    self.prompt_execute(k)\n            elif k == \"enter\":\n                self.prompt_execute(self._w.get_edit_text())\n            else:\n                if common.is_keypress(k):\n                    self._w.keypress(size, k)\n                else:\n                    return k\n\n    def clear(self):\n        self._w = urwid.Text(\"\")\n        self.prompting = None\n\n    def prompt_done(self):\n        self.prompting = None\n        self.onekey = False\n        signals.status_message.send(message=\"\")\n        signals.focus.send(self, section=\"body\")\n\n    def prompt_execute(self, txt):\n        p = self.prompting\n        self.prompt_done()\n        msg = p(txt)\n        if msg:\n            signals.status_message.send(message=msg, expire=1)\n\n\nclass StatusBar(urwid.WidgetWrap):\n    keyctx = \"\"\n\n    def __init__(\n        self, master: \"mitmproxy.tools.console.master.ConsoleMaster\"\n    ) -> None:\n        self.master = master\n        self.ib = urwid.WidgetWrap(urwid.Text(\"\"))\n        self.ab = ActionBar(self.master)\n        super().__init__(urwid.Pile([self.ib, self.ab]))\n        signals.update_settings.connect(self.sig_update)\n        signals.flowlist_change.connect(self.sig_update)\n        master.options.changed.connect(self.sig_update)\n        master.view.focus.sig_change.connect(self.sig_update)\n        master.view.sig_view_add.connect(self.sig_update)\n        self.redraw()\n\n    def sig_update(self, sender, flow=None, updated=None):\n        self.redraw()\n\n    def keypress(self, *args, **kwargs):\n        return self.ab.keypress(*args, **kwargs)\n\n    def get_status(self):\n        r = []\n\n        sreplay = self.master.addons.get(\"serverplayback\")\n        creplay = self.master.addons.get(\"clientplayback\")\n\n        if len(self.master.options.setheaders):\n            r.append(\"[\")\n            r.append((\"heading_key\", \"H\"))\n            r.append(\"eaders]\")\n        if len(self.master.options.replacements):\n            r.append(\"[%d replacements]\" % len(self.master.options.replacements))\n        if creplay.count():\n            r.append(\"[\")\n            r.append((\"heading_key\", \"cplayback\"))\n            r.append(\":%s]\" % creplay.count())\n        if sreplay.count():\n            r.append(\"[\")\n            r.append((\"heading_key\", \"splayback\"))\n            r.append(\":%s]\" % sreplay.count())\n        if self.master.options.ignore_hosts:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"I\"))\n            r.append(\"gnore:%d]\" % len(self.master.options.ignore_hosts))\n        if self.master.options.tcp_hosts:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"T\"))\n            r.append(\"CP:%d]\" % len(self.master.options.tcp_hosts))\n        if self.master.options.intercept:\n            r.append(\"[\")\n            if not self.master.options.intercept_active:\n                r.append(\"X\")\n            r.append((\"heading_key\", \"i\"))\n            r.append(\":%s]\" % self.master.options.intercept)\n        if self.master.options.view_filter:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"f\"))\n            r.append(\":%s]\" % self.master.options.view_filter)\n        if self.master.options.stickycookie:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"t\"))\n            r.append(\":%s]\" % self.master.options.stickycookie)\n        if self.master.options.stickyauth:\n            r.append(\"[\")\n            r.append((\"heading_key\", \"u\"))\n            r.append(\":%s]\" % self.master.options.stickyauth)\n        if self.master.options.console_default_contentview != 'auto':\n            r.append(\"[contentview:%s]\" % (self.master.options.console_default_contentview))\n        if self.master.options.has_changed(\"view_order\"):\n            r.append(\"[\")\n            r.append((\"heading_key\", \"o\"))\n            r.append(\":%s]\" % self.master.options.view_order)\n\n        opts = []\n        if self.master.options.anticache:\n            opts.append(\"anticache\")\n        if self.master.options.anticomp:\n            opts.append(\"anticomp\")\n        if self.master.options.showhost:\n            opts.append(\"showhost\")\n        if not self.master.options.server_replay_refresh:\n            opts.append(\"norefresh\")\n        if self.master.options.server_replay_kill_extra:\n            opts.append(\"killextra\")\n        if not self.master.options.upstream_cert:\n            opts.append(\"no-upstream-cert\")\n        if self.master.options.console_focus_follow:\n            opts.append(\"following\")\n        if self.master.options.stream_large_bodies:\n            opts.append(self.master.options.stream_large_bodies)\n\n        if opts:\n            r.append(\"[%s]\" % (\":\".join(opts)))\n\n        if self.master.options.mode != \"regular\":\n            r.append(\"[%s]\" % self.master.options.mode)\n        if self.master.options.scripts:\n            r.append(\"[scripts:%s]\" % len(self.master.options.scripts))\n\n        if self.master.options.save_stream_file:\n            r.append(\"[W:%s]\" % self.master.options.save_stream_file)\n\n        return r\n\n    def redraw(self):\n        fc = len(self.master.view)\n        if self.master.view.focus.flow is None:\n            offset = 0\n        else:\n            offset = self.master.view.focus.index + 1\n\n        if self.master.options.view_order_reversed:\n            arrow = common.SYMBOL_UP\n        else:\n            arrow = common.SYMBOL_DOWN\n\n        marked = \"\"\n        if self.master.view.show_marked:\n            marked = \"M\"\n\n        t = [\n            ('heading', (\"%s %s [%s/%s]\" % (arrow, marked, offset, fc)).ljust(11)),\n        ]\n\n        if self.master.options.server:\n            host = self.master.options.listen_host\n            if host == \"0.0.0.0\" or host == \"\":\n                host = \"*\"\n            boundaddr = \"[%s:%s]\" % (host, self.master.options.listen_port)\n        else:\n            boundaddr = \"\"\n        t.extend(self.get_status())\n        status = urwid.AttrWrap(urwid.Columns([\n            urwid.Text(t),\n            urwid.Text(boundaddr, align=\"right\"),\n        ]), \"heading\")\n        self.ib._w = status\n\n    def selectable(self):\n        return True\n", "path": "mitmproxy/tools/console/statusbar.py"}]}