Full detail view of an issue including body and comments.
(issue: dict, brief: bool = False)
| 199 | |
| 200 | |
| 201 | def format_detail(issue: dict, brief: bool = False) -> str: |
| 202 | """Full detail view of an issue including body and comments.""" |
| 203 | lines = [ |
| 204 | f"#{issue['number']}: {issue['title']}", |
| 205 | f"State: {issue['state']} Author: {issue['author']} " |
| 206 | f"Created: {issue['created_at'][:10]} Updated: {issue['updated_at'][:10]}", |
| 207 | f"Labels: {', '.join(issue['labels']) or 'none'}", |
| 208 | f"Assignees: {', '.join(issue['assignees']) or 'none'}", |
| 209 | ] |
| 210 | if issue["reactions"]: |
| 211 | rxn = " ".join(f"{k}:{v}" for k, v in issue["reactions"].items()) |
| 212 | lines.append(f"Reactions: {rxn}") |
| 213 | lines.append(f"Comments: {issue['comment_count']}") |
| 214 | |
| 215 | # Cross-references (PRs and issues) |
| 216 | xrefs = [t for t in issue["timeline"] if t["type"] == "CrossReferencedEvent"] |
| 217 | if xrefs: |
| 218 | lines.append(f"Cross-references ({len(xrefs)}):") |
| 219 | for x in xrefs[:15]: |
| 220 | lines.append(f" {x['source_type']} #{x['source_number']} [{x['source_state']}]: {x['source_title'][:60]}") |
| 221 | |
| 222 | lines.append("") |
| 223 | |
| 224 | # Body |
| 225 | body = (issue["body"] or "").strip() |
| 226 | if brief: |
| 227 | if len(body) > 1000: |
| 228 | body = body[:1000] + "\n... [truncated, use show without --brief for full]" |
| 229 | else: |
| 230 | # Full body, but cap at 5000 chars for very long issues |
| 231 | if len(body) > 5000: |
| 232 | body = body[:5000] + "\n... [truncated at 5000 chars]" |
| 233 | lines.append(body) |
| 234 | |
| 235 | # Comments |
| 236 | if issue["comments"]: |
| 237 | lines.append("") |
| 238 | lines.append(f"--- Comments ({issue['comment_count']}) ---") |
| 239 | comments = issue["comments"] |
| 240 | if brief: |
| 241 | # In brief mode, show just first and last comment |
| 242 | to_show = [] |
| 243 | if comments: |
| 244 | to_show.append(("first", comments[0])) |
| 245 | if len(comments) > 1: |
| 246 | to_show.append(("last", comments[-1])) |
| 247 | for label, c in to_show: |
| 248 | rxn = "" |
| 249 | if c["reactions"]: |
| 250 | rxn = " | " + " ".join(f"{k}:{v}" for k, v in c["reactions"].items()) |
| 251 | c_body = c["body"].replace("\n", " ").strip()[:300] |
| 252 | lines.append(f" [{label}] @{c['author'] or '?'} ({c['created_at'][:10]}){rxn}:") |
| 253 | lines.append(f" {c_body}") |
| 254 | if len(comments) > 2: |
| 255 | lines.append(f" ... {len(comments) - 2} more comments (use show without --brief)") |
| 256 | else: |
| 257 | # Full mode: show all comments |
| 258 | for idx, c in enumerate(comments): |