From 5161458217227123069911c4d2dae39fcb603720 Mon Sep 17 00:00:00 2001 From: Miroslav Date: Wed, 28 Feb 2018 00:18:18 +0200 Subject: Shortening notifications in statusbar --- mitmproxy/tools/console/master.py | 3 ++- mitmproxy/tools/console/statusbar.py | 32 +++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py index 5da6ef0b..397fc8e8 100644 --- a/mitmproxy/tools/console/master.py +++ b/mitmproxy/tools/console/master.py @@ -94,7 +94,8 @@ class ConsoleMaster(master.Master): self.start_err = entry else: signals.status_message.send( - message=(entry.level, "{}: {}".format(entry.level.title(), entry.msg)), + message=(entry.level, "{}: {}".format(entry.level.title(), + entry.msg.lstrip())), expire=5 ) diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py index 8553a66f..d4563515 100644 --- a/mitmproxy/tools/console/statusbar.py +++ b/mitmproxy/tools/console/statusbar.py @@ -49,7 +49,7 @@ class ActionBar(urwid.WidgetWrap): def sig_message(self, sender, message, expire=1): if self.prompting: return - w = urwid.Text(message) + w = urwid.Text(self.prep_message(message)) self._w = w if expire: def cb(*args): @@ -60,6 +60,36 @@ class ActionBar(urwid.WidgetWrap): def prep_prompt(self, p): return p.strip() + ": " + def prep_message(self, msg): + cols, _ = self.master.ui.get_cols_rows() + eventlog_prompt = "(more in eventlog)" + if isinstance(msg, (tuple, list)): + log_level, msg_text = msg + elif isinstance(msg, str): + log_level, msg_text = None, msg + else: + return msg + + msg_lines = msg_text.split("\n") + first_line = msg_lines[0] + + def prep_line(line, eventlog_prompt, cols): + if cols < len(eventlog_prompt) + 3: + first_line = "..." + else: + first_line = line[:cols - len(eventlog_prompt) - 3] + "..." + return first_line + + if len(msg_lines) > 1: + if len(first_line) + len(eventlog_prompt) > cols: + first_line = prep_line(first_line, eventlog_prompt, cols) + else: + if len(first_line) > cols: + first_line = prep_line(first_line, eventlog_prompt, cols) + else: + eventlog_prompt = "" + return [(log_level, first_line), ("warn", eventlog_prompt)] + def sig_prompt(self, sender, prompt, text, callback, args=()): signals.focus.send(self, section="footer") self._w = urwid.Edit(self.prep_prompt(prompt), text or "") -- cgit v1.2.3 From d151c6c32230f71146b3b1215fc2b41a4e9e880d Mon Sep 17 00:00:00 2001 From: Miroslav Date: Thu, 1 Mar 2018 01:18:05 +0200 Subject: Initial tests. New conditions. --- mitmproxy/tools/console/statusbar.py | 34 +++++++++++--------------- test/mitmproxy/tools/console/test_statusbar.py | 25 +++++++++++++++++++ 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py index d4563515..a8806b30 100644 --- a/mitmproxy/tools/console/statusbar.py +++ b/mitmproxy/tools/console/statusbar.py @@ -61,34 +61,28 @@ class ActionBar(urwid.WidgetWrap): return p.strip() + ": " def prep_message(self, msg): - cols, _ = self.master.ui.get_cols_rows() - eventlog_prompt = "(more in eventlog)" - if isinstance(msg, (tuple, list)): - log_level, msg_text = msg + if isinstance(msg, tuple): + disp_attr, msg_text = msg elif isinstance(msg, str): - log_level, msg_text = None, msg + disp_attr, msg_text = None, msg else: return msg + cols, _ = self.master.ui.get_cols_rows() + prompt = "(more in eventlog)" msg_lines = msg_text.split("\n") first_line = msg_lines[0] - def prep_line(line, eventlog_prompt, cols): - if cols < len(eventlog_prompt) + 3: - first_line = "..." - else: - first_line = line[:cols - len(eventlog_prompt) - 3] + "..." - return first_line + oneline_fits = len(first_line) > cols and len(msg_lines) == 1 + manylines_first_fits = (len(first_line) + len(prompt) > cols and + len(msg_lines) > 1) + if oneline_fits or manylines_first_fits: + shortening_index = max(0, cols - len(prompt) - 3) + first_line = first_line[:shortening_index] + "..." + elif len(msg_lines) == 1 and len(first_line) <= cols: + prompt = "" - if len(msg_lines) > 1: - if len(first_line) + len(eventlog_prompt) > cols: - first_line = prep_line(first_line, eventlog_prompt, cols) - else: - if len(first_line) > cols: - first_line = prep_line(first_line, eventlog_prompt, cols) - else: - eventlog_prompt = "" - return [(log_level, first_line), ("warn", eventlog_prompt)] + return [(disp_attr, first_line), ("warn", prompt)] def sig_prompt(self, sender, prompt, text, callback, args=()): signals.focus.send(self, section="footer") diff --git a/test/mitmproxy/tools/console/test_statusbar.py b/test/mitmproxy/tools/console/test_statusbar.py index db8a63a7..22bb761f 100644 --- a/test/mitmproxy/tools/console/test_statusbar.py +++ b/test/mitmproxy/tools/console/test_statusbar.py @@ -1,6 +1,8 @@ from mitmproxy import options from mitmproxy.tools.console import statusbar, master +from unittest import mock + def test_statusbar(monkeypatch): o = options.Options() @@ -31,3 +33,26 @@ def test_statusbar(monkeypatch): bar = statusbar.StatusBar(m) # this already causes a redraw assert bar.ib._w + + +def test_prep_message(): + o = options.Options() + m = master.ConsoleMaster(o) + m.ui = mock.MagicMock() + m.ui.get_cols_rows = mock.MagicMock(return_value=(50, 50)) + ab = statusbar.ActionBar(m) + + prep_msg = ab.prep_message("Error: Fits into statusbar") + assert prep_msg == [(None, "Error: Fits into statusbar"), ("warn", "")] + + prep_msg = ab.prep_message("Error: Doesn't fit into statusbar"*2) + assert prep_msg == [(None, "Error: Doesn't fit into statu..."), + ("warn", "(more in eventlog)")] + + prep_msg = ab.prep_message("Error: Two lines.\nFirst fits") + assert prep_msg == [(None, "Error: Two lines."), + ("warn", "(more in eventlog)")] + + prep_msg = ab.prep_message("Error: Two lines"*4 + "\nFirst doensn't fit") + assert prep_msg == [(None, "Error: Two linesError: Two li..."), + ("warn", "(more in eventlog)")] -- cgit v1.2.3 From 0dcdb6c3cc54eb11d8af55157c1910acddfa7d00 Mon Sep 17 00:00:00 2001 From: Miroslav Date: Fri, 2 Mar 2018 23:40:58 +0200 Subject: Finalization of tests. Conditions rewritten again. --- mitmproxy/tools/console/master.py | 5 +-- mitmproxy/tools/console/statusbar.py | 15 +++++---- test/mitmproxy/tools/console/test_statusbar.py | 42 ++++++++++++++------------ 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py index 397fc8e8..5cc1cf43 100644 --- a/mitmproxy/tools/console/master.py +++ b/mitmproxy/tools/console/master.py @@ -94,8 +94,9 @@ class ConsoleMaster(master.Master): self.start_err = entry else: signals.status_message.send( - message=(entry.level, "{}: {}".format(entry.level.title(), - entry.msg.lstrip())), + message=(entry.level, + "{}: {}".format(entry.level.title(), + str(entry.msg).lstrip())), expire=5 ) diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py index a8806b30..caffe4e6 100644 --- a/mitmproxy/tools/console/statusbar.py +++ b/mitmproxy/tools/console/statusbar.py @@ -72,15 +72,18 @@ class ActionBar(urwid.WidgetWrap): msg_lines = msg_text.split("\n") first_line = msg_lines[0] + if len(msg_lines) > 1: + # Messages with a few lines must end with prompt. + line_length = len(first_line) + len(prompt) + else: + line_length = len(first_line) - oneline_fits = len(first_line) > cols and len(msg_lines) == 1 - manylines_first_fits = (len(first_line) + len(prompt) > cols and - len(msg_lines) > 1) - if oneline_fits or manylines_first_fits: + if line_length > cols: shortening_index = max(0, cols - len(prompt) - 3) first_line = first_line[:shortening_index] + "..." - elif len(msg_lines) == 1 and len(first_line) <= cols: - prompt = "" + else: + if len(msg_lines) == 1: + prompt = "" return [(disp_attr, first_line), ("warn", prompt)] diff --git a/test/mitmproxy/tools/console/test_statusbar.py b/test/mitmproxy/tools/console/test_statusbar.py index 22bb761f..7b991890 100644 --- a/test/mitmproxy/tools/console/test_statusbar.py +++ b/test/mitmproxy/tools/console/test_statusbar.py @@ -1,6 +1,7 @@ +import pytest + from mitmproxy import options from mitmproxy.tools.console import statusbar, master - from unittest import mock @@ -35,24 +36,27 @@ def test_statusbar(monkeypatch): assert bar.ib._w -def test_prep_message(): - o = options.Options() - m = master.ConsoleMaster(o) - m.ui = mock.MagicMock() - m.ui.get_cols_rows = mock.MagicMock(return_value=(50, 50)) +@pytest.mark.parametrize("message,ready_message", [ + ("", [(None, ""), ("warn", "")]), + (("info", "Line fits into statusbar"), [("info", "Line fits into statusbar"), + ("warn", "")]), + ("Line doesn't fit into statusbar", [(None, "Line does..."), + ("warn", "(more in eventlog)")]), + (("alert", "Two lines.\nFirst fits"), [("alert", "Two lines."), + ("warn", "(more in eventlog)")]), + ("Two long lines\nFirst doesn't fit", [(None, "Two long ..."), + ("warn", "(more in eventlog)")]) +]) +def test_prep_message(message, ready_message): + m = mock.Mock() + m.ui.get_cols_rows.return_value = (30, 30) ab = statusbar.ActionBar(m) + assert ab.prep_message(message) == ready_message - prep_msg = ab.prep_message("Error: Fits into statusbar") - assert prep_msg == [(None, "Error: Fits into statusbar"), ("warn", "")] - prep_msg = ab.prep_message("Error: Doesn't fit into statusbar"*2) - assert prep_msg == [(None, "Error: Doesn't fit into statu..."), - ("warn", "(more in eventlog)")] - - prep_msg = ab.prep_message("Error: Two lines.\nFirst fits") - assert prep_msg == [(None, "Error: Two lines."), - ("warn", "(more in eventlog)")] - - prep_msg = ab.prep_message("Error: Two lines"*4 + "\nFirst doensn't fit") - assert prep_msg == [(None, "Error: Two linesError: Two li..."), - ("warn", "(more in eventlog)")] +def test_prep_message_narrow(): + m = mock.Mock() + m.ui.get_cols_rows.return_value = (4, 4) + ab = statusbar.ActionBar(m) + prep_msg = ab.prep_message("error") + assert prep_msg == [(None, "..."), ("warn", "(more in eventlog)")] -- cgit v1.2.3 From 63f0a712d8519401240b7f8ca5b79b363204631f Mon Sep 17 00:00:00 2001 From: Miroslav Date: Sat, 3 Mar 2018 00:32:32 +0200 Subject: Addition to the comment --- mitmproxy/tools/console/statusbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py index caffe4e6..f65031b3 100644 --- a/mitmproxy/tools/console/statusbar.py +++ b/mitmproxy/tools/console/statusbar.py @@ -73,7 +73,7 @@ class ActionBar(urwid.WidgetWrap): msg_lines = msg_text.split("\n") first_line = msg_lines[0] if len(msg_lines) > 1: - # Messages with a few lines must end with prompt. + # First line of messages with a few lines must end with prompt. line_length = len(first_line) + len(prompt) else: line_length = len(first_line) -- cgit v1.2.3 From 237320a539c90411bcc27a40a6ae30fb800cda16 Mon Sep 17 00:00:00 2001 From: Miroslav Date: Sat, 3 Mar 2018 22:12:56 +0200 Subject: Minor fixes. Renaming prep_message method to shorten_message. Docstring. \u2026 instead of .... max_width parameter. --- mitmproxy/tools/console/statusbar.py | 16 ++++++++++------ test/mitmproxy/tools/console/test_statusbar.py | 23 +++++++++++------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py index f65031b3..d601968e 100644 --- a/mitmproxy/tools/console/statusbar.py +++ b/mitmproxy/tools/console/statusbar.py @@ -49,7 +49,8 @@ class ActionBar(urwid.WidgetWrap): def sig_message(self, sender, message, expire=1): if self.prompting: return - w = urwid.Text(self.prep_message(message)) + cols, _ = self.master.ui.get_cols_rows() + w = urwid.Text(self.shorten_message(message, cols)) self._w = w if expire: def cb(*args): @@ -60,14 +61,17 @@ class ActionBar(urwid.WidgetWrap): def prep_prompt(self, p): return p.strip() + ": " - def prep_message(self, msg): + def shorten_message(self, msg, max_width): + """ + Shorten message so that it fits into a single line in the statusbar. + """ if isinstance(msg, tuple): disp_attr, msg_text = msg elif isinstance(msg, str): disp_attr, msg_text = None, msg else: return msg - cols, _ = self.master.ui.get_cols_rows() + msg_end = "\u2026" # unicode ellipsis for the end of shortened message prompt = "(more in eventlog)" msg_lines = msg_text.split("\n") @@ -78,9 +82,9 @@ class ActionBar(urwid.WidgetWrap): else: line_length = len(first_line) - if line_length > cols: - shortening_index = max(0, cols - len(prompt) - 3) - first_line = first_line[:shortening_index] + "..." + if line_length > max_width: + shortening_index = max(0, max_width - len(prompt) - len(msg_end)) + first_line = first_line[:shortening_index] + msg_end else: if len(msg_lines) == 1: prompt = "" diff --git a/test/mitmproxy/tools/console/test_statusbar.py b/test/mitmproxy/tools/console/test_statusbar.py index 7b991890..108f238e 100644 --- a/test/mitmproxy/tools/console/test_statusbar.py +++ b/test/mitmproxy/tools/console/test_statusbar.py @@ -2,7 +2,6 @@ import pytest from mitmproxy import options from mitmproxy.tools.console import statusbar, master -from unittest import mock def test_statusbar(monkeypatch): @@ -40,23 +39,23 @@ def test_statusbar(monkeypatch): ("", [(None, ""), ("warn", "")]), (("info", "Line fits into statusbar"), [("info", "Line fits into statusbar"), ("warn", "")]), - ("Line doesn't fit into statusbar", [(None, "Line does..."), + ("Line doesn't fit into statusbar", [(None, "Line doesn'\u2026"), ("warn", "(more in eventlog)")]), (("alert", "Two lines.\nFirst fits"), [("alert", "Two lines."), ("warn", "(more in eventlog)")]), - ("Two long lines\nFirst doesn't fit", [(None, "Two long ..."), + ("Two long lines\nFirst doesn't fit", [(None, "Two long li\u2026"), ("warn", "(more in eventlog)")]) ]) -def test_prep_message(message, ready_message): - m = mock.Mock() - m.ui.get_cols_rows.return_value = (30, 30) +def test_shorten_message(message, ready_message): + o = options.Options() + m = master.ConsoleMaster(o) ab = statusbar.ActionBar(m) - assert ab.prep_message(message) == ready_message + assert ab.shorten_message(message, max_width=30) == ready_message -def test_prep_message_narrow(): - m = mock.Mock() - m.ui.get_cols_rows.return_value = (4, 4) +def test_shorten_message_narrow(): + o = options.Options() + m = master.ConsoleMaster(o) ab = statusbar.ActionBar(m) - prep_msg = ab.prep_message("error") - assert prep_msg == [(None, "..."), ("warn", "(more in eventlog)")] + shorten_msg = ab.shorten_message("error", max_width=4) + assert shorten_msg == [(None, "\u2026"), ("warn", "(more in eventlog)")] -- cgit v1.2.3