;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015, 2016 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
;;;
;;; This file is part of GNU Guix.
;;;
#:use-module (guix monads)
#:use-module (guix records)
#:use-module (guix sets)
+ #:use-module (rnrs io ports)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-26)
node-transitive-edges
node-reachable-count
+ %graph-backends
+ %d3js-backend
%graphviz-backend
graph-backend?
graph-backend
+ graph-backend-name
+ graph-backend-description
export-graph))
;;;
(define-record-type <graph-backend>
- (graph-backend prologue epilogue node edge)
+ (graph-backend name description prologue epilogue node edge)
graph-backend?
- (prologue graph-backend-prologue)
- (epilogue graph-backend-epilogue)
- (node graph-backend-node)
- (edge graph-backend-edge))
+ (name graph-backend-name)
+ (description graph-backend-description)
+ (prologue graph-backend-prologue)
+ (epilogue graph-backend-epilogue)
+ (node graph-backend-node)
+ (edge graph-backend-edge))
(define %colors
;; See colortbl.h in Graphviz.
id1 id2 (pop-color id1)))
(define %graphviz-backend
- (graph-backend emit-prologue emit-epilogue
+ (graph-backend "graphviz"
+ "Generate graph in DOT format for use with Graphviz."
+ emit-prologue emit-epilogue
emit-node emit-edge))
+\f
+;;;
+;;; d3js export.
+;;;
+
+(define (emit-d3js-prologue name port)
+ (format port "\
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=\"utf-8\">
+ <style>
+text {
+ font: 10px sans-serif;
+ pointer-events: none;
+}
+ </style>
+ <script type=\"text/javascript\" src=\"~a\"></script>
+ </head>
+ <body>
+ <script type=\"text/javascript\">
+var nodes = {},
+ nodeArray = [],
+ links = [];
+" (search-path %load-path "d3.v3.js")))
+
+(define (emit-d3js-epilogue port)
+ (format port "</script><script type=\"text/javascript\" src=\"~a\"></script></body></html>"
+ (search-path %load-path "graph.js")))
+
+(define (emit-d3js-node id label port)
+ (format port "\
+nodes[\"~a\"] = {\"id\": \"~a\", \"label\": \"~a\", \"index\": nodeArray.length};
+nodeArray.push(nodes[\"~a\"]);~%"
+ id id label id))
+
+(define (emit-d3js-edge id1 id2 port)
+ (format port "links.push({\"source\": \"~a\", \"target\": \"~a\"});~%"
+ id1 id2))
+
+(define %d3js-backend
+ (graph-backend "d3js"
+ "Generate chord diagrams with d3js."
+ emit-d3js-prologue emit-d3js-epilogue
+ emit-d3js-node emit-d3js-edge))
+
+
+\f
+;;;
+;;; Cypher export.
+;;;
+
+(define (emit-cypher-prologue name port)
+ (format port ""))
+
+(define (emit-cypher-epilogue port)
+ (format port ""))
+
+(define (emit-cypher-node id label port)
+ (format port "MERGE (p:Package { id: ~s }) SET p.name = ~s;~%"
+ id label ))
+
+(define (emit-cypher-edge id1 id2 port)
+ (format port "MERGE (a:Package { id: ~s });~%" id1)
+ (format port "MERGE (b:Package { id: ~s });~%" id2)
+ (format port "MATCH (a:Package { id: ~s }), (b:Package { id: ~s }) CREATE UNIQUE (a)-[:NEEDS]->(b);~%"
+ id1 id2))
+
+(define %cypher-backend
+ (graph-backend "cypher"
+ "Generate Cypher queries."
+ emit-cypher-prologue emit-cypher-epilogue
+ emit-cypher-node emit-cypher-edge))
+
+
+\f
+;;;
+;;; Shared.
+;;;
+
+(define %graph-backends
+ (list %graphviz-backend
+ %d3js-backend
+ %cypher-backend))
+
(define* (export-graph sinks port
#:key
reverse-edges? node-type
given BACKEND. Use NODE-TYPE to traverse the DAG. When REVERSE-EDGES? is
true, draw reverse arrows."
(match backend
- (($ <graph-backend> emit-prologue emit-epilogue emit-node emit-edge)
+ (($ <graph-backend> _ _ emit-prologue emit-epilogue emit-node emit-edge)
(emit-prologue (node-type-name node-type) port)
(match node-type