changeset 33:e19ac0784287

find regex
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 14 Apr 2025 12:48:05 -0600
parents 15dacd8f5bfc
children 8535209b61ff
files editor.luan
diffstat 1 files changed, 42 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
diff -r 15dacd8f5bfc -r e19ac0784287 editor.luan
--- a/editor.luan	Sun Apr 13 23:29:26 2025 -0600
+++ b/editor.luan	Mon Apr 14 12:48:05 2025 -0600
@@ -9,6 +9,8 @@
 local starts_with = String.starts_with or error()
 local to_number = String.to_number or error()
 local find = String.find or error()
+local regex = String.regex or error()
+local regex_quote = String.regex_quote or error()
 local Io = require "luan:Io.luan"
 local print = Io.print or error()
 local new_file = Io.schemes.file or error()
@@ -78,6 +80,15 @@
 	update_undo_redo()
 	document.add_undo_listener(update_undo_redo)
 
+	local find_menu_item = new_check_box_menu_item{
+		text = "Find and Replace"
+		accelerator = "meta F"
+		action_listener = function(event)
+			window.show_find_panel(event.source.state)
+		end
+	}
+	window.find_menu_item = find_menu_item
+
 	local menu_bar = new_menu_bar{
 		menus = {
 			new_menu{
@@ -150,15 +161,10 @@
 			new_menu{
 				text = "Find"
 				menu_items = {
-					new_check_box_menu_item{
-						text = "Find and Replace"
-						accelerator = "meta F"
-						action_listener = function(event)
-							window.show_find_panel(event.source.state)
-						end
-					}
+					find_menu_item
 					new_menu_item{
 						text = "Find Case Insensitive"
+						action_listener = window.find_case_insensitive
 					}
 					new_menu_item{
 						text = "Convert Leading Tabs to Spaces"
@@ -209,34 +215,40 @@
 end
 
 local function get_matches(text,s)
-	local n = #s
-	if n == 0 then
-		return nil
-	end
+	local r = regex(s)
 	local matches = {}
 	local i = 0
 	while(true) do
-		local j = find(text,s,i)
-		if j == nil then
+		local j1, j2 = r.find(text,i)
+		if j1 == nil then
 			break
 		end
-		matches[#matches+1] = { start=j, end_=j+n }
-		i = j + n
+		matches[#matches+1] = { start=j1, end_=j2 }
+		i = j2
 	end
 	return matches
 end
 
 local function make_find_panel(window)
 	local text_area = window.text_area
-	local find_field, output
+	local find_field, regex_check_box, 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
+		if #s == 0 then
 			output.text = ""
 			return
 		end
+		if not regex_check_box.is_selected then
+			s = regex_quote(s)
+		end
+		local matches
+		try
+			matches = get_matches( text_area.text, s )
+		catch e
+			output.text = "Regex error: "..e.get_message()
+			return
+		end
 		local n_matches = #matches
 		if n_matches == 0 then
 			output.text = "0 matches"
@@ -278,6 +290,9 @@
 		action = "next"
 		action_listener = find_match
 	}
+	regex_check_box = new_check_box{
+		text = "Use Regex"
+	}
 	output = new_label{
 		constraints = "span"
 	}
@@ -323,9 +338,7 @@
 				constraints = "span,wrap"
 				layout = new_mig_layout("insets 0,gap 16px")
 				children = {
-					new_check_box{
-						text = "Use Regex"
-					}
+					regex_check_box
 					new_button{
 						text = "Learn About Regular Expressions"
 					}
@@ -340,6 +353,14 @@
 			find_field.request_focus_in_window()
 		end
 	end
+	function window.find_case_insensitive(_)
+		find_panel.visible = true
+		window.find_menu_item.is_selected = true
+		regex_check_box.is_selected = true
+		find_field.text = "(?i)\Q\E"
+		find_field.set_selection(7)
+		find_field.request_focus_in_window()
+	end
 	return find_panel
 end