diff options
-rw-r--r-- | edit.lua | 7 | ||||
-rw-r--r-- | main.lua | 1 | ||||
-rw-r--r-- | select.lua | 8 | ||||
-rw-r--r-- | source_edit.lua | 4 | ||||
-rw-r--r-- | source_text.lua | 28 | ||||
-rw-r--r-- | text.lua | 28 | ||||
-rw-r--r-- | undo.lua | 16 |
7 files changed, 55 insertions, 37 deletions
diff --git a/edit.lua b/edit.lua index 8383a11..af04832 100644 --- a/edit.lua +++ b/edit.lua @@ -177,7 +177,7 @@ function edit.mouse_release(State, x,y, mouse_button) --? print_and_log(('edit.mouse_release(%d,%d): cursor at %d,%d'):format(x,y, State.cursor1.line, State.cursor1.pos)) State.mouse_down = nil if y < State.top then - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) edit.clean_up_mouse_press(State) return end @@ -216,7 +216,7 @@ end function edit.mouse_wheel_move(State, dx,dy) if dy > 0 then - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) for i=1,math.floor(dy) do Text.up(State) end @@ -258,6 +258,9 @@ function edit.keychord_press(State, chord, key) local len = utf8.len(State.search_term) local byte_offset = Text.offset(State.search_term, len) State.search_term = string.sub(State.search_term, 1, byte_offset-1) + State.cursor = deepcopy(State.search_backup.cursor) + State.screen_top = deepcopy(State.search_backup.screen_top) + Text.search_next(State) elseif chord == 'down' then State.cursor1.pos = State.cursor1.pos+1 Text.search_next(State) diff --git a/main.lua b/main.lua index fca94b5..582f05a 100644 --- a/main.lua +++ b/main.lua @@ -48,6 +48,7 @@ function App.load() load_file_from_source_or_save_directory('text.lua') load_file_from_source_or_save_directory('search.lua') load_file_from_source_or_save_directory('select.lua') + load_file_from_source_or_save_directory('undo.lua') load_file_from_source_or_save_directory('text_tests.lua') load_file_from_source_or_save_directory('run_tests.lua') elseif Current_app == 'source' then diff --git a/select.lua b/select.lua index 2d0851a..018ddef 100644 --- a/select.lua +++ b/select.lua @@ -1,9 +1,8 @@ -- helpers for selecting portions of text --- Return any intersection of the region from State.selection1 to State.cursor1 (or --- current mouse, if mouse is pressed; or recent mouse if mouse is pressed and --- currently over a drawing) with the region between {line=line_index, pos=apos} --- and {line=line_index, pos=bpos}. +-- Return any intersection of the region from State.selection1 to +-- State.cursor1 (or current mouse, if mouse is pressed) with the region +-- between {line=line_index, pos=apos} and {line=line_index, pos=bpos}. -- apos must be less than bpos. However State.selection1 and State.cursor1 can be in any order. -- Result: positions spos,epos between apos,bpos. function Text.clip_selection(State, line_index, apos, bpos) @@ -45,7 +44,6 @@ function Text.clip_selection(State, line_index, apos, bpos) end -- draw highlight for line corresponding to (lo,hi) given an approximate x,y and pos on the same screen line --- Creates text objects every time, so use this sparingly. -- Returns some intermediate computation useful elsewhere. function Text.draw_highlight(State, line, x,y, pos, lo,hi) if lo then diff --git a/source_edit.lua b/source_edit.lua index 5351857..34e12c3 100644 --- a/source_edit.lua +++ b/source_edit.lua @@ -308,7 +308,7 @@ function edit.mouse_release(State, x,y, mouse_button) else --? print_and_log('edit.mouse_release: no current drawing') if y < State.top then - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) edit.clean_up_mouse_press(State) return end @@ -351,7 +351,7 @@ end function edit.mouse_wheel_move(State, dx,dy) if dy > 0 then - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) edit.put_cursor_on_next_text_line(State) for i=1,math.floor(dy) do Text.up(State) diff --git a/source_text.lua b/source_text.lua index 6e0c4f9..931dd00 100644 --- a/source_text.lua +++ b/source_text.lua @@ -338,12 +338,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-left' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.left(State) elseif chord == 'S-right' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.right(State) -- C- hotkeys reserved for drawings, so we'll use M- @@ -355,12 +355,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'M-S-left' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.word_left(State) elseif chord == 'M-S-right' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.word_right(State) elseif chord == 'home' then @@ -371,12 +371,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-home' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.start_of_line(State) elseif chord == 'S-end' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.end_of_line(State) elseif chord == 'up' then @@ -387,12 +387,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-up' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.up(State) elseif chord == 'S-down' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.down(State) elseif chord == 'pageup' then @@ -403,12 +403,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-pageup' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.pageup(State) elseif chord == 'S-pagedown' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.pagedown(State) end @@ -425,7 +425,7 @@ end function Text.pageup(State) State.screen_top1 = Text.previous_screen_top1(State) - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State) Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks end @@ -474,7 +474,7 @@ end function Text.pagedown(State) State.screen_top1 = Text.screen_bottom1(State) - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State) Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks end @@ -594,7 +594,7 @@ end function Text.start_of_line(State) State.cursor1.pos = 1 if Text.lt1(State.cursor1, State.screen_top1) then - State.screen_top1 = {line=State.cursor1.line, pos=State.cursor1.pos} -- copy + State.screen_top1 = deepcopy(State.cursor1) end end @@ -1103,7 +1103,7 @@ function Text.tweak_screen_top_and_cursor(State) -- make sure cursor is on screen local screen_bottom1 = Text.screen_bottom1(State) if Text.lt1(State.cursor1, State.screen_top1) then - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) elseif State.cursor1.line >= screen_bottom1.line then if Text.cursor_out_of_screen(State) then State.cursor1 = Text.final_text_loc_on_screen(State) diff --git a/text.lua b/text.lua index ec28509..f2f4d6e 100644 --- a/text.lua +++ b/text.lua @@ -146,12 +146,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-left' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.left(State) elseif chord == 'S-right' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.right(State) -- C- hotkeys reserved for drawings, so we'll use M- @@ -163,12 +163,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'M-S-left' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.word_left(State) elseif chord == 'M-S-right' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.word_right(State) elseif chord == 'home' then @@ -179,12 +179,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-home' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.start_of_line(State) elseif chord == 'S-end' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.end_of_line(State) elseif chord == 'up' then @@ -195,12 +195,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-up' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.up(State) elseif chord == 'S-down' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.down(State) elseif chord == 'pageup' then @@ -211,12 +211,12 @@ function Text.keychord_press(State, chord) State.selection1 = {} elseif chord == 'S-pageup' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.pageup(State) elseif chord == 'S-pagedown' then if State.selection1.line == nil then - State.selection1 = {line=State.cursor1.line, pos=State.cursor1.pos} + State.selection1 = deepcopy(State.cursor1) end Text.pagedown(State) end @@ -224,7 +224,7 @@ end function Text.pageup(State) State.screen_top1 = Text.previous_screen_top1(State) - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State) Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks end @@ -262,7 +262,7 @@ end function Text.pagedown(State) State.screen_top1 = Text.screen_bottom1(State) - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State) Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks end @@ -366,7 +366,7 @@ end function Text.start_of_line(State) State.cursor1.pos = 1 if Text.lt1(State.cursor1, State.screen_top1) then - State.screen_top1 = {line=State.cursor1.line, pos=State.cursor1.pos} -- copy + State.screen_top1 = deepcopy(State.cursor1) end end @@ -806,7 +806,7 @@ function Text.tweak_screen_top_and_cursor(State) -- make sure cursor is on screen local screen_bottom1 = Text.screen_bottom1(State) if Text.lt1(State.cursor1, State.screen_top1) then - State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos} + State.cursor1 = deepcopy(State.screen_top1) elseif State.cursor1.line >= screen_bottom1.line then if Text.cursor_out_of_screen(State) then State.cursor1 = Text.final_text_loc_on_screen(State) diff --git a/undo.lua b/undo.lua new file mode 100644 index 0000000..fcfdb6a --- /dev/null +++ b/undo.lua @@ -0,0 +1,16 @@ +-- https://stackoverflow.com/questions/640642/how-do-you-copy-a-lua-table-by-value/26367080#26367080 +function deepcopy(obj, seen) + if type(obj) ~= 'table' then return obj end + if seen and seen[obj] then return seen[obj] end + local s = seen or {} + local result = setmetatable({}, getmetatable(obj)) + s[obj] = result + for k,v in pairs(obj) do + result[deepcopy(k, s)] = deepcopy(v, s) + end + return result +end + +function minmax(a, b) + return math.min(a,b), math.max(a,b) +end |