Build a human-readable label for a node in DOT output.
(node: &KgNode)
| 547 | |
| 548 | /// Build a human-readable label for a node in DOT output. |
| 549 | fn node_label(node: &KgNode) -> String { |
| 550 | let kind = node.kind.to_lowercase(); |
| 551 | match kind.as_str() { |
| 552 | "module" => { |
| 553 | // Last path component + trailing slash |
| 554 | let last = node |
| 555 | .label |
| 556 | .rsplit('/') |
| 557 | .find(|s| !s.is_empty()) |
| 558 | .unwrap_or(&node.label); |
| 559 | format!("{}/", last) |
| 560 | } |
| 561 | "file" => { |
| 562 | // Filename, optionally with match count |
| 563 | let filename = node.label.rsplit('/').next().unwrap_or(&node.label); |
| 564 | if let Some(ref meta) = node.metadata { |
| 565 | if let Some(matches) = meta.get("content_matches").and_then(|v| v.as_u64()) { |
| 566 | return format!("{}\n{} matches", filename, matches); |
| 567 | } |
| 568 | } |
| 569 | filename.to_string() |
| 570 | } |
| 571 | "entity" => { |
| 572 | // Label + kind/line info from metadata |
| 573 | let mut label = node.label.clone(); |
| 574 | if let Some(ref meta) = node.metadata { |
| 575 | let ent_kind = meta.get("kind").and_then(|v| v.as_str()); |
| 576 | let line = meta.get("line").and_then(|v| v.as_u64()); |
| 577 | let end_line = meta.get("end_line").and_then(|v| v.as_u64()); |
| 578 | if let (Some(k), Some(l)) = (ent_kind, line) { |
| 579 | if let Some(el) = end_line { |
| 580 | label = format!("{}\n{} L{}-{}", label, k, l, el); |
| 581 | } else { |
| 582 | label = format!("{}\n{} L{}", label, k, l); |
| 583 | } |
| 584 | } |
| 585 | } |
| 586 | label |
| 587 | } |
| 588 | "change" => { |
| 589 | // Short hash + optional summary excerpt |
| 590 | let mut label = node.label.clone(); |
| 591 | if let Some(ref summary) = node.summary { |
| 592 | let excerpt: String = summary.chars().take(30).collect(); |
| 593 | label = format!("{}\n{}", label, excerpt); |
| 594 | } |
| 595 | label |
| 596 | } |
| 597 | _ => { |
| 598 | // Everything else: label truncated to 40 chars |
| 599 | if node.label.len() > 40 { |
| 600 | let truncated: String = node.label.chars().take(37).collect(); |
| 601 | format!("{}...", truncated) |
| 602 | } else { |
| 603 | node.label.clone() |
| 604 | } |
| 605 | } |
| 606 | } |