17
17
- [[#preparation][Preparation]]
18
18
- [[#language-presentation][Language presentation]]
19
19
- [[#global-variables][global variables]]
20
+ - [[#the-encode-stream][the encode stream]]
21
+ - [[#the-indent-level][the indent level]]
22
+ - [[#the-default-size-for-indent-tab][the default size for indent tab]]
20
23
- [[#how-to-render-a-dot-s-expression][how to render a dot s-expression]]
21
24
- [[#how-to-format-a-dot-s-expression][how to format a dot s-expression]]
22
25
- [[#graph][graph]]
23
26
- [[#stmt-list][stmt-list]]
24
27
- [[#stmt][stmt]]
25
28
- [[#node-statement][node statement]]
29
+ - [[#node-id][node id]]
26
30
- [[#edge-statement][edge statement]]
27
31
- [[#attribute-statement][attribute statement]]
28
32
- [[#attribute][attribute]]
@@ -53,10 +57,10 @@ We will use a lisp style to present the [[https://www.graphviz.org/doc/info/lang
53
57
graph : [ strict ] (graph | digraph) [ ID ] '{' stmt_list '}'
54
58
stmt_list : [ stmt [ ';' ] stmt_list ]
55
59
stmt : node_stmt
56
- | edge_stmt
57
- | attr_stmt
58
- | ID '=' ID
59
- | subgraph
60
+ | edge_stmt
61
+ | attr_stmt
62
+ | ID '=' ID
63
+ | subgraph
60
64
attr_stmt : (graph | node | edge) attr_list
61
65
attr_list : '[' [ a_list ] ']' [ attr_list ]
62
66
a_list : ID '=' ID [ (';' | ',') ] [ a_list ]
@@ -65,7 +69,7 @@ edgeRHS : edgeop (node_id | subgraph) [ edgeRHS ]
65
69
node_stmt : node_id [ attr_list ]
66
70
node_id : ID [ port ]
67
71
port : ':' ID [ ':' compass_pt ]
68
- | ':' compass_pt
72
+ | ':' compass_pt
69
73
subgraph : [ subgraph [ ID ] ] '{' stmt_list '}'
70
74
compass_pt : (n | ne | e | se | s | sw | w | nw | c | _)
71
75
#+end_src
@@ -101,6 +105,7 @@ for example svg, ps, gif, png, or jpg.
101
105
:name (pathname-name file-name) :type "dot")))
102
106
(with-open-file (stream dot-file-name :direction :output :if-exists :supersede
103
107
:if-does-not-exist :create)
108
+ (format stream "// This file is generated automatically by s-dot.~%~%")
104
109
(format-s-dot statement-list :graph-type graph-type :id id :stream stream))
105
110
(uiop:run-program (format nil "~a -o ~a ~a~a ~a"
106
111
dot-exe file-name dot-output-format-switch
@@ -111,9 +116,10 @@ for example svg, ps, gif, png, or jpg.
111
116
We will provide a helpful routine to render a dot s-expression and open it in Emacs.
112
117
#+BEGIN_SRC lisp :load dev
113
118
(defmacro render-and-open-s-dot (file-name &rest left-args)
114
- `(progn
115
- (render-s-dot ,file-name ,@left-args)
116
- (swank:eval-in-emacs `(find-file ,,file-name) t)))
119
+ (let ((real-file-name (gensym "file-name")))
120
+ `(let ((,real-file-name (namestring ,file-name)))
121
+ (render-s-dot ,real-file-name ,@left-args)
122
+ (swank:eval-in-emacs `(find-file ,,real-file-name) t))))
117
123
#+END_SRC
118
124
119
125
@@ -193,9 +199,12 @@ There are many different kinds of statements,let's recogize them one by one.
193
199
If a statement starts without a known keyword, then it's a node statement,for example
194
200
#+BEGIN_SRC lisp :load no
195
201
(render-and-open-s-dot
196
- "/tmp/node1.pdf"
202
+ (merge-pathnames
203
+ #p"images/node1.png"
204
+ (asdf:component-pathname (asdf:find-system :dot)))
197
205
'((node1 (:label "nice node") (:shape :box) (:fontname "Arial") (:fontcolor "#AA0000"))))
198
206
#+END_SRC
207
+ file:./images/node1.png
199
208
200
209
#+BEGIN_SRC lisp
201
210
(defun format-node-stmt (stmt)
@@ -228,7 +237,9 @@ In a s-expression, it's a list that starts with an ~edgeop~ and an ~attr_list~ a
228
237
the rest are a list of ~node id~, for example
229
238
#+BEGIN_SRC lisp :load no
230
239
(render-and-open-s-dot
231
- "/tmp/edge1.pdf"
240
+ (merge-pathnames
241
+ #p"images/edge1.png"
242
+ (asdf:component-pathname (asdf:find-system :dot)))
232
243
'((:-> ((arrowhead :diamond)
233
244
(color "#FF0000")
234
245
(headlabel "head\nlabel")
@@ -240,6 +251,7 @@ the rest are a list of ~node id~, for example
240
251
node2
241
252
node3)))
242
253
#+END_SRC
254
+ file:./images/edge1.png
243
255
244
256
#+BEGIN_SRC lisp
245
257
(defun format-edge-stmt (stmt)
@@ -260,7 +272,9 @@ In a dot s-expression, it starts with keyword ~:graph~, ~:node~, ~:edge~ , and t
260
272
in the list is the ~attr_list~(ref:attr-list),for example:
261
273
#+begin_src lisp :load no
262
274
(render-and-open-s-dot
263
- "/tmp/node2.pdf"
275
+ (merge-pathnames
276
+ #p"images/node2.png"
277
+ (asdf:component-pathname (asdf:find-system :dot)))
264
278
'((:node
265
279
(:fillcolor "#AAFFAA")
266
280
(:shape :circle)
@@ -269,6 +283,7 @@ in the list is the ~attr_list~(ref:attr-list),for example:
269
283
(:fontsize 16))
270
284
(node1 (:id "a")(:label :test))))
271
285
#+end_src
286
+ file:./images/node2.png
272
287
273
288
#+BEGIN_SRC lisp
274
289
(defun format-attr-stmt (stmt)
@@ -280,10 +295,13 @@ a single attribute can be applied to global environment in a statement,
280
295
in a dot s-expression, it looks like this:
281
296
#+BEGIN_SRC lisp :load no
282
297
(render-and-open-s-dot
283
- "/tmp/attr.pdf"
298
+ (merge-pathnames
299
+ #p"images/attr.png"
300
+ (asdf:component-pathname (asdf:find-system :dot)))
284
301
'((= :compound t)
285
302
(node1 (:id :test)(:label :test))))
286
303
#+END_SRC
304
+ file:./images/attr.png
287
305
288
306
#+BEGIN_SRC lisp
289
307
(defun format-attribute (stmt)
@@ -298,12 +316,16 @@ It a subgraph's name starts with "cluster", then it has a special meaning.
298
316
in a dot s-expression, it looks like this:
299
317
#+BEGIN_SRC lisp
300
318
(render-and-open-s-dot
301
- "/tmp/subgraph.pdf"
319
+ (merge-pathnames
320
+ #p"images/cluster1.png"
321
+ (asdf:component-pathname (asdf:find-system :dot)))
302
322
'((:subgraph cluster_1
303
323
(node1 (:id :test)(:label :test))
304
324
(node2 (:id :test2)(:label :test2))
305
325
(:-> nil node1 node2))))
306
326
#+END_SRC
327
+ file:./images/cluster1.png
328
+
307
329
#+BEGIN_SRC lisp
308
330
(defun format-subgraph-stmt (stmt)
309
331
(let ((id (second stmt))
@@ -339,9 +361,12 @@ compass_pt : (n | ne | e | se | s | sw | w | nw | c | _)
339
361
In a dot s-expression, it looks like this:
340
362
#+BEGIN_SRC lisp :load no
341
363
(render-and-open-s-dot
342
- "/tmp/port.pdf"
364
+ (merge-pathnames
365
+ #p"images/port.png"
366
+ (asdf:component-pathname (asdf:find-system :dot)))
343
367
'((:-> nil (node1 :e) node2)))
344
368
#+END_SRC
369
+ file:./images/port.png
345
370
346
371
#+BEGIN_SRC lisp
347
372
(defun format-port (port)
0 commit comments