From 57e21f614d9999c9638107cd7a3dcf949ecd7176 Mon Sep 17 00:00:00 2001 From: Kevin Wu Date: Fri, 24 Nov 2023 10:32:12 -0500 Subject: [PATCH] Fix hang during substitution (#112) Using vim's substitute command could result in an infinite loop when substituting a string with a string containing itself while using the global flag. Consider the string "test". If we substituted "test" with "atest", an infinite loop would occur as we currently match strings from the beginning of the newly substituted string instead of the end. To fix this, we should begin searching from the end if searching for the next match. Furthermore, the end position of lastSearch is not properly updated when performing substitutions. This results in an infinite loop while substituting "test" with "12345test", even when properly searching from the end of the string. Instead, we should use the endCursorState callback of the executeEdits function as executeEdits does not change the cursor position, and set the lastSearch variable to the returned result of setEndPosition as setEndPosition on a Range returns a new Range instead of modifying the Range in place. --- src/cm_adapter.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/cm_adapter.js b/src/cm_adapter.js index d4c81a1..a98194d 100644 --- a/src/cm_adapter.js +++ b/src/cm_adapter.js @@ -1064,7 +1064,7 @@ class CMAdapter { } else { const pos = lastSearch ? model.getPositionAt( - model.getOffsetAt(lastSearch.getStartPosition()) + 1 + model.getOffsetAt(lastSearch.getEndPosition()) + 1 ) : monacoPos; match = model.findNextMatch(query, pos, isRegex, matchCase); @@ -1089,15 +1089,20 @@ class CMAdapter { }, replace(text) { if (lastSearch) { - editor.executeEdits("vim", [ - { - range: lastSearch, - text, - forceMoveMarkers: true, - }, - ]); - - lastSearch.setEndPosition(editor.getPosition()); + editor.executeEdits( + "vim", + [ + { + range: lastSearch, + text, + forceMoveMarkers: true, + }, + ], + function (edits) { + const { endLineNumber, endColumn } = edits[0].range; + lastSearch = lastSearch.setEndPosition(endLineNumber, endColumn); + } + ); editor.setPosition(lastSearch.getStartPosition()); } },