diff options
author | Aldo Cortesi <aldo@nullcube.com> | 2011-01-27 10:29:37 +1300 |
---|---|---|
committer | Aldo Cortesi <aldo@nullcube.com> | 2011-01-27 10:29:37 +1300 |
commit | 460107589c2ef425ef124c74908be1fa86ebab9d (patch) | |
tree | 75d97a6be79760524b735a4fdfea2678f560dc28 /libmproxy | |
parent | bd6c0499fb121306c7e3095ce38ddc3f5718d808 (diff) | |
download | mitmproxy-460107589c2ef425ef124c74908be1fa86ebab9d.tar.gz mitmproxy-460107589c2ef425ef124c74908be1fa86ebab9d.tar.bz2 mitmproxy-460107589c2ef425ef124c74908be1fa86ebab9d.zip |
Add tab completion for save and load path specs.
Diffstat (limited to 'libmproxy')
-rw-r--r-- | libmproxy/console.py | 83 |
1 files changed, 79 insertions, 4 deletions
diff --git a/libmproxy/console.py b/libmproxy/console.py index a986cc1c..d0213249 100644 --- a/libmproxy/console.py +++ b/libmproxy/console.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import Queue, mailcap, mimetypes, tempfile, os, subprocess +import Queue, mailcap, mimetypes, tempfile, os, subprocess, glob import os.path, sys import cStringIO import urwid.curses_display @@ -392,6 +392,70 @@ class ConnectionView(WWrap): return key +class _PathCompleter: + DEFAULTPATH = "/bin:/usr/bin:/usr/local/bin" + 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.rstrip("/") 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, *args, **kwargs): + urwid.Edit.__init__(self, *args, **kwargs) + _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) + + class ActionBar(WWrap): def __init__(self): self.message("") @@ -399,6 +463,9 @@ class ActionBar(WWrap): def selectable(self): return True + def path_prompt(self, prompt): + self.w = PathEdit(prompt) + def prompt(self, prompt): self.w = urwid.Edit(prompt) @@ -436,8 +503,11 @@ class StatusBar(WWrap): def get_edit_text(self): return self.ab.w.get_edit_text() + def path_prompt(self, prompt): + return self.ab.path_prompt(prompt) + def prompt(self, prompt): - self.ab.prompt(prompt) + return self.ab.prompt(prompt) def message(self, msg): self.ab.message(msg) @@ -786,6 +856,11 @@ class ConsoleMaster(controller.Master): self.nested = True self.make_view() + def path_prompt(self, prompt, callback): + self.statusbar.path_prompt(prompt) + self.view.set_focus("footer") + self.prompting = callback + def prompt(self, prompt, callback): self.statusbar.prompt(prompt) self.view.set_focus("footer") @@ -928,10 +1003,10 @@ class ConsoleMaster(controller.Master): else: raise Stop elif k == "S": - self.prompt("Save flows: ", self.save_flows) + self.path_prompt("Save flows: ", self.save_flows) k = None elif k == "L": - self.prompt("Load flows: ", self.load_flows) + self.path_prompt("Load flows: ", self.load_flows) k = None elif k == "c": self.prompt("Sticky cookie: ", self.set_stickycookie) |