about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-06-04 14:55:52 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-06-04 14:55:52 -0700
commitfa267e25e600a875696b6ab972b72515fa71e20a (patch)
treee08e70387ef93f6b7b10a8e3f911a96ff3e1c690
parent1326914d7bda65a5791c2121dae6d3987a907994 (diff)
downloadtext.love-fa267e25e600a875696b6ab972b72515fa71e20a.tar.gz
experiment: slightly adaptive scrolling
When long wrapping lines go past the current page, I find myself
scrolling before I get to the bottom. So let's scroll less, usually from
the start of the bottom-most line, even if it wraps multiple screen
lines.

The challenge with this is to ensure that a long line that fills the
whole page by itself doesn't get you stuck. I take some care to make
sure <pagedown> always makes forward progress.
-rw-r--r--text.lua16
-rw-r--r--text_tests.lua56
2 files changed, 56 insertions, 16 deletions
diff --git a/text.lua b/text.lua
index d3cc29d..cbccc85 100644
--- a/text.lua
+++ b/text.lua
@@ -395,8 +395,20 @@ function Text.pageup()
 end
 
 function Text.pagedown()
-  Screen_top1.line = Screen_bottom1.line
-  Screen_top1.pos = Screen_bottom1.pos
+  -- If a line/paragraph gets to a page boundary, I often want to scroll
+  -- before I get to the bottom.
+  -- However, only do this if it makes forward progress.
+  local top2 = Text.to2(Screen_bottom1)
+  if top2.screen_line > 1 then
+    top2.screen_line = math.max(top2.screen_line-10, 1)
+  end
+  local new_top1 = Text.to1(top2)
+  if Text.lt1(Screen_top1, new_top1) then
+    Screen_top1 = new_top1
+  else
+    Screen_top1.line = Screen_bottom1.line
+    Screen_top1.pos = Screen_bottom1.pos
+  end
 --?   print('setting top to', Screen_top1.line, Screen_top1.pos)
   Cursor1.line = Screen_top1.line
   Cursor1.pos = Screen_top1.pos
diff --git a/text_tests.lua b/text_tests.lua
index 8272faf..f3a2a6a 100644
--- a/text_tests.lua
+++ b/text_tests.lua
@@ -246,9 +246,9 @@ function test_pagedown_skips_drawings()
   App.screen.check(y, 'def', 'F - test_pagedown_skips_drawings/screen:1')
 end
 
-function test_pagedown_shows_one_screen_line_in_common()
-  io.write('\ntest_pagedown_shows_one_screen_line_in_common')
-  -- some lines of text with a drawing intermixed
+function test_pagedown_often_shows_start_of_wrapping_line()
+  io.write('\ntest_pagedown_often_shows_start_of_wrapping_line')
+  -- draw a few lines ending in part of a wrapping line
   App.screen.init{width=50, height=60}
   Lines = load_array{'abc', 'def ghi jkl', 'mno'}
   Line_width = App.screen.width
@@ -257,23 +257,51 @@ function test_pagedown_shows_one_screen_line_in_common()
   Screen_bottom1 = {}
   App.draw()
   local y = Margin_top
-  App.screen.check(y, 'abc', 'F - test_pagedown_shows_one_screen_line_in_common/baseline/screen:1')
+  App.screen.check(y, 'abc', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:1')
+  y = y + Line_height
+  App.screen.check(y, 'def ', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:2')
+  y = y + Line_height
+  App.screen.check(y, 'ghi ', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:3')
+  -- after pagedown we start drawing from the bottom _line_ (multiple screen lines)
+  App.run_after_keychord('pagedown')
+  check_eq(Screen_top1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:line')
+  check_eq(Screen_top1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:pos')
+  check_eq(Cursor1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:line')
+  check_eq(Cursor1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:pos')
+  y = Margin_top
+  App.screen.check(y, 'def ', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:1')
+  y = y + Line_height
+  App.screen.check(y, 'ghi ', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:2')
+  y = y + Line_height
+  App.screen.check(y, 'jkl', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:3')
+end
+
+function test_pagedown_can_start_from_middle_of_long_wrapping_line()
+  io.write('\ntest_pagedown_can_start_from_middle_of_long_wrapping_line')
+  -- draw a few lines starting from a very long wrapping line
+  App.screen.init{width=25+30, height=60}
+  Lines = load_array{'abc def ghi jkl mno pqr stu vwx yza bcd efg hij', 'XYZ'}
+  Line_width = App.screen.width
+  Cursor1 = {line=1, pos=2}
+  Screen_top1 = {line=1, pos=1}
+  Screen_bottom1 = {}
+  App.draw()
+  local y = Margin_top
+  App.screen.check(y, 'abc ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:1')
   y = y + Line_height
-  App.screen.check(y, 'def ', 'F - test_pagedown_shows_one_screen_line_in_common/baseline/screen:2')
+  App.screen.check(y, 'def ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:2')
   y = y + Line_height
-  App.screen.check(y, 'ghi ', 'F - test_pagedown_shows_one_screen_line_in_common/baseline/screen:3')
-  -- after pagedown the bottom screen line becomes the top
+  App.screen.check(y, 'ghi ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:3')
+  -- after pagedown we scroll down the very long wrapping line
   App.run_after_keychord('pagedown')
-  check_eq(Screen_top1.line, 2, 'F - test_pagedown_shows_one_screen_line_in_common/screen_top:line')
-  check_eq(Screen_top1.pos, 5, 'F - test_pagedown_shows_one_screen_line_in_common/screen_top:pos')
-  check_eq(Cursor1.line, 2, 'F - test_pagedown_shows_one_screen_line_in_common/cursor:line')
-  check_eq(Cursor1.pos, 5, 'F - test_pagedown_shows_one_screen_line_in_common/cursor:pos')
+  check_eq(Screen_top1.line, 1, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:line')
+  check_eq(Screen_top1.pos, 9, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:pos')
   y = Margin_top
-  App.screen.check(y, 'ghi ', 'F - test_pagedown_shows_one_screen_line_in_common/screen:1')
+  App.screen.check(y, 'ghi ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:1')
   y = y + Line_height
-  App.screen.check(y, 'jkl', 'F - test_pagedown_shows_one_screen_line_in_common/screen:2')
+  App.screen.check(y, 'jkl m', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:2')
   y = y + Line_height
-  App.screen.check(y, 'mn', 'F - test_pagedown_shows_one_screen_line_in_common/screen:3')
+  App.screen.check(y, 'no ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:3')
 end
 
 function test_down_arrow_moves_cursor()