From 528c64d690c2d1cb4b3b70c37008b3ba37d904b9 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 5 Sep 2022 11:28:03 -0700 Subject: support drawings in the source editor --- source_file.lua | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 139 insertions(+), 17 deletions(-) (limited to 'source_file.lua') diff --git a/source_file.lua b/source_file.lua index 9c0b8a4..6552667 100644 --- a/source_file.lua +++ b/source_file.lua @@ -25,17 +25,21 @@ function load_from_file(infile) while true do local line = infile_next_line() if line == nil then break end - local line_info = {} - if line:find(Fold) then - _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)') + if line == '```lines' then -- inflexible with whitespace since these files are always autogenerated + table.insert(result, load_drawing(infile_next_line)) else - line_info.data = line + local line_info = {mode='text'} + if line:find(Fold) then + _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)') + else + line_info.data = line + end + table.insert(result, line_info) end - table.insert(result, line_info) end end if #result == 0 then - table.insert(result, {data=''}) + table.insert(result, {mode='text', data=''}) end return result end @@ -46,16 +50,86 @@ function save_to_disk(State) error('failed to write to "'..State.filename..'"') end for _,line in ipairs(State.lines) do - outfile:write(line.data) - if line.dataB and #line.dataB > 0 then - outfile:write(Fold) - outfile:write(line.dataB) + if line.mode == 'drawing' then + store_drawing(outfile, line) + else + outfile:write(line.data) + if line.dataB and #line.dataB > 0 then + outfile:write(Fold) + outfile:write(line.dataB) + end + outfile:write('\n') end - outfile:write('\n') end outfile:close() end +function load_drawing(infile_next_line) + local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}} + while true do + local line = infile_next_line() + assert(line) + if line == '```' then break end + local shape = json.decode(line) + if shape.mode == 'freehand' then + -- no changes needed + elseif shape.mode == 'line' or shape.mode == 'manhattan' then + local name = shape.p1.name + shape.p1 = Drawing.find_or_insert_point(drawing.points, shape.p1.x, shape.p1.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.p1].name = name + name = shape.p2.name + shape.p2 = Drawing.find_or_insert_point(drawing.points, shape.p2.x, shape.p2.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.p2].name = name + elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then + for i,p in ipairs(shape.vertices) do + local name = p.name + shape.vertices[i] = Drawing.find_or_insert_point(drawing.points, p.x,p.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.vertices[i]].name = name + end + elseif shape.mode == 'circle' or shape.mode == 'arc' then + local name = shape.center.name + shape.center = Drawing.find_or_insert_point(drawing.points, shape.center.x,shape.center.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.center].name = name + elseif shape.mode == 'deleted' then + -- ignore + else + print(shape.mode) + assert(false) + end + table.insert(drawing.shapes, shape) + end + return drawing +end + +function store_drawing(outfile, drawing) + outfile:write('```lines\n') + for _,shape in ipairs(drawing.shapes) do + if shape.mode == 'freehand' then + outfile:write(json.encode(shape), '\n') + elseif shape.mode == 'line' or shape.mode == 'manhattan' then + local line = json.encode({mode=shape.mode, p1=drawing.points[shape.p1], p2=drawing.points[shape.p2]}) + outfile:write(line, '\n') + elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then + local obj = {mode=shape.mode, vertices={}} + for _,p in ipairs(shape.vertices) do + table.insert(obj.vertices, drawing.points[p]) + end + local line = json.encode(obj) + outfile:write(line, '\n') + elseif shape.mode == 'circle' then + outfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius}), '\n') + elseif shape.mode == 'arc' then + outfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius, start_angle=shape.start_angle, end_angle=shape.end_angle}), '\n') + elseif shape.mode == 'deleted' then + -- ignore + else + print(shape.mode) + assert(false) + end + end + outfile:write('```\n') +end + -- for tests function load_array(a) local result = {} @@ -64,16 +138,64 @@ function load_array(a) while true do i,line = next_line(a, i) if i == nil then break end - local line_info = {} - if line:find(Fold) then - _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)') +--? print(line) + if line == '```lines' then -- inflexible with whitespace since these files are always autogenerated +--? print('inserting drawing') + i, drawing = load_drawing_from_array(next_line, a, i) +--? print('i now', i) + table.insert(result, drawing) else - line_info.data = line +--? print('inserting text') + local line_info = {mode='text'} + if line:find(Fold) then + _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)') + else + line_info.data = line + end + table.insert(result, line_info) end - table.insert(result, line_info) end if #result == 0 then - table.insert(result, {data=''}) + table.insert(result, {mode='text', data=''}) end return result end + +function load_drawing_from_array(iter, a, i) + local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}} + local line + while true do + i, line = iter(a, i) + assert(i) +--? print(i) + if line == '```' then break end + local shape = json.decode(line) + if shape.mode == 'freehand' then + -- no changes needed + elseif shape.mode == 'line' or shape.mode == 'manhattan' then + local name = shape.p1.name + shape.p1 = Drawing.find_or_insert_point(drawing.points, shape.p1.x, shape.p1.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.p1].name = name + name = shape.p2.name + shape.p2 = Drawing.find_or_insert_point(drawing.points, shape.p2.x, shape.p2.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.p2].name = name + elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then + for i,p in ipairs(shape.vertices) do + local name = p.name + shape.vertices[i] = Drawing.find_or_insert_point(drawing.points, p.x,p.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.vertices[i]].name = name + end + elseif shape.mode == 'circle' or shape.mode == 'arc' then + local name = shape.center.name + shape.center = Drawing.find_or_insert_point(drawing.points, shape.center.x,shape.center.y, --[[large width to minimize overlap]] 1600) + drawing.points[shape.center].name = name + elseif shape.mode == 'deleted' then + -- ignore + else + print(shape.mode) + assert(false) + end + table.insert(drawing.shapes, shape) + end + return i, drawing +end -- cgit 1.4.1-2-gfad0