]> git.donarmstrong.com Git - lilypond.git/blob - scm/graphviz.scm
small graphing fixes
[lilypond.git] / scm / graphviz.scm
1 ;;;; graphviz.scm -- utilities for creating graphviz output
2 ;;;;
3 ;;;;  source file of the GNU LilyPond music typesetter
4 ;;;;
5 ;;;; (c) 2007 Joe Neeman <joeneeman@gmail.com>
6
7
8 (define-module (scm graphviz)
9   #:use-module (lily)
10   #:export (make-graph add-node add-edge add-cluster))
11
12 (define (make-graph filename)
13   (let ((empty-graph (list->vector (list filename '() '() '()))))
14     (ly:atexit write-graph (list empty-graph))
15     empty-graph))
16
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))
21
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
26                                  (cdr cluster)
27                                  '())))
28     (vector-set! graph 3 (assq-set! cs
29                                     cluster-name
30                                     (cons node-id already-in-cluster)))))
31
32 (define (add-node graph label . cluster-name)
33   (let* ((ns (nodes graph))
34          (id (length ns)))
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)))
39     id))
40
41 (define (add-edge graph node1 node2)
42   (vector-set! graph 2 (cons `(,node1 . ,node2) (edges graph))))
43
44 (define (write-graph graph)
45   (let ((out (open-file (filename graph) "w"))
46         (ns (nodes graph))
47         (es (edges graph))
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))
52          ns)
53     (map (lambda (e) (display (format "~a -> ~a\n" (car e) (cdr e)) out))
54          es)
55     (map (lambda (c)
56           (display (format "subgraph cluster_~a {\nlabel= \"~a\"\ncolor=blue\n"
57                            (string-filter (car c) char-alphabetic?)
58                            (car c))
59                    out)
60           (map (lambda (n) (display (format "~a\n" n) out)) (cdr c))
61           (display "}\n" out))
62          cs)
63     (display "}" out)))