6 Commits 549423b018 ... 7e5653c8d3

Author SHA1 Message Date
  Kartik K. Agaram 7e5653c8d3 Merge lines.love 3 weeks ago
  Kartik K. Agaram 6975b8b721 bugfix #3, attempt #2 in search UI 3 weeks ago
  Kartik K. Agaram 0940e72761 bugfix #3 in search UI 3 weeks ago
  Kartik K. Agaram 1693f1f160 bugfix #2 in search UI 3 weeks ago
  Kartik K. Agaram c1a3616964 bugfix in search UI 3 weeks ago
  Kartik K. Agaram 1609d79516 bugfix: restart search on backspace 3 weeks ago
6 changed files with 118 additions and 10 deletions
  1. 1 1
      app.lua
  2. 26 2
      edit.lua
  3. 2 0
      search.lua
  4. 33 7
      source_edit.lua
  5. 28 0
      source_text_tests.lua
  6. 28 0
      text_tests.lua

+ 1 - 1
app.lua

@@ -131,7 +131,7 @@ function App.run_tests()
   end
   table.sort(sorted_names)
 --?   App.initialize_for_test() -- debug: run a single test at a time like these 2 lines
---?   test_click_below_all_lines()
+--?   test_search()
   for _,name in ipairs(sorted_names) do
     App.initialize_for_test()
 --?     print('=== '..name)

+ 26 - 2
edit.lua

@@ -97,6 +97,28 @@ function edit.invalid_cursor1(State)
   return cursor1.pos > #State.lines[cursor1.line].data + 1
 end
 
+function edit.put_cursor_on_next_text_line_wrapping_around_if_necessary(State)
+  local line = State.cursor1.line
+  local max = #State.lines
+  for _ = 1, max-1 do
+    line = (line+1) % max
+    if State.lines[line].mode == 'text' then
+      State.cursor1.line = line
+      State.cursor1.pos = 1
+      break
+    end
+  end
+end
+
+function edit.put_cursor_on_next_loc_wrapping_around_if_necessary(State)
+  local cursor_line = State.lines[State.cursor1.line].data
+  if State.cursor1.pos <= utf8.len(cursor_line) then
+    State.cursor1.pos = State.cursor1.pos + 1
+  else
+    edit.put_cursor_on_next_text_line_wrapping_around_if_necessary(State)
+  end
+end
+
 function edit.draw(State)
   love.graphics.setFont(State.font)
   App.color(Text_color)
@@ -283,8 +305,10 @@ function edit.keychord_press(State, chord, key)
       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)
+      if #State.search_term > 0 then
+        edit.put_cursor_on_next_loc_wrapping_around_if_necessary(State)
+        Text.search_next(State)
+      end
     elseif chord == 'up' then
       Text.search_previous(State)
     end

+ 2 - 0
search.lua

@@ -17,6 +17,7 @@ function Text.draw_search_bar(State)
 end
 
 function Text.search_next(State)
+  if #State.search_term == 0 then return end
   -- search current line from cursor
   local curr_pos = State.cursor1.pos
   local curr_line = State.lines[State.cursor1.line].data
@@ -71,6 +72,7 @@ function Text.search_next(State)
 end
 
 function Text.search_previous(State)
+  if #State.search_term == 0 then return end
   -- search current line before cursor
   local curr_pos = State.cursor1.pos
   local curr_line = State.lines[State.cursor1.line].data

+ 33 - 7
source_edit.lua

@@ -142,15 +142,36 @@ function edit.cursor_on_text(State)
 end
 
 function edit.put_cursor_on_next_text_line(State)
-  while true do
-    if State.cursor1.line >= #State.lines then
+  local line = State.cursor1.line
+  while line < #State.lines do
+    line = line+1
+    if State.lines[line].mode == 'text' then
+      State.cursor1.line = line
+      State.cursor1.pos = 1
       break
     end
-    if State.lines[State.cursor1.line].mode == 'text' then
+  end
+end
+
+function edit.put_cursor_on_next_text_line_wrapping_around_if_necessary(State)
+  local line = State.cursor1.line
+  local max = #State.lines
+  for _ = 1, max-1 do
+    line = (line+1) % max
+    if State.lines[line].mode == 'text' then
+      State.cursor1.line = line
+      State.cursor1.pos = 1
       break
     end
-    State.cursor1.line = State.cursor1.line+1
-    State.cursor1.pos = 1
+  end
+end
+
+function edit.put_cursor_on_next_text_loc_wrapping_around_if_necessary(State)
+  local cursor_line = State.lines[State.cursor1.line].data
+  if State.cursor1.pos <= utf8.len(cursor_line) then
+    State.cursor1.pos = State.cursor1.pos + 1
+  else
+    edit.put_cursor_on_next_text_line_wrapping_around_if_necessary(State)
   end
 end
 
@@ -407,9 +428,14 @@ 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)
-    elseif chord == 'down' then
-      State.cursor1.pos = State.cursor1.pos+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
+      if #State.search_term > 0 then
+        edit.put_cursor_on_next_text_loc_wrapping_around_if_necessary(State)
+        Text.search_next(State)
+      end
     elseif chord == 'up' then
       Text.search_previous(State)
     end

+ 28 - 0
source_text_tests.lua

@@ -2073,3 +2073,31 @@ function test_search_wrap_upwards()
   check_eq(Editor_state.cursor1.line, 1, '1/cursor:line')
   check_eq(Editor_state.cursor1.pos, 6, '1/cursor:pos')
 end
+
+function test_search_downwards_from_end_of_line()
+  App.screen.init{width=120, height=60}
+  Editor_state = edit.initialize_test_state()
+  Editor_state.lines = load_array{'abc', 'def', 'ghi'}
+  Text.redraw_all(Editor_state)
+  Editor_state.cursor1 = {line=1, pos=4}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  edit.draw(Editor_state)
+  -- search for empty string
+  edit.run_after_keychord(Editor_state, 'C-f', 'f')
+  edit.run_after_keychord(Editor_state, 'down', 'down')
+  -- no crash
+end
+
+function test_search_downwards_from_final_pos_of_line()
+  App.screen.init{width=120, height=60}
+  Editor_state = edit.initialize_test_state()
+  Editor_state.lines = load_array{'abc', 'def', 'ghi'}
+  Text.redraw_all(Editor_state)
+  Editor_state.cursor1 = {line=1, pos=3}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  edit.draw(Editor_state)
+  -- search for empty string
+  edit.run_after_keychord(Editor_state, 'C-f', 'f')
+  edit.run_after_keychord(Editor_state, 'down', 'down')
+  -- no crash
+end

+ 28 - 0
text_tests.lua

@@ -1950,3 +1950,31 @@ function test_search_wrap_upwards()
   check_eq(Editor_state.cursor1.line, 1, '1/cursor:line')
   check_eq(Editor_state.cursor1.pos, 6, '1/cursor:pos')
 end
+
+function test_search_downwards_from_end_of_line()
+  App.screen.init{width=120, height=60}
+  Editor_state = edit.initialize_test_state()
+  Editor_state.lines = load_array{'abc', 'def', 'ghi'}
+  Text.redraw_all(Editor_state)
+  Editor_state.cursor1 = {line=1, pos=4}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  edit.draw(Editor_state)
+  -- search for empty string
+  edit.run_after_keychord(Editor_state, 'C-f', 'f')
+  edit.run_after_keychord(Editor_state, 'down', 'down')
+  -- no crash
+end
+
+function test_search_downwards_from_final_pos_of_line()
+  App.screen.init{width=120, height=60}
+  Editor_state = edit.initialize_test_state()
+  Editor_state.lines = load_array{'abc', 'def', 'ghi'}
+  Text.redraw_all(Editor_state)
+  Editor_state.cursor1 = {line=1, pos=3}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  edit.draw(Editor_state)
+  -- search for empty string
+  edit.run_after_keychord(Editor_state, 'C-f', 'f')
+  edit.run_after_keychord(Editor_state, 'down', 'down')
+  -- no crash
+end