Posted: Thu Feb 18, 2016 11:48 pm
Reread my first post in this thread.
The regex does match as much as it can. Having matched an entire line and replaced it with something, the cursor is at the end of the line. The question is: what should it match next? The answer is that, in the absence of special handling, the next thing it matches is the empty string between the cursor and the line terminator.
The reason for this is the "leftmost match" rule: when matching within a string always choose the leftmost (first) match. This rule takes precedence over the "longest match" rule (greediness): the leftmost match will be found even if there's a longer match that is not leftmost.
Suppose you are replacing a single match of .* with blah.
If the cursor is on an empty line, running the replacement will replace the leftmost match, that is, the empty string between the cursor and the line terminator, with blah. If that's not what you expect, you're using the wrong regex.
In the same way, if the cursor is at the end of a non-empty line, running the replacement will replace the leftmost match, that is, the empty string between the cursor and the line terminator, with blah. Again, if that's not what you expect, you're using the wrong regex.
If you run the replacement repeatedly, a single replacement at a time, then after each replacement, the cursor is at the end of the line. The leftmost match at this position is the empty string, which is replaced with blah. After the replacement, the cursor is still at the end of the line, and so the next leftmost match is again the empty string. Each single replacement therefore appends another blah.
TextPad handles a single "replace all" action in the same way as multiple "replace one" actions. This has the unfortunate consequence that replacing all matches of .* with blah will repeatedly append blahs until the process is interrupted, or it hangs, or the cows come home.
That is the answer to your question.
The question of how the endless loop can be avoided is a different one. When performing a "replace all" action TextPad might check after each single replacement whether the next match would be the empty string, and, if so, advance the cursor by one character. However, any such special handling is a case of doing something different from what the user requested. Whatever solution might be implemented, there will always be cases where the user wants a different solution.
Keep in mind that when the editor loops endlessly in such cases it is doing what the user told it to do, albeit that it is perhaps not what the user wanted it to do.
The regex does match as much as it can. Having matched an entire line and replaced it with something, the cursor is at the end of the line. The question is: what should it match next? The answer is that, in the absence of special handling, the next thing it matches is the empty string between the cursor and the line terminator.
The reason for this is the "leftmost match" rule: when matching within a string always choose the leftmost (first) match. This rule takes precedence over the "longest match" rule (greediness): the leftmost match will be found even if there's a longer match that is not leftmost.
Suppose you are replacing a single match of .* with blah.
If the cursor is on an empty line, running the replacement will replace the leftmost match, that is, the empty string between the cursor and the line terminator, with blah. If that's not what you expect, you're using the wrong regex.
In the same way, if the cursor is at the end of a non-empty line, running the replacement will replace the leftmost match, that is, the empty string between the cursor and the line terminator, with blah. Again, if that's not what you expect, you're using the wrong regex.
If you run the replacement repeatedly, a single replacement at a time, then after each replacement, the cursor is at the end of the line. The leftmost match at this position is the empty string, which is replaced with blah. After the replacement, the cursor is still at the end of the line, and so the next leftmost match is again the empty string. Each single replacement therefore appends another blah.
TextPad handles a single "replace all" action in the same way as multiple "replace one" actions. This has the unfortunate consequence that replacing all matches of .* with blah will repeatedly append blahs until the process is interrupted, or it hangs, or the cows come home.
That is the answer to your question.
The question of how the endless loop can be avoided is a different one. When performing a "replace all" action TextPad might check after each single replacement whether the next match would be the empty string, and, if so, advance the cursor by one character. However, any such special handling is a case of doing something different from what the user requested. Whatever solution might be implemented, there will always be cases where the user wants a different solution.
Keep in mind that when the editor loops endlessly in such cases it is doing what the user told it to do, albeit that it is perhaps not what the user wanted it to do.