changeset 28:bdb8754f1211

find work
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 11 Apr 2025 21:41:26 -0600
parents 32232df78246
children 01b8a25b38aa
files editor.luan
diffstat 1 files changed, 89 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/editor.luan	Fri Apr 11 11:43:41 2025 -0600
+++ b/editor.luan	Fri Apr 11 21:41:26 2025 -0600
@@ -1,12 +1,14 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
 local ipairs = Luan.ipairs or error()
+local range = Luan.range or error()
 local stringify = Luan.stringify or error()
 local String = require "luan:String.luan"
 local sub_string = String.sub or error()
 local replace = String.replace or error()
 local starts_with = String.starts_with or error()
 local to_number = String.to_number or error()
+local find = String.find or error()
 local Io = require "luan:Io.luan"
 local print = Io.print or error()
 local new_file = Io.schemes.file or error()
@@ -177,7 +179,6 @@
 						accelerator = "meta G"
 						action_listener = function(_)
 							local input = show_input_dialog( window.frame, "Goto line" )
-							--logger.info("input "..input)
 							local line = input and to_number(input)
 							if line ~= nil then
 								window.goto(line)
@@ -190,14 +191,93 @@
 	}
 end
 
+local function get_matches(text,s)
+	local n = #s
+	if n == 0 then
+		return nil
+	end
+	local matches = {}
+	local i = 0
+	while(true) do
+		local j = find(text,s,i)
+		if j == nil then
+			break
+		end
+		matches[#matches+1] = { start=j, end_=j+n }
+		i = j + n
+	end
+	return matches
+end
+
 local function make_find_dialog(window)
+	local text_area = window.text_area
+	local find_field, output
+	local function find_match(event)
+		--logger.info("action "..event.action)
+		local s = find_field.text
+		local matches = get_matches( text_area.text, s )
+		if matches == nil then
+			output.text = ""
+			return
+		end
+		local n_matches = #matches
+		if n_matches == 0 then
+			output.text = "0 matches"
+			return
+		end
+		local action = event.action
+		if action == "next" then
+			local _, pos = text_area.get_selection()
+			for i, match in ipairs(matches) do
+				if match.start >= pos then
+					text_area.set_selection( match.start, match.end_ )
+					output.text = i.." of "..n_matches.." matches"
+					return
+				end
+			end
+			local match = matches[1]
+			text_area.set_selection( match.start, match.end_ )
+			output.text = "1 of "..n_matches.." matches; wrapped past end"
+		elseif action == "previous" then
+			local pos = text_area.get_selection()
+			for i in range(n_matches,1,-1) do
+				local match = matches[i]
+				if match.end_ <= pos then
+					text_area.set_selection( match.start, match.end_ )
+					output.text = i.." of "..n_matches.." matches"
+					return
+				end
+			end
+			local match = matches[n_matches]
+			text_area.set_selection( match.start, match.end_ )
+			output.text = n_matches.." of "..n_matches.." matches; wrapped past end"
+		else
+			error(action)
+		end
+	end
+	find_field = new_text_field{
+		constraints = "wrap,growx"
+		columns = 20
+		action = "next"
+		action_listener = find_match
+	}
+	output = new_label{
+		constraints = "span,grow"
+		text = "testing"
+	}
 	local dialog = new_dialog{
 		owner_frame = window.frame
 		content_pane = new_panel{
-			layout = new_mig_layout("debug","[][grow]","[][grow,top]")
+			layout = new_mig_layout("","[][grow]")
 			children = {
 				new_label{
-					text = "Find Next:"
+					constraints = "right"
+					text = "Find:"
+				}
+				find_field
+				new_label{
+					constraints = "right"
+					text = "Replace:"
 				}
 				new_text_field{
 					constraints = "wrap,growx"
@@ -205,18 +285,21 @@
 				}
 				new_panel{
 					constraints = "span,wrap"
-					layout = new_mig_layout("debug,insets 0")
-					--border = create_empty_border(8,8,8,8)
-					--border = create_line_border(int_to_color(0))
+					layout = new_mig_layout("insets 0")
 					children = {
 						new_button{
 							text = "Find Next"
+							action = "next"
+							action_listener = find_match
 						}
 						new_button{
 							text = "Find Previous"
+							action = "previous"
+							action_listener = find_match
 						}
 					}
 				}
+				output
 			}
 		}
 	}