Mercurial Hosting > editor
comparison editor.luan @ 36:0a8865de3d53
replace all
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 14 Apr 2025 21:17:04 -0600 |
parents | c5b57654147b |
children |
comparison
equal
deleted
inserted
replaced
35:c5b57654147b | 36:0a8865de3d53 |
---|---|
10 local to_number = String.to_number or error() | 10 local to_number = String.to_number or error() |
11 local find = String.find or error() | 11 local find = String.find or error() |
12 local regex = String.regex or error() | 12 local regex = String.regex or error() |
13 local regex_quote = String.regex_quote or error() | 13 local regex_quote = String.regex_quote or error() |
14 local regex_quote_replacement = String.regex_quote_replacement or error() | 14 local regex_quote_replacement = String.regex_quote_replacement or error() |
15 local repeated = String.repeated or error() | |
15 local Io = require "luan:Io.luan" | 16 local Io = require "luan:Io.luan" |
16 local print = Io.print or error() | 17 local print = Io.print or error() |
17 local new_file = Io.schemes.file or error() | 18 local new_file = Io.schemes.file or error() |
18 local Math = require "luan:Math.luan" | 19 local Math = require "luan:Math.luan" |
19 local min = Math.min or error() | 20 local min = Math.min or error() |
167 text = "Find Case Insensitive" | 168 text = "Find Case Insensitive" |
168 action_listener = window.find_case_insensitive | 169 action_listener = window.find_case_insensitive |
169 } | 170 } |
170 new_menu_item{ | 171 new_menu_item{ |
171 text = "Convert Leading Tabs to Spaces" | 172 text = "Convert Leading Tabs to Spaces" |
173 action_listener = window.tabs_to_spaces | |
172 } | 174 } |
173 new_menu_item{ | 175 new_menu_item{ |
174 text = "Convert Leading Spaces to Tabs" | 176 text = "Convert Leading Spaces to Tabs" |
177 action_listener = window.spaces_to_tabs | |
175 } | 178 } |
176 } | 179 } |
177 } | 180 } |
178 new_menu{ | 181 new_menu{ |
179 text = "View" | 182 text = "View" |
216 end | 219 end |
217 | 220 |
218 local function get_matches(text,s) | 221 local function get_matches(text,s) |
219 local r = regex(s) | 222 local r = regex(s) |
220 local matches = {} | 223 local matches = {} |
221 local i = 0 | 224 local i = 1 |
222 while(true) do | 225 local n = #text |
226 while i <= n do | |
223 local j1, j2 = r.find(text,i) | 227 local j1, j2 = r.find(text,i) |
224 if j1 == nil then | 228 if j1 == nil then |
225 break | 229 break |
226 end | 230 end |
227 j2 = j2 + 1 | 231 j2 = j2 + 1 |
228 matches[#matches+1] = { start=j1, end_=j2 } | 232 if j1 == j2 then |
229 i = j2 | 233 i = j2 + 1 |
234 else | |
235 matches[#matches+1] = { start=j1, end_=j2 } | |
236 i = j2 | |
237 end | |
230 end | 238 end |
231 return matches | 239 return matches |
232 end | 240 end |
233 | 241 |
234 local function make_find_panel(window) | 242 local function make_find_panel(window) |
284 output.text = n_matches.." of "..n_matches.." matches; wrapped past end" | 292 output.text = n_matches.." of "..n_matches.." matches; wrapped past end" |
285 else | 293 else |
286 error(action) | 294 error(action) |
287 end | 295 end |
288 end | 296 end |
289 local function replace_match(_) | 297 local function replace_match(event) |
290 local find = find_field.text | 298 local find = find_field.text |
291 if #find == 0 then | 299 if #find == 0 then |
292 output.text = "" | 300 output.text = "" |
293 return | 301 return |
294 end | 302 end |
302 r = regex(find) | 310 r = regex(find) |
303 catch e | 311 catch e |
304 output.text = "Regex error: "..e.get_message() | 312 output.text = "Regex error: "..e.get_message() |
305 return | 313 return |
306 end | 314 end |
307 local selection = text_area.selected_text | 315 local new, n |
308 local new, n = r.gsub(selection,replace) | 316 local action = event.action |
309 if n > 0 then | 317 if action == "replace" then |
310 text_area.selected_text = new | 318 local selection = text_area.selected_text |
319 new, n = r.gsub(selection,replace) | |
320 if n > 0 then | |
321 text_area.selected_text = new | |
322 end | |
323 elseif action == "replace_all" then | |
324 local text = text_area.text | |
325 new, n = r.gsub(text,replace) | |
326 if n > 0 then | |
327 text_area.text = new | |
328 end | |
329 else | |
330 error(action) | |
311 end | 331 end |
312 output.text = n.." replacements" | 332 output.text = n.." replacements" |
313 end | 333 end |
314 find_field = new_text_field{ | 334 find_field = new_text_field{ |
315 constraints = "growx" | 335 constraints = "growx" |
318 action_listener = find_match | 338 action_listener = find_match |
319 } | 339 } |
320 replace_field = new_text_field{ | 340 replace_field = new_text_field{ |
321 constraints = "growx" | 341 constraints = "growx" |
322 show_whitespace = true | 342 show_whitespace = true |
343 action = "replace" | |
323 action_listener = replace_match | 344 action_listener = replace_match |
324 } | 345 } |
325 regex_check_box = new_check_box{ | 346 regex_check_box = new_check_box{ |
326 text = "Use Regex" | 347 text = "Use Regex" |
327 } | 348 } |
357 replace_field | 378 replace_field |
358 new_button{ | 379 new_button{ |
359 constraints = "grow" | 380 constraints = "grow" |
360 text = "Replace" | 381 text = "Replace" |
361 tool_tip_text = "Replace matches in selected text" | 382 tool_tip_text = "Replace matches in selected text" |
383 action = "replace" | |
362 action_listener = replace_match | 384 action_listener = replace_match |
363 } | 385 } |
364 new_button{ | 386 new_button{ |
365 constraints = "grow,wrap" | 387 constraints = "grow,wrap" |
366 text = "Replace All" | 388 text = "Replace All" |
389 action = "replace_all" | |
390 action_listener = replace_match | |
367 } | 391 } |
368 new_panel{ | 392 new_panel{ |
369 constraints = "span,wrap" | 393 constraints = "span,wrap" |
370 layout = new_mig_layout("insets 0,gap 16px") | 394 layout = new_mig_layout("insets 0,gap 16px") |
371 children = { | 395 children = { |
389 window.find_menu_item.is_selected = true | 413 window.find_menu_item.is_selected = true |
390 regex_check_box.is_selected = true | 414 regex_check_box.is_selected = true |
391 find_field.text = "(?i)\Q\E" | 415 find_field.text = "(?i)\Q\E" |
392 find_field.set_selection(7) | 416 find_field.set_selection(7) |
393 find_field.request_focus_in_window() | 417 find_field.request_focus_in_window() |
394 output.text = "" | 418 output.text = [[Put search text between "\Q" and "\E"]] |
419 end | |
420 function window.tabs_to_spaces(_) | |
421 find_panel.visible = true | |
422 window.find_menu_item.is_selected = true | |
423 regex_check_box.is_selected = true | |
424 find_field.text = [[(?m)^(\t*)\t]] | |
425 local spaces = repeated( " ", text_area.tab_size ) | |
426 replace_field.text = "$1"..spaces | |
427 output.text = [[Do "Replace All" until 0 replacements]] | |
428 end | |
429 function window.spaces_to_tabs(_) | |
430 find_panel.visible = true | |
431 window.find_menu_item.is_selected = true | |
432 regex_check_box.is_selected = true | |
433 local tab_size = text_area.tab_size | |
434 find_field.text = `%>(?m)^(( {<%=tab_size%>})*) {<%=tab_size%>}<%` | |
435 replace_field.text = "$1\t" | |
436 output.text = [[Do "Replace All" until 0 replacements]] | |
395 end | 437 end |
396 return find_panel | 438 return find_panel |
397 end | 439 end |
398 | 440 |
399 local n_windows = 0 | 441 local n_windows = 0 |