ProgerXP / Notepad2e

Word highlighting, simultaneous editing, split views, math evaluation, un/grep, comment reformatting, UAC elevation, complete regexps (PCRE), Lua lexers, DPI awareness and more (XP+)
Other
372 stars 52 forks source link

Special Search strings #341

Open ProgerXP opened 3 years ago

ProgerXP commented 3 years ago

By analogy with #340, recognize ^c, ^cl, ^cm (also subject to Regexp and Backslashes switches and shows an error if ^c/^cl resulted in invalid Regexp).

^cm works like this: from all lines with ^, take parts from line start until ^, then search for these parts; do not apply Regexp/Backslashes modes to these parts but behave as if Regexp is enabled for the Search string only (i.e. perform a Regexp search but use state of Regexp/Backslashes checkboxes for Replace string) and the Search string itself was match1|match2|match3|..., i.e. parts found earlier joined using | and escaped for Regexp (to avoid $, etc. being treated specially). Thus, Replace from ^cm to ^cm will replace all keys in the map.

^cl can be used in both Search and Replace strings. For single Replace (non-All, non-In Selection) first Search chops its line, then Replace (even if no match was found(*)). As a result, doing a single Replace from ^cl to ^cl with clipboard having foo\nbar is the same as doing Replace from foo to bar. Replace All or In Selection takes 1 line for Search then 1 line per every found match plus 1 (i.e. per every replacement performed plus one more, for the search that didn't match anything else(*)). Note that Search is using the same chopped line for the entire Replace operation but if user repeats Replace (using F2/F3, F4 or the dialog) then Search chops another line. User can manually do a series of single Replace from ^cl to ^cl, thus his clipboard would be from1|to1|from2|to2|... (| = \n) but it seems for the same effect but simpler he can reformat the clipboard (from1^to1|from2^to2) and do single Replace All from ^cm to ^cm.

(*) This is up to implementation. If it's simpler, alternative is to parse ^cl in Replace only when a match was found, thus not chopping Replace line when there's no match. The version above assumes it's simpler to first prepare both Search and Replace strings as if they were entered by the user and then perform the actual operation without considering how those strings were supplied.

To "escape" and search for literal strings user can enable Regexp and use something like \^c or simply copy literal "^c" to clipboard.

F2/F3 work as if user has called the Find dialog, re-interpreting ^cl and others. However, F4 might have a problem: Notepad2 does some kind of check on the selected text to make sure it matches the earlier found value (easy to test: search for a, then change selection and press F4 - it will not replace new selection but will do a new search) but Search string can now have side effects (with ^cl). The solution depends on how Notepad2 does the check: if it remembers earlier found position then nothing needs to be done, but if it repeats the search and compares with the selected text then ^cl will chop off new line and F4 will search for another value than the previous operation - in this case detect when Search is ^cl and disable the check so F4 always assumes selected text is the match when searching for a special string with side effects.


Practical usage examples:

  1. Do searches for disparate strings. First, copy all strings to be found to clipboard, then do Find for ^cl. Then, either Find>Find Next/Previous or F3/Shift+F3 will locate the next line from clipboard. To locale literal match without reading new line from clipboard, press Alt+F3 or Ctrl+F3 (do Find for selected text, replacing previous Find's ^cl Search string).
  2. Do a series of replacements where matches cannot be matched by a single expression. For example, foo = bar and 123 = abc. First, copy the replace map to clipboard (like below), then do Replace All from ^cm to ^cm:
foo^bar
123^abc

Last example could be done without ^cm in Search if Regexp mode is enabled and Search = foo|123 (^cm internally evaluates to this Regexp).