Update the pret-trans to current context beta.
[matthijs/master-project/report.git] / pret-trans.lua
1 -- filename : type-trans.lua
2 -- comment  : Pretty printing of core transformations. Parses a specific
3 --            syntax, consisting of a before / after with a dashed lined in
4 --            between, and some extra conditions to the right of the line.
5 --            Recreates this layout using frames and line commands.
6 -- author   : Matthijs Kooijman, Universiteit Twente, NL
7 -- copyright: Matthijs Kooijman
8 -- license  : None
9
10 local utf = unicode.utf8
11
12 vis = buffers.newvisualizer("trans")
13
14 local commands = {}
15 -- A command to create a horizontal rule.
16 commands.rule = "\\blackrule[height=0.5pt,depth=0pt,width=.45\\textwidth]"
17 -- Pretty printer to use for the stuff before and after the line
18 commands.before_pret = "lam"
19 commands.after_pret = "lam"
20 -- Frame commands to use for the left (before + line + after) and right
21 -- (conditions) parts. Should include an opening {, which will be closed
22 -- automatically.
23 commands.leftframe = "\\framed[offset=0mm,location=middle,strut=no,align=right,frame=off,width=.5\\textwidth]{\\sans"
24 commands.rightframe = "\\framed[offset=0mm,location=middle,strut=no,align=right,frame=off,width=.5\\textwidth]{"
25
26 -- A table to keep the lines in this buffer, so we can process them all at
27 -- once at the end.
28 local lines
29
30 -- Some helper functions
31 local function ltrim(s)
32     return (string.gsub(s, "^%s*", ""))
33 end
34
35 local function rtrim(s)
36     return (string.gsub(s, "%s*$", ""))
37 end
38
39 -- Insert n blank lines
40 local function blanks(n)
41     print("Inserting " .. n .. " blanks")
42     for i = 1,n do
43         buffers.visualizers.handlers.default.empty_line()
44     end
45 end
46
47 -- Prettyprint the given lines using the given pretty printer
48 local function prettyprint(ppr, lines)
49     -- Change the current visualizer
50     buffers.setvisualizer('lam')
51
52     -- Output the lines
53     buffers.hooks.begin_of_display()
54     line = 0
55     for i = 1,#lines do
56         _, line = buffers.typeline(lines[i], i, #lines, line)
57     end
58     buffers.hooks.end_of_display()
59
60     -- Change the visualizer back
61     buffers.setvisualizer('trans')
62 end
63
64 -- Capture all lines, without generating any output
65 function vis.begin_of_display()
66     lines = {}
67 end
68 function vis.begin_of_line(n)
69     -- Don't generate output here
70 end
71 function vis.flush_line(str, nested)
72     table.insert(lines, str)
73     -- Don't generate output here
74 end
75 function vis.end_of_line(n)
76     -- Don't generate output here
77 end
78 function vis.empty_line()
79     table.insert(lines, '')
80     -- Don't generate output here
81 end
82
83 -- We do the actual work here. Process all the lines in the buffer and
84 -- generate output for them.
85 function vis.end_of_display()
86     -- Find the horizontal rule, and see how long it is.
87     len = nil
88     for i = 1,#lines do
89         match = utf.match(lines[i], "^%-%-%-*")
90         if match then
91             len = utf.len(match)
92             break
93         end
94     end
95     print("Rule length: " .. len)
96    
97     -- Split the input in three parts. Stuff before the line, stuff
98     -- after the line, stuff to the right of the line.
99     before, after, rights = {}, {}, {}
100     found_line = false
101     for i = 1,#lines do
102         line = lines[i]
103         -- Split the line into a left and right part
104         left = rtrim(utf.sub(line, 1, len))
105         right = ltrim(utf.sub(line, len + 1))
106         if utf.match(left, "^%-%-%-*") then
107             found_line = true
108         else
109             print("Looking at " .. line .. "('" .. left .. "', '" .. right .. "')")
110             if utf.len(left) > 0 then
111                 if not found_line then
112                     table.insert(before, left)
113                 else
114                     table.insert(after, left)
115                 end
116             end
117         end
118         if utf.len(right) > 0 then
119             table.insert(rights, right)
120         end
121     end
122
123     --
124     -- Real output starts here
125     --
126
127     -- Ensure the left and right frames end up next to each other.
128     tex.sprint("\\dontleavehmode")
129
130     -- Open and fill the left frame
131     tex.sprint(commands.leftframe)
132
133     prettyprint('lam', before)
134
135     tex.sprint(commands.rule)
136
137     prettyprint('lam', after)
138
139     -- Close the left frame
140     tex.sprint("}")
141
142     -- Open and fill the right frame
143     tex.sprint(commands.rightframe)
144
145     -- Insert spacer blank lines to align the middle condition with the
146     -- conclusion rule
147     n_blanks = #before - math.ceil((#rights - 1) / 2)
148     n_blanks = math.max(0, n_blanks)
149     blanks(n_blanks)
150
151     -- Print the conditions
152     for i = 1,#rights do
153         tex.sprint(rights[i])
154         buffers.visualizers.handlers.default.end_of_line()
155     end
156
157     -- Fill up the remaining space with blanks
158     n_blanks = (#before + 1 + #after) - (n_blanks + #rights)
159     n_blanks = math.max(0, n_blanks)
160     blanks(n_blanks)
161
162     -- Close the right frame 
163     tex.sprint("}")
164     
165     -- Clean up
166     lines = {}
167 end
168
169 -- vim: set sw=4 sts=4 expandtab ai: