about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-05-23 17:39:00 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-05-23 17:39:00 -0700
commita35b130f08e6f580863edc8603c33b1100709c0b (patch)
treeaadf33317b124e430e437e11bfd9d191aa0a74d3
parent288d8426f1ca9e8df8e3d8ea89c17b61013d5285 (diff)
downloadview.love-a35b130f08e6f580863edc8603c33b1100709c0b.tar.gz
one bug I've repeatedly run into while testing with Moby Dick
https://www.hogbaysoftware.com/posts/moby-dick-workout
-rw-r--r--app.lua1
-rw-r--r--text.lua71
2 files changed, 69 insertions, 3 deletions
diff --git a/app.lua b/app.lua
index 2060f36..0a43319 100644
--- a/app.lua
+++ b/app.lua
@@ -187,6 +187,7 @@ function App.width(text)
 end
 
 function App.screen.check(y, expected_contents, msg)
+--?   print('checking for "'..expected_contents..'" at y '..tostring(y))
   local screen_row = 'y'..tostring(y)
   local contents = ''
   if App.screen.contents[screen_row] == nil then
diff --git a/text.lua b/text.lua
index 17d93b0..cb5fe3f 100644
--- a/text.lua
+++ b/text.lua
@@ -356,7 +356,7 @@ end
 
 function test_up_arrow_scrolls_up_by_one_screen_line()
   print('test_up_arrow_scrolls_up_by_one_screen_line')
-  -- display lines starting from the second screen line of line 3
+  -- display lines starting from second screen line of a line
   App.screen.init{width=25+30, height=60}
   Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
   Line_width = App.screen.width
@@ -371,7 +371,7 @@ function test_up_arrow_scrolls_up_by_one_screen_line()
   App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_by_one_screen_line/baseline/screen:1')
   y = y + line_height
   App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_by_one_screen_line/baseline/screen:2')
-  -- after hitting the up arrow the screen scrolls up by one line
+  -- after hitting the up arrow the screen scrolls up to first screen line
   App.run_after_keychord('up')
   y = screen_top_margin
   App.screen.check(y, 'ghi ', 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen:1')
@@ -385,6 +385,39 @@ function test_up_arrow_scrolls_up_by_one_screen_line()
   check_eq(Cursor1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor')
 end
 
+function test_up_arrow_scrolls_up_to_final_screen_line()
+  print('test_up_arrow_scrolls_up_to_final_screen_line')
+  -- display lines starting just after a long line
+  App.screen.init{width=25+30, height=60}
+  Lines = load_array{'abc def', 'ghi', 'jkl', 'mno'}
+  Line_width = App.screen.width
+  Cursor1 = {line=2, pos=1}
+  Screen_top1 = {line=2, pos=1}
+  Screen_bottom1 = {}
+  Zoom = 1
+  local screen_top_margin = 15  -- pixels
+  local line_height = math.floor(15*Zoom)  -- pixels
+  App.draw()
+  local y = screen_top_margin
+  App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:1')
+  y = y + line_height
+  App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:2')
+  y = y + line_height
+  App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:3')
+  -- after hitting the up arrow the screen scrolls up to final screen line of previous line
+  App.run_after_keychord('up')
+  y = screen_top_margin
+  App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:1')
+  y = y + line_height
+  App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:2')
+  y = y + line_height
+  App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:3')
+  check_eq(Screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top')
+  check_eq(Screen_top1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top')
+  check_eq(Cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor')
+  check_eq(Cursor1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor')
+end
+
 function Text.compute_fragments(line, line_width)
 --?   print('compute_fragments')
   line.fragments = {}
@@ -557,16 +590,21 @@ function Text.keychord_pressed(chord)
       while new_cursor_line > 1 do
         new_cursor_line = new_cursor_line-1
         if Lines[new_cursor_line].mode == 'text' then
+--?           print('found previous text line')
           Cursor1.line = new_cursor_line
+          Text.populate_screen_line_starting_pos(Cursor1.line)
           if Lines[Cursor1.line].screen_line_starting_pos == nil then
             Cursor1.pos = Text.nearest_cursor_pos(Lines[Cursor1.line].data, Cursor_x)
             break
           end
           -- previous text line found, pick its final screen line
+--?           print('has multiple screen lines')
           local screen_line_starting_pos = Lines[Cursor1.line].screen_line_starting_pos
+--?           print(#screen_line_starting_pos)
           screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos]
 --?           print('previous screen line starts at pos '..tostring(screen_line_starting_pos)..' of its line')
-          if Screen_top1.line == Cursor1.line and Screen_top1.pos == screen_line_starting_pos then
+          if Screen_top1.line > Cursor1.line then
+            Screen_top1.line = Cursor1.line
             Screen_top1.pos = screen_line_starting_pos
 --?             print('pos of top of screen is also '..tostring(Screen_top1.pos)..' of the same line')
           end
@@ -882,4 +920,31 @@ function Text.previous_screen_line(pos2)
   end
 end
 
+function Text.populate_screen_line_starting_pos(line_index)
+  -- duplicate some logic from Text.draw
+  local line = Lines[line_index]
+  if line.fragments == nil then
+    Text.compute_fragments(line, Line_width)
+  end
+  local x = 25
+  local pos = 1
+  for _, f in ipairs(line.fragments) do
+    local frag, frag_text = f.data, f.text
+--?     print(x, frag)
+    -- render fragment
+    local frag_width = math.floor(App.width(frag_text)*Zoom)
+    if x + frag_width > Line_width then
+      x = 25
+      if line.screen_line_starting_pos == nil then
+        line.screen_line_starting_pos = {1, pos}
+      else
+        table.insert(line.screen_line_starting_pos, pos)
+      end
+    end
+    x = x + frag_width
+    local frag_len = utf8.len(frag)
+    pos = pos + frag_len
+  end
+end
+
 return Text