package.cpath = package.cpath .. ";../target/debug/?.so" package.path = package.path .. ";../lua-bindings/?.lua" local dia = require("diaphragm") dia.util.eprint("----------") local nord_colors = { base00 = "#2E3440", base01 = "#3B4252", base02 = "#434C5E", base03 = "#4C566A", base04 = "#D8DEE9", base05 = "#E5E9F0", base06 = "#ECEFF4", base07 = "#8FBCBB", base08 = "#BF616A", base09 = "#D08770", base0A = "#EBCB8B", base0B = "#A3BE8C", base0C = "#88C0D0", base0D = "#81A1C1", base0E = "#B48EAD", base0F = "#5E81AC", } local function begin(params) local result = dia.shape(params) result.icon = dia.rectangle.surrounding(result, { height = 10, width = 10, fill_color = nord_colors.base00, }) result.beginning = result.middle_left result.ending = result.middle_right function result:draw() self.icon:draw() end return result end local function stop(params) return begin(params) end function token(params) local result = dia.shape(params) result.name = params.name or "token" result.font = params.font or dia.text.font({ family = "Fira Code", size = 14 * 1024 }) result.text = params.text or dia.text.new({ content = result.name, font = result.font, }) result.fill_color = params.fill_color or nord_colors.base04 result.padding = params.padding or 5 result.box = dia.rectangle.surrounding(result.text, { fill_color = result.fill_color, -- TODO: make that a parameter margin_left = 5, margin_right = 5, margin_top = 2, margin_bottom = 2, }) dia.constraint.inset(result.box, result) result.beginning = result.box.middle_left result.ending = result.box.middle_right function result:draw() self.box:draw() self.text:draw() end return result end function optional(params) local result = dia.shape(params) result.line_spacing = params.line_spacing or 10 result.beginning = result.element.beginning - { x = result.line_spacing } result.ending = result.element.ending + { x = result.line_spacing } result.top_left = result.element.top_left - { x = result.line_spacing, y = result.line_spacing, } result.top_right = result.element.top_right + { x = result.line_spacing, y = -result.line_spacing, } result.overline = dia.straight_path.new({ points = { result.beginning, result.top_left, result.top_right, result.ending, }, }) result.left_line = dia.straight_path.new({ points = { result.beginning, result.element.beginning }, }) result.right_line = dia.straight_path.new({ points = { result.element.ending, result.ending }, }) result.bottom = result.element.bottom function result:draw() result.overline:draw() result.left_line:draw() result.right_line:draw() result.element:draw() end return result end function choice(params) local result = dia.shape(params) result.line_spacing = params.line_spacing or 10 result.padding = params.padding or 10 result.stack = dia.layout.vstack({ elements = result.choices, align = "left", top = result.top, bottom = result.bottom, spacing = result.padding, }) result.beginning = result.choices[1].beginning - { x = result.line_spacing } result.ending = { x = result.stack.right + result.line_spacing, y = result.choices[1].ending.y, } result.left_hook = dia.straight_path.new({ points = { result.choices[1].beginning, result.beginning, result.choices[#result.choices].beginning - { x = result.line_spacing }, result.choices[#result.choices].beginning, }, }) result.right_hook = dia.straight_path.new({ points = { result.choices[1].ending, result.ending, { x = result.ending.x, y = result.choices[#result.choices].ending.y, }, result.choices[#result.choices].ending, }, }) result.left_connections = {} result.right_connections = {} for i = 2, #result.choices - 1 do table.insert( result.left_connections, dia.straight_path.new({ points = { result.choices[i].beginning - { x = result.line_spacing }, result.choices[i].beginning, }, }) ) table.insert( result.right_connections, dia.straight_path.new({ points = { result.choices[i].ending, { x = result.ending.x, y = result.choices[i].ending.y }, }, }) ) end dia.constraint.inset(result.stack, result, { margin_left = result.line_spacing, margin_right = result.line_spacing, }) function result:draw() result.left_hook:draw() result.right_hook:draw() for _, left_conn in ipairs(self.left_connections) do left_conn:draw() end for _, right_conn in ipairs(self.right_connections) do right_conn:draw() end self.stack:draw() end return result end function ident(params) return token(dia.util.tbl_extend({ fill_color = nord_colors.base0A, }, params)) end function typ(params) return token(dia.util.tbl_extend({ fill_color = nord_colors.base08, }, params)) end function tt(params) return token(dia.util.tbl_extend({ fill_color = nord_colors.base0C, }, params)) end function connect(params) local result = dia.shape(params) result.elements = params.elements or {} result.spacing = params.spacing or 10 result.beginning = result.elements[1].beginning result.ending = result.elements[#result.elements].ending result.stack = dia.layout.hstack({ elements = result.elements, align = "none", spacing = result.spacing, }) dia.constraint.inset(result.stack, result) result.lines = {} for i = 1, #result.elements - 1 do local left_el = result.elements[i] local right_el = result.elements[i + 1] table.insert( result.lines, dia.straight_path.new({ points = { left_el.ending, right_el.beginning }, }) ) dia.constrain(left_el.ending.y:eq(right_el.beginning.y)) end function result:draw() self.stack:draw() for _, line in ipairs(self.lines) do line:draw() end end return result end dia.draw({ draw = function(self) local figure = connect({ elements = { begin(), optional({ element = token({ name = "pub" }) }), ident({ name = "name" }), token({ name = "<" }), typ({ name = "a" }), choice({ choices = { connect({ elements = { token({ name = "," }), choice({ choices = { connect({ elements = { typ({ name = "i" }), token({ name = "," }), typ({ name = "o" }), optional({ element = connect({ elements = { token({ name = "," }), typ({ name = "e" }), }, }), }), }, }), typ({ name = "o" }), }, }), token({ name = ">" }), }, }), connect({ elements = { token({ name = ">" }), optional({ element = connect({ elements = { token({ name = "(" }), typ({ name = "i" }), token({ name = ")" }), token({ name = "->" }), typ({ name = "o" }), }, }), }), }, }), }, }), token({ name = "," }), optional({ element = token({ name = "mut" }) }), ident({ name = "self_" }), token({ name = "," }), ident({ name = "submac" }), token({ name = "!" }), token({ name = "(" }), optional({ element = tt({ name = "args" }) }), token({ name = ")" }), stop(), }, center = self.center, }) dia.rectangle .surrounding(self, { fill_color = nord_colors.base06, stroke_width = 0, }) :draw() figure:draw() dia.constraint.inset(figure, self, { margin = 20 }) end, output = {}, })