Repository: mitmproxy/mitmproxy

Issue:
marked less than one item ,mitmproxy will broken  
##### Steps to reproduce the problem:

1. click `m` toggle flow mark
2. click `M` toggle marked flow view
3. only **1 item** had mark,then click `m` to cancel mark.
4. click `M` return back..mitmproxy will broken.

in other words,when marked ** less than one item ** mitmproxy will broken  



##### System information


```
    Traceback (most recent call last):
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/mitmproxy/console/master.py", line 482, in run
    self.loop.run()
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/main_loop.py", line 278, in run
    self._run()
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/main_loop.py", line 376, in _run
    self.event_loop.run()
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/main_loop.py", line 682, in run
    self._loop()
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/main_loop.py", line 719, in _loop
    self._watch_files[fd]()
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/raw_display.py", line 393, in <lambda>
    event_loop, callback, self.get_available_raw_input())
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/raw_display.py", line 493, in parse_input
    callback(processed, processed_codes)
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/main_loop.py", line 403, in _update
    self.process_input(keys)
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/main_loop.py", line 503, in process_input
    k = self._topmost_widget.keypress(self.screen_size, k)
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/mitmproxy/console/window.py", line 86, in keypress
    k = super(self.__class__, self).keypress(size, k)
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/container.py", line 1128, in keypress
    return self.body.keypress( (maxcol, remaining), key )
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/mitmproxy/console/flowlist.py", line 385, in keypress
    return urwid.ListBox.keypress(self, size, key)
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/urwid/listbox.py", line 987, in keypress
    key = focus_widget.keypress((maxcol,),key)
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/mitmproxy/console/flowlist.py", line 179, in keypress
    self.state.disable_marked_filter()
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/mitmproxy/console/master.py", line 183, in disable_marked_filter
    self.set_focus_flow(nearest_marked)
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/mitmproxy/console/master.py", line 107, in set_focus_flow
    self.set_focus(self.view.index(f))
  File "/usr/local/Cellar/mitmproxy/0.18.2_1/libexec/lib/python2.7/site-packages/mitmproxy/flow/state.py", line 36, in index
    return self._list.index(f)
ValueError: None is not in list

mitmproxy has crashed!
Please lodge a bug report at:
	https://github.com/mitmproxy/mitmproxy
Shutting down...
```



Discussion:
Thanks for the report!

The good news is that this is fixed on master (at least I can't reproduce it, and the instructions are clear), the bad news is see two other bugs:

1. It is not indicated that we enter the marked flow view.
2. Entering the marked flow view without any flows being marked causes the list to go empty. Pressing `M` again does not show the flows again.

Resolving patch:
diff --git a/mitmproxy/tools/console/flowlist.py b/mitmproxy/tools/console/flowlist.py
--- a/mitmproxy/tools/console/flowlist.py
+++ b/mitmproxy/tools/console/flowlist.py
@@ -178,8 +178,6 @@ def keypress(self, xxx_todo_changeme, key):
         elif key == "m":
             self.flow.marked = not self.flow.marked
             signals.flowlist_change.send(self)
-        elif key == "M":
-            self.master.view.toggle_marked()
         elif key == "r":
             try:
                 self.master.replay_request(self.flow)
@@ -375,6 +373,8 @@ def keypress(self, size, key):
                 prompt = "Load flows",
                 callback = self.master.load_flows_callback
             )
+        elif key == "M":
+            self.master.view.toggle_marked()
         elif key == "n":
             signals.status_prompt_onekey.send(
                 prompt = "Method",
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
@@ -263,8 +263,12 @@ def redraw(self):
         else:
             arrow = common.SYMBOL_DOWN
 
+        marked = ""
+        if self.master.view.show_marked:
+            marked = "M"
+
         t = [
-            ('heading', ("%s [%s/%s]" % (arrow, offset, fc)).ljust(11)),
+            ('heading', ("%s %s [%s/%s]" % (arrow, marked, offset, fc)).ljust(11)),
         ]
 
         if self.master.server.bound:


Test patch:
diff --git a/test/mitmproxy/addons/test_view.py b/test/mitmproxy/addons/test_view.py
--- a/test/mitmproxy/addons/test_view.py
+++ b/test/mitmproxy/addons/test_view.py
@@ -123,6 +123,11 @@ def test_filter():
     v.set_filter(None)
 
     assert len(v) == 4
+    v.toggle_marked()
+    assert len(v) == 0
+    v.toggle_marked()
+    assert len(v) == 4
+
     v[1].marked = True
     v.toggle_marked()
     assert len(v) == 1