lizmat / App-Rak

21st century grep / find / ack / ag / rg on steroids
Artistic License 2.0
152 stars 7 forks source link

problems with --modify-files #52

Closed finanalyst closed 3 weeks ago

finanalyst commented 5 months ago

rak with --modify-files produces (I think) incorrect reports and does not allow non-destructive potential results. a) A zipped directory is attached with three files in a directory 'rak-test' raktest.zip b) Two files contain 'processed', one contains 'xrocessed', each file has 9 lines c) The following rak commands and output were obtained

rak '*.subst(/ "processed" /, ":processing")' rak-test/ --modify-files --dryrun
Processed 3 files, 3 files changed, 27 lines changed
*** no changes where made because of --dryrun ***
$ rak '/ "processed" /' rak-test/ --files-with-matches
rak-test/01.rakutest
rak-test/02.rakutest

After running the first stanza, I would have expected the result to be 3 files, 2 files changed, 4 lines changed

Further, I wanted to see what might be changed.

$ rak '*.subst(/ "processed" /, ":processing")' rak-test/ --modify-files --dryrun --files-with-matches
The --files-with-matches option is not being handled and will be ignored.
If you believe this to be incorrect, please report an issue with <snip>

I have had problems with --modify-files because I have mis-specified the regex and changed too much or too many files with no way of easily determining what is being picked up.

Perhaps the output to --dryrun --verbose could be each line changed with the original followed by the changed line (coloured differently ?).

Info:

$ rak --version
rak - provided by App::Rak 0.2.20, running Raku 6.d with Rakudo 2024.02.
lizmat commented 5 months ago

The documentation of --modify-files states:

--modify-files

Only makes sense with a Callable pattern.  Indicates that the inspected
files may be potentially changed.  If the value returned by the
Callable pattern is not True/False/Nil/Empty and different from the
given line, then that line will be replaced by the returned value(s).
Else it will be kept unchanged because of an implicit --passthru-context
argument being active.

I would assume that currently the "and different from the given line" check is failing (or possibly not even implemented).

Since you used .subst in your example, every line is considered changed (because of the above bug).

Note that you can also specify --verbose, to get more verbose feedback.

So, as a temporary workaround, you could do this:

$ rak '{ .subst("processed", :processing) if .contains("processed") }' rak-test/ --modify-files --dryrun --verbose
Processed 2 files, 2 files changed, 4 lines changed
rak-test/01.rakutest: 2 changes
rak-test/02.rakutest: 2 changes

Now, this is already a lot more info as you can see. I wonder though where the "Processed 2 files" comes from, it should have said 3.

I'll see if I can quickly fix these...

lizmat commented 5 months ago

Ok, it looks like it is not going to be an easy fix. Please use the workaround for now.

finanalyst commented 5 months ago

If .subst returns a string whether it is changed or not, and a string coerces to True, then .subst will report all lines in all files will be changed, so under this view, the problem is not rak, but .subst Suppose, for rak you introduce a new method .on-subst that returns a string - True - if the match succeeds on a string, and returns False if the match does not exist, or mixes in the Bool value of the match to the string, so that when the match succeeds, the string has a True value when coerced to a Bool, and a False value if the match does not succeed when when coerced to a Bool.

lizmat commented 5 months ago

The semantics of .subst are by now more or less cast in stone.

It's the rak module that needs fixing: it needs to check whether the returned string is the same as the source string, and not mark it as changed. As per the documentation :-)

lizmat commented 3 weeks ago

This has been fixed with release 0.3.1, now in he ecosystem!