ToDot generates a Graphviz DOT format
(focusTaskID string)
| 244 | |
| 245 | // ToDot generates a Graphviz DOT format |
| 246 | func (g *Graph) ToDot(focusTaskID string) string { |
| 247 | var sb strings.Builder |
| 248 | sb.WriteString("digraph tasks {\n") |
| 249 | sb.WriteString(" rankdir=TB;\n") |
| 250 | sb.WriteString(" node [shape=box, style=rounded];\n\n") |
| 251 | |
| 252 | // Sort tasks by ID for consistent output |
| 253 | sortedTasks := make([]*model.Task, len(g.Tasks)) |
| 254 | copy(sortedTasks, g.Tasks) |
| 255 | sort.Slice(sortedTasks, func(i, j int) bool { |
| 256 | return sortedTasks[i].ID < sortedTasks[j].ID |
| 257 | }) |
| 258 | |
| 259 | // Define nodes |
| 260 | for _, task := range sortedTasks { |
| 261 | color := "lightgray" |
| 262 | if task.ID == focusTaskID { |
| 263 | color = "red" |
| 264 | } else { |
| 265 | switch task.Status { |
| 266 | case model.StatusCompleted: |
| 267 | color = "lightgreen" |
| 268 | case model.StatusInProgress: |
| 269 | color = "yellow" |
| 270 | case model.StatusBlocked: |
| 271 | color = "gray" |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | // Escape special characters |
| 276 | title := strings.ReplaceAll(task.Title, "\"", "\\\"") |
| 277 | label := fmt.Sprintf("%s: %s", task.ID, title) |
| 278 | sb.WriteString(fmt.Sprintf(" %s [label=\"%s\", fillcolor=%s, style=filled];\n", task.ID, label, color)) |
| 279 | } |
| 280 | |
| 281 | sb.WriteString("\n") |
| 282 | |
| 283 | // Define edges |
| 284 | edges := make(map[string]bool) |
| 285 | for _, task := range sortedTasks { |
| 286 | for _, depID := range task.Dependencies { |
| 287 | edgeKey := depID + "->" + task.ID |
| 288 | if !edges[edgeKey] { |
| 289 | edges[edgeKey] = true |
| 290 | sb.WriteString(fmt.Sprintf(" %s -> %s;\n", depID, task.ID)) |
| 291 | } |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | sb.WriteString("}\n") |
| 296 | return sb.String() |
| 297 | } |
| 298 | |
| 299 | // ToASCII generates an ASCII tree representation. |
| 300 | // An optional ASCIIFormatter applies styling callbacks; pass nil for plain text. |