Repository: mitmproxy/mitmproxy

Issue:
Options and Keybinding screen: home and end crash mitmproxy
#### Problem Description

In both the Options and Keybindings views pressing home or end will crash mitmproxy.

#### Steps to reproduce the behavior:

1.  `mitmproxy`, K, Home

or

1. `mitmproxy`, O, Home

#### System Information

```
$ mitmproxy --version
Mitmproxy: 7.0.0.dev (+449, commit 4f60e52)
Python:    3.9.2
OpenSSL:   OpenSSL 1.1.1k  25 Mar 2021
Platform:  Linux-5.10.0-kali3-amd64-x86_64-with-glibc2.31
```

```
Mitmproxy: 7.0.0.dev (+449, commit 4f60e52)
Python:    3.9.4
OpenSSL:   OpenSSL 1.1.1i  8 Dec 2020
Platform:  macOS-10.15.7-x86_64-i386-64bit
```

#### Patch

Not really sure this is perfect but this fixed it locally. I can send this as a PR if it is appropriate.

```diff
diff --git a/mitmproxy/tools/console/keybindings.py b/mitmproxy/tools/console/keybindings.py
index 312c19f94..6d08d135e 100644
--- a/mitmproxy/tools/console/keybindings.py
+++ b/mitmproxy/tools/console/keybindings.py
@@ -66,6 +66,8 @@ class KeyListWalker(urwid.ListWalker):
         self.index = index
         self.focus_obj = self._get(self.index)
         keybinding_focus_change.send(binding.help or "")
+        self._modified()
+
 
     def get_next(self, pos):
         if pos >= len(self.bindings) - 1:
@@ -79,6 +81,12 @@ class KeyListWalker(urwid.ListWalker):
             return None, None
         return self._get(pos), pos
 
+    def positions(self, reverse=False):
+        if reverse:
+            return reversed(range(len(self.bindings)))
+        else:
+            return range(len(self.bindings))
+
 
 class KeyList(urwid.ListBox):
     def __init__(self, master):
diff --git a/mitmproxy/tools/console/options.py b/mitmproxy/tools/console/options.py
index 5e5ef2a68..0c780f638 100644
--- a/mitmproxy/tools/console/options.py
+++ b/mitmproxy/tools/console/options.py
@@ -142,6 +142,8 @@ class OptionListWalker(urwid.ListWalker):
         self.index = index
         self.focus_obj = self._get(self.index, self.editing)
         option_focus_change.send(opt.help)
+        self._modified()
+
 
     def get_next(self, pos):
         if pos >= len(self.opts) - 1:
@@ -155,6 +157,11 @@ class OptionListWalker(urwid.ListWalker):
             return None, None
         return self._get(pos, False), pos
 
+    def positions(self, reverse=False):
+        if reverse:
+            return reversed(range(len(self.opts)))
+        else:
+            return range(len(self.opts))
 
 class OptionsList(urwid.ListBox):
     def __init__(self, master):
```



Discussion:

Resolving patch:
diff --git a/mitmproxy/tools/console/keybindings.py b/mitmproxy/tools/console/keybindings.py
--- a/mitmproxy/tools/console/keybindings.py
+++ b/mitmproxy/tools/console/keybindings.py
@@ -66,6 +66,7 @@ def set_focus(self, index):
         self.index = index
         self.focus_obj = self._get(self.index)
         keybinding_focus_change.send(binding.help or "")
+        self._modified()
 
     def get_next(self, pos):
         if pos >= len(self.bindings) - 1:
@@ -79,6 +80,12 @@ def get_prev(self, pos):
             return None, None
         return self._get(pos), pos
 
+    def positions(self, reverse=False):
+        if reverse:
+            return reversed(range(len(self.bindings)))
+        else:
+            return range(len(self.bindings))
+
 
 class KeyList(urwid.ListBox):
     def __init__(self, master):
diff --git a/mitmproxy/tools/console/options.py b/mitmproxy/tools/console/options.py
--- a/mitmproxy/tools/console/options.py
+++ b/mitmproxy/tools/console/options.py
@@ -142,6 +142,7 @@ def set_focus(self, index):
         self.index = index
         self.focus_obj = self._get(self.index, self.editing)
         option_focus_change.send(opt.help)
+        self._modified()
 
     def get_next(self, pos):
         if pos >= len(self.opts) - 1:
@@ -155,6 +156,12 @@ def get_prev(self, pos):
             return None, None
         return self._get(pos, False), pos
 
+    def positions(self, reverse=False):
+        if reverse:
+            return reversed(range(len(self.opts)))
+        else:
+            return range(len(self.opts))
+
 
 class OptionsList(urwid.ListBox):
     def __init__(self, master):


Test patch:
diff --git a/test/mitmproxy/tools/console/test_integration.py b/test/mitmproxy/tools/console/test_integration.py
--- a/test/mitmproxy/tools/console/test_integration.py
+++ b/test/mitmproxy/tools/console/test_integration.py
@@ -43,3 +43,11 @@ def test_integration(tdata, console):
     console.type(f":view.flows.load {tdata.path('mitmproxy/data/dumpfile-7.mitm')}<enter>")
     console.type("<enter><tab><tab>")
     console.type("<space><tab><tab>")  # view second flow
+
+
+def test_options_home_end(console):
+    console.type("O<home><end>")
+
+
+def test_keybindings_home_end(console):
+    console.type("K<home><end>")
\ No newline at end of file