1 #+OPTIONS: H:3 num:nil toc:t \n:nil ::t |:t ^:t -:t f:t *:t tex:t d:(HIDE) tags:not-in-toc
2 #+STARTUP: align fold nodlcheck hidestars oddeven lognotestate
3 #+SEQ_TODO: TODO(t) INPROGRESS(i) WAITING(w@) | DONE(d) CANCELED(c@)
4 #+TAGS: Write(w) Update(u) Fix(f) Check(c)
5 #+TITLE: Org tutorial on generating simple process diagrams using dot and tables
7 #+EMAIL: tools AT Karl MINUS Voit DOT at
10 #+CATEGORY: org-tutorial
12 [[file:../index.org][{Worg's index}]] > [[file:index.org][{Org-tutorials}]]
16 This tutorial summarizes one specific method which defines (process)
17 elements within tables in order to generate a simple work flow
18 diagram using [[https://code.google.com/p/pydot/][dot]].
20 An alternative way of accomplishing the task would be using [[http://plantuml.com/][PlantUML]]
21 (a wrapper to [[http://www.graphviz.org/][Graphviz]]) which can be [[http://plantuml.com/emacs][integrated to Emacs]] as well.
23 We first demonstrate a compact version for one-time usage (tables and
24 code snippet). Then, we show how to re-use this method for multiple
25 sets of tables in an efficient way.
27 * Defining the Process Elements
29 We are using tables to define our work-flow. The first table holds
30 the node identifiers (internal names), node labels, optional shape
31 definitions, and optional fill colors:
33 : #+name: example-node-table
34 : | *node* | *label* | *shape* | *fillcolor* |
35 : |------------+----------------+---------+-------------|
36 : | S_start | start | ellipse | green |
37 : | S_fill | fill form | | |
38 : | S_send | send form | | |
39 : | S_complete | form complete? | diamond | yellow |
40 : | S_do | do task | | red |
41 : | S_end | end | ellipse | |
43 The second table contains information about connections between nodes
44 (using node identifiers) and optional labels:
46 : #+name: example-graph
47 : | from | to | label |
48 : |------------+------------+-------|
49 : | S_start | S_fill | |
50 : | S_fill | S_send | |
51 : | S_send | S_complete | |
52 : | S_complete | S_fill | N |
53 : | S_complete | S_do | Y |
56 * ELISP code snippet for generating the diagram using dot
58 In the next step, we are going to generate the diagram file (in PNG
59 format) using [[https://code.google.com/p/pydot/][dot]]. You should make sure that you have a working dot
60 installation and probably tried out [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-dot.html][a tutorial about using dot within
63 The author of this code is [[https://orgmode.org/list/4c174089656ce0b08177f464325c4bf9@mail.rickster.com][Rick Frankel]]. It is written in Emacs LISP
64 which directly executes the generated dot script:
66 : #+name: graph-from-tables
67 : #+HEADER: :var nodes=example-node-table graph=example-graph
68 : #+BEGIN_SRC emacs-lisp :file ~/example-diagram.png :colnames yes :exports results
69 : (org-babel-execute:dot
72 : "//rankdir=LR;\n" ;; remove comment characters '//' for horizontal layout; add for vertical layout
75 : (format "%s [label=\"%s\" shape=%s style=\"filled\" fillcolor=\"%s\"]"
78 : (if (string= "" (nth 2 x)) "box" (nth 2 x))
79 : (if (string= "" (nth 3 x)) "none" (nth 3 x))
84 : (format "%s -> %s [taillabel=\"%s\"]"
85 : (car x) (nth 1 x) (nth 2 x))) graph "\n")
89 As you can see, the node table and the graph table are being defined
90 in the header using the ~:var~ argument for babel. The resulting PNG
91 file name is defined as ~:file~ argument below.
93 By executing the babel script (e.g., ~C-c C-c~) the PNG file gets
96 You can remove the dot-comment (~//~) in front of ~rankdir~ in order
97 to switch to a horizontal layout of the diagram.
99 [[file:../images/org-dot/example-diagram.png]]
101 * Re-using the code snippet with call-statements
103 When you are generating multiple diagrams within one single Org-mode
104 file, you might want to re-use the ELISP code for all of your
105 diagrams. However, you want to use different definition tables and a
106 different output file name. The ELISP code is the same for all of
109 This can be achieved by using [[https://orgmode.org/manual/Evaluating-code-blocks.html][the ~call~ command]]. In this example, we
110 are re-using the ELISP code from above with two newly created tables
111 of the very important process 42 (please notice also the differences
112 in the ~name~ arguments of the tables):
114 : #+name: process42-node-table
115 : | *node* | *label* | *shape* | *fillcolor* |
116 : |---------+---------------------+---------+-------------|
117 : | mystart | start | ellipse | yellow |
118 : | mywatch | is Bob here? | diamond | |
119 : | mywait | wait for 10 minutes | | red |
120 : | mytalk | talk to Bob | | |
121 : | myend | end | ellipse | green |
123 The second table contains information about connections between nodes
124 (using node identifiers) and optional labels:
126 : #+name: process42-graph
127 : | from | to | label |
128 : |---------+---------+-------|
129 : | mystart | mywatch | |
130 : | mywatch | mywait | N |
131 : | mywait | mywatch | |
132 : | mywatch | mytalk | Y |
133 : | mytalk | myend | |
135 The ~call~ statement consists of the name of the code
136 (~graph-from-tables~), an insider header argument for the new file
137 name, and arguments which defines the input tables. For [[https://orgmode.org/list/5e6cbdf1d1de558009527836766630b7@mail.rickster.com][technical
138 reasons]], we have to add table ranges as well (~[2:-1]~):
140 : #+call: graph-from-tables[:file ~/diagram-process42.png](nodes=process42-node-table[2:-1],graph=process42-graph[2:-1]) :results file
142 By invoking the call statement (place the cursor on it and use the
143 usual ~C-c C-c~ command to execute), you generate the diagram for our
146 [[file:../images/org-dot/diagram-process42.png]]
150 Pretty handy for generating (simple) process diagrams.