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
370 stars 52 forks source link

New command: Parse Lines (Alt+A) #453

Open ProgerXP opened 1 year ago

ProgerXP commented 1 year ago

This command is made last in Edit > Block (P&arse). It's similar to Modify Lines (Alt+M) in treating initial selection, dialog layout with Syslink and remembering input values. Dialog has two buttons on the side, &Parse each line:, input, Use |scanf()| instead of regular &expression (checkbox, checked by default; |...| = link to an online reference), bunch of links and texts similar to Alt+M's, &Replace matching line:, input, another bunch of links and texts. Links and texts will be determined later.

Operation:

  1. If the scanf() checkbox is checked, preprocess the Parse string (see below).
    • if it isn't and the regexp is malformed, either disable OK (as done in Find) or focus Parse and exit
  2. Walk document line by line like Alt+M does; for every line:
    • run vsscanf() or regexp on it; if sscanf()'s result is not exactly N or if the regexp doesn't match, skip to next line
    • replace the line with the result of calling vsprintf()

It's very easy to have undefined behaviour and even crash with bad format strings. It's also possible that vs...f() cannot be used in our scenario. In this case rather than calling them once for each input line, call them once per each format specifier in the format string and/or write custom implementation. If one call per line is made, preprocessing determines N - the number of format specifiers producing data (i.e. non-%* and non-%% specifiers) and may do some checks to avoid UB.

All functions use neutral locale ("C"), in particular no grouping (12,345) and . for decimal part (3.14). This corresponds to Math Eval's copy result format.

We must support the limited feature set of scanf():

Featureset of printf():


This feature will allow changing column order in a CSV: Parse = %s;%s, Replace = %2$s;%1$s; as well as aligning text:

int n = 0;
char[] str = "foo\n";

Parse = %s %s = %s;, Replace = %6s %-3s = %s;:

   int n   = 0;
char[] str = "foo\n";

Combined with Sort (Alt+O), one can order lines by their length:

a
ccc
bb

First Alt+A (Parse = %s%n, Replace = %2$06d %1$s), then Alt+O (Logical number comparison`):

000001 a
000002 bb
000003 ccc