aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/tools/console/commander/commander.py40
-rw-r--r--mitmproxy/tools/console/pathedit.py71
-rw-r--r--test/mitmproxy/tools/console/test_commander.py13
-rw-r--r--test/mitmproxy/tools/console/test_pathedit.py72
4 files changed, 51 insertions, 145 deletions
diff --git a/mitmproxy/tools/console/commander/commander.py b/mitmproxy/tools/console/commander/commander.py
index dbbc8ff2..c79bc379 100644
--- a/mitmproxy/tools/console/commander/commander.py
+++ b/mitmproxy/tools/console/commander/commander.py
@@ -1,7 +1,10 @@
+import abc
+import glob
+import os
+import typing
+
import urwid
from urwid.text_layout import calc_coords
-import typing
-import abc
import mitmproxy.master
import mitmproxy.command
@@ -34,6 +37,30 @@ class ListCompleter(Completer):
return ret
+# Generates the completion options for a specific starting input
+def pathOptions(start: str) -> typing.Sequence[str]:
+ if not start:
+ start = "./"
+ path = os.path.expanduser(start)
+ ret = []
+ if os.path.isdir(path):
+ files = glob.glob(os.path.join(path, "*"))
+ prefix = start
+ else:
+ files = glob.glob(path + "*")
+ prefix = os.path.dirname(start)
+ prefix = prefix or "./"
+ for f in files:
+ display = os.path.normpath(os.path.join(prefix, os.path.basename(f)))
+ if os.path.isdir(f):
+ display += "/"
+ ret.append(display)
+ if not ret:
+ ret = [start]
+ ret.sort()
+ return ret
+
+
CompletionState = typing.NamedTuple(
"CompletionState",
[
@@ -93,6 +120,15 @@ class CommandBuffer():
),
parse = parts,
)
+ elif last.type == mitmproxy.command.Path:
+ self.completion = CompletionState(
+ completer = ListCompleter(
+ "",
+ pathOptions(parts[1].value)
+ ),
+ parse = parts,
+ )
+
if self.completion:
nxt = self.completion.completer.cycle()
buf = " ".join([i.value for i in self.completion.parse[:-1]]) + " " + nxt
diff --git a/mitmproxy/tools/console/pathedit.py b/mitmproxy/tools/console/pathedit.py
deleted file mode 100644
index 10ee1416..00000000
--- a/mitmproxy/tools/console/pathedit.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import glob
-import os.path
-
-import urwid
-
-
-class _PathCompleter:
-
- def __init__(self, _testing=False):
- """
- _testing: disables reloading of the lookup table to make testing
- possible.
- """
- self.lookup, self.offset = None, None
- self.final = None
- self._testing = _testing
-
- def reset(self):
- self.lookup = None
- self.offset = -1
-
- def complete(self, txt):
- """
- Returns the next completion for txt, or None if there is no
- completion.
- """
- path = os.path.expanduser(txt)
- if not self.lookup:
- if not self._testing:
- # Lookup is a set of (display value, actual value) tuples.
- self.lookup = []
- if os.path.isdir(path):
- files = glob.glob(os.path.join(path, "*"))
- prefix = txt
- else:
- files = glob.glob(path + "*")
- prefix = os.path.dirname(txt)
- prefix = prefix or "./"
- for f in files:
- display = os.path.join(prefix, os.path.basename(f))
- if os.path.isdir(f):
- display += "/"
- self.lookup.append((display, f))
- if not self.lookup:
- self.final = path
- return path
- self.lookup.sort()
- self.offset = -1
- self.lookup.append((txt, txt))
- self.offset += 1
- if self.offset >= len(self.lookup):
- self.offset = 0
- ret = self.lookup[self.offset]
- self.final = ret[1]
- return ret[0]
-
-
-class PathEdit(urwid.Edit, _PathCompleter):
-
- def __init__(self, prompt, last_path):
- urwid.Edit.__init__(self, prompt, last_path)
- _PathCompleter.__init__(self)
-
- def keypress(self, size, key):
- if key == "tab":
- comp = self.complete(self.get_edit_text())
- self.set_edit_text(comp)
- self.set_edit_pos(len(comp))
- else:
- self.reset()
- return urwid.Edit.keypress(self, size, key)
diff --git a/test/mitmproxy/tools/console/test_commander.py b/test/mitmproxy/tools/console/test_commander.py
index 1ac4c5c6..e8974869 100644
--- a/test/mitmproxy/tools/console/test_commander.py
+++ b/test/mitmproxy/tools/console/test_commander.py
@@ -1,5 +1,18 @@
+import os
+
from mitmproxy.tools.console.commander import commander
from mitmproxy.test import taddons
+from mitmproxy.test import tutils
+
+
+def test_pathOptions():
+ cd = os.path.normpath(tutils.test_data.path("mitmproxy/completion"))
+
+ ret = [x[len(cd):] for x in commander.pathOptions(cd)]
+ assert ret == ['/aaa', '/aab', '/aac', '/bbb/']
+
+ ret = [x[len(cd):] for x in commander.pathOptions(os.path.join(cd, "a"))]
+ assert ret == ['/aaa', '/aab', '/aac']
class TestListCompleter:
diff --git a/test/mitmproxy/tools/console/test_pathedit.py b/test/mitmproxy/tools/console/test_pathedit.py
deleted file mode 100644
index b9f51f5a..00000000
--- a/test/mitmproxy/tools/console/test_pathedit.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import os
-from os.path import normpath
-from unittest import mock
-
-from mitmproxy.tools.console import pathedit
-from mitmproxy.test import tutils
-
-
-class TestPathCompleter:
-
- def test_lookup_construction(self):
- c = pathedit._PathCompleter()
-
- cd = os.path.normpath(tutils.test_data.path("mitmproxy/completion"))
- ca = os.path.join(cd, "a")
- assert c.complete(ca).endswith(normpath("/completion/aaa"))
- assert c.complete(ca).endswith(normpath("/completion/aab"))
- c.reset()
- ca = os.path.join(cd, "aaa")
- assert c.complete(ca).endswith(normpath("/completion/aaa"))
- assert c.complete(ca).endswith(normpath("/completion/aaa"))
- c.reset()
- assert c.complete(cd).endswith(normpath("/completion/aaa"))
-
- def test_completion(self):
- c = pathedit._PathCompleter(True)
- c.reset()
- c.lookup = [
- ("a", "x/a"),
- ("aa", "x/aa"),
- ]
- assert c.complete("a") == "a"
- assert c.final == "x/a"
- assert c.complete("a") == "aa"
- assert c.complete("a") == "a"
-
- c = pathedit._PathCompleter(True)
- r = c.complete("l")
- assert c.final.endswith(r)
-
- c.reset()
- assert c.complete("/nonexistent") == "/nonexistent"
- assert c.final == "/nonexistent"
- c.reset()
- assert c.complete("~") != "~"
-
- c.reset()
- s = "thisisatotallynonexistantpathforsure"
- assert c.complete(s) == s
- assert c.final == s
-
-
-class TestPathEdit:
-
- def test_keypress(self):
-
- pe = pathedit.PathEdit("", "")
-
- with mock.patch('urwid.widget.Edit.get_edit_text') as get_text, \
- mock.patch('urwid.widget.Edit.set_edit_text') as set_text:
-
- cd = os.path.normpath(tutils.test_data.path("mitmproxy/completion"))
- get_text.return_value = os.path.join(cd, "a")
-
- # Pressing tab should set completed path
- pe.keypress((1,), "tab")
- set_text_called_with = set_text.call_args[0][0]
- assert set_text_called_with.endswith(normpath("/completion/aaa"))
-
- # Pressing any other key should reset
- pe.keypress((1,), "a")
- assert pe.lookup is None