Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap #18

Merged
merged 10 commits into from
Aug 10, 2011
11 changes: 9 additions & 2 deletions pudb/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
h - toggle highlighting
@ - toggle repetition at top
* - toggle private members
w - toggle line wrapping
n/insert - add new watch expression
enter - edit options (also to delete)

Expand Down Expand Up @@ -378,6 +379,7 @@ def change_var_state(w, size, key):
elif key == "h": iinfo.highlighted = not iinfo.highlighted
elif key == "@": iinfo.repeated_at_top = not iinfo.repeated_at_top
elif key == "*": iinfo.show_private_members = not iinfo.show_private_members
elif key == "w": iinfo.wrap = not iinfo.wrap

self.update_var_view()

Expand Down Expand Up @@ -423,6 +425,7 @@ def edit_inspector_detail(w, size, key):
iinfo.display_type == CONFIG["custom_stringifier"])


wrap_checkbox = urwid.CheckBox("Line Wrap", iinfo.wrap)
expanded_checkbox = urwid.CheckBox("Expanded", iinfo.show_detail)
highlighted_checkbox = urwid.CheckBox("Highlighted", iinfo.highlighted)
repeated_at_top_checkbox = urwid.CheckBox("Repeated at top", iinfo.repeated_at_top)
Expand All @@ -432,6 +435,7 @@ def edit_inspector_detail(w, size, key):
lb = urwid.ListBox(
id_segment+rb_grp+[
urwid.Text(""),
wrap_checkbox,
expanded_checkbox,
highlighted_checkbox,
repeated_at_top_checkbox,
Expand All @@ -442,6 +446,7 @@ def edit_inspector_detail(w, size, key):

if result == True:
iinfo.show_detail = expanded_checkbox.get_state()
iinfo.wrap = wrap_checkbox.get_state()
iinfo.highlighted = highlighted_checkbox.get_state()
iinfo.repeated_at_top = repeated_at_top_checkbox.get_state()
iinfo.show_private_members = show_private_checkbox.get_state()
Expand Down Expand Up @@ -492,6 +497,8 @@ def insert_watch(w, size, key):
self.var_list.listen("c", change_var_state)
self.var_list.listen("h", change_var_state)
self.var_list.listen("@", change_var_state)
self.var_list.listen("*", change_var_state)
self.var_list.listen("w", change_var_state)
self.var_list.listen("enter", edit_inspector_detail)
self.var_list.listen("n", insert_watch)
self.var_list.listen("insert", insert_watch)
Expand Down Expand Up @@ -884,14 +891,14 @@ def keypress(self, size, key):
show_mod(sys.modules[str(new_mod_name)])
break
else:
show_mod(sys.modules[widget.get_text()[0]])
show_mod(sys.modules[widget.base_widget.get_text()[0]])
break
elif result == False:
break
elif result == "reload":
widget, pos = lb.get_focus()
if widget is not new_mod_entry:
mod_name = widget.get_text()[0]
mod_name = widget.base_widget.get_text()[0]
mod = sys.modules[mod_name]
reload(mod)
self.message("'%s' was successfully reloaded." % mod_name)
Expand Down
30 changes: 27 additions & 3 deletions pudb/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,19 @@ def load_config():
conf_dict.setdefault("custom_theme", "")
conf_dict.setdefault("custom_stringifier", "")

conf_dict.setdefault("wrap_variables", True)

def normalize_bool_inplace(name):
try:
if conf_dict[name].lower() in ["0", "false", "off"]:
conf_dict[name] = False
else:
conf_dict[name] = True
except:
pass

normalize_bool_inplace("line_numbers")
normalize_bool_inplace("wrap_variables")

return conf_dict

Expand Down Expand Up @@ -122,6 +127,9 @@ def _update_stringifier():
pudb.var_view.custom_stringifier_dict = {}
ui.update_var_view()

def _update_wrap_variables():
ui.update_var_view()

def _update_config(check_box, new_state, option_newvalue):
option, newvalue = option_newvalue
new_conf_dict = {option: newvalue}
Expand Down Expand Up @@ -156,6 +164,10 @@ def _update_config(check_box, new_state, option_newvalue):

conf_dict.update(stringifier=newvalue)
_update_stringifier()
elif option == "wrap_variables":
new_conf_dict["wrap_variables"] = not check_box.get_state()
conf_dict.update(new_conf_dict)
_update_wrap_variables()

heading = urwid.Text("This is the preferences screen for PuDB. "
"Hit Ctrl-P at any time to get back to it.\n\n"
Expand Down Expand Up @@ -240,10 +252,18 @@ def _update_config(check_box, new_state, option_newvalue):
"The file should contain a function called pudb_stringifier() "
"at the module level, which should take a single argument and "
"return the desired string form of the object passed to it. "
"Note that the variables view will not be updated until you "
"close this dialog."),
"Note that if you choose a custom stringifier, the variables "
"view will not be updated until you close this dialog."),
]

cb_wrap_variables = urwid.CheckBox("Wrap variables",
bool(conf_dict["wrap_variables"]), on_state_change=_update_config,
user_data=("wrap_variables", None))

wrap_variables_info = urwid.Text("\nNote that you can change this option on "
"a per-variable basis by selecting the "
"variable and pressing 'w'.")

lb_contents =(
[heading]
+ [urwid.AttrMap(urwid.Text("Line Numbers:\n"), "group head")]
Expand All @@ -258,7 +278,11 @@ def _update_config(check_box, new_state, option_newvalue):
+ stack_rbs
+ [urwid.AttrMap(urwid.Text("\nVariable Stringifier:\n"), "group head")]
+ [stringifier_info]
+ stringifier_rbs)
+ stringifier_rbs
+ [urwid.AttrMap(urwid.Text("\nWrap Variables:\n"), "group head")]
+ [cb_wrap_variables]
+ [wrap_variables_info]
)

lb = urwid.ListBox(lb_contents)

Expand Down
116 changes: 96 additions & 20 deletions pudb/var_view.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

# constants and imports -------------------------------------------------------
import urwid

Expand Down Expand Up @@ -30,6 +32,7 @@ def __init__(self):
self.highlighted = False
self.repeated_at_top = False
self.show_private_members = False
self.wrap = CONFIG["wrap_variables"]

class WatchExpression(object):
def __init__(self, expression):
Expand Down Expand Up @@ -61,20 +64,41 @@ def get_str_safe_types():
# widget ----------------------------------------------------------------------
class VariableWidget(urwid.FlowWidget):
def __init__(self, prefix, var_label, value_str, id_path=None, attr_prefix=None,
watch_expr=None):
watch_expr=None, iinfo=None):
self.prefix = prefix
self.var_label = var_label
self.value_str = value_str
self.id_path = id_path
self.attr_prefix = attr_prefix or "var"
self.watch_expr = watch_expr
if iinfo is None:
self.wrap = CONFIG["wrap_variables"]
else:
self.wrap = iinfo.wrap

def selectable(self):
return True

SIZE_LIMIT = 20

def _get_text(self, size):
maxcol = size[0] - len(self.prefix) # self.prefix is a padding
var_label = self.var_label or ''
value_str = self.value_str or ''
alltext = var_label + ": " + value_str
# The first line is not indented
firstline = self.prefix + alltext[:maxcol]
if not alltext[maxcol:]:
return [firstline]
fulllines, rest = divmod(len(alltext) - maxcol, maxcol - 2)
restlines = [alltext[(maxcol - 2)*i + maxcol:(maxcol - 2)*i + 2*maxcol - 2]
for i in xrange(fulllines + bool(rest))]
return [firstline] + [" " + self.prefix + i for i in restlines]

def rows(self, size, focus=False):
if self.wrap:
return len(self._get_text(size))

if (self.value_str is not None
and self.var_label is not None
and len(self.prefix) + len(self.var_label) > self.SIZE_LIMIT):
Expand All @@ -83,12 +107,42 @@ def rows(self, size, focus=False):
return 1

def render(self, size, focus=False):
from pudb.ui_tools import make_canvas

maxcol = size[0]
if focus:
apfx = "focused "+self.attr_prefix+" "
else:
apfx = self.attr_prefix+" "

var_label = self.var_label or ''
value_str = self.value_str or ''

if self.wrap:
text = self._get_text(size)

extralabel_full, extralabel_rem = divmod(len(var_label[maxcol:]), maxcol)
totallen = sum([len(i) for i in text])
labellen = (len(self.prefix) # Padding of first line

+ (len(self.prefix) + 2) # Padding of subsequent lines
* (extralabel_full + bool(extralabel_rem))

+ len(var_label)

+ 2 # for ": "
)

_attr = [(apfx+"label", labellen), (apfx+"value", totallen - labellen)]
from urwid.util import rle_subseg

fullcols, rem = divmod(totallen, maxcol)

attr = [rle_subseg(_attr, i*maxcol, (i + 1)*maxcol)
for i in xrange(fullcols + bool(rem))]

return make_canvas(text, attr, maxcol, apfx+"value")

if self.value_str is not None:
if self.var_label is not None:
if len(self.prefix) + len(self.var_label) > self.SIZE_LIMIT:
Expand Down Expand Up @@ -117,7 +171,26 @@ def render(self, size, focus=False):

attr = [[ (apfx+"label", len(self.prefix) + len(self.var_label)), ]]

from pudb.ui_tools import make_canvas
# Ellipses to show text was cut off
encoding = urwid.util.detected_encoding

if False: # encoding[:3] == "UTF":
# Unicode is supported, use single character ellipsis
for i in xrange(len(text)):
if len(text[i]) > maxcol:
text[i] = (unicode(text[i][:maxcol-1])
+ unicode(u'…') + unicode(text[i][maxcol:]))
# XXX: This doesn't work. It just gives a ?
# Strangely, the following does work (it gives the …
# three characters from the right):
#
# text[i] = (unicode(text[i][:maxcol-3])
# + unicode(u'…')) + unicode(text[i][maxcol-2:])
else:
for i in xrange(len(text)):
if len(text[i]) > maxcol:
text[i] = text[i][:maxcol-3] + "..."

return make_canvas(text, attr, maxcol, apfx+"value")

def keypress(self, size, key):
Expand Down Expand Up @@ -164,6 +237,9 @@ def _stringifier(value):

# tree walking ----------------------------------------------------------------
class ValueWalker:

PREFIX = "| "

def __init__(self, frame_var_info):
self.frame_var_info = frame_var_info

Expand All @@ -176,7 +252,7 @@ def walk_value(self, prefix, label, value, id_path=None, attr_prefix=None):
if isinstance(value, (int, float, long, complex)):
self.add_item(prefix, label, repr(value), id_path, attr_prefix)
elif isinstance(value, (str, unicode)):
self.add_item(prefix, label, repr(value)[:200], id_path, attr_prefix)
self.add_item(prefix, label, repr(value), id_path, attr_prefix)
else:
displayed_value = get_stringifier(iinfo)(value)

Expand All @@ -193,13 +269,13 @@ def walk_value(self, prefix, label, value, id_path=None, attr_prefix=None):
cont_id_path = "%s.cont-%d" % (id_path, i)
if not self.frame_var_info.get_inspect_info(
cont_id_path, read_only=True).show_detail:
self.add_item(prefix+" ", "...", None, cont_id_path)
self.add_item(prefix+self.PREFIX, "...", None, cont_id_path)
break

self.walk_value(prefix+" ", None, entry,
self.walk_value(prefix+self.PREFIX, None, entry,
"%s[%d]" % (id_path, i))
if not value:
self.add_item(prefix+" ", "<empty>", None)
self.add_item(prefix+self.PREFIX, "<empty>", None)
return

# containers --------------------------------------------------
Expand Down Expand Up @@ -231,14 +307,14 @@ def walk_value(self, prefix, label, value, id_path=None, attr_prefix=None):
if not self.frame_var_info.get_inspect_info(
cont_id_path, read_only=True).show_detail:
self.add_item(
prefix+" ", "...", None, cont_id_path)
prefix+self.PREFIX, "...", None, cont_id_path)
break

self.walk_value(prefix+" ", repr(key), value[key],
self.walk_value(prefix+self.PREFIX, repr(key), value[key],
"%s[%r]" % (id_path, key))
cnt += 1
if not cnt:
self.add_item(prefix+" ", "<empty>", None)
self.add_item(prefix+self.PREFIX, "<empty>", None)
return

# class types -------------------------------------------------
Expand Down Expand Up @@ -274,18 +350,18 @@ def walk_value(self, prefix, label, value, id_path=None, attr_prefix=None):
except:
attr_value = WatchEvalError()

self.walk_value(prefix+" ",
self.walk_value(prefix+self.PREFIX,
".%s" % key, attr_value,
"%s.%s" % (id_path, key))

if not keys:
if cnt_omitted:
self.add_item(prefix+" ", "<omitted private attributes>", None)
self.add_item(prefix+self.PREFIX, "<omitted private attributes>", None)
else:
self.add_item(prefix+" ", "<empty>", None)
self.add_item(prefix+self.PREFIX, "<empty>", None)

if not key_its:
self.add_item(prefix+" ", "<?>", None)
self.add_item(prefix+self.PREFIX, "<?>", None)



Expand All @@ -301,8 +377,8 @@ def add_item(self, prefix, var_label, value_str, id_path=None, attr_prefix=None)
if iinfo.highlighted:
attr_prefix = "highlighted var"

self.widget_list.append(
VariableWidget(prefix, var_label, value_str, id_path, attr_prefix))
self.widget_list.append(VariableWidget(prefix, var_label, value_str,
id_path, attr_prefix, iinfo=iinfo))



Expand All @@ -320,7 +396,7 @@ def add_item(self, prefix, var_label, value_str, id_path=None, attr_prefix=None)

self.widget_list.append(
VariableWidget(prefix, var_label, value_str, id_path, attr_prefix,
watch_expr=self.watch_expr))
watch_expr=self.watch_expr, iinfo=iinfo))



Expand Down Expand Up @@ -348,11 +424,11 @@ def add_item(self, prefix, var_label, value_str, id_path=None, attr_prefix=None)
repeated_at_top = True

if repeated_at_top:
self.top_widget_list.append(
VariableWidget(prefix, var_label, value_str, id_path, attr_prefix))
self.top_widget_list.append(VariableWidget(prefix, var_label,
value_str, id_path, attr_prefix, iinfo=iinfo))

self.main_widget_list.append(
VariableWidget(prefix, var_label, value_str, id_path, attr_prefix))
self.main_widget_list.append(VariableWidget(prefix, var_label,
value_str, id_path, attr_prefix, iinfo=iinfo))



Expand Down