changeset 36:0a8865de3d53

replace all
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 14 Apr 2025 21:17:04 -0600
parents c5b57654147b
children b7ff52d45b9a
files editor.luan
diffstat 1 files changed, 52 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
diff -r c5b57654147b -r 0a8865de3d53 editor.luan
--- a/editor.luan	Mon Apr 14 19:07:12 2025 -0600
+++ b/editor.luan	Mon Apr 14 21:17:04 2025 -0600
@@ -12,6 +12,7 @@
 local regex = String.regex or error()
 local regex_quote = String.regex_quote or error()
 local regex_quote_replacement = String.regex_quote_replacement or error()
+local repeated = String.repeated or error()
 local Io = require "luan:Io.luan"
 local print = Io.print or error()
 local new_file = Io.schemes.file or error()
@@ -169,9 +170,11 @@
 					}
 					new_menu_item{
 						text = "Convert Leading Tabs to Spaces"
+						action_listener = window.tabs_to_spaces
 					}
 					new_menu_item{
 						text = "Convert Leading Spaces to Tabs"
+						action_listener = window.spaces_to_tabs
 					}
 				}
 			}
@@ -218,15 +221,20 @@
 local function get_matches(text,s)
 	local r = regex(s)
 	local matches = {}
-	local i = 0
-	while(true) do
+	local i = 1
+	local n = #text
+	while i <= n do
 		local j1, j2 = r.find(text,i)
 		if j1 == nil then
 			break
 		end
 		j2 = j2 + 1
-		matches[#matches+1] = { start=j1, end_=j2 }
-		i = j2
+		if j1 == j2 then
+			i = j2 + 1
+		else
+			matches[#matches+1] = { start=j1, end_=j2 }
+			i = j2
+		end
 	end
 	return matches
 end
@@ -286,7 +294,7 @@
 			error(action)
 		end
 	end
-	local function replace_match(_)
+	local function replace_match(event)
 		local find = find_field.text
 		if #find == 0 then
 			output.text = ""
@@ -304,10 +312,22 @@
 			output.text = "Regex error: "..e.get_message()
 			return
 		end
-		local selection = text_area.selected_text
-		local new, n = r.gsub(selection,replace)
-		if n > 0 then
-			text_area.selected_text = new
+		local new, n
+		local action = event.action
+		if action == "replace" then
+			local selection = text_area.selected_text
+			new, n = r.gsub(selection,replace)
+			if n > 0 then
+				text_area.selected_text = new
+			end
+		elseif action == "replace_all" then
+			local text = text_area.text
+			new, n = r.gsub(text,replace)
+			if n > 0 then
+				text_area.text = new
+			end
+		else
+			error(action)
 		end
 		output.text = n.." replacements"
 	end
@@ -320,6 +340,7 @@
 	replace_field = new_text_field{
 		constraints = "growx"
 		show_whitespace = true
+		action = "replace"
 		action_listener = replace_match
 	}
 	regex_check_box = new_check_box{
@@ -359,11 +380,14 @@
 				constraints = "grow"
 				text = "Replace"
 				tool_tip_text = "Replace matches in selected text"
+				action = "replace"
 				action_listener = replace_match
 			}
 			new_button{
 				constraints = "grow,wrap"
 				text = "Replace All"
+				action = "replace_all"
+				action_listener = replace_match
 			}
 			new_panel{
 				constraints = "span,wrap"
@@ -391,7 +415,25 @@
 		find_field.text = "(?i)\Q\E"
 		find_field.set_selection(7)
 		find_field.request_focus_in_window()
-		output.text = ""
+		output.text = [[Put search text between "\Q" and "\E"]]
+	end
+	function window.tabs_to_spaces(_)
+		find_panel.visible = true
+		window.find_menu_item.is_selected = true
+		regex_check_box.is_selected = true
+		find_field.text = [[(?m)^(\t*)\t]]
+		local spaces = repeated( " ", text_area.tab_size )
+		replace_field.text = "$1"..spaces
+		output.text = [[Do "Replace All" until 0 replacements]]
+	end
+	function window.spaces_to_tabs(_)
+		find_panel.visible = true
+		window.find_menu_item.is_selected = true
+		regex_check_box.is_selected = true
+		local tab_size = text_area.tab_size
+		find_field.text = `%>(?m)^(( {<%=tab_size%>})*) {<%=tab_size%>}<%`
+		replace_field.text = "$1\t"
+		output.text = [[Do "Replace All" until 0 replacements]]
 	end
 	return find_panel
 end