support drawings in the source editor
[?]
Sep 5, 2022, 6:28 PM
OI4FPFINEROK6GNDEMOBTGSPYIULCLRGGT5W3H7VLM7VFH22GMWQCDependencies
- [2]
UN7L3DNNavoid some string concatenations - [3]
UPCIYZEUdrop an unnecessary level of indent - [4]
E4HEHLRTextract a variable - [5]
KV7GGVERcouple of accidental globals - [6]
KKMFQDR4editing source code from within the app - [7]
5DOTWNVMright margin - [8]
QCPXQ2E3add state arg to a few functions - [9]
V5MJRFOZbugfix: down arrow doesn't scroll up unnecessarily - [10]
VSBSWTE4bugfix: where cursor is drawn - [11]
PX3736DXbetter error message - [12]
PFT5Y2ZYmove - [13]
PV2YA7KSsubsection headings in a long switch - [14]
SVJZZDC3snapshot - no, that's all wrong - [15]
ZPUQSPQPextract a few methods - [16]
WQOSZSUEwarn on unused commandline args - [17]
KZ5GAYRPthis fixes the immediate regression - [18]
VHQCNMARseveral more modules - [19]
EGH7XDBKsupport non-text lines in Text.to2 - [20]
M6TH7VSZrip out notion of Line_width - [21]
LF7BWEG4group all editor globals - [22]
WJBZZQE4fold together two largely similar cases - [23]
NDHQN23Gdone passing left/right margins everywhere - [24]
MXA3RZYKdeduce left/right from state where possible - [25]
ODLKHO7Bswitch to line index in a function - [26]
HGC5RGJPswitch to line index in a function - [27]
ILOA5BYFseparate data structure for each line's cache data - [28]
KURLAXXIclean up some prints - [29]
2RXZ3PGObeginning of a new approach to scroll+wrap - [30]
EAEGCJV5rename - [31]
KOYAJWE4extract a couple more methods - [32]
X3F7ECSLadd state arg to some functions - [33]
X3CQLBTRset window title within each app - [34]
IMEJA43Lsnapshot - [35]
KECEMMMRextract couple of functions - [36]
2L5MEZV3experiment: new edit namespace - [37]
CVSRHMJ2experiment: slightly adaptive scrolling - [38]
2LOQ5ALJadd args to some functions - [39]
LNUHQOGHstart passing in Editor_state explicitly - [40]
QYIFOHW3first test! - [41]
Z5HLXU4Padd state arg to a few functions - [42]
F65ADDGLadd state arg to a few functions - [43]
LSYLEVBDdrop some redundant args when clearing the cache - [44]
HOSPP2ANcrisp font rendering - [45]
SPNMXTYRhave file API operate on state object - [46]
5USLYLBVduplicate - [*]
BULPIBEGbeginnings of a module for the text editor - [*]
GNQC72UXgeneralize a function - [*]
KOTI3MFGbugfix in previous commit - [*]
OTIBCAUJlove2d scaffold - [*]
K464QQR4more defensive resize handling
Change contents
- replacement in text.lua at line 118
--? print('x: '..tostring(x)..'; '..tostring(State.right-x)..'px to go')--? print('x: '..tostring(x)..'; frag_width: '..tostring(frag_width)..'; '..tostring(State.right-x)..'px to go') - replacement in text.lua at line 368
State.cursor1.line = State.cursor1.line+1State.cursor1.pos = 1State.cursor1 = {line=State.cursor1.line+1, pos=1} - replacement in text.lua at line 388
State.cursor1.line = State.screen_top1.lineState.cursor1.pos = State.screen_top1.posState.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} - replacement in text.lua at line 407
State.screen_top1.line = State.screen_bottom1.lineState.screen_top1.pos = State.screen_bottom1.posState.screen_top1 = {line=State.screen_bottom1.line, pos=State.screen_bottom1.pos} - replacement in text.lua at line 410
State.cursor1.line = State.screen_top1.lineState.cursor1.pos = State.screen_top1.posState.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} - replacement in text.lua at line 429
State.cursor1.line = new_cursor_lineState.cursor1 = {line=State.cursor1.line-1, pos=nil} - replacement in text.lua at line 468
State.cursor1.line = new_cursor_lineState.cursor1.pos = Text.nearest_cursor_pos(State.lines[State.cursor1.line].data, State.cursor_x, State.left)State.cursor1 = {line = new_cursor_line,pos = Text.nearest_cursor_pos(State.lines[new_cursor_line].data, State.cursor_x, State.left),} - edit in text.lua at line 487
Text.populate_screen_line_starting_pos(State, State.cursor1.line) - replacement in text.lua at line 584
State.cursor1.line = new_cursor_lineState.cursor1.pos = utf8.len(State.lines[State.cursor1.line].data) + 1State.cursor1 = {line = new_cursor_line,pos = utf8.len(State.lines[new_cursor_line].data) + 1,} - replacement in text.lua at line 615
State.cursor1.line = new_cursor_lineState.cursor1.pos = 1State.cursor1 = {line=new_cursor_line, pos=1} - edit in text.lua at line 666
--? print('to2:', State.cursor1.line, State.cursor1.pos) - edit in text.lua at line 668
--? print('to2: =>', top2.line, top2.screen_line, top2.screen_pos)-- slide to start of screen line - edit in text.lua at line 671
--? print('snap', State.screen_top1.line, State.screen_top1.pos, State.screen_top1.posB, State.cursor1.line, State.cursor1.pos, State.screen_bottom1.line, State.screen_bottom1.pos) - edit in text.lua at line 701
--? print('snap =>', State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos, State.screen_bottom1.line, State.screen_bottom1.pos) - replacement in text.lua at line 861
local result = {line=loc1.line, screen_line=1}local result = {line=loc1.line} - edit in source_undo.lua at line 53
current_drawing_mode=Drawing_mode,previous_drawing_mode=State.previous_drawing_mode, - replacement in source_undo.lua at line 63
table.insert(event.lines, {data=line.data, dataB=line.dataB})if line.mode == 'text' thentable.insert(event.lines, {mode='text', data=line.data, dataB=line.dataB})elseif line.mode == 'drawing' thenlocal points=deepcopy(line.points)--? print('copying', line.points, 'with', #line.points, 'points into', points)local shapes=deepcopy(line.shapes)--? print('copying', line.shapes, 'with', #line.shapes, 'shapes into', shapes)table.insert(event.lines, {mode='drawing', h=line.h, points=points, shapes=shapes, pending={}})--? table.insert(event.lines, {mode='drawing', h=line.h, points=deepcopy(line.points), shapes=deepcopy(line.shapes), pending={}})elseprint(line.mode)assert(false)end - edit in source_text_tests.lua at line 15
endfunction test_click_to_create_drawing()io.write('\ntest_click_to_create_drawing')App.screen.init{width=120, height=60}Editor_state = edit.initialize_test_state()Editor_state.lines = load_array{}Text.redraw_all(Editor_state)edit.draw(Editor_state)edit.run_after_mouse_click(Editor_state, 8,Editor_state.top+8, 1)-- cursor skips drawing to always remain on textcheck_eq(#Editor_state.lines, 2, 'F - test_click_to_create_drawing/#lines')check_eq(Editor_state.cursor1.line, 2, 'F - test_click_to_create_drawing/cursor')endfunction test_backspace_to_delete_drawing()io.write('\ntest_backspace_to_delete_drawing')-- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)App.screen.init{width=120, height=60}Editor_state = edit.initialize_test_state()Editor_state.lines = load_array{'```lines', '```', ''}Text.redraw_all(Editor_state)-- cursor is on text as always (outside tests this will get initialized correctly)Editor_state.cursor1.line = 2-- backspacing deletes the drawingedit.run_after_keychord(Editor_state, 'backspace')check_eq(#Editor_state.lines, 1, 'F - test_backspace_to_delete_drawing/#lines')check_eq(Editor_state.cursor1.line, 1, 'F - test_backspace_to_delete_drawing/cursor') - edit in source_text_tests.lua at line 724
endfunction test_pagedown_skips_drawings()io.write('\ntest_pagedown_skips_drawings')-- some lines of text with a drawing intermixedlocal drawing_width = 50App.screen.init{width=Editor_state.left+drawing_width, height=80}Editor_state = edit.initialize_test_state()Editor_state.lines = load_array{'abc', -- height 15'```lines', '```', -- height 25'def', -- height 15'ghi'} -- height 15Text.redraw_all(Editor_state)check_eq(Editor_state.lines[2].mode, 'drawing', 'F - test_pagedown_skips_drawings/baseline/lines')Editor_state.cursor1 = {line=1, pos=1}Editor_state.screen_top1 = {line=1, pos=1}Editor_state.screen_bottom1 = {}local drawing_height = Drawing_padding_height + drawing_width/2 -- default-- initially the screen displays the first line and the drawing-- 15px margin + 15px line1 + 10px margin + 25px drawing + 10px margin = 75px < screen height 80pxedit.draw(Editor_state)local y = Editor_state.topApp.screen.check(y, 'abc', 'F - test_pagedown_skips_drawings/baseline/screen:1')-- after pagedown the screen draws the drawing up top-- 15px margin + 10px margin + 25px drawing + 10px margin + 15px line3 = 75px < screen height 80pxedit.run_after_keychord(Editor_state, 'pagedown')check_eq(Editor_state.screen_top1.line, 2, 'F - test_pagedown_skips_drawings/screen_top')check_eq(Editor_state.cursor1.line, 3, 'F - test_pagedown_skips_drawings/cursor')y = Editor_state.top + drawing_heightApp.screen.check(y, 'def', 'F - test_pagedown_skips_drawings/screen:1') - replacement in source_text_tests.lua at line 1588
Editor_state.lines = load_array{'abc', 'def', 'ghi', 'deg'}Editor_state.lines = load_array{'```lines', '```', 'def', 'ghi', 'deg'} - edit in source_text.lua at line 56
--? if Foo then--? print('draw:', State.lines[line_index].data, "=====", State.lines[line_index].dataB, 'starting from x', x+AB_padding)--? end - edit in source_text.lua at line 196
if line.mode ~= 'text' then return end - edit in source_text.lua at line 223
if line.mode ~= 'text' then return end - replacement in source_text.lua at line 418
-- join linesState.cursor1.pos = utf8.len(State.lines[State.cursor1.line-1].data)+1State.lines[State.cursor1.line-1].data = State.lines[State.cursor1.line-1].data..State.lines[State.cursor1.line].datatable.remove(State.lines, State.cursor1.line)table.remove(State.line_cache, State.cursor1.line)if State.lines[State.cursor1.line-1].mode == 'drawing' thentable.remove(State.lines, State.cursor1.line-1)table.remove(State.line_cache, State.cursor1.line-1)else-- join linesState.cursor1.pos = utf8.len(State.lines[State.cursor1.line-1].data)+1State.lines[State.cursor1.line-1].data = State.lines[State.cursor1.line-1].data..State.lines[State.cursor1.line].datatable.remove(State.lines, State.cursor1.line)table.remove(State.line_cache, State.cursor1.line)end - replacement in source_text.lua at line 478
-- join linesState.lines[State.cursor1.line].data = State.lines[State.cursor1.line].data..State.lines[State.cursor1.line+1].data-- delete side B on first lineState.lines[State.cursor1.line].dataB = State.lines[State.cursor1.line+1].dataBif State.lines[State.cursor1.line+1].mode == 'text' then-- join linesState.lines[State.cursor1.line].data = State.lines[State.cursor1.line].data..State.lines[State.cursor1.line+1].data-- delete side B on first lineState.lines[State.cursor1.line].dataB = State.lines[State.cursor1.line+1].dataBend - replacement in source_text.lua at line 539
table.insert(State.lines, State.cursor1.line+1, {data=string.sub(State.lines[State.cursor1.line].data, byte_offset), dataB=State.lines[State.cursor1.line].dataB})table.insert(State.lines, State.cursor1.line+1, {mode='text', data=string.sub(State.lines[State.cursor1.line].data, byte_offset), dataB=State.lines[State.cursor1.line].dataB}) - replacement in source_text.lua at line 559
y = y - State.line_heightif State.lines[State.screen_top1.line].mode == 'text' theny = y - State.line_heightelseif State.lines[State.screen_top1.line].mode == 'drawing' theny = y - Drawing_padding_height - Drawing.pixels(State.lines[State.screen_top1.line].h, State.width)end - replacement in source_text.lua at line 580
State.screen_top1 = {line=State.screen_bottom1.line, pos=State.screen_bottom1.pos}State.screen_top1 = {line=State.screen_bottom1.line, pos=State.screen_bottom1.pos, posB=State.screen_bottom1.posB} - edit in source_text.lua at line 591
assert(State.lines[State.cursor1.line].mode == 'text') - replacement in source_text.lua at line 605
if State.cursor1.line > 1 then--? print('found previous text line')State.cursor1 = {line=State.cursor1.line-1, pos=nil}Text.populate_screen_line_starting_pos(State, State.cursor1.line)-- previous text line found, pick its final screen line--? print('has multiple screen lines')local screen_line_starting_pos = State.line_cache[State.cursor1.line].screen_line_starting_pos--? print(#screen_line_starting_pos)screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos]local screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, screen_line_starting_pos)local s = string.sub(State.lines[State.cursor1.line].data, screen_line_starting_byte_offset)State.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1local new_cursor_line = State.cursor1.linewhile new_cursor_line > 1 donew_cursor_line = new_cursor_line-1if State.lines[new_cursor_line].mode == 'text' then--? print('found previous text line')State.cursor1 = {line=State.cursor1.line-1, pos=nil}Text.populate_screen_line_starting_pos(State, State.cursor1.line)-- previous text line found, pick its final screen line--? print('has multiple screen lines')local screen_line_starting_pos = State.line_cache[State.cursor1.line].screen_line_starting_pos--? print(#screen_line_starting_pos)screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos]local screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, screen_line_starting_pos)local s = string.sub(State.lines[State.cursor1.line].data, screen_line_starting_byte_offset)State.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1breakend - replacement in source_text.lua at line 645
if State.cursor1.line > 1 thenState.cursor1.line = State.cursor1.line-1State.cursor1.posB = nilText.populate_screen_line_starting_pos(State, State.cursor1.line)local prev_line_cache = State.line_cache[State.cursor1.line]local prev_screen_line_starting_pos = prev_line_cache.screen_line_starting_pos[#prev_line_cache.screen_line_starting_pos]local prev_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, prev_screen_line_starting_pos)local s = string.sub(State.lines[State.cursor1.line].data, prev_screen_line_starting_byte_offset)State.cursor1.pos = prev_screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1local new_cursor_line = State.cursor1.linewhile new_cursor_line > 1 donew_cursor_line = new_cursor_line-1if State.lines[new_cursor_line].mode == 'text' thenState.cursor1 = {line=State.cursor1.line-1, posB=nil}Text.populate_screen_line_starting_pos(State, State.cursor1.line)local prev_line_cache = State.line_cache[State.cursor1.line]local prev_screen_line_starting_pos = prev_line_cache.screen_line_starting_pos[#prev_line_cache.screen_line_starting_pos]local prev_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, prev_screen_line_starting_pos)local s = string.sub(State.lines[State.cursor1.line].data, prev_screen_line_starting_byte_offset)State.cursor1.pos = prev_screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1breakend - edit in source_text.lua at line 696
assert(State.lines[State.cursor1.line].mode == 'text') - replacement in source_text.lua at line 701
if State.cursor1.line < #State.lines thenState.cursor1 = {line = State.cursor1.line+1,pos = Text.nearest_cursor_pos(State.lines[State.cursor1.line+1].data, State.cursor_x, State.left)}--? print(State.cursor1.pos)local new_cursor_line = State.cursor1.linewhile new_cursor_line < #State.lines donew_cursor_line = new_cursor_line+1if State.lines[new_cursor_line].mode == 'text' thenState.cursor1 = {line = new_cursor_line,pos = Text.nearest_cursor_pos(State.lines[new_cursor_line].data, State.cursor_x, State.left),}--? print(State.cursor1.pos)breakend - replacement in source_text.lua at line 766
State.screen_top1 = {line=State.cursor1.line, pos=1} -- copyState.screen_top1 = {line=State.cursor1.line, pos=State.cursor1.pos, posB=State.cursor1.posB} -- copy - replacement in source_text.lua at line 948
elseif State.cursor1.line > 1 thenState.cursor1 = {line = State.cursor1.line-1,pos = utf8.len(State.lines[State.cursor1.line-1].data) + 1,}elselocal new_cursor_line = State.cursor1.linewhile new_cursor_line > 1 donew_cursor_line = new_cursor_line-1if State.lines[new_cursor_line].mode == 'text' thenState.cursor1 = {line = new_cursor_line,pos = utf8.len(State.lines[new_cursor_line].data) + 1,}breakendend - edit in source_text.lua at line 991
assert(State.lines[State.cursor1.line].mode == 'text') - replacement in source_text.lua at line 1002
elseif State.cursor1.line <= #State.lines-1 thenState.cursor1 = {line=State.cursor1.line+1, pos=1}elselocal new_cursor_line = State.cursor1.linewhile new_cursor_line <= #State.lines-1 donew_cursor_line = new_cursor_line+1if State.lines[new_cursor_line].mode == 'text' thenState.cursor1 = {line=new_cursor_line, pos=1}breakendend - replacement in source_text.lua at line 1017
elseif State.cursor1.line <= #State.lines-1 thenelse - replacement in source_text.lua at line 1019
State.cursor1 = {line=State.cursor1.line+1, pos=1}local new_cursor_line = State.cursor1.linewhile new_cursor_line <= #State.lines-1 donew_cursor_line = new_cursor_line+1if State.lines[new_cursor_line].mode == 'text' thenState.cursor1 = {line=new_cursor_line, pos=1}breakendend - replacement in source_text.lua at line 1078
if State.top > App.screen.height - State.line_height thenlocal y = State.topwhile State.cursor1.line <= #State.lines doif State.lines[State.cursor1.line].mode == 'text' thenbreakend--? print('cursor skips', State.cursor1.line)y = y + Drawing_padding_height + Drawing.pixels(State.lines[State.cursor1.line].h, State.width)State.cursor1.line = State.cursor1.line + 1end-- hack: insert a text line at bottom of file if necessaryif State.cursor1.line > #State.lines thenassert(State.cursor1.line == #State.lines+1)table.insert(State.lines, {mode='text', data=''})table.insert(State.line_cache, {})end--? print(y, App.screen.height, App.screen.height-State.line_height)if y > App.screen.height - State.line_height then - replacement in source_text.lua at line 1119
local h = State.line_heightif y - h < State.top thenbreakif top2.screen_line > 1 or State.lines[top2.line-1].mode == 'text' thenlocal h = State.line_heightif y - h < State.top thenbreakendy = y - helseassert(top2.line > 1)assert(State.lines[top2.line-1].mode == 'drawing')-- We currently can't draw partial drawings, so either skip it entirely-- or not at all.local h = Drawing_padding_height + Drawing.pixels(State.lines[top2.line-1].h, State.width)if y - h < State.top thenbreakend--? print('skipping drawing of height', h)y = y - h - edit in source_text.lua at line 1137
y = y - h - edit in source_text.lua at line 1144
Foo = true - edit in source_text.lua at line 1417
if State.lines[loc1.line].mode == 'drawing' thenreturn {line=loc1.line, screen_line=1, screen_pos=1}end - edit in source_text.lua at line 1530
--? print('a') - edit in source_text.lua at line 1532
--? print('b') - replacement in source_file.lua at line 28
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 autogeneratedtable.insert(result, load_drawing(infile_next_line)) - replacement in source_file.lua at line 31
line_info.data = linelocal line_info = {mode='text'}if line:find(Fold) then_, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)')elseline_info.data = lineendtable.insert(result, line_info) - edit in source_file.lua at line 39
table.insert(result, line_info) - replacement in source_file.lua at line 42
table.insert(result, {data=''})table.insert(result, {mode='text', data=''}) - replacement in source_file.lua at line 53
outfile:write(line.data)if line.dataB and #line.dataB > 0 thenoutfile:write(Fold)outfile:write(line.dataB)if line.mode == 'drawing' thenstore_drawing(outfile, line)elseoutfile:write(line.data)if line.dataB and #line.dataB > 0 thenoutfile:write(Fold)outfile:write(line.dataB)endoutfile:write('\n') - edit in source_file.lua at line 63
outfile:write('\n') - edit in source_file.lua at line 65
endfunction load_drawing(infile_next_line)local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}while true dolocal line = infile_next_line()assert(line)if line == '```' then break endlocal shape = json.decode(line)if shape.mode == 'freehand' then-- no changes neededelseif shape.mode == 'line' or shape.mode == 'manhattan' thenlocal name = shape.p1.nameshape.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 = namename = shape.p2.nameshape.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 = nameelseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' thenfor i,p in ipairs(shape.vertices) dolocal name = p.nameshape.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 = nameendelseif shape.mode == 'circle' or shape.mode == 'arc' thenlocal name = shape.center.nameshape.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 = nameelseif shape.mode == 'deleted' then-- ignoreelseprint(shape.mode)assert(false)endtable.insert(drawing.shapes, shape)endreturn drawingendfunction store_drawing(outfile, drawing)outfile:write('```lines\n')for _,shape in ipairs(drawing.shapes) doif shape.mode == 'freehand' thenoutfile:write(json.encode(shape), '\n')elseif shape.mode == 'line' or shape.mode == 'manhattan' thenlocal 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' thenlocal obj = {mode=shape.mode, vertices={}}for _,p in ipairs(shape.vertices) dotable.insert(obj.vertices, drawing.points[p])endlocal line = json.encode(obj)outfile:write(line, '\n')elseif shape.mode == 'circle' thenoutfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius}), '\n')elseif shape.mode == 'arc' thenoutfile: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-- ignoreelseprint(shape.mode)assert(false)endendoutfile:write('```\n') - replacement in source_file.lua at line 141
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) - replacement in source_file.lua at line 148
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..']*)')elseline_info.data = lineendtable.insert(result, line_info) - edit in source_file.lua at line 157
table.insert(result, line_info) - replacement in source_file.lua at line 159
table.insert(result, {data=''})table.insert(result, {mode='text', data=''}) - edit in source_file.lua at line 163[6.152398]
function load_drawing_from_array(iter, a, i)local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}local linewhile true doi, line = iter(a, i)assert(i)--? print(i)if line == '```' then break endlocal shape = json.decode(line)if shape.mode == 'freehand' then-- no changes neededelseif shape.mode == 'line' or shape.mode == 'manhattan' thenlocal name = shape.p1.nameshape.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 = namename = shape.p2.nameshape.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 = nameelseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' thenfor i,p in ipairs(shape.vertices) dolocal name = p.nameshape.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 = nameendelseif shape.mode == 'circle' or shape.mode == 'arc' thenlocal name = shape.center.nameshape.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 = nameelseif shape.mode == 'deleted' then-- ignoreelseprint(shape.mode)assert(false)endtable.insert(drawing.shapes, shape)endreturn i, drawingend - edit in source_edit.lua at line 4
Stroke_color = {r=0, g=0, b=0}Current_stroke_color = {r=0.7, g=0.7, b=0.7} -- in process of being drawnCurrent_name_background_color = {r=1, g=0, b=0, a=0.1} -- name currently being edited - edit in source_edit.lua at line 9
Icon_color = {r=0.7, g=0.7, b=0.7} -- color of current mode icon in drawingsHelp_color = {r=0, g=0.5, b=0}Help_background_color = {r=0, g=0.5, b=0, a=0.1} - edit in source_edit.lua at line 18
Drawing_padding_top = 10Drawing_padding_bottom = 10Drawing_padding_height = Drawing_padding_top + Drawing_padding_bottom - edit in source_edit.lua at line 23
Same_point_distance = 4 -- pixel distance at which two points are considered the same - replacement in source_edit.lua at line 30
-- a line of bifold text consists of an A side and an optional B side, each of which is a string-- expanded: whether to show B sidelines = {{data='', dataB=nil, expanded=nil}}, -- array of lines-- a line is either bifold text or a drawing-- a line of bifold text consists of an A side and an optional B side-- mode = 'text',-- string data,-- string dataB,-- expanded: whether to show B side-- a drawing is a table with:-- mode = 'drawing'-- a (y) coord in pixels (updated while painting screen),-- a (h)eight,-- an array of points, and-- an array of shapes-- a shape is a table containing:-- a mode-- an array points for mode 'freehand' (raw x,y coords; freehand drawings don't pollute the points array of a drawing)-- an array vertices for mode 'polygon', 'rectangle', 'square'-- p1, p2 for mode 'line'-- center, radius for mode 'circle'-- center, radius, start_angle, end_angle for mode 'arc'-- Unless otherwise specified, coord fields are normalized; a drawing is always 256 units wide-- The field names are carefully chosen so that switching modes in midstream-- remembers previously entered points where that makes sense.lines = {{mode='text', data='', dataB=nil, expanded=nil}}, -- array of lines - edit in source_edit.lua at line 82
current_drawing_mode = 'line',previous_drawing_mode = nil, -- extra state for some ephemeral modes like moving/deleting/naming points - edit in source_edit.lua at line 109
function edit.fixup_cursor(State)for i,line in ipairs(State.lines) doif line.mode == 'text' thenState.cursor1.line = ibreakendendend - replacement in source_edit.lua at line 132
--? print('draw:', y, line_index, line)--? print('draw:', y, line_index, line, line.mode) - edit in source_edit.lua at line 135
if line.mode == 'text' then - replacement in source_edit.lua at line 137
local startpos, startposB = 1, nilif line_index == State.screen_top1.line thenif State.screen_top1.pos thenstartpos = State.screen_top1.poselsestartpos, startposB = nil, State.screen_top1.posBlocal startpos, startposB = 1, nilif line_index == State.screen_top1.line thenif State.screen_top1.pos thenstartpos = State.screen_top1.poselsestartpos, startposB = nil, State.screen_top1.posBendendif line.data == '' then-- button to insert new drawingbutton(State, 'draw', {x=4,y=y+4, w=12,h=12, color={1,1,0},icon = icon.insert_drawing,onpress1 = function()Drawing.before = snapshot(State, line_index-1, line_index)table.insert(State.lines, line_index, {mode='drawing', y=y, h=256/2, points={}, shapes={}, pending={}})table.insert(State.line_cache, line_index, {})if State.cursor1.line >= line_index thenState.cursor1.line = State.cursor1.line+1endschedule_save(State)record_undo_event(State, {before=Drawing.before, after=snapshot(State, line_index-1, line_index+1)})end,}) - edit in source_edit.lua at line 161
y, State.screen_bottom1.pos, State.screen_bottom1.posB = Text.draw(State, line_index, y, startpos, startposB)y = y + State.line_height--? print('=> y', y)elseif line.mode == 'drawing' theny = y+Drawing_padding_topDrawing.draw(State, line_index, y)y = y + Drawing.pixels(line.h, State.width) + Drawing_padding_bottomelseprint(line.mode)assert(false) - edit in source_edit.lua at line 172
y, State.screen_bottom1.pos, State.screen_bottom1.posB = Text.draw(State, line_index, y, startpos, startposB)y = y + State.line_height--? print('=> y', y) - edit in source_edit.lua at line 179
Drawing.update(State, dt) - replacement in source_edit.lua at line 201
--? print('press', State.selection1.line, State.selection1.pos)--? print('press') - replacement in source_edit.lua at line 208
if Text.in_line(State, line_index, x,y) thenlocal pos,posB = Text.to_pos_on_line(State, line_index, x, y)--? print(x,y, 'setting cursor:', line_index, pos, posB)State.cursor1 = {line=line_index, pos=pos, posB=posB}breakif line.mode == 'text' thenif Text.in_line(State, line_index, x,y) thenlocal pos,posB = Text.to_pos_on_line(State, line_index, x, y)--? print(x,y, 'setting cursor:', line_index, pos, posB)State.cursor1 = {line=line_index, pos=pos, posB=posB}breakendelseif line.mode == 'drawing' thenlocal line_cache = State.line_cache[line_index]if Drawing.in_drawing(line, line_cache, x, y, State.left,State.right) thenState.lines.current_drawing_index = line_indexState.lines.current_drawing = lineDrawing.before = snapshot(State, line_index)Drawing.mouse_pressed(State, line_index, x,y, mouse_button)breakend - edit in source_edit.lua at line 229
if State.search_term then return end--? print('release')if State.lines.current_drawing thenDrawing.mouse_released(State, x,y, mouse_button)schedule_save(State)if Drawing.before thenrecord_undo_event(State, {before=Drawing.before, after=snapshot(State, State.lines.current_drawing_index)})Drawing.before = nilendend - edit in source_edit.lua at line 247
elseif State.current_drawing_mode == 'name' thenlocal before = snapshot(State, State.lines.current_drawing_index)local drawing = State.lines.current_drawinglocal p = drawing.points[drawing.pending.target_point]p.name = p.name..trecord_undo_event(State, {before=before, after=snapshot(State, State.lines.current_drawing_index)}) - replacement in source_edit.lua at line 305
elseif chord == 'C-d' thenelseif chord == 'C-i' then - edit in source_edit.lua at line 340
-- invalidate various cached bits of linesState.lines.current_drawing = nil - edit in source_edit.lua at line 354
-- invalidate various cached bits of linesState.lines.current_drawing = nil - replacement in source_edit.lua at line 393
-- dispatch to text-- dispatch to drawing or textelseif App.mouse_down(1) or chord:sub(1,2) == 'C-' then-- DON'T reset line_cache.starty herelocal drawing_index, drawing = Drawing.current_drawing(State)if drawing_index thenlocal before = snapshot(State, drawing_index)Drawing.keychord_pressed(State, chord)record_undo_event(State, {before=before, after=snapshot(State, drawing_index)})schedule_save(State)endelseif chord == 'escape' and not App.mouse_down(1) thenfor _,line in ipairs(State.lines) doif line.mode == 'drawing' thenline.show_help = falseendendelseif State.current_drawing_mode == 'name' thenif chord == 'return' thenState.current_drawing_mode = State.previous_drawing_modeState.previous_drawing_mode = nilelselocal before = snapshot(State, State.lines.current_drawing_index)local drawing = State.lines.current_drawinglocal p = drawing.points[drawing.pending.target_point]if chord == 'escape' thenp.name = nilrecord_undo_event(State, {before=before, after=snapshot(State, State.lines.current_drawing_index)})elseif chord == 'backspace' thenlocal len = utf8.len(p.name)local byte_offset = Text.offset(p.name, len-1)if len == 1 then byte_offset = 0 endp.name = string.sub(p.name, 1, byte_offset)record_undo_event(State, {before=before, after=snapshot(State, State.lines.current_drawing_index)})endendschedule_save(State) - replacement in source.lua at line 280
if Editor_state.left <= x and x < Editor_state.right thenif x < Editor_state.right + Margin_right then - edit in main.lua at line 26[6.184859][52.162]
-- both sides use drawingsload_file_from_source_or_save_directory('icons.lua')load_file_from_source_or_save_directory('drawing.lua')load_file_from_source_or_save_directory('geom.lua')load_file_from_source_or_save_directory('help.lua')load_file_from_source_or_save_directory('drawing_tests.lua') - edit in main.lua at line 53
load_file_from_source_or_save_directory('icons.lua') - edit in main.lua at line 55
load_file_from_source_or_save_directory('drawing.lua')load_file_from_source_or_save_directory('geom.lua')load_file_from_source_or_save_directory('help.lua')load_file_from_source_or_save_directory('drawing_tests.lua') - replacement in file.lua at line 47
outfile:write(line.data, '\n')outfile:write(line.data)outfile:write('\n') - replacement in edit.lua at line 137
State.screen_bottom1.line = line_indexState.screen_bottom1 = {line=line_index, pos=nil} - edit in edit.lua at line 172
--? print('screen bottom: '..tostring(State.screen_bottom1.pos)..' in '..tostring(State.lines[State.screen_bottom1.line].data)) - replacement in edit.lua at line 333
State.search_backup = {cursor={line=State.cursor1.line, pos=State.cursor1.pos}, screen_top={line=State.screen_top1.line, pos=State.screen_top1.pos}}State.search_backup = {cursor={line=State.cursor1.line, pos=State.cursor1.pos},screen_top={line=State.screen_top1.line, pos=State.screen_top1.pos},} - replacement in commands.lua at line 31
add_hotkey_to_menu('ctrl+d: create/edit debug print')add_hotkey_to_menu('ctrl+i: create/edit debug print')