about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-05-16 20:55:21 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-05-16 20:55:21 -0700
commit0da2ec385021f7a3735518ad90fa8a3b7f9da40d (patch)
tree35cc79fa63d549a4fe2120747279d2e3ef1b251f
parent63df6d04e00877acd135de710c1118306554945c (diff)
downloadlines.love-0da2ec385021f7a3735518ad90fa8a3b7f9da40d.tar.gz
binary search to most natural up/down with proportional fonts
-rw-r--r--main.lua44
1 files changed, 35 insertions, 9 deletions
diff --git a/main.lua b/main.lua
index 263e96e..5392742 100644
--- a/main.lua
+++ b/main.lua
@@ -157,9 +157,7 @@ function love.draw()
       if i == cursor_line then
         -- cursor
         love.graphics.setColor(0,0,0)
-        local line_before_cursor = lines[cursor_line]:sub(1, cursor_pos-1)
-        local text_before_cursor = love.graphics.newText(love.graphics.getFont(), line_before_cursor)
-        love.graphics.print('_', 25+text_before_cursor:getWidth()*1.5, y+6)  -- drop the cursor down a bit to account for the increased font size
+        love.graphics.print('_', 25+cursor_x(lines[cursor_line], cursor_pos)*1.5, y+6)  -- drop the cursor down a bit to account for the increased font size
       end
     end
   end
@@ -540,19 +538,21 @@ function keychord_pressed(chord)
     if cursor_pos <= #lines[cursor_line] then
       cursor_pos = cursor_pos + 1
     end
+  elseif chord == 'home' then
+    cursor_pos = 1
+  elseif chord == 'end' then
+    cursor_pos = #lines[cursor_line]+1
   elseif chord == 'up' then
     if cursor_line > 1 then
+      local old_x = cursor_x(lines[cursor_line], cursor_pos)
       cursor_line = cursor_line-1
-      if cursor_pos > #lines[cursor_line] then
-        cursor_pos = #lines[cursor_line]+1
-      end
+      cursor_pos = nearest_cursor_pos(lines[cursor_line], old_x)
     end
   elseif chord == 'down' then
     if cursor_line < #lines then
+      local old_x = cursor_x(lines[cursor_line], cursor_pos)
       cursor_line = cursor_line+1
-      if cursor_pos > #lines[cursor_line] then
-        cursor_pos = #lines[cursor_line]+1
-      end
+      cursor_pos = nearest_cursor_pos(lines[cursor_line], old_x)
     end
   elseif chord == 'delete' then
     if cursor_pos <= #lines[cursor_line] then
@@ -706,6 +706,32 @@ function keychord_pressed(chord)
   end
 end
 
+function cursor_x(line, cursor_pos)
+  local line_before_cursor = line:sub(1, cursor_pos-1)
+  local text_before_cursor = love.graphics.newText(love.graphics.getFont(), line_before_cursor)
+  return text_before_cursor:getWidth()
+end
+
+function nearest_cursor_pos(line, x)
+  if x == 0 then
+    return 1
+  end
+  local left, right = 1, #line+1
+  while left < right-1 do
+    local curr = math.floor((left+right)/2)
+    local currx = cursor_x(line, curr)
+    if currx > x-2 and currx < x+2 then
+      return curr
+    end
+    if currx > x then
+      right = curr
+    else
+      left = curr
+    end
+  end
+  return right
+end
+
 function in_drawing()
   local x, y = love.mouse.getX(), love.mouse.getY()
   for _,drawing in ipairs(lines) do