feat(nbd): add ASCII graph rendering to display.rs [e14172]
Adds format_graph, print_graph, format_subtree, and print_subtree. Renders dependency forest with box-drawing characters (├──, └──, │). Cycle-safe via visited HashSet; repeated nodes labelled [cycle]. 8 unit tests covering single tickets, chains, branching, subtrees, cycles, unknown IDs, and the empty graph. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>quotesdb
parent
d0dd720316
commit
d5697d5c4e
@ -0,0 +1,68 @@
|
||||
+++
|
||||
title = "ASCII graph rendering in display.rs"
|
||||
priority = 5
|
||||
status = "done"
|
||||
ticket_type = "feature"
|
||||
dependencies = ["9c9ebe"]
|
||||
+++
|
||||
Add `format_graph` and `print_graph` to `src/display.rs` to render a ticket dependency DAG as an ASCII tree.
|
||||
|
||||
## Motivation
|
||||
|
||||
The `nbd graph` command needs to convert the `TicketGraph` data structure (from `src/graph.rs`) into a human-readable ASCII representation. Rendering belongs in `display.rs` next to `format_list` and `format_ticket`.
|
||||
|
||||
## Output format
|
||||
|
||||
The graph is a forest of trees. Each root ticket (no in-graph dependencies) starts at column 0. Its dependents (tickets that depend on it) are indented below it using box-drawing characters.
|
||||
|
||||
```
|
||||
a3f9c2 [todo] Fix login bug
|
||||
├── b7d41e [todo] Add rate limiting
|
||||
│ └── c9e823 [in_progress] Write tests
|
||||
└── d1f302 [done] Update docs
|
||||
e4a781 [todo] New feature (no deps)
|
||||
```
|
||||
|
||||
**Node format per line:**
|
||||
```
|
||||
{prefix}{id} [{status}] {title}
|
||||
```
|
||||
|
||||
Where `{prefix}` is built from indentation characters (`│ `, `├── `, `└── `).
|
||||
|
||||
**Blocked indicator (optional):** Consider marking tickets that have unresolved (non-done/closed) dependencies with a `[blocked]` tag or `!` prefix so the graph visually distinguishes ready from blocked tickets.
|
||||
|
||||
## Signatures
|
||||
|
||||
```rust
|
||||
/// Render the full dependency forest as an ASCII tree string.
|
||||
pub fn format_graph(graph: &TicketGraph) -> String
|
||||
|
||||
/// Print the full dependency forest.
|
||||
pub fn print_graph(graph: &TicketGraph)
|
||||
|
||||
/// Render the subtree rooted at `root_id` as an ASCII tree string.
|
||||
pub fn format_subtree(graph: &TicketGraph, root_id: &str) -> String
|
||||
|
||||
/// Print the subtree rooted at `root_id`.
|
||||
pub fn print_subtree(graph: &TicketGraph, root_id: &str)
|
||||
```
|
||||
|
||||
## Implementation notes
|
||||
|
||||
- Use a recursive helper that tracks a `prefix: String` carrying the accumulated indentation characters.
|
||||
- For each node's children (its dependents in the graph), iterate:
|
||||
- If not the last child: prefix extension is `│ `; connector is `├── `.
|
||||
- If the last child: prefix extension is ` `; connector is `└── `.
|
||||
- Cycle guard: track a `visited: HashSet<&str>` across the recursion; if a node ID is already visited, render `{prefix}{connector}{id} [cycle]` and stop descending.
|
||||
- Status is shown as the serde string: `todo`, `in_progress`, `done`, `closed`.
|
||||
|
||||
## Files touched
|
||||
- `src/display.rs` — `format_graph`, `print_graph`, `format_subtree`, `print_subtree`
|
||||
|
||||
## Tests (unit, in `src/tests.rs`)
|
||||
- `format_graph` on a single ticket with no deps produces a single line.
|
||||
- `format_graph` on a two-ticket chain shows the child indented with `└──`.
|
||||
- `format_graph` with a branching parent shows `├──` for all but the last child and `└──` for the last.
|
||||
- `format_subtree` only shows the specified root's subtree.
|
||||
- A cycle in the graph does not cause infinite recursion; the repeated node is labelled `[cycle]`.
|
||||
Loading…
Reference in New Issue