Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
match beginning and end of line correctly #3575
match beginning and end of line correctly #3575
Changes from all commits
c9643fd
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still, what is the advantage of using
findAll()
to remember all matches in some temporary storage to handle them afterwards, instead of just usingfindDown()
and handling each match right away?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One could do that. I wrote the code with the idea in mind to have some public
FindAll
function at a later point. That code would be based on the currentfindAll
. One could changefindAll
to somefindAllFunc
that takes a callback function as argument (simialr toReplaceAllFunc
). This way the problem of creating temporary lists would disappear. (That would also be a good idea for a public function.) CurrentlyfindAll
is only called for the first and last lines, so that performance doesn't really matter. That would change of course if we used this function for all lines.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow I missed the email notification about your comments a week ago...
Still, what for? Why not keep things simple?
A single line may be huge. (Although that's an edge case, and currently micro handles huge lines very poorly anyway, for unrelated reasons, due to the dumb data structure with O(n) access, which IMO we should fix some day, because that's a shame.)
But my point is not so much about performance but about simplicity. We have a chance to try to make the logic not just more correct but at the same time simpler, by simply calling
findDown()
in a loop for the entire range, instead of complicating the code with more special cases, so why not take this chance?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to call
MultipleReplace
only once inReplaceRegex
with all deltas at once (as done in master and this PR), then I believe we cannot deal with each match right away (unless we modifyMultipleReplace
). The problem is that multiple deltas on a single line only work if the last (= rightmost) change comes first. If we simply want to callfindDown
repeatedly over the whole buffer, then we have to store all matches in a list (currently done infindAll
) and then process this list backwards (done inReplaceRegex
). (My understanding is that there is no efficient way in Go to prepend to a slice.)Apart from this list reversal, this would indeed lead to fairly simple code. Padded repexps would be compiled for almost every call to
findDown
. If one doesn't want that, then one could create the padded regexps before callingfindDown
.Please let me know how you want to proceed.
EDIT: Modifying the processing of deltas should be easy to do (in
ExecuteTextEvent
). As far as I can tell,MultipleReplace
is the only place where aTextEvent
with multiple deltas is created, andReplaceRegex
is the only function callingMultipleReplace
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, good point. Thanks for explanations.
I've analyzed all this in more detail and now it seems to me that the current approach in this PR is already as simple and practical as it can be without further refactoring of EventHandler (which we can do separately, if we want to).
Yeah, that's also an argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you be interested in a separate PR that modifies
ExecuteTextEvent
? In a separate commit I could modify the search code (precompile padded regexps and use thefindDown
method only inReplaceRegex
).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it goes well, why not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's now the first part of #3658.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've noticed that because of this
ReplaceAll()
usage, matching\b
still doesn't work fully correctly:replace \\b aaa
(interactive replace) -> finds matches but doesn't replace them (IOW correctly finds the next beginning or end of a word, but doesn't insertaaa
here).replace \\b aaa -a
with selected text -> if the first or last line of the selection is not fully covered by the selection, it doesn't replace matches in this (first or last) line.This "fixes" both problems for me:
but this is an incorrect hack (at least because we should not disable expanding
${1}
etc even if the match is empty).I'm not sure how to fix it correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bug is in master already. The problem is to apply the given regexp to
b.Substr(match[0], match[1])
because this substring may fail to have a word boundary matching\b
.The good news is that this problem does not seem to exist in my draft PR #3658. There, instead of using
(*Regexp).ReplaceAll()
, I store the match and use it for(*Regexp).Expand()
,https://github.com/matthias314/micro/blob/bab91644e3ae8a90371f145b1f6106ad67619886/internal/buffer/search.go#L326-L333
For
replaceall
that should fix the problem. It also seems to work for interactive replacements although the new function(*Buffer).ReplaceAll()
(which replaced(*Buffer).ReplaceRegex()
is called there. I still need to understand why. Even if there is a problem, one should be able to solve it by usingExpand
there, too.EDIT: I think that #3658 works for interactive replaces, too. The reason is that the added padding makes the problem of an empty match disappear, and then
(*Regexp).Expand()
works as forreplaceall
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, for sure this is not a regression.
Cool. Yeah I see, to fix the problem we just need to
Expand()
on the original line, but that seems tricky to do without some rework inEventHandler
first.I'll take a look at #3658 once I have some time. In the meantime I think we can merge this PR now anyway.