diff options
-rw-r--r-- | becommands/comment.py | 12 | ||||
-rw-r--r-- | becommands/show.py | 13 | ||||
-rw-r--r-- | libbe/bugdir.py | 23 | ||||
-rw-r--r-- | libbe/cmdutil.py | 48 |
4 files changed, 87 insertions, 9 deletions
diff --git a/becommands/comment.py b/becommands/comment.py index 37fd37d..4f0bf3b 100644 --- a/becommands/comment.py +++ b/becommands/comment.py @@ -46,7 +46,7 @@ def execute(args): options, args = get_parser().parse_args(args) if len(args) < 1: raise cmdutil.UsageError() - bug = cmdutil.get_bug(args[0]) + bug, parent_comment = cmdutil.get_bug_and_comment(args[0]) if len(args) == 1: try: body = utility.editor_string() @@ -61,15 +61,21 @@ def execute(args): body+='\n' comment = bugdir.new_comment(bug, body) + if parent_comment is not None: + comment.in_reply_to = parent_comment.uuid comment.save() def get_parser(): - parser = cmdutil.CmdOptionParser("be comment BUG-ID COMMENT") + parser = cmdutil.CmdOptionParser("be comment ID COMMENT") return parser longhelp=""" -Add a comment to a bug. +To add a comment to a bug, use the bug ID as the argument. To reply to another +comment, specify the comment name (as shown in "be show" output). + +$EDITOR is used to launch an editor. If unspecified, no comment will be +created.) """ def help(): diff --git a/becommands/show.py b/becommands/show.py index 9e60586..db3bb90 100644 --- a/becommands/show.py +++ b/becommands/show.py @@ -30,8 +30,11 @@ def execute(args): time_str = "%s (%s)" % (utility.handy_time(bug.time), utility.time_to_str(bug.time)) print "Created: %s" % time_str - for comment in bug.list_comments(): - print "--------- Comment ---------" - print "From: %s" % comment.From - print "Date: %s\n" % utility.time_to_str(comment.date) - print comment.body.rstrip('\n') + unique_name = cmdutil.unique_name(bug, bug_dir.list()) + comments = [] + name_map = {} + for c_name, comment in cmdutil.iter_comment_name(bug, unique_name): + name_map[comment.uuid] = c_name + comments.append(comment) + threaded = bugdir.thread_comments(comments) + cmdutil.print_threaded_comments(threaded, name_map) diff --git a/libbe/bugdir.py b/libbe/bugdir.py index b78ec06..fafd1ac 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -370,7 +370,28 @@ class Comment(object): if name is None: return my_dir return os.path.join(my_dir, name) - + + +def thread_comments(comments): + child_map = {} + top_comments = [] + for comment in comments: + child_map[comment.uuid] = [] + for comment in comments: + if comment.in_reply_to is None or comment.in_reply_to not in child_map: + top_comments.append(comment) + continue + child_map[comment.in_reply_to].append(comment) + + def recurse_children(comment): + child_list = [] + for child in child_map[comment.uuid]: + child_list.append(recurse_children(child)) + return (comment, child_list) + print top_comments + return [recurse_children(c) for c in top_comments] + + def pyname_to_header(name): return name.capitalize().replace('_', '-') diff --git a/libbe/cmdutil.py b/libbe/cmdutil.py index 2f24490..3c5baae 100644 --- a/libbe/cmdutil.py +++ b/libbe/cmdutil.py @@ -19,6 +19,8 @@ import plugin import locale import os import optparse +from textwrap import TextWrapper +from StringIO import StringIO import utility def unique_name(bug, bugs): @@ -118,6 +120,34 @@ def raise_get_help(option, opt, value, parser): raise GetHelp +def iter_comment_name(bug, unique_name): + """Iterate through id, comment pairs, in date order. + (This is a user-friendly id, not the comment uuid) + """ + def key(comment): + return comment.date + for num, comment in enumerate(sorted(bug.list_comments(), key=key)): + yield ("%s:%d" % (unique_name, num+1), comment) + + +def comment_from_name(bug, unique_name, name): + """Use a comment name to look up a comment""" + for cur_name, comment in iter_comment_name(bug, unique_name): + if name == cur_name: + return comment + raise KeyError(name) + + +def get_bug_and_comment(identifier, bug_dir=None): + ids = identifier.split(':') + bug = get_bug(ids[0], bug_dir) + if len(ids) == 2: + comment = comment_from_name(bug, ids[0], identifier) + else: + comment = None + return bug, comment + + class CmdOptionParser(optparse.OptionParser): def __init__(self, usage): optparse.OptionParser.__init__(self, usage) @@ -148,6 +178,24 @@ def underlined(instring): return "%s\n%s" % (instring, "="*len(instring)) +def print_threaded_comments(comments, name_map, indent=""): + """Print a threaded display of comments""" + tw = TextWrapper(initial_indent = indent, subsequent_indent = indent, + width=80) + for comment, children in comments: + s = StringIO() + print >> s, "--------- Comment ---------" + print >> s, "Name: %s" % name_map[comment.uuid] + print >> s, "From: %s" % comment.From + print >> s, "Date: %s\n" % utility.time_to_str(comment.date) + print >> s, comment.body.rstrip('\n') + + s.seek(0) + for line in s: + print tw.fill(line).rstrip('\n') + print_threaded_comments(children, name_map, indent=indent+" ") + + def bug_tree(dir=None): """Retrieve the bug tree specified by the user. If no directory is specified, the current working directory is used. |