about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-06-02 22:53:34 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-06-02 22:53:34 -0700
commitb94b007db55d5a0c0b102ee6ecb644863b8858dc (patch)
tree54109239e3c63516da267a1c13c3b223fd8cbb67
parent63f59e7c2cda73ec6e932249523723c6fb970a11 (diff)
downloadlines.love-b94b007db55d5a0c0b102ee6ecb644863b8858dc.tar.gz
find text
-rw-r--r--main.lua48
-rw-r--r--text.lua80
2 files changed, 119 insertions, 9 deletions
diff --git a/main.lua b/main.lua
index 8917f8e..5d33b5a 100644
--- a/main.lua
+++ b/main.lua
@@ -69,6 +69,11 @@ Filename = love.filesystem.getUserDirectory()..'/lines.txt'
 History = {}
 Next_history = 1
 
+-- search
+Search_term = nil
+Search_text = nil
+Search_backup_cursor1 = nil  -- where to position the cursor if search term was not found
+
 end  -- App.initialize_globals
 
 function App.initialize(arg)
@@ -148,8 +153,10 @@ function App.draw()
                          Cursor1.line = Cursor1.line+1
                        end
                      end})
-          if line_index == Cursor1.line then
-            Text.draw_cursor(25, y)
+          if Search_term == nil then
+            if line_index == Cursor1.line then
+              Text.draw_cursor(25, y)
+            end
           end
         y = y + math.floor(15*Zoom)  -- text height
       elseif line.mode == 'drawing' then
@@ -167,7 +174,9 @@ function App.draw()
     end
   end
 --?   print('screen bottom: '..tostring(Screen_bottom1.pos)..' in '..tostring(Lines[Screen_bottom1.line].data))
---?   os.exit(1)
+  if Search_term then
+    Text.draw_search_bar()
+  end
 end
 
 function App.update(dt)
@@ -175,6 +184,7 @@ function App.update(dt)
 end
 
 function App.mousepressed(x,y, mouse_button)
+  if Search_term then return end
   propagate_to_button_handlers(x,y, mouse_button)
 
   for line_index,line in ipairs(Lines) do
@@ -200,11 +210,16 @@ function App.mousepressed(x,y, mouse_button)
 end
 
 function App.mousereleased(x,y, button)
+  if Search_term then return end
   Drawing.mouse_released(x,y, button)
 end
 
 function App.textinput(t)
-  if Current_drawing_mode == 'name' then
+  if Search_term then
+    Search_term = Search_term..t
+    Search_text = nil
+    Text.search_next()
+  elseif Current_drawing_mode == 'name' then
     local drawing = Lines.current
     local p = drawing.points[drawing.pending.target_point]
     p.name = p.name..t
@@ -215,7 +230,30 @@ function App.textinput(t)
 end
 
 function App.keychord_pressed(chord)
-  if love.mouse.isDown('1') or chord:sub(1,2) == 'C-' then
+  if Search_term then
+    if chord == 'escape' then
+      Search_term = nil
+      Search_text = nil
+      Cursor1 = Search_backup_cursor1
+      Search_backup_cursor1 = nil
+    elseif chord == 'return' then
+      Search_term = nil
+      Search_text = nil
+    elseif chord == 'backspace' then
+      local len = utf8.len(Search_term)
+      local byte_offset = utf8.offset(Search_term, len)
+      Search_term = string.sub(Search_term, 1, byte_offset-1)
+      Search_text = nil
+    elseif chord == 'down' then
+      Cursor1.pos = Cursor1.pos+1
+      Text.search_next()
+    end
+    return
+  elseif chord == 'C-f' then
+    Search_term = ''
+    Search_backup_cursor1 = {line=Cursor1.line, pos=Cursor1.pos}
+    assert(Search_text == nil)
+  elseif love.mouse.isDown('1') or chord:sub(1,2) == 'C-' then
     Drawing.keychord_pressed(chord)
   elseif chord == 'escape' and love.mouse.isDown('1') then
     local drawing = Drawing.current_drawing()
diff --git a/text.lua b/text.lua
index c397ff3..a8d99f6 100644
--- a/text.lua
+++ b/text.lua
@@ -76,20 +76,93 @@ function Text.draw(line, line_width, line_index)
     -- render cursor if necessary
     if line_index == Cursor1.line then
       if pos <= Cursor1.pos and pos + frag_len > Cursor1.pos then
-        Text.draw_cursor(x+Text.x(frag, Cursor1.pos-pos+1), y)
+        if Search_term then
+          if Lines[Cursor1.line].data:sub(Cursor1.pos, Cursor1.pos+utf8.len(Search_term)-1) == Search_term then
+            if Search_text == nil then
+              Search_text = App.newText(love.graphics.getFont(), Search_term)
+            end
+            love.graphics.setColor(0.7,1,1)
+            love.graphics.rectangle('fill', x,y, math.floor(App.width(Search_text)*Zoom),math.floor(15*Zoom))
+            love.graphics.setColor(0,0,0)
+            love.graphics.print(Search_term, x,y, 0, Zoom)
+          end
+        else
+          Text.draw_cursor(x+Text.x(frag, Cursor1.pos-pos+1), y)
+        end
       end
     end
     x = x + frag_width
     pos = pos + frag_len
   end
-  if line_index == Cursor1.line and Cursor1.pos == pos then
-    Text.draw_cursor(x, y)
+  if Search_term == nil then
+    if line_index == Cursor1.line and Cursor1.pos == pos then
+      Text.draw_cursor(x, y)
+    end
   end
   return y, screen_line_starting_pos
 end
 -- manual tests:
 --  draw with small line_width of 100
 
+function Text.draw_search_bar()
+  local h = math.floor(15*Zoom)+2
+  local y = App.screen.height-h
+  love.graphics.setColor(0.9,0.9,0.9)
+  love.graphics.rectangle('fill', 0, y-10, App.screen.width-1, h+8)
+  love.graphics.setColor(0.6,0.6,0.6)
+  love.graphics.line(0, y-10, App.screen.width-1, y-10)
+  love.graphics.setColor(1,1,1)
+  love.graphics.rectangle('fill', 20, y-6, App.screen.width-40, h+2, 2,2)
+  love.graphics.setColor(0.6,0.6,0.6)
+  love.graphics.rectangle('line', 20, y-6, App.screen.width-40, h+2, 2,2)
+  love.graphics.setColor(0,0,0)
+  App.screen.print(Search_term, 25,y-5, 0, Zoom)
+  love.graphics.setColor(1,0,0)
+  if Search_text == nil then
+    Search_text = App.newText(love.graphics.getFont(), Search_term)
+  end
+  love.graphics.circle('fill', 25+math.floor(App.width(Search_text)*Zoom),y-5+h, 2)
+  love.graphics.setColor(0,0,0)
+end
+
+function Text.search_next()
+  -- search current line
+  local pos = Lines[Cursor1.line].data:find(Search_term, Cursor1.pos)
+  if pos then
+    Cursor1.pos = pos
+  end
+  if pos == nil then
+    for i=Cursor1.line+1,#Lines do
+      pos = Lines[i].data:find(Search_term)
+      if pos then
+        Cursor1.line = i
+        Cursor1.pos = pos
+        break
+      end
+    end
+  end
+  if pos == nil then
+    -- wrap around
+    for i=1,Cursor1.line-1 do
+      pos = Lines[i].data:find(Search_term)
+      if pos then
+        Cursor1.line = i
+        Cursor1.pos = pos
+        break
+      end
+    end
+  end
+  if pos == nil then
+    Cursor1.line = Search_backup_cursor1.line
+    Cursor1.pos = Search_backup_cursor1.pos
+  end
+  if Text.lt1(Cursor1, Screen_top1) or Text.lt1(Screen_bottom1, Cursor1) then
+    Screen_top1.line = Cursor1.line
+    local _, pos = Text.pos_at_start_of_cursor_screen_line()
+    Screen_top1.pos = pos
+  end
+end
+
 -- Return any intersection of the region from Selection1 to Cursor1 with the
 -- region between {line=line_index, pos=apos} and {line=line_index, pos=bpos}.
 -- apos must be less than bpos. However Selection1 and Cursor1 can be in any order.
@@ -1823,7 +1896,6 @@ function Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necess
   end
 --?   print(y, App.screen.height, App.screen.height-math.floor(15*Zoom))
   if y > App.screen.height - math.floor(15*Zoom) then
---?   if Cursor1.line > Screen_bottom1.line then
 --?     print('scroll up')
     Screen_top1.line = Cursor1.line
     Text.scroll_up_while_cursor_on_screen()