-
Notifications
You must be signed in to change notification settings - Fork 1.3k
quick fix for #3700 #3914
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
quick fix for #3700 #3914
Conversation
internal/buffer/search.go
Outdated
| if b.Settings["ignorecase"].(bool) { | ||
| r, err = regexp.Compile("(?i)" + s) | ||
| } else { | ||
| r, err = regexp.Compile(s) | ||
| } | ||
|
|
||
| if err == nil { | ||
| _, err = regexp.Compile("(" + s + ")") | ||
| } | ||
|
|
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 like how it is proposed to simplify in #3913:
if b.Settings["ignorecase"].(bool) {
s = "(?i)" + s
}Afterwards we can perform your introduced check with:
r, err = regexp.Compile("(" + s + ")")
if err != nil {
return [2]Loc{}, false, err
}The benefit is, that we should compile the string only once to find out if it is valid or not.
Would it hurt to have it in that moment already in an additional capture group? If no, then nothing more needs to be added, if yes then the non-grouped compilation (+ additional sanity check for err):
r, err = regexp.Compile(s)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 also like the ignorecase approach you mentioned. Regarding the capture group, I guess it doesn't matter, but in order be clean, I would go with a non-capturing group
r, err = regexp.Compile("(?:" + s + ")")
Shall I update the PR along these lines?
EDIT: In this appraoch, all regexp error messages would look "weird": For example, if a user searches for (x, the message becomes
error parsing regexp: missing closing ): `(?:(x)`
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'm only taking a quick look at the moment, but the check should also probably be done in ReplaceRegex.
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.
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 was thinking of adding return 0, 0 when the check fails, which seems unlikely to significantly increase the difficulty of the rebase.
If this will be done, shouldn't we also modify > replace to report an error by performing the check? Crashing on > replace or displaying no results despite \Qexample test being valid before seems like a regression as well, and we could stop compiling twice with #3658 at least.
EDIT: In this appraoch, all regexp error messages would look "weird": For example, if a user searches for
(x, the message becomeserror parsing regexp: missing closing ): `(?:(x)`
Wouldn't it be fine to return a new error if its type is syntax.Error and Expr matches the whole modified string?
Edit: Combining the actual compilation and check has a flaw, which I cannot thoroughly lookup and explain yet right now.
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.
Could you add the check in
ReplaceCmdif the change is small enough for 2.0.15?
This question is still open. For consistency it might be better to add it already now.
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 is automatic because now the regexp is checked in findLineParams. All regexps for search and replace operations pass through this function.
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.
Yes, checking the regex and adjusting it in findLineParams is enough.
Just to be slightly clear about the information left here on > replace: \Q without \E is indeed accepted since it doesn't display an error, but without this PR it can crash in ReplaceRegex. Reproduction steps slightly differ with #3700.
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.
It's not only that it doesn't display an error -- it actually performs the correct replacements.
EDIT: I mean "with this PR".
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 think it succeeds in most cases, but this is one minimal example where it crashes without this PR:
- Open an empty buffer, then insert one space and "a"
- Select "a" only and run
> replace '\Qa' b
8d0bfcd to
266b2b1
Compare
|
The Go gurus say that |
266b2b1 to
560bfcf
Compare
dmaluka
left a comment
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.
Looks nice, thanks.
This is a quick fix on top of current master. A separate commit (also in my PR #3658) ensures that regexp error messages are displayed. The error message for
\Qwithout\Eis slightly weird,but at least there is an error message instead of a crash.
Fixes #3700