1 ;;;; graphviz.scm -- utilities for creating graphviz output
3 ;;;; source file of the GNU LilyPond music typesetter
5 ;;;; (c) 2007 Joe Neeman <joeneeman@gmail.com>
8 (define-module (scm graphviz)
10 #:export (make-graph add-node add-edge add-cluster))
12 (define (make-graph filename)
13 (let ((empty-graph (list->vector (list filename '() '() '()))))
14 (ly:atexit write-graph (list empty-graph))
17 (define (filename g) (vector-ref g 0))
18 (define (nodes g) (vector-ref g 1))
19 (define (edges g) (vector-ref g 2))
20 (define (clusters g) (vector-ref g 3))
22 (define (add-cluster graph node-id cluster-name)
23 (let* ((cs (clusters graph))
24 (cluster (assq cluster-name cs))
25 (already-in-cluster (if cluster
28 (vector-set! graph 3 (assq-set! cs
30 (cons node-id already-in-cluster)))))
32 (define (add-node graph label . cluster-name)
33 (let* ((ns (nodes graph))
35 (vector-set! graph 1 (cons `(,id . ,label) ns))
36 (if (and (not (null? cluster-name))
37 (string? (car cluster-name)))
38 (add-cluster graph id (car cluster-name)))
41 (define (add-edge graph node1 node2)
42 (vector-set! graph 2 (cons `(,node1 . ,node2) (edges graph))))
44 (define (write-graph graph)
45 (let ((out (open-file (filename graph) "w"))
48 (cs (clusters graph)))
49 (ly:message (format "writing graph ~s..." (filename graph)))
50 (display "digraph G {\nrankdir=\"LR\"\nnode [shape=rectangle]\n" out)
51 (map (lambda (n) (display (format "~a [label=\"~a\"]\n" (car n) (cdr n)) out))
53 (map (lambda (e) (display (format "~a -> ~a\n" (car e) (cdr e)) out))
56 (display (format "subgraph cluster_~a {\nlabel= \"~a\"\ncolor=blue\n"
57 (string-filter (car c) char-alphabetic?)
60 (map (lambda (n) (display (format "~a\n" n) out)) (cdr c))