From 7f433753b6f84e1107a2c3298ade3b309c493795 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 26 Mar 2023 07:19:27 -0700 Subject: bugfix scenario: open a file starting with a drawing After this commit the program doesn't crash. Error: [string "edit.lua"]:127: attempt to get length of field 'data' (a nil value) stack traceback: [love "boot.lua"]:345: in function '__len' [string "edit.lua"]:127: in function 'invalid1' [string "edit.lua"]:116: in function 'check_locs' [string "run.lua"]:35: in function 'initialize' main.lua:96: in function 'initialize' [string "app.lua"]:144: in function 'run_tests_and_initialize' [string "app.lua"]:16: in function <[string "app.lua"]:13> [C]: in function 'xpcall' [love "boot.lua"]:361: in function <[love "boot.lua"]:348> [C]: in function 'xpcall' --- edit.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/edit.lua b/edit.lua index 2b405a7..c05a2e5 100644 --- a/edit.lua +++ b/edit.lua @@ -122,8 +122,10 @@ function edit.check_locs(State) end function edit.invalid1(State, loc1) - return loc1.line > #State.lines - or loc1.pos > #State.lines[loc1.line].data + if loc1.line > #State.lines then return true end + local l = State.lines[loc1.line] + if l.mode ~= 'text' then return false end -- pos is irrelevant to validity for a drawing line + return loc1.pos > #State.lines[loc1.line].data end function edit.cursor_on_text(State) -- cgit 1.4.1-2-gfad0 From 0ae94b0de59618bb86a55edcaa8e961abb192f2d Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 26 Mar 2023 08:17:31 -0700 Subject: bugfix --- drawing_tests.lua | 31 +++++++++++++++++++++++++++++++ edit.lua | 10 ++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drawing_tests.lua b/drawing_tests.lua index 91c4825..0c4de54 100644 --- a/drawing_tests.lua +++ b/drawing_tests.lua @@ -426,6 +426,37 @@ function test_name_point() check_eq(p2.name, 'A', 'save') end +function test_name_point_then_hit_backspace() + -- create a drawing with a line + App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state = edit.initialize_test_state() + Editor_state.filename = 'foo' + Editor_state.lines = load_array{'```lines', '```', ''} + Text.redraw_all(Editor_state) + Editor_state.current_drawing_mode = 'line' + edit.draw(Editor_state) + -- draw a line + edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1) + edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] + check_eq(#drawing.shapes, 1, 'baseline/#shapes') + check_eq(#drawing.points, 2, 'baseline/#points') + check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1') + local p1 = drawing.points[drawing.shapes[1].p1] + local p2 = drawing.points[drawing.shapes[1].p2] + check_eq(p1.x, 5, 'baseline/p1:x') + check_eq(p1.y, 6, 'baseline/p1:y') + check_eq(p2.x, 35, 'baseline/p2:x') + check_eq(p2.y, 36, 'baseline/p2:y') + check_nil(p2.name, 'baseline/p2:name') + -- enter 'name' mode without moving the mouse + edit.run_after_keychord(Editor_state, 'C-n') + check_eq(Editor_state.current_drawing_mode, 'name', 'mode:1') + -- hit backspace + edit.run_after_keychord(Editor_state, 'backspace') + -- no crash +end + function test_move_point() -- create a drawing with a line App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels diff --git a/edit.lua b/edit.lua index c05a2e5..38c2883 100644 --- a/edit.lua +++ b/edit.lua @@ -491,10 +491,12 @@ function edit.keychord_press(State, chord, key) record_undo_event(State, {before=before, after=snapshot(State, State.lines.current_drawing_index)}) elseif chord == 'backspace' then local len = utf8.len(p.name) - local byte_offset = Text.offset(p.name, len-1) - if len == 1 then byte_offset = 0 end - p.name = string.sub(p.name, 1, byte_offset) - record_undo_event(State, {before=before, after=snapshot(State, State.lines.current_drawing_index)}) + if len > 0 then + local byte_offset = Text.offset(p.name, len-1) + if len == 1 then byte_offset = 0 end + p.name = string.sub(p.name, 1, byte_offset) + record_undo_event(State, {before=before, after=snapshot(State, State.lines.current_drawing_index)}) + end end end schedule_save(State) -- cgit 1.4.1-2-gfad0 From eae5c9505c665b343af7690d9665431ae17ed5e9 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 26 Mar 2023 09:36:41 -0700 Subject: bugfix: naming points --- app.lua | 4 +++- drawing_tests.lua | 35 +++++++++++++++++++++++++++++++++++ edit.lua | 9 +++++---- text.lua | 1 + 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/app.lua b/app.lua index 30fc696..59dff31 100644 --- a/app.lua +++ b/app.lua @@ -369,6 +369,7 @@ function App.run_tests() table.sort(sorted_names) for _,name in ipairs(sorted_names) do App.initialize_for_test() +--? print('=== '..name) xpcall(_G[name], function(err) prepend_debug_info_to_test_failure(name, err) end) end -- clean up all test methods @@ -380,9 +381,10 @@ end -- prepend file/line/test function prepend_debug_info_to_test_failure(test_name, err) local err_without_line_number = err:gsub('^[^:]*:[^:]*: ', '') - local stack_trace = debug.traceback('', --[[stack frame]]5) + local stack_trace = debug.traceback('', --[[stack frame]]4) local file_and_line_number = stack_trace:gsub('stack traceback:\n', ''):gsub(': .*', '') local full_error = file_and_line_number..':'..test_name..' -- '..err_without_line_number +--? local full_error = file_and_line_number..':'..test_name..' -- '..err_without_line_number..'\t\t'..stack_trace:gsub('\n', '\n\t\t') table.insert(Test_errors, full_error) end diff --git a/drawing_tests.lua b/drawing_tests.lua index 0c4de54..491ff3a 100644 --- a/drawing_tests.lua +++ b/drawing_tests.lua @@ -457,6 +457,41 @@ function test_name_point_then_hit_backspace() -- no crash end +function test_name_point_then_exit_drawing() + -- create a drawing with a line + App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state = edit.initialize_test_state() + Editor_state.filename = 'foo' + Editor_state.lines = load_array{'```lines', '```', ''} + Text.redraw_all(Editor_state) + edit.check_locs(Editor_state) + Editor_state.current_drawing_mode = 'line' + edit.draw(Editor_state) + -- draw a line + edit.run_after_mouse_press(Editor_state, Editor_state.left+5, Editor_state.top+Drawing_padding_top+6, 1) + edit.run_after_mouse_release(Editor_state, Editor_state.left+35, Editor_state.top+Drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] + check_eq(#drawing.shapes, 1, 'baseline/#shapes') + check_eq(#drawing.points, 2, 'baseline/#points') + check_eq(drawing.shapes[1].mode, 'line', 'baseline/shape:1') + local p1 = drawing.points[drawing.shapes[1].p1] + local p2 = drawing.points[drawing.shapes[1].p2] + check_eq(p1.x, 5, 'baseline/p1:x') + check_eq(p1.y, 6, 'baseline/p1:y') + check_eq(p2.x, 35, 'baseline/p2:x') + check_eq(p2.y, 36, 'baseline/p2:y') + check_nil(p2.name, 'baseline/p2:name') + -- enter 'name' mode without moving the mouse + edit.run_after_keychord(Editor_state, 'C-n') + check_eq(Editor_state.current_drawing_mode, 'name', 'mode:1') + -- click outside the drawing + edit.run_after_mouse_click(Editor_state, App.screen.width-5, App.screen.height-5, 1) + -- press a key + edit.run_after_text_input(Editor_state, 'a') + -- key goes to text + check_eq(Editor_state.lines[2].data, 'a') +end + function test_move_point() -- create a drawing with a line App.screen.init{width=Test_margin_left+256, height=300} -- drawing coordinates 1:1 with pixels diff --git a/edit.lua b/edit.lua index 38c2883..3cea87f 100644 --- a/edit.lua +++ b/edit.lua @@ -226,7 +226,7 @@ end function edit.mouse_press(State, x,y, mouse_button) if State.search_term then return end ---? print('press', State.selection1.line, State.selection1.pos) +--? print('press', State.cursor1.line) if mouse_press_consumed_by_any_button_handler(State, x,y, mouse_button) then -- press on a button and it returned 'true' to short-circuit return @@ -269,7 +269,7 @@ end function edit.mouse_release(State, x,y, mouse_button) if State.search_term then return end ---? print('release') +--? print('release', State.cursor1.line) if State.lines.current_drawing then Drawing.mouse_release(State, x,y, mouse_button) schedule_save(State) @@ -321,11 +321,12 @@ function edit.mouse_wheel_move(State, dx,dy) end function edit.text_input(State, t) +--? print('text input', t) if State.search_term then State.search_term = State.search_term..t State.search_text = nil Text.search_next(State) - elseif State.current_drawing_mode == 'name' then + elseif State.lines.current_drawing and State.current_drawing_mode == 'name' then local before = snapshot(State, State.lines.current_drawing_index) local drawing = State.lines.current_drawing local p = drawing.points[drawing.pending.target_point] @@ -478,7 +479,7 @@ function edit.keychord_press(State, chord, key) line.show_help = false end end - elseif State.current_drawing_mode == 'name' then + elseif State.lines.current_drawing and State.current_drawing_mode == 'name' then if chord == 'return' then State.current_drawing_mode = State.previous_drawing_mode State.previous_drawing_mode = nil diff --git a/text.lua b/text.lua index 35b30c4..589e4fd 100644 --- a/text.lua +++ b/text.lua @@ -161,6 +161,7 @@ function Text.text_input(State, t) end function Text.insert_at_cursor(State, t) + assert(State.lines[State.cursor1.line].mode == 'text') local byte_offset = Text.offset(State.lines[State.cursor1.line].data, State.cursor1.pos) State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_offset-1)..t..string.sub(State.lines[State.cursor1.line].data, byte_offset) Text.clear_screen_line_cache(State, State.cursor1.line) -- cgit 1.4.1-2-gfad0